From 6280e4e7cbad956aab1a2a519d93620c3990eedc Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sat, 14 Sep 2019 18:01:52 -0400 Subject: msp430f5529: Add empty msp_exp430f5529lp BSP and DCD. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 116 ++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/portable/ti/msp430x5xx/dcd_msp430x5xx.c (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c new file mode 100644 index 000000000..4c8c370ce --- /dev/null +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -0,0 +1,116 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 William D. Jones + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MSP430x5xx ) + +#include "device/dcd.h" + +/*------------------------------------------------------------------*/ +/* MACRO TYPEDEF CONSTANT ENUM + *------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------*/ +/* Controller API + *------------------------------------------------------------------*/ +void dcd_init (uint8_t rhport) +{ + (void) rhport; +} + +void dcd_int_enable (uint8_t rhport) +{ + (void) rhport; +} + +void dcd_int_disable (uint8_t rhport) +{ + (void) rhport; +} + +void dcd_set_address (uint8_t rhport, uint8_t dev_addr) +{ + (void) rhport; + (void) dev_addr; +} + +void dcd_set_config (uint8_t rhport, uint8_t config_num) +{ + (void) rhport; + (void) config_num; + // Nothing to do +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; +} + +/*------------------------------------------------------------------*/ +/* DCD Endpoint port + *------------------------------------------------------------------*/ + +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) +{ + (void) rhport; + (void) desc_edpt; + + return false; +} + +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + (void) rhport; + (void) ep_addr; + (void) buffer; + (void) total_bytes; + + return false; +} + +void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + (void) ep_addr; +} + +void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + (void) ep_addr; +} + +/*------------------------------------------------------------------*/ + +void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) +{ + +} + +#endif -- cgit v1.3.1 From 907bc3df9ba70c9a82ad2f98031879f17e2ad2b5 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Mon, 23 Sep 2019 17:48:18 -0400 Subject: msp430f5529: Ensure cdc_msc demo compiles. --- hw/bsp/msp_exp430f5529lp/board.mk | 3 ++- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 1 + src/tusb_option.h | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/hw/bsp/msp_exp430f5529lp/board.mk b/hw/bsp/msp_exp430f5529lp/board.mk index 741b3e00e..b47e764bd 100644 --- a/hw/bsp/msp_exp430f5529lp/board.mk +++ b/hw/bsp/msp_exp430f5529lp/board.mk @@ -1,6 +1,7 @@ CFLAGS += \ -D__MSP430F5529__ \ - -DCFG_TUSB_MCU=OPT_MCU_MSP430x5xx + -DCFG_TUSB_MCU=OPT_MCU_MSP430x5xx \ + -DCFG_EXAMPLE_MSC_READONLY # All source paths should be relative to the top level. LD_FILE = hw/bsp/msp_exp430f5529lp/msp430f5529.ld diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 4c8c370ce..b2df9e3b6 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -29,6 +29,7 @@ #if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MSP430x5xx ) +#include "msp430.h" #include "device/dcd.h" /*------------------------------------------------------------------*/ diff --git a/src/tusb_option.h b/src/tusb_option.h index eccb4245c..5de599951 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -60,6 +60,8 @@ #define OPT_MCU_STM32F7 305 ///< ST STM32F7 #define OPT_MCU_STM32H7 306 ///< ST STM32H7 +#define OPT_MCU_MSP430x5xx 400 ///< TI MSP430x5xx + /** @} */ -- cgit v1.3.1 From a6a79df9fb6864ad2d30dde85fd04c836f28f5d5 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Mon, 23 Sep 2019 18:53:31 -0400 Subject: msp430f5529: Enable clocks/PLL for msp_exp430f5529lp and enable USB module in dcd_msp430x5xx; device does not enumerate. --- hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c | 33 +++++++++++++++++++++++++++- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 5 +++++ 2 files changed, 37 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c b/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c index 5fa69465d..29f88ccf5 100644 --- a/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c +++ b/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c @@ -36,6 +36,8 @@ #define BUTTON_PIN BIT1 #define BUTTON_STATE_ACTIVE 1 +uint32_t cnt = 0; + static void SystemClock_Config(void) { WDTCTL = WDTPW + WDTHOLD; // Disable watchdog. @@ -86,16 +88,45 @@ static void SystemClock_Config(void) TA0CCTL0 |= CCIE; TA0CCR0 = 999; // 1000 ticks. TA0CTL |= TASSEL_2 + ID_3 + MC__UP; // Use SMCLK, divide by 8, start timer. + + // Initialize USB power and PLL. + USBKEYPID = USBKEY; + + // VUSB enabled automatically. + // Wait two milliseconds to stabilize, per manual recommendation. + uint32_t ms_elapsed = board_millis(); + do + { + while((board_millis() - ms_elapsed) < 2); + }while(!(USBPWRCTL & USBBGVBV)); + + // USB uses XT2 (4 MHz) directly. Enable the PLL. + USBPLLDIVB |= USBPLL_SETCLK_4_0; + USBPLLCTL |= (UPFDEN | UPLLEN); + + // Wait until PLL locks. Check every 2ms, per manual. + ms_elapsed = board_millis(); + do + { + USBPLLIR &= ~USBOOLIFG; + while((board_millis() - ms_elapsed) < 2); + }while(USBPLLIR & USBOOLIFG); + + USBKEYPID = 0; } void board_init(void) { - SystemClock_Config(); __bis_SR_register(GIE); // Enable interrupts. + SystemClock_Config(); P1DIR |= LED_PIN; // LED output. P1REN |= BUTTON_PIN; // Internal resistor enable. P1OUT |= BUTTON_PIN; // Pullup. + + USBKEYPID = USBKEY; + USBPHYCTL |= PUSEL; // Convert USB D+/D- pins to USB functionality. + USBKEYPID = 0; } //--------------------------------------------------------------------+ diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index b2df9e3b6..e9ca76853 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -43,6 +43,11 @@ void dcd_init (uint8_t rhport) { (void) rhport; + + // Enable the module! + USBKEYPID = USBKEY; + USBCNF |= (PUR_EN | USB_EN); + USBKEYPID = 0; } void dcd_int_enable (uint8_t rhport) -- cgit v1.3.1 From 950614a841a69f09ffd8b97205183e1c85b09443 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Mon, 23 Sep 2019 22:58:49 -0400 Subject: msp430f5529: Implement dcd_int_enable/disable. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index e9ca76853..e01c0243f 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -35,6 +35,11 @@ /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ +// usbpllir_mirror and usbmaintl_mirror can be added later if needed. +static volatile uint16_t usbiepie_mirror = 0; +static volatile uint16_t usboepie_mirror = 0; +static volatile uint16_t usbie_mirror = 0; +static volatile uint16_t usbpwrctl_mirror = 0; /*------------------------------------------------------------------*/ @@ -50,14 +55,40 @@ void dcd_init (uint8_t rhport) USBKEYPID = 0; } +// There is no "USB peripheral interrupt disable" bit on MSP430, so we have +// to save the relevant registers individually. +// WARNING: Unlike the ARM/NVIC routines, these functions are _not_ idempotent +// if you modified the registers saved in between calls so they don't match +// the mirrors; mirrors will be updated to reflect most recent register +// contents. void dcd_int_enable (uint8_t rhport) { (void) rhport; + + __bic_SR_register(GIE); // Unlikely to be called in ISR, but let's be safe. + // Also, this cleanly disables all USB interrupts + // atomically from application's POV. + USBOEPIE = usboepie_mirror; + USBIEPIE = usbiepie_mirror; + USBIE = usbie_mirror; + USBPWRCTL |= usbpwrctl_mirror; + __bis_SR_register(GIE); } void dcd_int_disable (uint8_t rhport) { (void) rhport; + + __bic_SR_register(GIE); + usboepie_mirror = USBOEPIE; + usbiepie_mirror = USBIEPIE; + usbie_mirror = USBIE; + usbpwrctl_mirror = (USBPWRCTL & (VUOVLIE | VBONIE | VBOFFIE)); + USBOEPIE = 0; + USBIEPIE = 0; + USBIE = 0; + USBPWRCTL &= ~(VUOVLIE | VBONIE | VBOFFIE); + __bis_SR_register(GIE); } void dcd_set_address (uint8_t rhport, uint8_t dev_addr) -- cgit v1.3.1 From d2e4af5a7b42ab54510bc8507ca28aed3604d9d1 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Tue, 24 Sep 2019 02:41:11 -0400 Subject: msp430f5529: Change EP0 size to 8, implement interrupt logic up to bus reset detection. --- hw/bsp/msp_exp430f5529lp/board.mk | 3 +- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 79 ++++++++++++++++++++++++++--- 2 files changed, 74 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/hw/bsp/msp_exp430f5529lp/board.mk b/hw/bsp/msp_exp430f5529lp/board.mk index b47e764bd..1ae7330c9 100644 --- a/hw/bsp/msp_exp430f5529lp/board.mk +++ b/hw/bsp/msp_exp430f5529lp/board.mk @@ -1,7 +1,8 @@ CFLAGS += \ -D__MSP430F5529__ \ -DCFG_TUSB_MCU=OPT_MCU_MSP430x5xx \ - -DCFG_EXAMPLE_MSC_READONLY + -DCFG_EXAMPLE_MSC_READONLY \ + -DCFG_TUD_ENDOINT0_SIZE=8 # All source paths should be relative to the top level. LD_FILE = hw/bsp/msp_exp430f5529lp/msp430f5529.ld diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index e01c0243f..9ff63f839 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -38,8 +38,16 @@ // usbpllir_mirror and usbmaintl_mirror can be added later if needed. static volatile uint16_t usbiepie_mirror = 0; static volatile uint16_t usboepie_mirror = 0; -static volatile uint16_t usbie_mirror = 0; +static volatile uint8_t usbie_mirror = 0; static volatile uint16_t usbpwrctl_mirror = 0; +static bool in_isr = false; + +uint8_t _setup_packet[8]; + +static void bus_reset(void) +{ + +} /*------------------------------------------------------------------*/ @@ -49,9 +57,27 @@ void dcd_init (uint8_t rhport) { (void) rhport; - // Enable the module! USBKEYPID = USBKEY; - USBCNF |= (PUR_EN | USB_EN); + + // Enable the module (required to write config regs)! + USBCNF |= USB_EN; + + // Reset used interrupts + USBOEPIE = 0; + USBIEPIE = 0; + USBIE = 0; + USBOEPIFG = 0; + USBIEPIFG = 0; + USBIFG = 0; + USBPWRCTL &= ~(VUOVLIE | VBONIE | VBOFFIE | VUOVLIFG | VBONIFG | VBOFFIFG); + USBVECINT = 0; + + // Enable reset and wait for it before continuing. + USBIE |= RSTRIE; + + // Enable pullup. + USBCNF |= PUR_EN; + USBKEYPID = 0; } @@ -68,10 +94,18 @@ void dcd_int_enable (uint8_t rhport) __bic_SR_register(GIE); // Unlikely to be called in ISR, but let's be safe. // Also, this cleanly disables all USB interrupts // atomically from application's POV. - USBOEPIE = usboepie_mirror; - USBIEPIE = usbiepie_mirror; - USBIE = usbie_mirror; - USBPWRCTL |= usbpwrctl_mirror; + + // This guard is required because tinyusb can enable interrupts without + // having disabled them first. + if(in_isr) + { + USBOEPIE = usboepie_mirror; + USBIEPIE = usbiepie_mirror; + USBIE = usbie_mirror; + USBPWRCTL |= usbpwrctl_mirror; + } + + in_isr = false; __bis_SR_register(GIE); } @@ -88,6 +122,7 @@ void dcd_int_disable (uint8_t rhport) USBIEPIE = 0; USBIE = 0; USBPWRCTL &= ~(VUOVLIE | VBONIE | VBOFFIE); + in_isr = true; __bis_SR_register(GIE); } @@ -145,8 +180,38 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) /*------------------------------------------------------------------*/ +static void handle_setup_packet(void) +{ + +} + void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) { + // Setup is special- reading USBVECINT to handle setup packets is done to + // stop NAKs on EP0. + uint8_t setup_status = USBIFG & SETUPIFG; + + if(setup_status) + { + handle_setup_packet(); + } + + uint16_t curr_vector = USBVECINT; + + switch(curr_vector) + { + case USBVECINT_RSTR: + bus_reset(); + dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + break; + + // Clear the NAK on EP 0 after a SETUP packet is received. + case USBVECINT_SETUP_PACKET_RECEIVED: + break; + + default: + break; + } } -- cgit v1.3.1 From 550e8215f3ee60c13548e623925ca870023b20e4 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Tue, 24 Sep 2019 03:43:51 -0400 Subject: dcd_msp430x5xx: Setup packets are now received successfully (with delay). --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 41 ++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 9ff63f839..4b35cd984 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -35,6 +35,8 @@ /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ +#define USB_BUF_PTR(_x) (uint8_t *) ((uint16_t) _x) + // usbpllir_mirror and usbmaintl_mirror can be added later if needed. static volatile uint16_t usbiepie_mirror = 0; static volatile uint16_t usboepie_mirror = 0; @@ -46,7 +48,19 @@ uint8_t _setup_packet[8]; static void bus_reset(void) { - + // Enable the control EP 0. Also enable Indication Enable- a guard flag + // separate from the Interrupt Enable mask. + USBOEPCNF_0 |= (UBME | USBIIE); + USBIEPCNF_0 |= (UBME | USBIIE); + + // Enable interrupts for this endpoint. + USBOEPIE |= BIT0; + USBIEPIE |= BIT0; + + // Clear NAK so packets can be received. + // Dedicated buffers in hardware for SETUP and EP0, no setup needed. + USBOEPCNT_0 &= ~NAK; + USBIEPCNT_0 &= ~NAK; } @@ -180,9 +194,26 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) /*------------------------------------------------------------------*/ +static void receive_packet(void) +{ + +} + +static void transmit_packet(void) +{ + +} + static void handle_setup_packet(void) { + volatile uint8_t * setup_buf = &USBSUBLK; + + for(int i = 0; i < 8; i++) + { + _setup_packet[i] = setup_buf[i]; + } + dcd_event_setup_received(0, (uint8_t*) &_setup_packet[0], true); } void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) @@ -209,6 +240,14 @@ void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) case USBVECINT_SETUP_PACKET_RECEIVED: break; + case USBVECINT_INPUT_ENDPOINT0: + transmit_packet(); + break; + + case USBVECINT_OUTPUT_ENDPOINT0: + receive_packet(); + break; + default: break; } -- cgit v1.3.1 From 01b4115b0b26a9fb5c706daf320c85556d16f920 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Tue, 24 Sep 2019 04:06:34 -0400 Subject: dcd_msp430x5xx: Fix Setup packet delay by actually enabling corresponding interrupt. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 4b35cd984..fe78218df 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -61,6 +61,9 @@ static void bus_reset(void) // Dedicated buffers in hardware for SETUP and EP0, no setup needed. USBOEPCNT_0 &= ~NAK; USBIEPCNT_0 &= ~NAK; + + // Now safe to respond to SETUP packets. + USBIE |= SETUPIE; } -- cgit v1.3.1 From c4483d244b04a6679d85376e3e686c23b9ee82af Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 27 Sep 2019 12:41:46 -0400 Subject: Fix typo of CFG_TUD_ENDOINT0_SIZE. --- examples/device/board_test/src/tusb_config.h | 2 +- examples/device/cdc_msc/src/tusb_config.h | 4 ++-- examples/device/cdc_msc/src/usb_descriptors.c | 2 +- examples/device/cdc_msc_hid_freertos/src/tusb_config.h | 4 ++-- examples/device/cdc_msc_hid_freertos/src/usb_descriptors.c | 2 +- examples/device/hid_composite/src/tusb_config.h | 4 ++-- examples/device/hid_composite/src/usb_descriptors.c | 2 +- examples/device/hid_generic_inout/src/tusb_config.h | 4 ++-- examples/device/hid_generic_inout/src/usb_descriptors.c | 2 +- examples/device/midi_test/src/tusb_config.h | 4 ++-- examples/device/midi_test/src/usb_descriptors.c | 2 +- examples/device/msc_dual_lun/src/tusb_config.h | 4 ++-- examples/device/msc_dual_lun/src/usb_descriptors.c | 2 +- examples/device/webusb_serial/src/tusb_config.h | 4 ++-- examples/device/webusb_serial/src/usb_descriptors.c | 2 +- hw/bsp/msp_exp430f5529lp/board.mk | 2 +- src/device/usbd_control.c | 2 +- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 4 ++-- src/portable/nxp/lpc18_43/dcd_lpc18_43.c | 2 +- 19 files changed, 27 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/examples/device/board_test/src/tusb_config.h b/examples/device/board_test/src/tusb_config.h index 5c3cac83a..2f2a4deeb 100644 --- a/examples/device/board_test/src/tusb_config.h +++ b/examples/device/board_test/src/tusb_config.h @@ -64,7 +64,7 @@ // DEVICE CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUD_ENDOINT0_SIZE 64 +#define CFG_TUD_ENDPOINT0_SIZE 64 //------------- CLASS -------------// #define CFG_TUD_CDC 0 diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index e307870ed..4455f665e 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -68,8 +68,8 @@ //-------------------------------------------------------------------- // DEVICE CONFIGURATION //-------------------------------------------------------------------- -#ifndef CFG_TUD_ENDOINT0_SIZE -#define CFG_TUD_ENDOINT0_SIZE 64 +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 #endif //------------- CLASS -------------// diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index ac8214e37..11d07e9ba 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -50,7 +50,7 @@ tusb_desc_device_t const desc_device = .bDeviceSubClass = MISC_SUBCLASS_COMMON, .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = 0xCafe, .idProduct = USB_PID, diff --git a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h index 7869e24cc..f84874ab1 100644 --- a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h @@ -69,8 +69,8 @@ // DEVICE CONFIGURATION //-------------------------------------------------------------------- -#ifndef CFG_TUD_ENDOINT0_SIZE -#define CFG_TUD_ENDOINT0_SIZE 64 +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 #endif //------------- CLASS -------------// diff --git a/examples/device/cdc_msc_hid_freertos/src/usb_descriptors.c b/examples/device/cdc_msc_hid_freertos/src/usb_descriptors.c index 5d93cc2f6..d60c9a585 100644 --- a/examples/device/cdc_msc_hid_freertos/src/usb_descriptors.c +++ b/examples/device/cdc_msc_hid_freertos/src/usb_descriptors.c @@ -57,7 +57,7 @@ tusb_desc_device_t const desc_device = .bDeviceProtocol = 0x00, #endif - .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = 0xCafe, .idProduct = USB_PID, diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index 13ecfa415..8d29f10be 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -69,8 +69,8 @@ // DEVICE CONFIGURATION //-------------------------------------------------------------------- -#ifndef CFG_TUD_ENDOINT0_SIZE -#define CFG_TUD_ENDOINT0_SIZE 64 +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 #endif //------------- CLASS -------------// diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index 678b7528b..01f2cb59b 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -47,7 +47,7 @@ tusb_desc_device_t const desc_device = .bDeviceClass = 0x00, .bDeviceSubClass = 0x00, .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = 0xCafe, .idProduct = USB_PID, diff --git a/examples/device/hid_generic_inout/src/tusb_config.h b/examples/device/hid_generic_inout/src/tusb_config.h index c82588c2f..a7ce7acf8 100644 --- a/examples/device/hid_generic_inout/src/tusb_config.h +++ b/examples/device/hid_generic_inout/src/tusb_config.h @@ -69,8 +69,8 @@ // DEVICE CONFIGURATION //-------------------------------------------------------------------- -#ifndef CFG_TUD_ENDOINT0_SIZE -#define CFG_TUD_ENDOINT0_SIZE 64 +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 #endif //------------- CLASS -------------// diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index d0fc6b1bc..07989c5fd 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -46,7 +46,7 @@ tusb_desc_device_t const desc_device = .bDeviceClass = 0x00, .bDeviceSubClass = 0x00, .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = 0xCafe, .idProduct = USB_PID, diff --git a/examples/device/midi_test/src/tusb_config.h b/examples/device/midi_test/src/tusb_config.h index 4a84812c5..fcd6b97c2 100644 --- a/examples/device/midi_test/src/tusb_config.h +++ b/examples/device/midi_test/src/tusb_config.h @@ -69,8 +69,8 @@ // DEVICE CONFIGURATION //-------------------------------------------------------------------- -#ifndef CFG_TUD_ENDOINT0_SIZE -#define CFG_TUD_ENDOINT0_SIZE 64 +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 #endif //------------- CLASS -------------// diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c index 7cebc6a15..2305c9f68 100644 --- a/examples/device/midi_test/src/usb_descriptors.c +++ b/examples/device/midi_test/src/usb_descriptors.c @@ -46,7 +46,7 @@ tusb_desc_device_t const desc_device = .bDeviceClass = 0x00, .bDeviceSubClass = 0x00, .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = 0xCafe, .idProduct = USB_PID, diff --git a/examples/device/msc_dual_lun/src/tusb_config.h b/examples/device/msc_dual_lun/src/tusb_config.h index 073e2379f..b45e9c4dc 100644 --- a/examples/device/msc_dual_lun/src/tusb_config.h +++ b/examples/device/msc_dual_lun/src/tusb_config.h @@ -69,8 +69,8 @@ // DEVICE CONFIGURATION //-------------------------------------------------------------------- -#ifndef CFG_TUD_ENDOINT0_SIZE -#define CFG_TUD_ENDOINT0_SIZE 64 +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 #endif //------------- CLASS -------------// diff --git a/examples/device/msc_dual_lun/src/usb_descriptors.c b/examples/device/msc_dual_lun/src/usb_descriptors.c index cab37cf1f..e0a5904a4 100644 --- a/examples/device/msc_dual_lun/src/usb_descriptors.c +++ b/examples/device/msc_dual_lun/src/usb_descriptors.c @@ -46,7 +46,7 @@ tusb_desc_device_t const desc_device = .bDeviceClass = 0x00, .bDeviceSubClass = 0x00, .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = 0xCafe, .idProduct = USB_PID, diff --git a/examples/device/webusb_serial/src/tusb_config.h b/examples/device/webusb_serial/src/tusb_config.h index b2f09cac0..8a73e8353 100644 --- a/examples/device/webusb_serial/src/tusb_config.h +++ b/examples/device/webusb_serial/src/tusb_config.h @@ -69,8 +69,8 @@ // DEVICE CONFIGURATION //-------------------------------------------------------------------- -#ifndef CFG_TUD_ENDOINT0_SIZE -#define CFG_TUD_ENDOINT0_SIZE 64 +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 #endif //------------- CLASS -------------// diff --git a/examples/device/webusb_serial/src/usb_descriptors.c b/examples/device/webusb_serial/src/usb_descriptors.c index a1d5cd9b9..740defe4e 100644 --- a/examples/device/webusb_serial/src/usb_descriptors.c +++ b/examples/device/webusb_serial/src/usb_descriptors.c @@ -50,7 +50,7 @@ tusb_desc_device_t const desc_device = .bDeviceClass = TUSB_CLASS_MISC, .bDeviceSubClass = MISC_SUBCLASS_COMMON, .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = 0xCafe, .idProduct = USB_PID, diff --git a/hw/bsp/msp_exp430f5529lp/board.mk b/hw/bsp/msp_exp430f5529lp/board.mk index 1ae7330c9..2e6e77f18 100644 --- a/hw/bsp/msp_exp430f5529lp/board.mk +++ b/hw/bsp/msp_exp430f5529lp/board.mk @@ -2,7 +2,7 @@ CFLAGS += \ -D__MSP430F5529__ \ -DCFG_TUSB_MCU=OPT_MCU_MSP430x5xx \ -DCFG_EXAMPLE_MSC_READONLY \ - -DCFG_TUD_ENDOINT0_SIZE=8 + -DCFG_TUD_ENDPOINT0_SIZE=8 # All source paths should be relative to the top level. LD_FILE = hw/bsp/msp_exp430f5529lp/msp430f5529.ld diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 4ec432185..eed933f68 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -124,7 +124,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result _control_state.total_transferred += xferred_bytes; _control_state.buffer += xferred_bytes; - if ( _control_state.total_len == _control_state.total_transferred || xferred_bytes < CFG_TUD_ENDOINT0_SIZE ) + if ( _control_state.total_len == _control_state.total_transferred || xferred_bytes < CFG_TUD_ENDPOINT0_SIZE ) { // DATA stage is complete bool is_ok = true; diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 2b49f52e9..97809e758 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -172,8 +172,8 @@ void dcd_init(uint8_t rhport) //------------- user manual 11.13 usb device controller initialization -------------// // step 6 : set up control endpoint - set_ep_size(0, CFG_TUD_ENDOINT0_SIZE); - set_ep_size(1, CFG_TUD_ENDOINT0_SIZE); + set_ep_size(0, CFG_TUD_ENDPOINT0_SIZE); + set_ep_size(1, CFG_TUD_ENDPOINT0_SIZE); bus_reset(); diff --git a/src/portable/nxp/lpc18_43/dcd_lpc18_43.c b/src/portable/nxp/lpc18_43/dcd_lpc18_43.c index 519e0dcc6..3619a7c2b 100644 --- a/src/portable/nxp/lpc18_43/dcd_lpc18_43.c +++ b/src/portable/nxp/lpc18_43/dcd_lpc18_43.c @@ -115,7 +115,7 @@ static void bus_reset(uint8_t rhport) //------------- Set up Control Endpoints (0 OUT, 1 IN) -------------// p_dcd->qhd[0].zero_length_termination = p_dcd->qhd[1].zero_length_termination = 1; - p_dcd->qhd[0].max_package_size = p_dcd->qhd[1].max_package_size = CFG_TUD_ENDOINT0_SIZE; + p_dcd->qhd[0].max_package_size = p_dcd->qhd[1].max_package_size = CFG_TUD_ENDPOINT0_SIZE; p_dcd->qhd[0].qtd_overlay.next = p_dcd->qhd[1].qtd_overlay.next = QTD_NEXT_INVALID; p_dcd->qhd[0].int_on_setup = 1; // OUT only -- cgit v1.3.1 From 3ac43076da7acf8e8e83086bf895e0b2c5f8105e Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Fri, 27 Sep 2019 21:20:33 -0400 Subject: dcd_msp430x5xx: Implement EP0 IN xfers, clean up. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 105 ++++++++++++++++++++++++---- 1 file changed, 91 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index fe78218df..c52cf5505 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -35,8 +35,6 @@ /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ -#define USB_BUF_PTR(_x) (uint8_t *) ((uint16_t) _x) - // usbpllir_mirror and usbmaintl_mirror can be added later if needed. static volatile uint16_t usbiepie_mirror = 0; static volatile uint16_t usboepie_mirror = 0; @@ -46,8 +44,26 @@ static bool in_isr = false; uint8_t _setup_packet[8]; +typedef struct { + uint8_t * buffer; + uint16_t total_len; + uint16_t queued_len; + uint16_t max_size; + bool short_packet; +} xfer_ctl_t; + +xfer_ctl_t xfer_status[8][2]; +#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] + + static void bus_reset(void) { + // Hardcoded into the USB core. + xfer_status[0][TUSB_DIR_OUT].max_size = 8; + xfer_status[0][TUSB_DIR_IN].max_size = 8; + + USBKEYPID = USBKEY; + // Enable the control EP 0. Also enable Indication Enable- a guard flag // separate from the Interrupt Enable mask. USBOEPCNF_0 |= (UBME | USBIIE); @@ -57,13 +73,17 @@ static void bus_reset(void) USBOEPIE |= BIT0; USBIEPIE |= BIT0; - // Clear NAK so packets can be received. - // Dedicated buffers in hardware for SETUP and EP0, no setup needed. - USBOEPCNT_0 &= ~NAK; - USBIEPCNT_0 &= ~NAK; + // Set NAK until a setup packet is received. + USBOEPCNT_0 |= NAK; + USBIEPCNT_0 |= NAK; + + USBCTL |= FEN; // Enable responding to packets. + // Dedicated buffers in hardware for SETUP and EP0, no setup needed. // Now safe to respond to SETUP packets. USBIE |= SETUPIE; + + USBKEYPID = 0; } @@ -87,6 +107,11 @@ void dcd_init (uint8_t rhport) USBIEPIFG = 0; USBIFG = 0; USBPWRCTL &= ~(VUOVLIE | VBONIE | VBOFFIE | VUOVLIFG | VBONIFG | VBOFFIFG); + usboepie_mirror = 0; + usbiepie_mirror = 0; + usbie_mirror = 0; + usbpwrctl_mirror = 0; + USBVECINT = 0; // Enable reset and wait for it before continuing. @@ -173,14 +198,40 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return false; } +static volatile uint8_t iepcnt = 0xFF; + bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { (void) rhport; - (void) ep_addr; - (void) buffer; - (void) total_bytes; - return false; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->short_packet = false; + + if(epnum == 0) + { + if(dir == TUSB_DIR_OUT) + { + // Interrupt will notify us when data was received. + USBCTL &= ~DIR; + USBOEPCNT_0 &= ~NAK; + } + else + { + // Kickstart the IN packet handler by queuing initial data and calling + // the ISR to transmit the first packet. + // Interrupt only fires on completed xfer. + USBCTL |= DIR; + USBIEPIFG |= BIT0; + } + } + + return true; } void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) @@ -197,14 +248,39 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) /*------------------------------------------------------------------*/ -static void receive_packet(void) +static void receive_packet(uint8_t ep_num) { + (void) ep_num; } -static void transmit_packet(void) +static void transmit_packet(uint8_t ep_num) { + xfer_ctl_t * xfer = XFER_CTL_BASE(ep_num, TUSB_DIR_IN); + if(ep_num == 0) + { + if(xfer->total_len == xfer->queued_len) + { + dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); + return; + } + + uint8_t * base = (xfer->buffer + xfer->queued_len); + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint8_t xfer_size = (xfer->max_size < xfer->total_len) ? xfer->max_size : remaining; + + xfer->queued_len += xfer_size; + + volatile uint8_t * ep0in_buf = &USBIEP0BUF; + for(int i = 0; i < xfer_size; i++) + { + ep0in_buf[i] = base[i]; + } + + USBIEPCNT_0 = (USBIEPCNT_0 & 0xF0) + xfer_size; + USBIEPCNT_0 &= ~NAK; + } } static void handle_setup_packet(void) @@ -244,14 +320,15 @@ void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) break; case USBVECINT_INPUT_ENDPOINT0: - transmit_packet(); + transmit_packet(0); break; case USBVECINT_OUTPUT_ENDPOINT0: - receive_packet(); + receive_packet(0); break; default: + while(true); break; } -- cgit v1.3.1 From 030560792d1d2d6a2d4febf1c54f9735cddc7aca Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Fri, 27 Sep 2019 21:59:45 -0400 Subject: dcd_msp430x5xx: Implement dcd_set_address. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index c52cf5505..66b7ab293 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -50,6 +50,7 @@ typedef struct { uint16_t queued_len; uint16_t max_size; bool short_packet; + bool zlp_sent; } xfer_ctl_t; xfer_ctl_t xfer_status[8][2]; @@ -171,7 +172,11 @@ void dcd_int_disable (uint8_t rhport) void dcd_set_address (uint8_t rhport, uint8_t dev_addr) { (void) rhport; - (void) dev_addr; + + USBFUNADR = dev_addr; + + // Response with status after changing device address + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } void dcd_set_config (uint8_t rhport, uint8_t config_num) @@ -212,6 +217,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->total_len = total_bytes; xfer->queued_len = 0; xfer->short_packet = false; + xfer->zlp_sent = false; if(epnum == 0) { @@ -260,7 +266,8 @@ static void transmit_packet(uint8_t ep_num) if(ep_num == 0) { - if(xfer->total_len == xfer->queued_len) + bool zlp = (xfer->total_len == 0); + if((!zlp && (xfer->total_len == xfer->queued_len)) || xfer->zlp_sent) { dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); return; @@ -271,6 +278,10 @@ static void transmit_packet(uint8_t ep_num) uint8_t xfer_size = (xfer->max_size < xfer->total_len) ? xfer->max_size : remaining; xfer->queued_len += xfer_size; + if(xfer->total_len == 0) + { + xfer->zlp_sent = true; + } volatile uint8_t * ep0in_buf = &USBIEP0BUF; for(int i = 0; i < xfer_size; i++) -- cgit v1.3.1 From 63c94ff684372e804011ef9f2b283f2340bb67fd Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sat, 28 Sep 2019 01:51:05 -0400 Subject: dcd_msp430x5xx: Improve EP0 IN handling (reuse short_packet field). --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 66b7ab293..62aaee3cb 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -50,7 +50,6 @@ typedef struct { uint16_t queued_len; uint16_t max_size; bool short_packet; - bool zlp_sent; } xfer_ctl_t; xfer_ctl_t xfer_status[8][2]; @@ -203,8 +202,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return false; } -static volatile uint8_t iepcnt = 0xFF; - bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { (void) rhport; @@ -217,7 +214,6 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->total_len = total_bytes; xfer->queued_len = 0; xfer->short_packet = false; - xfer->zlp_sent = false; if(epnum == 0) { @@ -266,21 +262,27 @@ static void transmit_packet(uint8_t ep_num) if(ep_num == 0) { - bool zlp = (xfer->total_len == 0); - if((!zlp && (xfer->total_len == xfer->queued_len)) || xfer->zlp_sent) + // First, determine whether we should even send a packet or finish + // up the xfer. + bool zlp = (xfer->total_len == 0); // By necessity, xfer->total_len will + // equal xfer->queued_len for ZLPs. + // Of course a ZLP is a short packet. + if((!zlp && (xfer->total_len == xfer->queued_len)) || xfer->short_packet) { dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); return; } + // Then actually commit to transmit a packet. uint8_t * base = (xfer->buffer + xfer->queued_len); uint16_t remaining = xfer->total_len - xfer->queued_len; uint8_t xfer_size = (xfer->max_size < xfer->total_len) ? xfer->max_size : remaining; xfer->queued_len += xfer_size; - if(xfer->total_len == 0) + if(xfer_size < xfer->max_size) { - xfer->zlp_sent = true; + // Next "xfer complete interrupt", the transfer will end. + xfer->short_packet = true; } volatile uint8_t * ep0in_buf = &USBIEP0BUF; -- cgit v1.3.1 From 5d9f83391544261117fffa2dec218b80ccd1d01c Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sat, 28 Sep 2019 02:09:03 -0400 Subject: dcd_msp430x5xx: Implement STALL logic for EP 0. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 34 +++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 62aaee3cb..7a4599c26 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -239,13 +239,43 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; - (void) ep_addr; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if(epnum == 0) + { + if(dir == TUSB_DIR_OUT) + { + USBOEPCNT_0 |= NAK; + USBOEPCNF_0 |= STALL; + } + else + { + USBIEPCNT_0 |= NAK; + USBIEPCNF_0 |= STALL; + } + } } void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; - (void) ep_addr; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if(epnum == 0) + { + if(dir == TUSB_DIR_OUT) + { + USBOEPCNT_0 &= ~NAK; + } + else + { + USBIEPCNT_0 &= ~NAK; + } + } } /*------------------------------------------------------------------*/ -- cgit v1.3.1 From 529efcc0d2b60cceac14ca01a1f6e5fecab4d8aa Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sun, 29 Sep 2019 00:21:40 -0400 Subject: dcd_msp430x5xx: Implement dcd_edpt_open. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 74 +++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 7a4599c26..aac4f01db 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -44,7 +44,9 @@ static bool in_isr = false; uint8_t _setup_packet[8]; -typedef struct { +// Xfer control +typedef struct +{ uint8_t * buffer; uint16_t total_len; uint16_t queued_len; @@ -55,6 +57,21 @@ typedef struct { xfer_ctl_t xfer_status[8][2]; #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] +// Accessing endpoint regs +typedef volatile uint8_t * ep_regs_t; + +typedef enum +{ + CNF = 0, + BBAX = 1, + BCTX = 2, + BBAY = 5, + BCTY = 6, + SIZXY = 7 +} ep_regs_index_t; + +#define EP_REGS(epnum, dir) &USBOEPCNF_1 + 64*dir + 8*(epnum - 1) + static void bus_reset(void) { @@ -197,9 +214,60 @@ void dcd_remote_wakeup(uint8_t rhport) bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { (void) rhport; - (void) desc_edpt; - return false; + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); + + // Unsupported endpoint numbers/size or type (Iso not supported. Control + // not supported on nonzero endpoints). + if((desc_edpt->wMaxPacketSize.size > 64) || (epnum > 7) || \ + (desc_edpt->bmAttributes.xfer == 0) || \ + (desc_edpt->bmAttributes.xfer == 1)) { + return false; + } + + // Buffer allocation scheme: + // For simplicity, only single buffer for now, since tinyusb currently waits + // for an xfer to complete before scheduling another one. This means only + // the X buffer is used. + // + // 1904 bytes are available, the max endpoint size supported on msp430 is + // 64 bytes. This is enough RAM for all 14 endpoints enabled _with_ double + // bufferring (64*14*2 = 1792 bytes). Extra RAM exists for triple and higher + // order bufferring, which must be maintained in software. + // + // For simplicity, each endpoint gets a hardcoded 64 byte chunk (regardless + // of actual wMaxPacketSize) whose start address is the following: + // addr = 128 * (epnum - 1) + 64 * dir. + // + // Double buffering equation: + // x_addr = 256 * (epnum - 1) + 128 * dir + // y_addr = x_addr + 64 + + ep_regs_t ep_regs = EP_REGS(epnum, dir); + uint8_t buf_base = (128 * (epnum - 1) + 64 * dir) >> 3; + + // IN and OUT EP registers have the same structure. + + ep_regs[SIZXY] = desc_edpt->wMaxPacketSize.size; + ep_regs[BCTX] |= NAK; + ep_regs[BBAX] = buf_base; + ep_regs[CNF] &= ~TOGGLE; // ISO xfers not supported on MSP430, so no need + // to gate DATA0/1 and frame behavior. + ep_regs[CNF] |= (UBME | USBIIE); + + USBKEYPID = USBKEY; + if(dir == TUSB_DIR_OUT) + { + USBOEPIE |= (1 << epnum); + } + else + { + USBIEPIE |= (1 << epnum); + } + USBKEYPID = 0; + + return true; } bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -- cgit v1.3.1 From ea0e799df6594fa6644575493547f41994c9be27 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sun, 29 Sep 2019 02:17:59 -0400 Subject: dcd_msp430x5xx: Fix clear stall logic. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index aac4f01db..edb707963 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -337,11 +337,11 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { if(dir == TUSB_DIR_OUT) { - USBOEPCNT_0 &= ~NAK; + USBOEPCNT_0 &= ~STALL; } else { - USBIEPCNT_0 &= ~NAK; + USBIEPCNT_0 &= ~STALL; } } } -- cgit v1.3.1 From 2247f132ca00667253630f833459f0129eb75f11 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sun, 29 Sep 2019 02:22:09 -0400 Subject: Implement dcd_edpt_xfer for nonzero endpoints. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 56 +++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index edb707963..3950a6204 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -226,6 +226,9 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return false; } + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->max_size = desc_edpt->wMaxPacketSize.size; + // Buffer allocation scheme: // For simplicity, only single buffer for now, since tinyusb currently waits // for an xfer to complete before scheduling another one. This means only @@ -243,17 +246,23 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // Double buffering equation: // x_addr = 256 * (epnum - 1) + 128 * dir // y_addr = x_addr + 64 + // Address is right-shifted by 3 to fit into 8 bits. - ep_regs_t ep_regs = EP_REGS(epnum, dir); uint8_t buf_base = (128 * (epnum - 1) + 64 * dir) >> 3; // IN and OUT EP registers have the same structure. + ep_regs_t ep_regs = EP_REGS(epnum, dir); + // FIXME: I was able to get into a situation where OUT EP 3 would stall + // while debugging, despite stall code never being called. It appears + // these registers don't get cleared on reset, being part of RAM. + // Investigate and see if I can duplicate. ep_regs[SIZXY] = desc_edpt->wMaxPacketSize.size; ep_regs[BCTX] |= NAK; ep_regs[BBAX] = buf_base; - ep_regs[CNF] &= ~TOGGLE; // ISO xfers not supported on MSP430, so no need - // to gate DATA0/1 and frame behavior. + ep_regs[CNF] &= ~TOGGLE; // ISO xfers not supported on MSP430, + // so no need to gate DATA0/1 and frame + // behavior. ep_regs[CNF] |= (UBME | USBIIE); USBKEYPID = USBKEY; @@ -300,6 +309,21 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t USBIEPIFG |= BIT0; } } + else + { + ep_regs_t ep_regs = EP_REGS(epnum, dir); + + ep_regs[CNF] &= ~TOGGLE; // Bulk and int begin on DATA0. + + if(dir == TUSB_DIR_OUT) + { + ep_regs[BCTX] &= ~NAK; + } + else + { + USBIEPIFG |= (1 << epnum); + } + } return true; } @@ -438,6 +462,32 @@ void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) receive_packet(0); break; + case USBVECINT_INPUT_ENDPOINT1: + case USBVECINT_INPUT_ENDPOINT2: + case USBVECINT_INPUT_ENDPOINT3: + case USBVECINT_INPUT_ENDPOINT4: + case USBVECINT_INPUT_ENDPOINT5: + case USBVECINT_INPUT_ENDPOINT6: + case USBVECINT_INPUT_ENDPOINT7: + { + uint8_t ep = ((curr_vector - USBVECINT_INPUT_ENDPOINT1) >> 1) + 1; + transmit_packet(ep); + } + break; + + case USBVECINT_OUTPUT_ENDPOINT1: + case USBVECINT_OUTPUT_ENDPOINT2: + case USBVECINT_OUTPUT_ENDPOINT3: + case USBVECINT_OUTPUT_ENDPOINT4: + case USBVECINT_OUTPUT_ENDPOINT5: + case USBVECINT_OUTPUT_ENDPOINT6: + case USBVECINT_OUTPUT_ENDPOINT7: + { + uint8_t ep = ((curr_vector - USBVECINT_OUTPUT_ENDPOINT1) >> 1) + 1; + receive_packet(ep); + } + break; + default: while(true); break; -- cgit v1.3.1 From 838b431faca79e0bd9d627a79b6905010769551c Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sun, 29 Sep 2019 02:43:05 -0400 Subject: dcd_msp430x5xx: Implement transmit_packet for nonzero endpoints. Untested. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 56 ++++++++++++++++++----------- 1 file changed, 35 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 3950a6204..da68074e7 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -382,31 +382,31 @@ static void transmit_packet(uint8_t ep_num) { xfer_ctl_t * xfer = XFER_CTL_BASE(ep_num, TUSB_DIR_IN); - if(ep_num == 0) + // First, determine whether we should even send a packet or finish + // up the xfer. + bool zlp = (xfer->total_len == 0); // By necessity, xfer->total_len will + // equal xfer->queued_len for ZLPs. + // Of course a ZLP is a short packet. + if((!zlp && (xfer->total_len == xfer->queued_len)) || xfer->short_packet) { - // First, determine whether we should even send a packet or finish - // up the xfer. - bool zlp = (xfer->total_len == 0); // By necessity, xfer->total_len will - // equal xfer->queued_len for ZLPs. - // Of course a ZLP is a short packet. - if((!zlp && (xfer->total_len == xfer->queued_len)) || xfer->short_packet) - { - dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); - return; - } + dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); + return; + } - // Then actually commit to transmit a packet. - uint8_t * base = (xfer->buffer + xfer->queued_len); - uint16_t remaining = xfer->total_len - xfer->queued_len; - uint8_t xfer_size = (xfer->max_size < xfer->total_len) ? xfer->max_size : remaining; + // Then actually commit to transmit a packet. + uint8_t * base = (xfer->buffer + xfer->queued_len); + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint8_t xfer_size = (xfer->max_size < xfer->total_len) ? xfer->max_size : remaining; - xfer->queued_len += xfer_size; - if(xfer_size < xfer->max_size) - { - // Next "xfer complete interrupt", the transfer will end. - xfer->short_packet = true; - } + xfer->queued_len += xfer_size; + if(xfer_size < xfer->max_size) + { + // Next "xfer complete interrupt", the transfer will end. + xfer->short_packet = true; + } + if(ep_num == 0) + { volatile uint8_t * ep0in_buf = &USBIEP0BUF; for(int i = 0; i < xfer_size; i++) { @@ -416,6 +416,20 @@ static void transmit_packet(uint8_t ep_num) USBIEPCNT_0 = (USBIEPCNT_0 & 0xF0) + xfer_size; USBIEPCNT_0 &= ~NAK; } + else + { + ep_regs_t ep_regs = EP_REGS(ep_num, TUSB_DIR_IN); + uint16_t in_buf_base = USBSTABUFF + (ep_regs[BBAX] << 3); + + volatile uint8_t * ep_buf = (volatile uint8_t *) (in_buf_base); + for(int i = 0; i < xfer_size; i++) + { + ep_buf[i] = base[i]; + } + + ep_regs[BCTX] = (ep_regs[BCTX] & 0xF0) + xfer_size; + ep_regs[BCTX] &= ~NAK; + } } static void handle_setup_packet(void) -- cgit v1.3.1 From 549ad1d9b6a0a5b05e3017c2ed0e46ab65137760 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sun, 29 Sep 2019 03:02:59 -0400 Subject: dcd_msp430x5xx: Fix missing mask when posting IN xfer events. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index da68074e7..e53a4b7cd 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -389,7 +389,7 @@ static void transmit_packet(uint8_t ep_num) // Of course a ZLP is a short packet. if((!zlp && (xfer->total_len == xfer->queued_len)) || xfer->short_packet) { - dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(0, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len, XFER_RESULT_SUCCESS, true); return; } -- cgit v1.3.1 From b623e3023e7aaa8c9541f7d17a0c458667861cd4 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sun, 29 Sep 2019 03:58:30 -0400 Subject: dcd_msp430x5xx: Implement receive_packet for all endpoints, correct some mistakes in transmit_packet. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 68 +++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index e53a4b7cd..5e9fbf0f1 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -374,8 +374,69 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) static void receive_packet(uint8_t ep_num) { - (void) ep_num; + xfer_ctl_t * xfer = XFER_CTL_BASE(ep_num, TUSB_DIR_OUT); + ep_regs_t ep_regs = EP_REGS(ep_num, TUSB_DIR_OUT); + uint8_t xfer_size; + if(ep_num == 0) + { + xfer_size = USBOEPCNT_0 & 0x0F; + } + else + { + xfer_size = ep_regs[BCTX] & 0x3F; + } + + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint16_t to_recv_size; + + if(remaining <= xfer->max_size) { + // Avoid buffer overflow. + to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; + } else { + // Room for full packet, choose recv_size based on what the microcontroller + // claims. + to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; + } + + uint8_t * base = (xfer->buffer + xfer->queued_len); + + if(ep_num == 0) + { + volatile uint8_t * ep0out_buf = &USBOEP0BUF; + for(uint16_t i = 0; i < to_recv_size; i++) + { + base[i] = ep0out_buf[i]; + } + } + else + { + volatile uint8_t * ep_buf = &USBSTABUFF + (ep_regs[BBAX] << 3); + for(uint16_t i = 0; i < to_recv_size ; i++) + { + base[i] = ep_buf[i]; + } + } + + xfer->queued_len += xfer_size; + + xfer->short_packet = (xfer_size < xfer->max_size); + if((xfer->total_len == xfer->queued_len) || xfer->short_packet) + { + dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); + } + else + { + // Schedule to receive another packet. + if(ep_num == 0) + { + USBOEPCNT_0 &= ~NAK; + } + else + { + ep_regs[BCTX] &= ~NAK; + } + } } static void transmit_packet(uint8_t ep_num) @@ -408,7 +469,7 @@ static void transmit_packet(uint8_t ep_num) if(ep_num == 0) { volatile uint8_t * ep0in_buf = &USBIEP0BUF; - for(int i = 0; i < xfer_size; i++) + for(uint16_t i = 0; i < xfer_size; i++) { ep0in_buf[i] = base[i]; } @@ -419,9 +480,8 @@ static void transmit_packet(uint8_t ep_num) else { ep_regs_t ep_regs = EP_REGS(ep_num, TUSB_DIR_IN); - uint16_t in_buf_base = USBSTABUFF + (ep_regs[BBAX] << 3); + volatile uint8_t * ep_buf = &USBSTABUFF + (ep_regs[BBAX] << 3); - volatile uint8_t * ep_buf = (volatile uint8_t *) (in_buf_base); for(int i = 0; i < xfer_size; i++) { ep_buf[i] = base[i]; -- cgit v1.3.1 From fad44c03c874ad5b278e41ab842e2fb36134ad2a Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Tue, 1 Oct 2019 23:03:39 -0400 Subject: dcd_msp430x5xx: Fix TOGGLE bit behavior, clear stall when endpoint opened due to reset potentially not resetting everything. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 5e9fbf0f1..121dd03ac 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -260,9 +260,9 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) ep_regs[SIZXY] = desc_edpt->wMaxPacketSize.size; ep_regs[BCTX] |= NAK; ep_regs[BBAX] = buf_base; - ep_regs[CNF] &= ~TOGGLE; // ISO xfers not supported on MSP430, + ep_regs[CNF] &= ~(TOGGLE | STALL); // ISO xfers not supported on MSP430, // so no need to gate DATA0/1 and frame - // behavior. + // behavior. Clear stall bit- see above comment. ep_regs[CNF] |= (UBME | USBIIE); USBKEYPID = USBKEY; @@ -313,8 +313,6 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t { ep_regs_t ep_regs = EP_REGS(epnum, dir); - ep_regs[CNF] &= ~TOGGLE; // Bulk and int begin on DATA0. - if(dir == TUSB_DIR_OUT) { ep_regs[BCTX] &= ~NAK; -- cgit v1.3.1 From 54478aaa2a57e62f946581f492da5792741116f9 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Tue, 1 Oct 2019 23:28:41 -0400 Subject: dcd_msp430x5xx: Add STALL support for nonzero endpoints. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 121dd03ac..5202f156a 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -346,6 +346,11 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) USBIEPCNF_0 |= STALL; } } + else + { + ep_regs_t ep_regs = EP_REGS(epnum, dir); + ep_regs[CNF] |= STALL; + } } void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) @@ -366,6 +371,13 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) USBIEPCNT_0 &= ~STALL; } } + else + { + ep_regs_t ep_regs = EP_REGS(epnum, dir); + // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt + // and bulk endpoints. + ep_regs[CNF] &= ~(STALL + TOGGLE); + } } /*------------------------------------------------------------------*/ -- cgit v1.3.1 From 19ee5199265d064e23c376c4ab0fdf92b08a5378 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Wed, 2 Oct 2019 00:01:58 -0400 Subject: dcd_msp430x5xx: Correct byte count masks in transmit/receive routines. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 5202f156a..2f67e5d37 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -394,7 +394,7 @@ static void receive_packet(uint8_t ep_num) } else { - xfer_size = ep_regs[BCTX] & 0x3F; + xfer_size = ep_regs[BCTX] & 0x7F; } uint16_t remaining = xfer->total_len - xfer->queued_len; @@ -497,7 +497,7 @@ static void transmit_packet(uint8_t ep_num) ep_buf[i] = base[i]; } - ep_regs[BCTX] = (ep_regs[BCTX] & 0xF0) + xfer_size; + ep_regs[BCTX] = (ep_regs[BCTX] & 0xF0) + (xfer_size & 0x7F); ep_regs[BCTX] &= ~NAK; } } -- cgit v1.3.1 From 3edb5548e98e76cda7479d2d039b0557eda26a1b Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Wed, 2 Oct 2019 01:18:56 -0400 Subject: dcd_msp430x5xx: Ensure DBUF bit is cleared on endpoint open, as it could get spuriously set in debugging sessions. cdc_msc functional. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 2f67e5d37..ac7e27ee7 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -257,12 +257,16 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // while debugging, despite stall code never being called. It appears // these registers don't get cleared on reset, being part of RAM. // Investigate and see if I can duplicate. + // Also, DBUF got set on OUT EP 2 while debugging. Only OUT EPs seem to be + // affected at this time. USB RAM directly precedes main RAM; perhaps I'm + // overwriting registers via buffer overflow w/ my debugging code? ep_regs[SIZXY] = desc_edpt->wMaxPacketSize.size; ep_regs[BCTX] |= NAK; ep_regs[BBAX] = buf_base; - ep_regs[CNF] &= ~(TOGGLE | STALL); // ISO xfers not supported on MSP430, - // so no need to gate DATA0/1 and frame - // behavior. Clear stall bit- see above comment. + ep_regs[CNF] &= ~(TOGGLE | STALL | DBUF); // ISO xfers not supported on + // MSP430, so no need to gate DATA0/1 and frame + // behavior. Clear stall and double buffer bit as + // well- see above comment. ep_regs[CNF] |= (UBME | USBIIE); USBKEYPID = USBKEY; -- cgit v1.3.1 From 05914de10992c0bc0f35f6fc3c6bc8064ffcd935 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Wed, 2 Oct 2019 22:36:45 -0400 Subject: dcd_msp430x5xx: Fix typos in dcd_edpt_clear_stall. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index ac7e27ee7..32565c38e 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -368,11 +368,11 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { if(dir == TUSB_DIR_OUT) { - USBOEPCNT_0 &= ~STALL; + USBOEPCNF_0 &= ~STALL; } else { - USBIEPCNT_0 &= ~STALL; + USBIEPCNF_0 &= ~STALL; } } else -- cgit v1.3.1 From b0b737b42a14982a1f928e408ba7eadc3f474d04 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Wed, 2 Oct 2019 23:02:55 -0400 Subject: usbd_control.c: Decide whether a control transfer has a data stage based on setup packet wLength. --- src/device/usbd_control.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index eed933f68..69ab47b4d 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -94,7 +94,7 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo _control_state.total_len = tu_min16(len, request->wLength); _control_state.total_transferred = 0; - if ( len ) + if ( _control_state.total_len ) { TU_ASSERT(buffer); -- cgit v1.3.1 From a01b0a73c13ca771e77440d040b0e1e3c5ecbcf7 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Thu, 3 Oct 2019 23:58:24 -0400 Subject: Remove accidentally-commited debug var. --- src/device/usbd_control.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src') diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 070ff504b..e1e9b9f01 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -116,7 +116,6 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo return true; } -volatile int dummy = 0; // callback when a transaction complete on DATA stage of control endpoint bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -133,13 +132,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result _control_state.total_transferred += xferred_bytes; _control_state.buffer = ((uint8_t*)_control_state.buffer) + xferred_bytes; - if((_control_state.total_transferred >= 144)) - { - dummy = 1; - } - if ( (_control_state.requested_len == _control_state.total_transferred) || xferred_bytes < CFG_TUD_ENDPOINT0_SIZE ) - { // DATA stage is complete bool is_ok = true; -- cgit v1.3.1 From c8e899fef03461d0aecfd82370f818483e8c9a3d Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Thu, 10 Oct 2019 04:02:35 -0400 Subject: dcd_msp430x5xx: Improve SETUP packet and EP0 NAK interactions, per 42.3.1.3 in Reference Manual; fix is incomplete but works. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 32565c38e..7b31ddd0a 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -90,9 +90,9 @@ static void bus_reset(void) USBOEPIE |= BIT0; USBIEPIE |= BIT0; - // Set NAK until a setup packet is received. - USBOEPCNT_0 |= NAK; - USBIEPCNT_0 |= NAK; + // Clear NAK until a setup packet is received. + USBOEPCNT_0 &= ~NAK; + USBIEPCNT_0 &= ~NAK; USBCTL |= FEN; // Enable responding to packets. @@ -515,6 +515,11 @@ static void handle_setup_packet(void) _setup_packet[i] = setup_buf[i]; } + // The NAK bits must be clear to receive a SETUP packet. Clearing SETUPIFG + // by reading USBVECINT does not set NAK, so now that we have a SETUP packet + // force NAKs. + USBIEPCNT_0 |= NAK; + USBOEPCNT_0 |= NAK; dcd_event_setup_received(0, (uint8_t*) &_setup_packet[0], true); } -- cgit v1.3.1 From d0146be00b4dd41826f29e36bb10e0ecafce5e47 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Thu, 10 Oct 2019 04:19:48 -0400 Subject: dcd_msp430x5xx: Fix typo in copy-paste in transmit_packet. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 7b31ddd0a..a6efee094 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -501,7 +501,7 @@ static void transmit_packet(uint8_t ep_num) ep_buf[i] = base[i]; } - ep_regs[BCTX] = (ep_regs[BCTX] & 0xF0) + (xfer_size & 0x7F); + ep_regs[BCTX] = (ep_regs[BCTX] & 0x80) + (xfer_size & 0x7F); ep_regs[BCTX] &= ~NAK; } } -- cgit v1.3.1 From de333a6f1879f43fde6e17f4dc866ad2ad77dc6b Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 29 Oct 2019 16:21:31 +0700 Subject: clean up warning, msp430 gcc 8.3 fixed the library lto issue --- examples/make.mk | 4 ---- src/tusb.c | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/examples/make.mk b/examples/make.mk index 4a2af3c22..95b2593bd 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -77,10 +77,6 @@ CFLAGS += \ -ffunction-sections \ -fdata-sections -ifneq ($(BOARD), msp_exp430f5529lp) - CFLAGS += -Wno-error=lto-type-mismatch -endif - # This causes lots of warning with nrf5x build due to nrfx code # CFLAGS += -Wcast-align diff --git a/src/tusb.c b/src/tusb.c index 271b35f1e..e7f5d800d 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -71,7 +71,7 @@ char const* const tusb_strerr[TUSB_ERROR_COUNT] = { ERROR_TABLE(ERROR_STRING) }; static void dump_str_line(uint8_t const* buf, uint16_t count) { // each line is 16 bytes - for(int i=0; i Date: Tue, 29 Oct 2019 16:25:32 +0700 Subject: should fix #184 only response up to EP0 size with get device descriptor if not addressed. --- src/device/usbd.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index f2becab95..5c6fc3748 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -44,6 +44,7 @@ typedef struct { struct TU_ATTR_PACKED { volatile uint8_t connected : 1; + volatile uint8_t addressed : 1; volatile uint8_t configured : 1; volatile uint8_t suspended : 1; @@ -478,6 +479,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Depending on mcu, status phase could be sent either before or after changing device address // Therefore DCD must include zero-length status response dcd_set_address(rhport, (uint8_t) p_request->wValue); + _usbd_dev.addressed = 1; return true; // skip status break; @@ -752,7 +754,17 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const switch(desc_type) { case TUSB_DESC_DEVICE: - return tud_control_xfer(rhport, p_request, (void*) tud_descriptor_device_cb(), sizeof(tusb_desc_device_t)); + { + uint16_t len = sizeof(tusb_desc_device_t); + + // Only send up to EP0 Packet Size if not addressed + if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed) + { + len = CFG_TUD_ENDPOINT0_SIZE; + } + + return tud_control_xfer(rhport, p_request, (void*) tud_descriptor_device_cb(), len); + } break; case TUSB_DESC_BOS: @@ -820,6 +832,7 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) case DCD_EVENT_UNPLUGGED: _usbd_dev.connected = 0; + _usbd_dev.addressed = 0; _usbd_dev.configured = 0; _usbd_dev.suspended = 0; osal_queue_send(_usbd_q, event, in_isr); -- cgit v1.3.1 From 66faa96f1609a1a6e95004ec7adbcd1568df01e2 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Tue, 29 Oct 2019 11:33:19 -0400 Subject: tusb_option.h: Assign msp430 ID range 500+ to avoid conflict with Sony. --- src/tusb_option.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/tusb_option.h b/src/tusb_option.h index 5ebda9f3b..d8cd3782b 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -72,7 +72,7 @@ #define OPT_MCU_CXD56 400 ///< SONY CXD56 // TI MSP430 -#define OPT_MCU_MSP430x5xx 400 ///< TI MSP430x5xx +#define OPT_MCU_MSP430x5xx 500 ///< TI MSP430x5xx /** @} */ -- cgit v1.3.1 From 3f0f7cfd07e04e6a5a154de44b94b074ab5b4307 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Tue, 29 Oct 2019 12:52:56 -0400 Subject: dcd_msp430x5xx: Clarify hardware STALL behavior and current vs ideal behavior of driver in comments. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index a6efee094..e2a9a9e95 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -515,9 +515,12 @@ static void handle_setup_packet(void) _setup_packet[i] = setup_buf[i]; } - // The NAK bits must be clear to receive a SETUP packet. Clearing SETUPIFG - // by reading USBVECINT does not set NAK, so now that we have a SETUP packet - // force NAKs. + // The EP0 NAK bits must be clear to receive a SETUP packet, according to the + // manual (we don't do this right now- see below comments). + // Race conditions where the hardware STALLs can occur if the NAK bits aren't + // set for both IN/OUT EP0. Clearing SETUPIFG by reading USBVECINT does not + // set NAK, so now that we have a SETUP packet, force NAKs. + // FIXME: Explain more accurately why the STALL occurs. USBIEPCNT_0 |= NAK; USBOEPCNT_0 |= NAK; dcd_event_setup_received(0, (uint8_t*) &_setup_packet[0], true); @@ -526,7 +529,7 @@ static void handle_setup_packet(void) void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) { // Setup is special- reading USBVECINT to handle setup packets is done to - // stop NAKs on EP0. + // stop hardware-generated NAKs on EP0. uint8_t setup_status = USBIFG & SETUPIFG; if(setup_status) @@ -543,7 +546,14 @@ void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); break; - // Clear the NAK on EP 0 after a SETUP packet is received. + // Clear the (hardware-enforced) NAK on EP 0 after a SETUP packet + // is received. The NAK bits for EP0 should still be set because it's + // possible for the hardware to STALL in the middle of a control xfer + // if the EP0 NAK bits aren't set properly. + // See: https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/845259 + // FIXME: Per manual, we should be clearing the NAK bits of EP0 after the + // Status Phase of a control xfer is done, in preparation of another + // possible setup packet. No clean way to do this right now. case USBVECINT_SETUP_PACKET_RECEIVED: break; -- cgit v1.3.1 From 5d585c03bdf5059c7856d5ee32a754bd3cdbdd2f Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Tue, 29 Oct 2019 14:08:39 -0400 Subject: dcd_msp430x5xx: Improve comments regarding SETUP packet handling. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 35 ++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index e2a9a9e95..3a73cf9bf 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -515,12 +515,9 @@ static void handle_setup_packet(void) _setup_packet[i] = setup_buf[i]; } - // The EP0 NAK bits must be clear to receive a SETUP packet, according to the - // manual (we don't do this right now- see below comments). - // Race conditions where the hardware STALLs can occur if the NAK bits aren't - // set for both IN/OUT EP0. Clearing SETUPIFG by reading USBVECINT does not - // set NAK, so now that we have a SETUP packet, force NAKs. - // FIXME: Explain more accurately why the STALL occurs. + // Clearing SETUPIFG by reading USBVECINT does not set NAK, so now that we + // have a SETUP packet, force NAKs until tinyusb can handle the SETUP + // packet and prepare for a new xfer. USBIEPCNT_0 |= NAK; USBOEPCNT_0 |= NAK; dcd_event_setup_received(0, (uint8_t*) &_setup_packet[0], true); @@ -547,13 +544,31 @@ void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) break; // Clear the (hardware-enforced) NAK on EP 0 after a SETUP packet - // is received. The NAK bits for EP0 should still be set because it's - // possible for the hardware to STALL in the middle of a control xfer - // if the EP0 NAK bits aren't set properly. + // is received. At this point, even though the hardware is no longer + // forcing NAKs, the EP0 NAK bits should still be set to avoid + // sending/receiving data before tinyusb is ready. + // + // Furthermore, it's possible for the hardware to STALL in the middle of + // a control xfer if the EP0 NAK bits aren't set properly. // See: https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/845259 + // From my testing, if all of the following hold: + // * OUT EP0 NAK is cleared. + // * IN EP0 NAK is set. + // * DIR bit in USBCTL is clear. + // and an IN packet is received on EP0, the USB core will STALL. Setting + // both EP0 NAKs manually when a SETUP packet is received, as is done + // in handle_setup_packet(), avoids meeting STALL conditions. + // + // TODO: Figure out/explain why the STALL condition can be reached in the + // first place. When I first noticed the STALL, the only two places I + // touched the NAK bits were in dcd_edpt_xfer() and to _set_ (sic) them in + // bus_reset(). SETUP packet handling should've been unaffected. + // // FIXME: Per manual, we should be clearing the NAK bits of EP0 after the // Status Phase of a control xfer is done, in preparation of another - // possible setup packet. No clean way to do this right now. + // possible SETUP packet. We don't do this right now, as there is no + // "Status Phase done" callback the driver can use. However, SETUP packets + // _are_ correctly handled by the USB core without clearing the NAKs. case USBVECINT_SETUP_PACKET_RECEIVED: break; -- cgit v1.3.1 From 1b51b78eafb1a078aa7fc8caf57d01d92b84ca0f Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 3 Nov 2019 00:17:17 +0700 Subject: hack the request length for the first get device descriptor if EP0 size =8 or 16 to prevent usbd control send out ZLP --- src/device/usbd.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 8661717f5..360881f34 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -771,9 +771,13 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const uint16_t len = sizeof(tusb_desc_device_t); // Only send up to EP0 Packet Size if not addressed + // This only happens with the very first get device descriptor and EP0 size = 8 or 16. if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed) { len = CFG_TUD_ENDPOINT0_SIZE; + + // Hack here: we modify the request length to prevent usbd_control response with zlp + ((tusb_control_request_t*) p_request)->wLength = CFG_TUD_ENDPOINT0_SIZE; } return tud_control_xfer(rhport, p_request, (void*) tud_descriptor_device_cb(), len); -- cgit v1.3.1 From 65e96e5d525ea02e0ca7f265a4d62b4f428cc821 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 3 Nov 2019 18:00:07 +0700 Subject: added optional dcd_control_status_complete() --- src/device/dcd.h | 4 ++++ src/device/usbd_control.c | 1 + test/test/device/usbd/test_usbd.c | 2 ++ 3 files changed, 7 insertions(+) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index 9fa98c669..c88465cbb 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -119,6 +119,10 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); // clear stall, data toggle is also reset to DATA0 void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +void dcd_control_status_complete(uint8_t rhport) TU_ATTR_WEAK; + //--------------------------------------------------------------------+ // Event API //--------------------------------------------------------------------+ diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index f41614ef1..d37e9ec2a 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -129,6 +129,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction ) { TU_ASSERT(0 == xferred_bytes); + if (dcd_control_status_complete) dcd_control_status_complete(rhport); return true; } diff --git a/test/test/device/usbd/test_usbd.c b/test/test/device/usbd/test_usbd.c index add947b3d..a4063a488 100644 --- a/test/test/device/usbd/test_usbd.c +++ b/test/test/device/usbd/test_usbd.c @@ -231,5 +231,7 @@ void test_usbd_control_in_zlp(void) dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_OUT, 0, 0, false); + dcd_control_status_complete_Expect(rhport); + tud_task(); } -- cgit v1.3.1 From 33c715bdd060c4c2bbc89da3ccc62f10b3faba09 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sat, 4 Jan 2020 13:59:20 -0600 Subject: CDC device: fix behavior for transfers that are a whole multiple of endpoint buffer --- src/class/cdc/cdc_device.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 3ff72b00c..a4c42863a 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -402,10 +402,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Data sent to host, we could continue to fetch data tx fifo to send. // But it will cause incorrect baudrate set in line coding. // Though maybe the baudrate is not really important !!! -// if ( ep_addr == p_cdc->ep_in ) -// { -// -// } + if ( ep_addr == p_cdc->ep_in ) + { + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) ) usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); + } // nothing to do with notif endpoint for now -- cgit v1.3.1 From 53732805b76882b3e0eba561ce854e0a95dd6dfe Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sat, 11 Jan 2020 15:31:42 -0600 Subject: CDC device: help ensure code is consistent with the size of the buffers it operates on --- src/class/cdc/cdc_device.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index a4c42863a..015c1c6fd 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -82,9 +82,9 @@ static void _prep_out_transaction (uint8_t itf) // Prepare for incoming data but only allow what we can store in the ring buffer. uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff); - if ( max_read >= CFG_TUD_CDC_EPSIZE ) + if ( max_read >= TU_ARRAY_SIZE(p_cdc->epout_buf) ) { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, CFG_TUD_CDC_EPSIZE); + usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, TU_ARRAY_SIZE(p_cdc->epout_buf)); } } @@ -162,7 +162,7 @@ bool tud_cdc_n_write_flush (uint8_t itf) cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in) ); // skip if previous transfer not complete - uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, CFG_TUD_CDC_EPSIZE); + uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, TU_ARRAY_SIZE(p_cdc->epin_buf)); if ( count ) { TU_VERIFY( tud_cdc_n_connected(itf) ); // fifo is empty if not connected @@ -198,8 +198,8 @@ void cdcd_init(void) p_cdc->line_coding.data_bits = 8; // config fifo - tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, 1, false); - tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, 1, false); + tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); + tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, false); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&p_cdc->rx_ff, osal_mutex_create(&p_cdc->rx_ff_mutex)); -- cgit v1.3.1 From 73228a67efd122915e43ed445ddaec8285786d28 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 16 Jan 2020 10:06:52 +0100 Subject: MIDI: Add packet interface This changes the internal buffering to the raw 4-byte messages. The conversion of the messages to a byte-stream moved to the read/write methods. It adds a raw packet interface to send and retrieve the raw 4-byte USB MIDI message: static inline bool tud_midi_receive (uint8_t packet[4]); static inline bool tud_midi_send (uint8_t const packet[4]); MIDI USB packets carry virtual cable/wire/plug data in the packet header, which cannot be exported in the byte-stream interface. The raw packet interface allows to send and and receive the complete USB message. --- src/class/midi/midi_device.c | 145 +++++++++++++++++++++++++++---------------- src/class/midi/midi_device.h | 15 +++++ 2 files changed, 106 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 312405621..82ceba87f 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -56,11 +56,15 @@ typedef struct osal_mutex_def_t tx_ff_mutex; #endif - // We need to pack messages into words before queueing their transmission so buffer across write - // calls. - uint8_t message_buffer[4]; - uint8_t message_buffer_length; - uint8_t message_target_length; + // Messages are always 4 bytes long, queue them for reading and writing so the + // callers can use the Stream interface with single-byte read/write calls. + uint8_t write_buffer[4]; + uint8_t write_buffer_length; + uint8_t write_target_length; + + uint8_t read_buffer[4]; + uint8_t read_buffer_length; + uint8_t read_target_length; // Endpoint Transfer buffer CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EPSIZE]; @@ -93,24 +97,14 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t jack_id) uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize) { (void) jack_id; - return tu_fifo_read_n(&_midid_itf[itf].rx_ff, buffer, bufsize); -} - -void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id) -{ - (void) jack_id; - tu_fifo_clear(&_midid_itf[itf].rx_ff); -} + midid_interface_t* midi = &_midid_itf[itf]; -void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) { - if (bufsize % 4 != 0) { - return; - } + // Fill empty buffer + if (midi->read_buffer_length == 0) { + if (!tud_midi_n_receive(itf, midi->read_buffer)) + return 0; - for(uint32_t i=0; i> 4; - uint8_t code_index = header & 0x0f; + uint8_t code_index = midi->read_buffer[0] & 0x0f; // We always copy over the first byte. uint8_t count = 1; // Ignore subsequent bytes based on the code. @@ -120,10 +114,40 @@ void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bu count = 3; } } - tu_fifo_write_n(&midi->rx_ff, &buffer[i + 1], count); + + midi->read_buffer_length = count; + } + + uint32_t n = midi->read_buffer_length - midi->read_target_length; + if (bufsize < n) + n = bufsize; + + // Skip the header in the buffer + memcpy(buffer, midi->read_buffer + 1 + midi->read_target_length, n); + midi->read_target_length += n; + + if (midi->read_target_length == midi->read_buffer_length) { + midi->read_buffer_length = 0; + midi->read_target_length = 0; } + + return n; +} + +void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id) +{ + (void) jack_id; + tu_fifo_clear(&_midid_itf[itf].rx_ff); +} + +bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]) +{ + return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4); } +void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) { + tu_fifo_write_n(&midi->rx_ff, buffer, bufsize); +} //--------------------------------------------------------------------+ // WRITE API @@ -154,62 +178,59 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u uint32_t i = 0; while (i < bufsize) { uint8_t data = buffer[i]; - if (midi->message_buffer_length == 0) { + if (midi->write_buffer_length == 0) { uint8_t msg = data >> 4; - midi->message_buffer[1] = data; - midi->message_buffer_length = 2; + midi->write_buffer[1] = data; + midi->write_buffer_length = 2; // Check to see if we're still in a SysEx transmit. - if (midi->message_buffer[0] == 0x4) { + if (midi->write_buffer[0] == 0x4) { if (data == 0xf7) { - midi->message_buffer[0] = 0x5; + midi->write_buffer[0] = 0x5; } else { - midi->message_buffer_length = 4; + midi->write_buffer_length = 4; } } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { - midi->message_buffer[0] = jack_id << 4 | msg; - midi->message_target_length = 4; - } else if (msg == 0xC || msg == 0xD) { - midi->message_buffer[0] = jack_id << 4 | msg; - midi->message_target_length = 3; + midi->write_buffer[0] = jack_id << 4 | msg; + midi->write_target_length = 4; } else if (msg == 0xf) { if (data == 0xf0) { - midi->message_buffer[0] = 0x4; - midi->message_target_length = 4; + midi->write_buffer[0] = 0x4; + midi->write_target_length = 4; } else if (data == 0xf1 || data == 0xf3) { - midi->message_buffer[0] = 0x2; - midi->message_target_length = 3; + midi->write_buffer[0] = 0x2; + midi->write_target_length = 3; } else if (data == 0xf2) { - midi->message_buffer[0] = 0x3; - midi->message_target_length = 4; + midi->write_buffer[0] = 0x3; + midi->write_target_length = 4; } else { - midi->message_buffer[0] = 0x5; - midi->message_target_length = 2; + midi->write_buffer[0] = 0x5; + midi->write_target_length = 2; } } else { // Pack individual bytes if we don't support packing them into words. - midi->message_buffer[0] = jack_id << 4 | 0xf; - midi->message_buffer[2] = 0; - midi->message_buffer[3] = 0; - midi->message_buffer_length = 2; - midi->message_target_length = 2; + midi->write_buffer[0] = jack_id << 4 | 0xf; + midi->write_buffer[2] = 0; + midi->write_buffer[3] = 0; + midi->write_buffer_length = 2; + midi->write_target_length = 2; } } else { - midi->message_buffer[midi->message_buffer_length] = data; - midi->message_buffer_length += 1; + midi->write_buffer[midi->write_buffer_length] = data; + midi->write_buffer_length += 1; // See if this byte ends a SysEx. - if (midi->message_buffer[0] == 0x4 && data == 0xf7) { - midi->message_buffer[0] = 0x4 + (midi->message_buffer_length - 1); - midi->message_target_length = midi->message_buffer_length; + if (midi->write_buffer[0] == 0x4 && data == 0xf7) { + midi->write_buffer[0] = 0x4 + (midi->write_buffer_length - 1); + midi->write_target_length = midi->write_buffer_length; } } - if (midi->message_buffer_length == midi->message_target_length) { - uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->message_buffer, 4); + if (midi->write_buffer_length == midi->write_target_length) { + uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); if (written < 4) { TU_ASSERT( written == 0 ); break; } - midi->message_buffer_length = 0; + midi->write_buffer_length = 0; } i++; } @@ -218,6 +239,22 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u return i; } +bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]) +{ + midid_interface_t* midi = &_midid_itf[itf]; + if (midi->itf_num == 0) { + return 0; + } + + if (tu_fifo_remaining(&midi->tx_ff) < 4) + return false; + + tu_fifo_write_n(&midi->tx_ff, packet, 4); + maybe_transmit(midi, itf); + + return true; +} + //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index fbf4bce0b..e4d4f9d51 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -62,6 +62,9 @@ uint32_t tud_midi_n_write (uint8_t itf, uint8_t jack_id, uint8_t const* buf static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3); +bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]); +bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]); + //--------------------------------------------------------------------+ // Application API (Interface0) //--------------------------------------------------------------------+ @@ -71,6 +74,8 @@ static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); static inline void tud_midi_read_flush (void); static inline uint32_t tud_midi_write (uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize); static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3); +static inline bool tud_midi_receive (uint8_t packet[4]); +static inline bool tud_midi_send (uint8_t const packet[4]); //--------------------------------------------------------------------+ // Application Callback API (weak is optional) @@ -118,6 +123,16 @@ static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b return tud_midi_write(jack_id, msg, 3); } +static inline bool tud_midi_receive (uint8_t packet[4]) +{ + return tud_midi_n_receive(0, packet); +} + +static inline bool tud_midi_send (uint8_t const packet[4]) +{ + return tud_midi_n_send(0, packet); +} + //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -- cgit v1.3.1 From cd8eb2a06bfb14c25788b56f1821784cb9c5535c Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sat, 25 Jan 2020 13:10:32 -0600 Subject: added support for Nuvoton NUC120 --- hw/bsp/nutiny_sdk_nuc120/board.mk | 56 ++++ hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld | 195 ++++++++++++ hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c | 122 ++++++++ hw/mcu/nuvoton | 2 +- src/portable/nuvoton/nuc120/dcd_nuc120.c | 433 +++++++++++++++++++++++++++ src/tusb_option.h | 1 + 6 files changed, 808 insertions(+), 1 deletion(-) create mode 100644 hw/bsp/nutiny_sdk_nuc120/board.mk create mode 100644 hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld create mode 100644 hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c create mode 100644 src/portable/nuvoton/nuc120/dcd_nuc120.c (limited to 'src') diff --git a/hw/bsp/nutiny_sdk_nuc120/board.mk b/hw/bsp/nutiny_sdk_nuc120/board.mk new file mode 100644 index 000000000..f2ee09f19 --- /dev/null +++ b/hw/bsp/nutiny_sdk_nuc120/board.mk @@ -0,0 +1,56 @@ +CFLAGS += \ + -flto \ + -mthumb \ + -mabi=aapcs-linux \ + -mcpu=cortex-m0 \ + -DCFG_TUSB_MCU=OPT_MCU_NUC120 + +# All source paths should be relative to the top level. +LD_FILE = hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld + +SRC_C += \ + hw/mcu/nuvoton/nuc100_120/Device/Nuvoton/NUC100Series/Source/system_NUC100Series.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/acmp.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/adc.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/clk.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/crc.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/fmc.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/gpio.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/i2c.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/i2s.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/pdma.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/ps2.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/pwm.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/rtc.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/sc.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/spi.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/sys.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/timer.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/uart.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/usbd.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/wdt.c \ + hw/mcu/nuvoton/nuc100_120/StdDriver/src/wwdt.c + +SRC_S += \ + hw/mcu/nuvoton/nuc100_120/Device/Nuvoton/NUC100Series/Source/GCC/startup_NUC100Series.S + +INC += \ + $(TOP)/hw/mcu/nuvoton/nuc100_120/Device/Nuvoton/NUC100Series/Include \ + $(TOP)/hw/mcu/nuvoton/nuc100_120/StdDriver/inc \ + $(TOP)/hw/mcu/nuvoton/nuc100_120/CMSIS/Include + +# For TinyUSB port source +VENDOR = nuvoton +CHIP_FAMILY = nuc120 + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM0 + +# For flash-jlink target +JLINK_DEVICE = NUC120LE3 +JLINK_IF = swd + +# Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton +# Please compile and install it from github source +flash: $(BUILD)/$(BOARD)-firmware.elf + openocd -f interface/nulink.cfg -f target/numicroM0.cfg -c "program $< reset exit" diff --git a/hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld b/hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld new file mode 100644 index 000000000..cab12c8b9 --- /dev/null +++ b/hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld @@ -0,0 +1,195 @@ +/* Linker script to configure memory regions. */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x20000 /* 128k */ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x4000 /* 16k */ +} + +/* Library configurations */ +GROUP(libgcc.a libc.a libm.a libnosys.a) + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + * __Vectors_End + * __Vectors_Size + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.vectors)) + __Vectors_End = .; + __Vectors_Size = __Vectors_End - __Vectors; + __end__ = .; + + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * uncomment .copy.table section and, + * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ + /* + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (__etext2) + LONG (__data2_start__) + LONG (__data2_end__ - __data2_start__) + __copy_table_end__ = .; + } > FLASH + */ + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ + /* + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (__bss2_start__) + LONG (__bss2_end__ - __bss2_start__) + __zero_table_end__ = .; + } > FLASH + */ + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __HeapBase = .; + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + KEEP(*(.stack*)) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c b/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c new file mode 100644 index 000000000..0650a4e3a --- /dev/null +++ b/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c @@ -0,0 +1,122 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "bsp/board.h" +#include "NUC100Series.h" +#include "clk.h" +#include "sys.h" + +#define LED_PORT PB +#define LED_PIN 0 +#define LED_PIN_IO PB0 +#define LED_STATE_ON 0 + +void board_init(void) +{ + SYS_UnlockReg(); + + /* Enable Internal RC 22.1184 MHz clock */ + CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk); + + /* Waiting for Internal RC clock ready */ + CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk); + + /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */ + CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1)); + + /* Enable external XTAL 12 MHz clock */ + CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk); + + /* Waiting for external XTAL clock ready */ + CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk); + + /* Set core clock */ + CLK_SetCoreClock(48000000); + + /* Enable module clock */ + CLK_EnableModuleClock(USBD_MODULE); + + /* Select module clock source */ + CLK_SetModuleClock(USBD_MODULE, 0, CLK_CLKDIV_USB(1)); + + SYS_LockReg(); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(48000000 / 1000); +#endif + + GPIO_SetMode(LED_PORT, 1UL << LED_PIN, GPIO_PMD_OUTPUT); +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ +#if 0 + /* this would be the simplest solution... *IF* the part supported the pin data interface */ + LED_PIN_IO = (state) ? LED_STATE_ON : (1-LED_STATE_ON); +#else + /* if the part's *PDIO pin data registers don't work, a more elaborate approach is needed */ + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + uint32_t current = LED_PORT->DOUT & ~(1UL << LED_PIN); + LED_PORT->DOUT = current | (((state) ? LED_STATE_ON : (1UL-LED_STATE_ON)) << LED_PIN); + __set_PRIMASK(irq_state); +#endif +} + +uint32_t board_button_read(void) +{ + return 0; +} + +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +int board_uart_write(void const * buf, int len) +{ + (void) buf; (void) len; + return 0; +} diff --git a/hw/mcu/nuvoton b/hw/mcu/nuvoton index dc96fff79..797dc6cd5 160000 --- a/hw/mcu/nuvoton +++ b/hw/mcu/nuvoton @@ -1 +1 @@ -Subproject commit dc96fff794d14818c93ea1d4d760d51a014d70c5 +Subproject commit 797dc6cd55c84aa6c23c4690da2f3900339a6e24 diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c new file mode 100644 index 000000000..4e1db24a4 --- /dev/null +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -0,0 +1,433 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-2020 Peter Lawrence + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +/* + Theory of operation: + + The NUC100/NUC120 USBD peripheral has six "EP"s, but each is simplex, + so two collectively (peripheral nomenclature of "EP0" and "EP1") are needed to + implement USB EP0. PERIPH_EP0 and PERIPH_EP1 are used by this driver for + EP0_IN and EP0_OUT respectively. This leaves up to four for user usage. +*/ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC120) + +#include "device/dcd.h" +#include "NUC100Series.h" + +/* allocation of USBD RAM for Setup, EP0_IN, and and EP_OUT */ +#define PERIPH_SETUP_BUF_BASE 0 +#define PERIPH_SETUP_BUF_LEN 8 +#define PERIPH_EP0_BUF_BASE (PERIPH_SETUP_BUF_BASE + PERIPH_SETUP_BUF_LEN) +#define PERIPH_EP0_BUF_LEN CFG_TUD_ENDPOINT0_SIZE +#define PERIPH_EP1_BUF_BASE (PERIPH_EP0_BUF_BASE + PERIPH_EP0_BUF_LEN) +#define PERIPH_EP1_BUF_LEN CFG_TUD_ENDPOINT0_SIZE +#define PERIPH_EP2_BUF_BASE (PERIPH_EP1_BUF_BASE + PERIPH_EP1_BUF_LEN) + +/* rather important info unfortunately not provided by device include files: how much there is */ +#define USBD_BUF_SIZE 512 + +enum ep_enum +{ + PERIPH_EP0 = 0, + PERIPH_EP1 = 1, + PERIPH_EP2 = 2, + PERIPH_EP3 = 3, + PERIPH_EP4 = 4, + PERIPH_EP5 = 5, + PERIPH_MAX_EP, +}; + +/* set by dcd_set_address() */ +static volatile uint8_t assigned_address; + +/* reset by dcd_init(), this is used by dcd_edpt_open() to assign USBD peripheral buffer addresses */ +static uint32_t bufseg_addr; + +/* used by dcd_edpt_xfer() and the ISR to reset the data sync (DATA0/DATA1) in an EP0_IN transfer */ +static bool active_ep0_xfer; + +/* RAM table needed to track ongoing transfers performed by dcd_edpt_xfer(), dcd_in_xfer(), and the ISR */ +static struct xfer_ctl_t +{ + uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */ + union { + uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */ + uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */ + }; + uint16_t max_packet_size; /* needed since device driver only finds out this at runtime */ + uint16_t total_bytes; /* quantity needed to pass as argument to dcd_event_xfer_complete() (for IN endpoints) */ +} xfer_table[PERIPH_MAX_EP]; + +/* + local helper functions +*/ + +static void usb_attach(void) +{ + USBD->DRVSE0 &= ~USBD_DRVSE0_DRVSE0_Msk; +} + +static void usb_detach(void) +{ + USBD->DRVSE0 |= USBD_DRVSE0_DRVSE0_Msk; +} + +static void usb_control_send_zlp(void) +{ + USBD->EP[PERIPH_EP0].CFG |= USBD_CFG_DSQ_SYNC_Msk; + USBD->EP[PERIPH_EP0].MXPLD = 0; +} + +/* reconstruct ep_addr from particular USB Configuration Register */ +static uint8_t decode_ep_addr(USBD_EP_T *ep) +{ + uint8_t ep_addr = ep->CFG & USBD_CFG_EP_NUM_Msk; + if ( USBD_CFG_EPMODE_IN == (ep->CFG & USBD_CFG_STATE_Msk) ) + ep_addr |= TUSB_DIR_IN_MASK; + return ep_addr; +} + +/* map 8-bit ep_addr into peripheral endpoint index (PERIPH_EP0...) */ +static USBD_EP_T *ep_entry(uint8_t ep_addr, bool add) +{ + USBD_EP_T *ep; + enum ep_enum ep_index; + + for (ep_index = PERIPH_EP0, ep = USBD->EP; ep_index < PERIPH_MAX_EP; ep_index++, ep++) + { + if (add) + { + /* take first peripheral endpoint that is unused */ + if (0 == (ep->CFG & USBD_CFG_STATE_Msk)) return ep; + } + else + { + /* find a peripheral endpoint that matches ep_addr */ + uint8_t candidate_ep_addr = decode_ep_addr(ep); + if (candidate_ep_addr == ep_addr) return ep; + } + } + + return NULL; +} + +/* perform an IN endpoint transfer; this is called by dcd_edpt_xfer() and the ISR */ +static void dcd_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) +{ + uint16_t bytes_now = tu_min16(xfer->in_remaining_bytes, xfer->max_packet_size); + + memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); + ep->MXPLD = bytes_now; +} + +/* called by dcd_init() as well as by the ISR during a USB bus reset */ +static void bus_reset(void) +{ + USBD->STBUFSEG = PERIPH_SETUP_BUF_BASE; + + for (enum ep_enum ep_index = PERIPH_EP0; ep_index < PERIPH_MAX_EP; ep_index++) + { + USBD->EP[ep_index].CFG = 0; + USBD->EP[ep_index].CFGP = 0; + } + + /* allocate the default EP0 endpoints */ + + USBD->EP[PERIPH_EP0].CFG = USBD_CFG_CSTALL_Msk | USBD_CFG_EPMODE_IN; + USBD->EP[PERIPH_EP0].BUFSEG = PERIPH_EP0_BUF_BASE; + xfer_table[PERIPH_EP0].max_packet_size = PERIPH_EP0_BUF_LEN; + + USBD->EP[PERIPH_EP1].CFG = USBD_CFG_CSTALL_Msk | USBD_CFG_EPMODE_OUT; + USBD->EP[PERIPH_EP1].BUFSEG = PERIPH_EP1_BUF_BASE; + xfer_table[PERIPH_EP1].max_packet_size = PERIPH_EP1_BUF_LEN; + + /* USB RAM beyond what we've allocated above is available to the user */ + bufseg_addr = PERIPH_EP2_BUF_BASE; + + /* Reset USB device address */ + USBD->FADDR = 0; + + /* reset EP0_IN flag */ + active_ep0_xfer = false; +} + +/* centralized location for USBD interrupt enable bit mask */ +static const uint32_t enabled_irqs = USBD_INTSTS_FLDET_STS_Msk | USBD_INTSTS_BUS_STS_Msk | USBD_INTSTS_SETUP_Msk | USBD_INTSTS_USB_STS_Msk; + +/* + NUC100/NUC120 TinyUSB API driver implementation +*/ + +void dcd_init(uint8_t rhport) +{ + (void) rhport; + + USBD->ATTR = 0x7D0; + + usb_detach(); + + bus_reset(); + + usb_attach(); + + USBD->INTSTS = enabled_irqs; + USBD->INTEN = enabled_irqs; +} + +void dcd_int_enable(uint8_t rhport) +{ + (void) rhport; + NVIC_EnableIRQ(USBD_IRQn); +} + +void dcd_int_disable(uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ(USBD_IRQn); +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void) rhport; + usb_control_send_zlp(); /* SET_ADDRESS is the one exception where TinyUSB doesn't use dcd_edpt_xfer() to generate a ZLP */ + assigned_address = dev_addr; +} + +void dcd_set_config(uint8_t rhport, uint8_t config_num) +{ + (void) rhport; + (void) config_num; +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; + USBD->ATTR = USBD_ATTR_RWAKEUP_Msk; +} + +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) +{ + (void) rhport; + + USBD_EP_T *ep = ep_entry(p_endpoint_desc->bEndpointAddress, true); + TU_ASSERT(ep); + + /* mine the data for the information we need */ + int const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); + int const size = p_endpoint_desc->wMaxPacketSize.size; + tusb_xfer_type_t const type = p_endpoint_desc->bmAttributes.xfer; + struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; + + /* allocate buffer from USB RAM */ + ep->BUFSEG = bufseg_addr; + bufseg_addr += size; + TU_ASSERT(bufseg_addr <= USBD_BUF_SIZE); + + /* construct USB Configuration Register value and then write it */ + uint32_t cfg = tu_edpt_number(p_endpoint_desc->bEndpointAddress); + cfg |= (TUSB_DIR_IN == dir) ? USBD_CFG_EPMODE_IN : USBD_CFG_EPMODE_OUT; + if (TUSB_XFER_ISOCHRONOUS == type) + cfg |= USBD_CFG_TYPE_ISO; + ep->CFG = cfg; + + /* make a note of the endpoint size */ + xfer->max_packet_size = size; + + return true; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +{ + (void) rhport; + + /* mine the data for the information we need */ + tusb_dir_t dir = tu_edpt_dir(ep_addr); + USBD_EP_T *ep = ep_entry(ep_addr, false); + struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; + + /* store away the information we'll needing now and later */ + xfer->data_ptr = buffer; + xfer->in_remaining_bytes = total_bytes; + xfer->total_bytes = total_bytes; + + /* for the first of one or more EP0_IN packets in a message, the first must be DATA1 */ + if ( (0x80 == ep_addr) && !active_ep0_xfer ) ep->CFG |= USBD_CFG_DSQ_SYNC_Msk; + + if (TUSB_DIR_IN == dir) + { + dcd_in_xfer(xfer, ep); + } + else + { + xfer->out_bytes_so_far = 0; + ep->MXPLD = xfer->max_packet_size; + } + + return true; +} + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + USBD_EP_T *ep = ep_entry(ep_addr, false); + ep->CFGP |= USBD_CFGP_SSTALL_Msk; +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + USBD_EP_T *ep = ep_entry(ep_addr, false); + ep->CFG |= USBD_CFG_CSTALL_Msk; +} + +void USBD_IRQHandler(void) +{ + uint32_t status = USBD->INTSTS; + uint32_t state = USBD->ATTR & 0xf; + + if(status & USBD_INTSTS_FLDET_STS_Msk) + { + if(USBD->FLDET & USBD_FLDET_FLDET_Msk) + { + /* USB connect */ + USBD->ATTR |= USBD_ATTR_USB_EN_Msk | USBD_ATTR_PHY_EN_Msk; + } + else + { + /* USB disconnect */ + USBD->ATTR &= ~USBD_ATTR_USB_EN_Msk; + } + } + + if(status & USBD_INTSTS_BUS_STS_Msk) + { + if(state & USBD_STATE_USBRST) + { + /* USB bus reset */ + USBD->ATTR |= USBD_ATTR_USB_EN_Msk | USBD_ATTR_PHY_EN_Msk; + + bus_reset(); + + dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + } + + if(state & USBD_STATE_SUSPEND) + { + /* Enable USB but disable PHY */ + USBD->ATTR &= ~USBD_ATTR_PHY_EN_Msk; + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + } + + if(state & USBD_STATE_RESUME) + { + /* Enable USB and enable PHY */ + USBD->ATTR |= USBD_ATTR_USB_EN_Msk | USBD_ATTR_PHY_EN_Msk; + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + } + + if(status & USBD_INTSTS_SETUP_Msk) + { + /* clear the data ready flag of control endpoints */ + USBD->EP[PERIPH_EP0].CFGP |= USBD_CFGP_CLRRDY_Msk; + USBD->EP[PERIPH_EP1].CFGP |= USBD_CFGP_CLRRDY_Msk; + + /* get SETUP packet from USB buffer */ + dcd_event_setup_received(0, (uint8_t *)USBD_BUF_BASE, true); + } + + if(status & USBD_INTSTS_USB_STS_Msk) + { + if (status & (1UL << USBD_INTSTS_EPEVT_Pos)) /* PERIPH_EP0 (EP0_IN) event: this is treated separately from the rest */ + { + /* 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; + + uint16_t const available_bytes = USBD->EP[PERIPH_EP0].MXPLD; + + active_ep0_xfer = (available_bytes == xfer_table[PERIPH_EP0].max_packet_size); + + dcd_event_xfer_complete(0, 0x80, available_bytes, XFER_RESULT_SUCCESS, true); + } + + /* service PERIPH_EP1 through PERIPH_EP7 */ + enum ep_enum ep_index; + uint32_t mask; + struct xfer_ctl_t *xfer; + USBD_EP_T *ep; + for (ep_index = PERIPH_EP1, mask = (2UL << USBD_INTSTS_EPEVT_Pos), xfer = &xfer_table[PERIPH_EP1], ep = &USBD->EP[PERIPH_EP1]; ep_index < PERIPH_MAX_EP; ep_index++, mask <<= 1, xfer++, ep++) + { + if(status & mask) + { + USBD->INTSTS = mask; + + uint16_t const available_bytes = ep->MXPLD; + uint8_t const ep_addr = decode_ep_addr(ep); + bool const out_ep = !(ep_addr & TUSB_DIR_IN_MASK); + + if (out_ep) + { + /* copy the data from the PC to the previously provided buffer */ + memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); + xfer->out_bytes_so_far += available_bytes; + xfer->data_ptr += available_bytes; + + /* when the transfer is finished, alert TinyUSB; otherwise, accept more data */ + if ( (xfer->total_bytes == xfer->out_bytes_so_far) || (available_bytes < xfer->max_packet_size) ) + dcd_event_xfer_complete(0, ep_addr, xfer->out_bytes_so_far, XFER_RESULT_SUCCESS, true); + else + ep->MXPLD = xfer->max_packet_size; + } + else + { + /* update the bookkeeping to reflect the data that has now been sent to the PC */ + xfer->in_remaining_bytes -= available_bytes; + xfer->data_ptr += available_bytes; + + /* if more data to send, send it; otherwise, alert TinyUSB that we've finished */ + if (xfer->in_remaining_bytes) + dcd_in_xfer(xfer, ep); + else + dcd_event_xfer_complete(0, ep_addr, xfer->total_bytes, XFER_RESULT_SUCCESS, true); + } + } + } + } + + /* acknowledge all interrupts */ + USBD->INTSTS = status & enabled_irqs; +} + +void dcd_isr(uint8_t rhport) +{ + (void) rhport; + USBD_IRQHandler(); +} + +#endif diff --git a/src/tusb_option.h b/src/tusb_option.h index d39dd1046..46684ff7f 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -79,6 +79,7 @@ #define OPT_MCU_NUC121 800 #define OPT_MCU_NUC126 801 +#define OPT_MCU_NUC120 802 /** @} */ -- cgit v1.3.1 From b6b9fe42af1828c2ed8f794a930999ecb4da2902 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Feb 2020 16:43:44 +0700 Subject: more log for debugging --- src/class/cdc/cdc_device.c | 11 ++++++++++- src/device/usbd_control.c | 14 +++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index c0de0cadd..f63418dae 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -335,25 +335,34 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request switch ( request->bRequest ) { case CDC_REQUEST_SET_LINE_CODING: + TU_LOG2(" Set Line Coding\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); break; case CDC_REQUEST_GET_LINE_CODING: + TU_LOG2(" Get Line Coding\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); break; case CDC_REQUEST_SET_CONTROL_LINE_STATE: + { // CDC PSTN v1.2 section 6.3.12 // Bit 0: Indicates if DTE is present or not. // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) // Bit 1: Carrier control for half-duplex modems. // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) + bool const dtr = tu_bit_test(request->wValue, 0); + bool const rts = tu_bit_test(request->wValue, 1); + p_cdc->line_state = (uint8_t) request->wValue; + TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\n", dtr, rts); + tud_control_status(rhport, request); // Invoke callback - if ( tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, tu_bit_test(request->wValue, 0), tu_bit_test(request->wValue, 1)); + if ( tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, dtr, rts); + } break; default: return false; // stall unsupported request diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index e6d1caf4b..5a0ba412f 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -51,8 +51,8 @@ typedef struct static usbd_control_xfer_t _ctrl_xfer; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; - +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN +static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; //--------------------------------------------------------------------+ // Application API @@ -60,8 +60,14 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbd_ctrl_buf[CFG_TUD_EN static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const * request) { + // Opposite to endpoint in Data Phase + uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; + + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", ep_addr, 0); + // status direction is reversed to one in the setup packet - return dcd_edpt_xfer(rhport, request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN, NULL, 0); + // Note: Status must always be DATA1 + return dcd_edpt_xfer(rhport, ep_addr, NULL, 0); } // Status phase @@ -106,6 +112,8 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo // Data stage TU_ASSERT( _data_stage_xact(rhport) ); + + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); }else { // Status stage -- cgit v1.3.1 From 9ca6311ac49559570c5d7366344fb5887b09e953 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Feb 2020 16:46:18 +0700 Subject: implement walkaround for incorrect DATA Toggle for status control. --- src/portable/microchip/samg/dcd_samg.c | 75 ++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index a93b26caa..835bbf01e 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -51,6 +51,11 @@ typedef struct // Endpoint 0-5, each can only be either OUT or In xfer_desc_t _dcd_xfer[EP_COUNT]; +// Indicate that DATA Toggle for Control Status is incorrect, which must always be DATA1 by USB Specs. +// However SAMG DToggle is read-only, therefore we must duplicate the status phase ( D0 then D1 ) +// as walk-around to resolve this. The D0 status packet is likely to be discarded by USB Host safely. +volatile bool _walkaround_incorrect_dtoggle_control_status; + void xfer_epsize_set(xfer_desc_t* xfer, uint16_t epsize) { xfer->epsize = epsize; @@ -111,6 +116,7 @@ static void xact_ep_read(uint8_t epnum, uint8_t* buffer, uint16_t xact_len) // Set up endpoint 0, clear all other endpoints static void bus_reset(void) { + _walkaround_incorrect_dtoggle_control_status = false; tu_memclr(_dcd_xfer, sizeof(_dcd_xfer)); xfer_epsize_set(&_dcd_xfer[0], CFG_TUD_ENDPOINT0_SIZE); @@ -201,7 +207,8 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re // Set new address & Function enable bit UDP->UDP_FADDR = UDP_FADDR_FEN_Msk | UDP_FADDR_FADD(dev_addr); - }else if (request->bRequest == TUSB_REQ_SET_CONFIGURATION) + } + else if (request->bRequest == TUSB_REQ_SET_CONFIGURATION) { // Configured State UDP->UDP_GLB_STAT |= UDP_GLB_STAT_CONFG_Msk; @@ -248,10 +255,47 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_desc_t* xfer = &_dcd_xfer[epnum]; xfer_begin(xfer, buffer, total_bytes); + // Control Endpoint direction and data toggle + if (epnum == 0) + { + // Transfer direction is opposite to one previously set on EP0 + // This transfer is Control Status Stage + if ( dir != tu_bit_test(UDP->UDP_CSR[epnum], UDP_CSR_DIR_Pos) ) + { + // Set/Clear DIR bit accordingly + if (dir) + { + UDP->UDP_CSR[epnum] |= UDP_CSR_DIR_Msk; + }else + { + UDP->UDP_CSR[epnum] &= ~UDP_CSR_DIR_Msk; + } + + // DATA Toggle is 0, USB Specs requires Status Stage must be DATA1 + // Since SAMG DToggle is read-only, we mark this and implement a walk-around + if ( !(UDP->UDP_CSR[epnum] & UDP_CSR_DTGLE_Msk) ) + { + TU_LOG2("Incorrect DATA TOGGLE, Control Status must be DATA1\n"); + + // DTGLE is read-only on SAMG, this statement has no effect + UDP->UDP_CSR[epnum] |= UDP_CSR_DTGLE_Msk; + + _walkaround_incorrect_dtoggle_control_status = true; + } + } + } + + if (dir == TUSB_DIR_IN) { - // Set DIR bit for EP0 - if ( epnum == 0 ) UDP->UDP_CSR[epnum] |= UDP_CSR_DIR_Msk; + // WALKROUND: duplicate IN transfer to send DATA1 status packet + if (_walkaround_incorrect_dtoggle_control_status) + { + UDP->UDP_CSR[epnum] |= UDP_CSR_TXPKTRDY_Msk; + while ( UDP->UDP_CSR[epnum] & UDP_CSR_TXPKTRDY_Msk ) {} + + _walkaround_incorrect_dtoggle_control_status = false; + } xact_ep_write(epnum, xfer->buffer, xfer_packet_len(xfer)); @@ -368,8 +412,17 @@ void dcd_isr(uint8_t rhport) // notify usbd dcd_event_setup_received(rhport, setup, true); - // Clear Setup bit - UDP->UDP_CSR[0] &= ~UDP_CSR_RXSETUP_Msk; + // Set EP direction bit according to DATA stage + if (setup[0] & 0x80) + { + UDP->UDP_CSR[0] |= UDP_CSR_DIR_Msk; + }else + { + UDP->UDP_CSR[0] &= ~UDP_CSR_DIR_Msk; + } + + // Clear Setup bit & stall bit if needed + UDP->UDP_CSR[0] &= ~(UDP_CSR_RXSETUP_Msk | UDP_CSR_FORCESTALL_Msk); return; } @@ -397,8 +450,12 @@ void dcd_isr(uint8_t rhport) UDP->UDP_CSR[epnum] |= UDP_CSR_TXPKTRDY_Msk; }else { - // xfer is complete - dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true); + // WALKAROUND: Skip reporting this incorrect DATA Toggle status transfer + if ( !(_walkaround_incorrect_dtoggle_control_status && (epnum == 0) && (xfer->actual_len == 0)) ) + { + // xfer is complete + dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true); + } } // Clear TX Complete bit @@ -406,8 +463,8 @@ void dcd_isr(uint8_t rhport) } // Endpoint OUT - // Ping-Pong is a must for Bulk/Iso - // When both Bank0 and Bank1 are both set, there is not way to know which one comes first + // Ping-Pong is a MUST for Bulk/Iso + // When both Bank0 and Bank1 are both set, there is no way to know which one comes first if (UDP->UDP_CSR[epnum] & (UDP_CSR_RX_DATA_BK0_Msk | UDP_CSR_RX_DATA_BK1_Msk)) { uint16_t const xact_len = (uint16_t) ((UDP->UDP_CSR[epnum] & UDP_CSR_RXBYTECNT_Msk) >> UDP_CSR_RXBYTECNT_Pos); -- cgit v1.3.1 From 02b2c602319a55226429582dfd8002c95cc3ff87 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Feb 2020 17:39:20 +0700 Subject: samg55 work with cdc msc example --- src/portable/microchip/samg/dcd_samg.c | 56 +++++++++------------------------- 1 file changed, 15 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 835bbf01e..53ccba961 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -304,34 +304,6 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } else { - // Clear DIR bit for EP0 - if ( epnum == 0 ) UDP->UDP_CSR[epnum] &= ~UDP_CSR_DIR_Msk; - - // OUT Data may already received and acked by hardware - // Read it as 1st packet then continue with transfer if needed - if ( UDP->UDP_CSR[epnum] & (UDP_CSR_RX_DATA_BK0_Msk | UDP_CSR_RX_DATA_BK1_Msk) ) - { -// uint16_t const xact_len = (uint16_t) ((UDP->UDP_CSR[epnum] & UDP_CSR_RXBYTECNT_Msk) >> UDP_CSR_RXBYTECNT_Pos); - -// TU_LOG2("xact_len = %d\r", xact_len); - -// // Read from EP fifo -// xact_ep_read(epnum, xfer->buffer, xact_len); -// xfer_packet_done(xfer); -// -// // Clear DATA Bank0 bit -// UDP->UDP_CSR[epnum] &= ~UDP_CSR_RX_DATA_BK0_Msk; -// -// if ( 0 == xfer_packet_len(xfer) ) -// { -// // Disable OUT EP interrupt when transfer is complete -// UDP->UDP_IER &= ~(1 << epnum); -// -// dcd_event_xfer_complete(rhport, epnum, xact_len, XFER_RESULT_SUCCESS, false); -// return true; // complete -// } - } - // Enable interrupt when starting OUT transfer if (epnum != 0) UDP->UDP_IER |= (1 << epnum); } @@ -387,13 +359,13 @@ void dcd_isr(uint8_t rhport) // if (intr_status & UDP_ISR_SOFINT_Msk) dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); // Suspend -// if (intr_status & UDP_ISR_RXSUSP_Msk) dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + if (intr_status & UDP_ISR_RXSUSP_Msk) dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); // Resume -// if (intr_status & UDP_ISR_RXRSM_Msk) dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); + if (intr_status & UDP_ISR_RXRSM_Msk) dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); // Wakeup -// if (intr_status & UDP_ISR_WAKEUP_Msk) dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); + if (intr_status & UDP_ISR_WAKEUP_Msk) dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); //------------- Endpoints -------------// @@ -434,7 +406,7 @@ void dcd_isr(uint8_t rhport) { xfer_desc_t* xfer = &_dcd_xfer[epnum]; - // Endpoint IN + //------------- Endpoint IN -------------// if (UDP->UDP_CSR[epnum] & UDP_CSR_TXCOMP_Msk) { xfer_packet_done(xfer); @@ -455,6 +427,9 @@ void dcd_isr(uint8_t rhport) { // xfer is complete dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true); + + // Required since control OUT can happen right after before stack handle this event + xfer_end(xfer); } } @@ -462,15 +437,14 @@ void dcd_isr(uint8_t rhport) UDP->UDP_CSR[epnum] &= ~UDP_CSR_TXCOMP_Msk; } - // Endpoint OUT + //------------- Endpoint OUT -------------// // Ping-Pong is a MUST for Bulk/Iso - // When both Bank0 and Bank1 are both set, there is no way to know which one comes first - if (UDP->UDP_CSR[epnum] & (UDP_CSR_RX_DATA_BK0_Msk | UDP_CSR_RX_DATA_BK1_Msk)) + // NOTE: When both Bank0 and Bank1 are both set, there is no way to know which one comes first + uint32_t const banks_complete = UDP->UDP_CSR[epnum] & (UDP_CSR_RX_DATA_BK0_Msk | UDP_CSR_RX_DATA_BK1_Msk); + if (banks_complete) { uint16_t const xact_len = (uint16_t) ((UDP->UDP_CSR[epnum] & UDP_CSR_RXBYTECNT_Msk) >> UDP_CSR_RXBYTECNT_Pos); - //if (epnum != 0) TU_LOG2("xact_len = %d\r", xact_len); - // Read from EP fifo xact_ep_read(epnum, xfer->buffer, xact_len); xfer_packet_done(xfer); @@ -480,12 +454,12 @@ void dcd_isr(uint8_t rhport) // Disable OUT EP interrupt when transfer is complete if (epnum != 0) UDP->UDP_IDR |= (1 << epnum); - dcd_event_xfer_complete(rhport, epnum, xact_len, XFER_RESULT_SUCCESS, true); -// xfer_end(xfer); + dcd_event_xfer_complete(rhport, epnum, xfer->actual_len, XFER_RESULT_SUCCESS, true); + xfer_end(xfer); } - // Clear DATA Bank0 bit - UDP->UDP_CSR[epnum] &= ~(UDP_CSR_RX_DATA_BK0_Msk | UDP_CSR_RX_DATA_BK1_Msk); + // Clear DATA Bank0/1 bit + UDP->UDP_CSR[epnum] &= ~banks_complete; } // Stall sent to host -- cgit v1.3.1 From 46f22860fb6eaf0b65469b47b099e20f489b2e47 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Feb 2020 22:13:38 +0700 Subject: correct waklaround with only status IN correct usb descriptor msc dual example to work with samg --- examples/device/cdc_msc/src/usb_descriptors.c | 2 +- examples/device/msc_dual_lun/src/usb_descriptors.c | 18 ++++-- src/portable/microchip/samg/dcd_samg.c | 67 ++++++++++------------ 3 files changed, 45 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index e8527df0b..5cae7760e 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -95,7 +95,7 @@ enum #define EPNUM_MSC_IN 0x85 #elif CFG_TUSB_MCU == OPT_MCU_SAMG - // SAMG doesn't support a same endpoint number with IN and OUT + // SAMG doesn't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_CDC_NOTIF 0x81 #define EPNUM_CDC_OUT 0x02 diff --git a/examples/device/msc_dual_lun/src/usb_descriptors.c b/examples/device/msc_dual_lun/src/usb_descriptors.c index e0a5904a4..88a96fb9a 100644 --- a/examples/device/msc_dual_lun/src/usb_descriptors.c +++ b/examples/device/msc_dual_lun/src/usb_descriptors.c @@ -80,10 +80,20 @@ enum #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 ... - #define EPNUM_MSC 0x02 + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ... + #define EPNUM_MSC_OUT 0x02 + #define EPNUM_MSC_IN 0x82 + +#elif CFG_TUSB_MCU == OPT_MCU_SAMG + // SAMG doesn't support a same endpoint number with different direction IN and OUT + // e.g EP1 OUT & EP1 IN cannot exist together + #define EPNUM_MSC_OUT 0x01 + #define EPNUM_MSC_IN 0x82 + #else - #define EPNUM_MSC 0x01 + #define EPNUM_MSC_OUT 0x01 + #define EPNUM_MSC_IN 0x81 + #endif uint8_t const desc_configuration[] = @@ -92,7 +102,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC, 0x80 | EPNUM_MSC, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 53ccba961..882072521 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -54,6 +54,7 @@ xfer_desc_t _dcd_xfer[EP_COUNT]; // Indicate that DATA Toggle for Control Status is incorrect, which must always be DATA1 by USB Specs. // However SAMG DToggle is read-only, therefore we must duplicate the status phase ( D0 then D1 ) // as walk-around to resolve this. The D0 status packet is likely to be discarded by USB Host safely. +// Note: Only needed for IN Status e.g CDC_SET_LINE_CODING, since out data is sent by host volatile bool _walkaround_incorrect_dtoggle_control_status; void xfer_epsize_set(xfer_desc_t* xfer, uint16_t epsize) @@ -255,46 +256,43 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_desc_t* xfer = &_dcd_xfer[epnum]; xfer_begin(xfer, buffer, total_bytes); - // Control Endpoint direction and data toggle - if (epnum == 0) + if (dir == TUSB_DIR_OUT) { - // Transfer direction is opposite to one previously set on EP0 - // This transfer is Control Status Stage - if ( dir != tu_bit_test(UDP->UDP_CSR[epnum], UDP_CSR_DIR_Pos) ) + // Clear EP0 direction bit + if (epnum == 0) UDP->UDP_CSR[epnum] &= ~UDP_CSR_DIR_Msk; + + // Enable interrupt when starting OUT transfer + if (epnum != 0) UDP->UDP_IER |= (1 << epnum); + } + else + { + if (epnum == 0) { - // Set/Clear DIR bit accordingly - if (dir) + // Previous EP0 direction is OUT --> This transfer is ZLP control status. + if ( !(UDP->UDP_CSR[epnum] & UDP_CSR_DIR_Msk) ) { + // Set EP0 dir bit UDP->UDP_CSR[epnum] |= UDP_CSR_DIR_Msk; - }else - { - UDP->UDP_CSR[epnum] &= ~UDP_CSR_DIR_Msk; - } - // DATA Toggle is 0, USB Specs requires Status Stage must be DATA1 - // Since SAMG DToggle is read-only, we mark this and implement a walk-around - if ( !(UDP->UDP_CSR[epnum] & UDP_CSR_DTGLE_Msk) ) - { - TU_LOG2("Incorrect DATA TOGGLE, Control Status must be DATA1\n"); + // DATA Toggle is 0, USB Specs requires Status Stage must be DATA1 + // Since SAMG DToggle is read-only, we mark this and implement the walk-around + if ( !(UDP->UDP_CSR[epnum] & UDP_CSR_DTGLE_Msk) ) + { + TU_LOG2("Incorrect DATA TOGGLE, Control Status must be DATA1\n"); - // DTGLE is read-only on SAMG, this statement has no effect - UDP->UDP_CSR[epnum] |= UDP_CSR_DTGLE_Msk; - - _walkaround_incorrect_dtoggle_control_status = true; - } - } - } + // DTGLE is read-only on SAMG, this statement has no effect + UDP->UDP_CSR[epnum] |= UDP_CSR_DTGLE_Msk; + // WALKROUND: duplicate IN transfer to send DATA1 status packet + // set flag for irq to skip reporting first incorrect packet + _walkaround_incorrect_dtoggle_control_status = true; - if (dir == TUSB_DIR_IN) - { - // WALKROUND: duplicate IN transfer to send DATA1 status packet - if (_walkaround_incorrect_dtoggle_control_status) - { - UDP->UDP_CSR[epnum] |= UDP_CSR_TXPKTRDY_Msk; - while ( UDP->UDP_CSR[epnum] & UDP_CSR_TXPKTRDY_Msk ) {} + UDP->UDP_CSR[epnum] |= UDP_CSR_TXPKTRDY_Msk; + while ( UDP->UDP_CSR[epnum] & UDP_CSR_TXPKTRDY_Msk ) {} - _walkaround_incorrect_dtoggle_control_status = false; + _walkaround_incorrect_dtoggle_control_status = false; + } + } } xact_ep_write(epnum, xfer->buffer, xfer_packet_len(xfer)); @@ -302,11 +300,6 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // TX ready for transfer UDP->UDP_CSR[epnum] |= UDP_CSR_TXPKTRDY_Msk; } - else - { - // Enable interrupt when starting OUT transfer - if (epnum != 0) UDP->UDP_IER |= (1 << epnum); - } return true; } @@ -422,7 +415,7 @@ void dcd_isr(uint8_t rhport) UDP->UDP_CSR[epnum] |= UDP_CSR_TXPKTRDY_Msk; }else { - // WALKAROUND: Skip reporting this incorrect DATA Toggle status transfer + // WALKAROUND: Skip reporting this incorrect DATA Toggle status IN transfer if ( !(_walkaround_incorrect_dtoggle_control_status && (epnum == 0) && (xfer->actual_len == 0)) ) { // xfer is complete -- cgit v1.3.1 From 7d8ecc63a60b039b6e59961023ffb1c228e20d4f Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Fri, 7 Feb 2020 20:11:00 -0600 Subject: add Nuvoton NUC505 --- README.md | 2 +- examples/device/cdc_dual_ports/src/tusb_config.h | 2 +- examples/device/cdc_msc/src/tusb_config.h | 2 +- .../device/cdc_msc_hid_freertos/src/tusb_config.h | 2 +- examples/device/dfu_rt/src/tusb_config.h | 2 +- examples/device/hid_composite/src/tusb_config.h | 2 +- .../device/hid_generic_inout/src/tusb_config.h | 2 +- examples/device/midi_test/src/tusb_config.h | 2 +- examples/device/msc_dual_lun/src/tusb_config.h | 2 +- examples/device/usbtmc/src/tusb_config.h | 2 +- examples/device/webusb_serial/src/tusb_config.h | 2 +- hw/bsp/nutiny_sdk_nuc505/board.mk | 52 ++ hw/bsp/nutiny_sdk_nuc505/nuc505_flashtoram.ld | 199 +++++++ hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c | 115 ++++ hw/mcu/nuvoton | 2 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 639 +++++++++++++++++++++ src/tusb_option.h | 1 + 17 files changed, 1018 insertions(+), 12 deletions(-) create mode 100644 hw/bsp/nutiny_sdk_nuc505/board.mk create mode 100644 hw/bsp/nutiny_sdk_nuc505/nuc505_flashtoram.ld create mode 100644 hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c create mode 100644 src/portable/nuvoton/nuc505/dcd_nuc505.c (limited to 'src') diff --git a/README.md b/README.md index 29052d01a..7ab55f781 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ The stack supports the following MCUs: - **Sony:** CXD56 - **ST:** STM32 series: L0, F0, F1, F2, F3, F4, F7, H7 (device only) - **[ValentyUSB](https://github.com/im-tomu/valentyusb)** eptri -- **Nuvoton:** NUC121/NUC125, NUC126 +- **Nuvoton:** NUC121/NUC125, NUC126, NUC505 [Here is the list of supported Boards](docs/boards.md) that can be used with provided examples. diff --git a/examples/device/cdc_dual_ports/src/tusb_config.h b/examples/device/cdc_dual_ports/src/tusb_config.h index 734b96c16..9783bd4f6 100644 --- a/examples/device/cdc_dual_ports/src/tusb_config.h +++ b/examples/device/cdc_dual_ports/src/tusb_config.h @@ -39,7 +39,7 @@ #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 +#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) #else #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index 5b7a1671e..d881cb638 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -39,7 +39,7 @@ #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 +#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) #else #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE diff --git a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h index 6788a7483..39738333c 100644 --- a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h @@ -39,7 +39,7 @@ #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 +#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) #else #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE diff --git a/examples/device/dfu_rt/src/tusb_config.h b/examples/device/dfu_rt/src/tusb_config.h index 27afdb6b6..96c3a2468 100644 --- a/examples/device/dfu_rt/src/tusb_config.h +++ b/examples/device/dfu_rt/src/tusb_config.h @@ -21,7 +21,7 @@ #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 +#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) #else #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index dd360741d..6d2fd0836 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -39,7 +39,7 @@ #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 +#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) #else #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE diff --git a/examples/device/hid_generic_inout/src/tusb_config.h b/examples/device/hid_generic_inout/src/tusb_config.h index 0053a7d0a..2debafd2a 100644 --- a/examples/device/hid_generic_inout/src/tusb_config.h +++ b/examples/device/hid_generic_inout/src/tusb_config.h @@ -39,7 +39,7 @@ #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 +#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) #else #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE diff --git a/examples/device/midi_test/src/tusb_config.h b/examples/device/midi_test/src/tusb_config.h index 5837db4eb..56f326f31 100644 --- a/examples/device/midi_test/src/tusb_config.h +++ b/examples/device/midi_test/src/tusb_config.h @@ -39,7 +39,7 @@ #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 +#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) #else #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE diff --git a/examples/device/msc_dual_lun/src/tusb_config.h b/examples/device/msc_dual_lun/src/tusb_config.h index baf857b71..82d07c60a 100644 --- a/examples/device/msc_dual_lun/src/tusb_config.h +++ b/examples/device/msc_dual_lun/src/tusb_config.h @@ -39,7 +39,7 @@ #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 +#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) #else #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE diff --git a/examples/device/usbtmc/src/tusb_config.h b/examples/device/usbtmc/src/tusb_config.h index 2932ea4d1..5dddc2c46 100644 --- a/examples/device/usbtmc/src/tusb_config.h +++ b/examples/device/usbtmc/src/tusb_config.h @@ -21,7 +21,7 @@ #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 +#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) #else #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE diff --git a/examples/device/webusb_serial/src/tusb_config.h b/examples/device/webusb_serial/src/tusb_config.h index 30acdaccf..b3f449f93 100644 --- a/examples/device/webusb_serial/src/tusb_config.h +++ b/examples/device/webusb_serial/src/tusb_config.h @@ -39,7 +39,7 @@ #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 +#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) #else #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE diff --git a/hw/bsp/nutiny_sdk_nuc505/board.mk b/hw/bsp/nutiny_sdk_nuc505/board.mk new file mode 100644 index 000000000..259d11082 --- /dev/null +++ b/hw/bsp/nutiny_sdk_nuc505/board.mk @@ -0,0 +1,52 @@ +CFLAGS += \ + -flto \ + -mthumb \ + -mabi=aapcs-linux \ + -mcpu=cortex-m4 \ + -DCFG_TUSB_MCU=OPT_MCU_NUC505 + +# All source paths should be relative to the top level. +LD_FILE = hw/bsp/nutiny_sdk_nuc505/nuc505_flashtoram.ld + +SRC_C += \ + hw/mcu/nuvoton/nuc505/Device/Nuvoton/NUC505Series/Source/system_NUC505Series.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/adc.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/clk.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/gpio.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/i2c.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/i2s.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/pwm.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/rtc.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/sd.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/spi.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/spim.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/sys.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/timer.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/uart.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/usbd.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/wdt.c \ + hw/mcu/nuvoton/nuc505/StdDriver/src/wwdt.c + +SRC_S += \ + hw/mcu/nuvoton/nuc505/Device/Nuvoton/NUC505Series/Source/GCC/startup_NUC505Series.S + +INC += \ + $(TOP)/hw/mcu/nuvoton/nuc505/Device/Nuvoton/NUC505Series/Include \ + $(TOP)/hw/mcu/nuvoton/nuc505/StdDriver/inc \ + $(TOP)/hw/mcu/nuvoton/nuc505/CMSIS/Include + +# For TinyUSB port source +VENDOR = nuvoton +CHIP_FAMILY = nuc505 + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM4 + +# For flash-jlink target +JLINK_DEVICE = NUC505YO13Y +JLINK_IF = swd + +# Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton +# Please compile and install it from github source +flash: $(BUILD)/$(BOARD)-firmware.elf + openocd -f interface/nulink.cfg -f target/numicroM4.cfg -c "program $< reset exit" diff --git a/hw/bsp/nutiny_sdk_nuc505/nuc505_flashtoram.ld b/hw/bsp/nutiny_sdk_nuc505/nuc505_flashtoram.ld new file mode 100644 index 000000000..53d385cd0 --- /dev/null +++ b/hw/bsp/nutiny_sdk_nuc505/nuc505_flashtoram.ld @@ -0,0 +1,199 @@ +/* Linker script to configure memory regions. */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000 /* 512k */ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x20000 /* 128k */ +} + +/* Library configurations */ +GROUP(libgcc.a libc.a libm.a libnosys.a) + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + * __Vectors_End + * __Vectors_Size + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .startup : + { + KEEP(*(.vectors)) + __Vectors_End = .; + __Vectors_Size = __Vectors_End - __Vectors; + __end__ = .; + + KEEP(*(.preinit)) + + KEEP(*(.init)) + KEEP(*(.fini)) + + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * uncomment .copy.table section and, + * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ + /* + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (__etext2) + LONG (__data2_start__) + LONG (__data2_end__ - __data2_start__) + __copy_table_end__ = .; + } > FLASH + */ + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ + /* + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (__bss2_start__) + LONG (__bss2_end__ - __bss2_start__) + __zero_table_end__ = .; + } > FLASH + */ + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + + *(.text*) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __HeapBase = .; + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + KEEP(*(.stack*)) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c b/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c new file mode 100644 index 000000000..e666a10aa --- /dev/null +++ b/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c @@ -0,0 +1,115 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "bsp/board.h" +#include "NUC505Series.h" + +#define LED_PORT PC +#define LED_PIN 3 +#define LED_STATE_ON 0 + +void board_init(void) +{ + /* Enable XTAL */ + CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk; + + CLK_SetCoreClock(96000000); + + /* Set PCLK divider */ + CLK_SetModuleClock(PCLK_MODULE, 0, 1); + + /* Update System Core Clock */ + SystemCoreClockUpdate(); + + /* Enable USB IP clock */ + CLK_EnableModuleClock(USBD_MODULE); + + /* Select USB IP clock source */ + CLK_SetModuleClock(USBD_MODULE, CLK_USBD_SRC_EXT, 0); + + CLK_SetModuleClock(PCLK_MODULE, 0, 1); + + /* Enable PHY */ + USBD_ENABLE_PHY(); + /* wait PHY clock ready */ + while (1) { + USBD->EP[EPA].EPMPS = 0x20; + if (USBD->EP[EPA].EPMPS == 0x20) + break; + } + + /* Force SE0, and then clear it to connect*/ + USBD_SET_SE0(); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(96000000 / 1000); +#endif + + GPIO_SetMode(LED_PORT, 1UL << LED_PIN, GPIO_MODE_OUTPUT); +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + uint32_t current = (state) ? LED_STATE_ON : (1-LED_STATE_ON); + current <<= LED_PIN; + current |= LED_PORT->DOUT & ~(1UL << LED_PIN); + LED_PORT->DOUT = current; +} + +uint32_t board_button_read(void) +{ + return 0; +} + +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +int board_uart_write(void const * buf, int len) +{ + (void) buf; (void) len; + return 0; +} diff --git a/hw/mcu/nuvoton b/hw/mcu/nuvoton index dc96fff79..2204191ec 160000 --- a/hw/mcu/nuvoton +++ b/hw/mcu/nuvoton @@ -1 +1 @@ -Subproject commit dc96fff794d14818c93ea1d4d760d51a014d70c5 +Subproject commit 2204191ec76283371419fbcec207da02e1bc22fa diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c new file mode 100644 index 000000000..2b6a66bc2 --- /dev/null +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -0,0 +1,639 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Peter Lawrence + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +/* + Theory of operation: + + The NUC505 USBD peripheral has twelve "EP"s, where each is simplex, in addition + to dedicated support for the control endpoint (EP0). The non-user endpoints + are referred to as "user" EPs in this code, and follow the datasheet + nomenclature of EPA through EPL. +*/ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC505) + +#include "device/dcd.h" +#include "NUC505Series.h" + +/* rather important info unfortunately not provided by device include files */ +#define USBD_BUF_SIZE 2048 /* how much USB buffer space there is */ +#define USBD_MAX_DMA_LEN 0x1000 /* max bytes that can be DMAed at one time */ + +enum ep_enum +{ + PERIPH_EPA = 0, + PERIPH_EPB = 1, + PERIPH_EPC = 2, + PERIPH_EPD = 3, + PERIPH_EPE = 4, + PERIPH_EPF = 5, + PERIPH_EPG = 6, + PERIPH_EPH = 7, + PERIPH_EPI = 8, + PERIPH_EPJ = 9, + PERIPH_EPK = 10, + PERIPH_EPL = 11, + PERIPH_MAX_EP, +}; + +static const uint8_t epcfg_eptype_table[] = +{ + [TUSB_XFER_CONTROL] = 0, /* won't happen, since control EPs have dedicated registers */ + [TUSB_XFER_ISOCHRONOUS] = 3 << USBD_EPCFG_EPTYPE_Pos, + [TUSB_XFER_BULK] = 1 << USBD_EPCFG_EPTYPE_Pos, + [TUSB_XFER_INTERRUPT] = 2 << USBD_EPCFG_EPTYPE_Pos, +}; + +static const uint8_t eprspctl_eptype_table[] = +{ + [TUSB_XFER_CONTROL] = 0, /* won't happen, since control EPs have dedicated registers */ + [TUSB_XFER_ISOCHRONOUS] = 2 << USBD_EPRSPCTL_MODE_Pos, /* Fly Mode */ + [TUSB_XFER_BULK] = 0 << USBD_EPRSPCTL_MODE_Pos, /* Auto-Validate Mode */ + [TUSB_XFER_INTERRUPT] = 1 << USBD_EPRSPCTL_MODE_Pos, /* Manual-Validate Mode */ +}; + +/* set by dcd_set_address() */ +static volatile uint8_t assigned_address; + +/* reset by bus_reset(), this is used by dcd_edpt_open() to assign USBD peripheral buffer addresses */ +static uint32_t bufseg_addr; + +/* RAM table needed to track ongoing transfers performed by dcd_edpt_xfer(), dcd_userEP_in_xfer(), and the ISR */ +static struct xfer_ctl_t +{ + uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */ + union { + uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */ + uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */ + }; + uint16_t max_packet_size; /* needed since device driver only finds out this at runtime */ + uint16_t total_bytes; /* quantity needed to pass as argument to dcd_event_xfer_complete() (for IN endpoints) */ + uint8_t ep_addr; + bool dma_requested; +} xfer_table[PERIPH_MAX_EP]; + +/* in addition to xfer_table, additional bespoke bookkeeping is maintained for control EP0 IN */ +static struct +{ + uint8_t *data_ptr; + uint16_t in_remaining_bytes; + uint16_t total_bytes; +} ctrl_in_xfer; + +static volatile bool configuration_changed; + +static volatile struct xfer_ctl_t *current_dma_xfer; + + +/* + local helper functions +*/ + +static void usb_attach(void) +{ + USBD->PHYCTL |= USBD_PHYCTL_DPPUEN_Msk; +} + +static void usb_control_send_zlp(void) +{ + USBD->CEPINTSTS = USBD_CEPINTSTS_STSDONEIF_Msk; + USBD->CEPCTL = 0; /* clear NAKCLR bit */ + USBD->CEPINTEN = USBD_CEPINTEN_STSDONEIEN_Msk; +} + +/* map 8-bit ep_addr into peripheral endpoint index (PERIPH_EPA...) */ +static USBD_EP_T *ep_entry(uint8_t ep_addr, bool add) +{ + USBD_EP_T *ep; + enum ep_enum ep_index; + struct xfer_ctl_t *xfer; + + for (ep_index = PERIPH_EPA, xfer = &xfer_table[PERIPH_EPA], ep = USBD->EP; ep_index < PERIPH_MAX_EP; ep_index++, xfer++, ep++) + { + if (add) + { + /* take first peripheral endpoint that is unused */ + if (0 == (ep->EPCFG & USBD_EPCFG_EPEN_Msk)) return ep; + } + else + { + /* find a peripheral endpoint that matches ep_addr */ + if (xfer->ep_addr == ep_addr) return ep; + } + } + + return NULL; +} + +/* perform a non-control IN endpoint transfer; this is called by the ISR */ +static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) +{ + uint16_t bytes_now = tu_min16(xfer->in_remaining_bytes, xfer->max_packet_size); + uint16_t countdown = bytes_now; + + /* precompute what amount of data will be left */ + xfer->in_remaining_bytes -= bytes_now; + + /* + if there will be no more data to send, we replace the BUFEMPTYIF EP interrupt with TXPKIF; + that way, we alert TinyUSB as soon as this last packet has been sent + */ + if (0 == xfer->in_remaining_bytes) + { + ep->EPINTSTS = USBD_EPINTSTS_TXPKIF_Msk; + ep->EPINTEN = USBD_EPINTEN_TXPKIEN_Msk; + } + + /* provided buffers are thankfully 32-bit aligned, allowing most data to be transfered as 32-bit */ + while (countdown > 3) + { + ep->EPDAT = *(uint32_t *)xfer->data_ptr; + xfer->data_ptr += 4; countdown -= 4; + } + while (countdown--) + ep->EPDAT_BYTE = *xfer->data_ptr++; + + /* for short packets, we must nudge the peripheral to say 'that's all folks' */ + if (bytes_now != xfer->max_packet_size) + ep->EPRSPCTL = USBD_EPRSPCTL_SHORTTXEN_Msk; +} + +/* called by dcd_init() as well as by the ISR during a USB bus reset */ +static void bus_reset(void) +{ + for (enum ep_enum ep_index = PERIPH_EPA; ep_index < PERIPH_MAX_EP; ep_index++) + { + USBD->EP[ep_index].EPCFG = 0; + xfer_table[ep_index].dma_requested = false; + } + + USBD->DMACNT = 0; + USBD->DMACTL = USBD_DMACTL_DMARST_Msk; + USBD->DMACTL = 0; + + /* allocate the default EP0 endpoints */ + + USBD->CEPBUFSTART = 0; + USBD->CEPBUFEND = 0 + CFG_TUD_ENDPOINT0_SIZE - 1; + + /* USB RAM beyond what we've allocated above is available to the user */ + bufseg_addr = CFG_TUD_ENDPOINT0_SIZE; + + /* Reset USB device address */ + USBD->FADDR = 0; + + configuration_changed = false; + current_dma_xfer = NULL; +} + +/* this must only be called by the ISR; it does its best to share the single DMA engine across all user EPs (IN and OUT) */ +static void service_dma(void) +{ + if (current_dma_xfer) + return; + + enum ep_enum ep_index; + struct xfer_ctl_t *xfer; + USBD_EP_T *ep; + + for (ep_index = PERIPH_EPA, xfer = &xfer_table[PERIPH_EPA], ep = &USBD->EP[PERIPH_EPA]; ep_index < PERIPH_MAX_EP; ep_index++, xfer++, ep++) + { + uint16_t const available_bytes = ep->EPDATCNT & USBD_EPDATCNT_DATCNT_Msk; + + if (!xfer->dma_requested || !available_bytes) + continue; + + /* + instruct DMA to copy the data from the PC to the previously provided buffer + when the bus interrupt DMADONEIEN subsequently fires, the transfer will have finished + */ + USBD->DMACTL = xfer->ep_addr & USBD_DMACTL_EPNUM_Msk; + USBD->DMAADDR = (uint32_t)xfer->data_ptr; + USBD->DMACNT = available_bytes; + USBD->BUSINTSTS = USBD_BUSINTSTS_DMADONEIF_Msk; + xfer->out_bytes_so_far += available_bytes; + current_dma_xfer = xfer; + USBD->DMACTL |= USBD_DMACTL_DMAEN_Msk; + + return; + } +} + +/* centralized location for USBD interrupt enable bit masks */ +static const uint32_t enabled_irqs = USBD_GINTEN_USBIEN_Msk | \ + USBD_GINTEN_EPAIEN_Msk | USBD_GINTEN_EPBIEN_Msk | USBD_GINTEN_EPCIEN_Msk | USBD_GINTEN_EPDIEN_Msk | USBD_GINTEN_EPEIEN_Msk | USBD_GINTEN_EPFIEN_Msk | \ + USBD_GINTEN_EPGIEN_Msk | USBD_GINTEN_EPHIEN_Msk | USBD_GINTEN_EPIIEN_Msk | USBD_GINTEN_EPJIEN_Msk | USBD_GINTEN_EPKIEN_Msk | USBD_GINTEN_EPLIEN_Msk | \ + USBD_GINTEN_CEPIEN_Msk; + +/* + NUC505 TinyUSB API driver implementation +*/ + +void dcd_init(uint8_t rhport) +{ + (void) rhport; + + /* configure interrupts in their initial state; BUSINTEN and CEPINTEN will be subsequently and dynamically re-written as needed */ + USBD->GINTEN = enabled_irqs; + USBD->BUSINTEN = USBD_BUSINTEN_RSTIEN_Msk | USBD_BUSINTEN_VBUSDETIEN_Msk | USBD_BUSINTEN_RESUMEIEN_Msk | USBD_BUSINTEN_DMADONEIEN_Msk; + USBD->CEPINTEN = 0; + + bus_reset(); + + usb_attach(); +} + +void dcd_int_enable(uint8_t rhport) +{ + (void) rhport; + NVIC_EnableIRQ(USBD_IRQn); +} + +void dcd_int_disable(uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ(USBD_IRQn); +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void) rhport; + usb_control_send_zlp(); /* SET_ADDRESS is the one exception where TinyUSB doesn't use dcd_edpt_xfer() to generate a ZLP */ + assigned_address = dev_addr; +} + +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) +{ + (void) rhport; + USBD->OPER |= USBD_OPER_RESUMEEN_Msk; +} + +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) +{ + (void) rhport; + + USBD_EP_T *ep = ep_entry(p_endpoint_desc->bEndpointAddress, true); + TU_ASSERT(ep); + + /* mine the data for the information we need */ + int const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); + int const size = p_endpoint_desc->wMaxPacketSize.size; + tusb_xfer_type_t const type = p_endpoint_desc->bmAttributes.xfer; + struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; + + /* allocate buffer from USB RAM */ + ep->EPBUFSTART = bufseg_addr; + bufseg_addr += size; + ep->EPBUFEND = bufseg_addr - 1; + TU_ASSERT(bufseg_addr <= USBD_BUF_SIZE); + + ep->EPMPS = size; + + ep->EPRSPCTL = USB_EP_RSPCTL_FLUSH | eprspctl_eptype_table[type]; + + /* construct USB Configuration Register value and then write it */ + uint32_t cfg = (uint32_t)tu_edpt_number(p_endpoint_desc->bEndpointAddress) << USBD_EPCFG_EPNUM_Pos; + if (TUSB_DIR_IN == dir) + cfg |= USBD_EPCFG_EPDIR_Msk; + cfg |= epcfg_eptype_table[type] | USBD_EPCFG_EPEN_Msk; + ep->EPCFG = cfg; + + /* make a note of the endpoint particulars */ + xfer->max_packet_size = size; + xfer->ep_addr = p_endpoint_desc->bEndpointAddress; + + return true; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +{ + (void) rhport; + + if (0x80 == ep_addr) /* control EP0 IN */ + { + if (total_bytes) + { + USBD->CEPCTL = USBD_CEPCTL_FLUSH_Msk; + ctrl_in_xfer.data_ptr = buffer; + ctrl_in_xfer.in_remaining_bytes = total_bytes; + ctrl_in_xfer.total_bytes = total_bytes; + USBD->CEPINTSTS = USBD_CEPINTSTS_INTKIF_Msk; + USBD->CEPINTEN = USBD_CEPINTEN_INTKIEN_Msk; + } + else + { + usb_control_send_zlp(); + } + } + else if (0x00 == ep_addr) /* control EP0 OUT */ + { + if (total_bytes) + { + /* if TinyUSB is asking for EP0 OUT data, it is almost certainly already in the buffer */ + while (total_bytes < USBD->CEPRXCNT); + for (int count = 0; count < total_bytes; count++) + *buffer++ = USBD->CEPDAT_BYTE; + + usb_control_send_zlp(); + } + } + else + { + /* mine the data for the information we need */ + tusb_dir_t dir = tu_edpt_dir(ep_addr); + USBD_EP_T *ep = ep_entry(ep_addr, false); + struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; + + /* store away the information we'll needing now and later */ + xfer->data_ptr = buffer; + xfer->in_remaining_bytes = total_bytes; + xfer->total_bytes = total_bytes; + + if (TUSB_DIR_IN == dir) + { + ep->EPINTEN = USBD_EPINTEN_BUFEMPTYIEN_Msk; + } + else + { + xfer->out_bytes_so_far = 0; + ep->EPINTEN = USBD_EPINTEN_RXPKIEN_Msk; + } + } + + return true; +} + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + if (tu_edpt_number(ep_addr)) + { + USBD_EP_T *ep = ep_entry(ep_addr, false); + ep->EPRSPCTL = (ep->EPRSPCTL & 0xf7) | USBD_EPRSPCTL_HALT_Msk; + } + else + { + USBD->CEPCTL = USBD_CEPCTL_STALLEN_Msk; + } +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + if (tu_edpt_number(ep_addr)) + { + USBD_EP_T *ep = ep_entry(ep_addr, false); + ep->EPRSPCTL = USBD_EPRSPCTL_TOGGLE_Msk; + } +} + +void USBD_IRQHandler(void) +{ + uint32_t status = USBD->GINTSTS; + + /* USB interrupt */ + if (status & USBD_GINTSTS_USBIF_Msk) + { + uint32_t bus_state = USBD->BUSINTSTS; + + if (bus_state & USBD_BUSINTSTS_SOFIF_Msk) + { + /* Start-Of-Frame event */ + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); + } + + if (bus_state & USBD_BUSINTSTS_RSTIF_Msk) + { + bus_reset(); + + USBD->CEPINTEN = USBD_CEPINTEN_SETUPPKIEN_Msk; + USBD->BUSINTEN = USBD_BUSINTEN_RSTIEN_Msk | USBD_BUSINTEN_RESUMEIEN_Msk | USBD_BUSINTEN_SUSPENDIEN_Msk | USBD_BUSINTEN_DMADONEIEN_Msk; + USBD->CEPINTSTS = 0x1ffc; + dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + } + + if (bus_state & USBD_BUSINTSTS_RESUMEIF_Msk) + { + USBD->BUSINTEN = USBD_BUSINTEN_RSTIEN_Msk | USBD_BUSINTEN_SUSPENDIEN_Msk | USBD_BUSINTEN_DMADONEIEN_Msk; + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + + if (bus_state & USBD_BUSINTSTS_SUSPENDIF_Msk) + { + USBD->BUSINTEN = USBD_BUSINTEN_RSTIEN_Msk | USBD_BUSINTEN_RESUMEIEN_Msk | USBD_BUSINTEN_DMADONEIEN_Msk; + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + } + + if (bus_state & USBD_BUSINTSTS_HISPDIF_Msk) + { + USBD->CEPINTEN = USBD_CEPINTEN_SETUPPKIEN_Msk; + } + + if (bus_state & USBD_BUSINTSTS_DMADONEIF_Msk) + { + if (current_dma_xfer) + { + current_dma_xfer->dma_requested = false; + + uint16_t available_bytes = USBD->DMACNT & USBD_DMACNT_DMACNT_Msk; + + /* if the most recent DMA finishes the transfer, alert TinyUSB; otherwise, the next RXPKIF/INTKIF endpoint interrupt will prompt the next DMA */ + if ( (current_dma_xfer->total_bytes == current_dma_xfer->out_bytes_so_far) || (available_bytes < current_dma_xfer->max_packet_size) ) + { + dcd_event_xfer_complete(0, current_dma_xfer->ep_addr, current_dma_xfer->out_bytes_so_far, XFER_RESULT_SUCCESS, true); + } + + current_dma_xfer = NULL; + service_dma(); + } + } + + if (bus_state & USBD_BUSINTSTS_VBUSDETIF_Msk) + { + if (USBD->PHYCTL & USBD_PHYCTL_VBUSDET_Msk) + { + /* USB connect */ + USBD->PHYCTL |= USBD_PHYCTL_PHYEN_Msk | USBD_PHYCTL_DPPUEN_Msk; + } + else + { + /* USB disconnect */ + USBD->PHYCTL &= ~USBD_PHYCTL_DPPUEN_Msk; + } + } + + USBD->BUSINTSTS = bus_state & (USBD_BUSINTSTS_SOFIF_Msk | USBD_BUSINTSTS_RSTIF_Msk | USBD_BUSINTSTS_RESUMEIF_Msk | USBD_BUSINTSTS_SUSPENDIF_Msk | USBD_BUSINTSTS_HISPDIF_Msk | USBD_BUSINTSTS_DMADONEIF_Msk | USBD_BUSINTSTS_PHYCLKVLDIF_Msk | USBD_BUSINTSTS_VBUSDETIF_Msk); + } + + if (status & USBD_GINTSTS_CEPIF_Msk) + { + uint32_t cep_state = USBD->CEPINTSTS & USBD->CEPINTEN; + + if (cep_state & USBD_CEPINTSTS_SETUPPKIF_Msk) + { + /* get SETUP packet from USB buffer */ + uint8_t setup_packet[8]; + setup_packet[0] = (uint8_t)(USBD->SETUP1_0 >> 0); + setup_packet[1] = (uint8_t)(USBD->SETUP1_0 >> 8); + setup_packet[2] = (uint8_t)(USBD->SETUP3_2 >> 0); + setup_packet[3] = (uint8_t)(USBD->SETUP3_2 >> 8); + setup_packet[4] = (uint8_t)(USBD->SETUP5_4 >> 0); + setup_packet[5] = (uint8_t)(USBD->SETUP5_4 >> 8); + setup_packet[6] = (uint8_t)(USBD->SETUP7_6 >> 0); + setup_packet[7] = (uint8_t)(USBD->SETUP7_6 >> 8); + dcd_event_setup_received(0, setup_packet, true); + } + else if (cep_state & USBD_CEPINTSTS_INTKIF_Msk) + { + USBD->CEPINTSTS = USBD_CEPINTSTS_TXPKIF_Msk; + + if (!(cep_state & USBD_CEPINTSTS_STSDONEIF_Msk)) + { + USBD->CEPINTEN = USBD_CEPINTEN_TXPKIEN_Msk; + uint16_t bytes_now = tu_min16(ctrl_in_xfer.in_remaining_bytes, CFG_TUD_ENDPOINT0_SIZE); + for (int count = 0; count < bytes_now; count++) + USBD->CEPDAT_BYTE = *ctrl_in_xfer.data_ptr++; + ctrl_in_xfer.in_remaining_bytes -= bytes_now; + USBD_START_CEP_IN(bytes_now); + } + else + { + USBD->CEPINTEN = USBD_CEPINTEN_TXPKIEN_Msk | USBD_CEPINTEN_STSDONEIEN_Msk; + } + } + else if (cep_state & USBD_CEPINTSTS_TXPKIF_Msk) + { + USBD->CEPINTSTS = USBD_CEPINTSTS_STSDONEIF_Msk; + USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR); + + /* alert TinyUSB that the EP0 IN transfer has finished */ + if ( (0 == ctrl_in_xfer.in_remaining_bytes) || (0 == ctrl_in_xfer.total_bytes) ) + dcd_event_xfer_complete(0, 0x80, ctrl_in_xfer.total_bytes, XFER_RESULT_SUCCESS, true); + + if (ctrl_in_xfer.in_remaining_bytes) + { + USBD->CEPINTSTS = USBD_CEPINTSTS_INTKIF_Msk; + USBD->CEPINTEN = USBD_CEPINTEN_INTKIEN_Msk; + } + else + { + /* TinyUSB does its own fragmentation and ZLP for EP0; a transfer of zero means a ZLP */ + if (0 == ctrl_in_xfer.total_bytes) USBD->CEPCTL = USBD_CEPCTL_ZEROLEN_Msk; + + USBD->CEPINTSTS = USBD_CEPINTSTS_STSDONEIF_Msk; + USBD->CEPINTEN = USBD_CEPINTEN_SETUPPKIEN_Msk | USBD_CEPINTEN_STSDONEIEN_Msk; + } + } + 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) + { + 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; + } + + USBD->CEPINTSTS = cep_state; + + return; + } + + if (status & (USBD_GINTSTS_EPAIF_Msk | USBD_GINTSTS_EPBIF_Msk | USBD_GINTSTS_EPCIF_Msk | USBD_GINTSTS_EPDIF_Msk | USBD_GINTSTS_EPEIF_Msk | USBD_GINTSTS_EPFIF_Msk | USBD_GINTSTS_EPGIF_Msk | USBD_GINTSTS_EPHIF_Msk | USBD_GINTSTS_EPIIF_Msk | USBD_GINTSTS_EPJIF_Msk | USBD_GINTSTS_EPKIF_Msk | USBD_GINTSTS_EPLIF_Msk)) + { + /* service PERIPH_EPA through PERIPH_EPL */ + enum ep_enum ep_index; + uint32_t mask; + struct xfer_ctl_t *xfer; + USBD_EP_T *ep; + for (ep_index = PERIPH_EPA, mask = USBD_GINTSTS_EPAIF_Msk, xfer = &xfer_table[PERIPH_EPA], ep = &USBD->EP[PERIPH_EPA]; ep_index < PERIPH_MAX_EP; ep_index++, mask <<= 1, xfer++, ep++) + { + if(status & mask) + { + uint8_t const ep_addr = xfer->ep_addr; + bool const out_ep = !(ep_addr & TUSB_DIR_IN_MASK); + uint32_t ep_state = ep->EPINTSTS & ep->EPINTEN; + + if (out_ep) + { +#if 1 + xfer->dma_requested = true; + service_dma(); +#else + uint16_t const available_bytes = ep->EPDATCNT & USBD_EPDATCNT_DATCNT_Msk; + /* copy the data from the PC to the previously provided buffer */ + for (int count = 0; (count < available_bytes) && (xfer->out_bytes_so_far < xfer->total_bytes); count++, xfer->out_bytes_so_far++) + *xfer->data_ptr++ = ep->EPDAT_BYTE; + + /* when the transfer is finished, alert TinyUSB; otherwise, continue accepting more data */ + if ( (xfer->total_bytes == xfer->out_bytes_so_far) || (available_bytes < xfer->max_packet_size) ) + dcd_event_xfer_complete(0, ep_addr, xfer->out_bytes_so_far, XFER_RESULT_SUCCESS, true); +#endif + + } + else if (ep_state & USBD_EPINTSTS_BUFEMPTYIF_Msk) + { + /* send any remaining data */ + dcd_userEP_in_xfer(xfer, ep); + } + else if (ep_state & USBD_EPINTSTS_TXPKIF_Msk) + { + /* alert TinyUSB that we've finished */ + dcd_event_xfer_complete(0, ep_addr, xfer->total_bytes, XFER_RESULT_SUCCESS, true); + ep->EPINTEN = 0; + } + + ep->EPINTSTS = ep_state; + } + } + } +} + +void dcd_isr(uint8_t rhport) +{ + (void) rhport; + USBD_IRQHandler(); +} + +#endif diff --git a/src/tusb_option.h b/src/tusb_option.h index d39dd1046..e0aa7a627 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -79,6 +79,7 @@ #define OPT_MCU_NUC121 800 #define OPT_MCU_NUC126 801 +#define OPT_MCU_NUC505 803 /** @} */ -- cgit v1.3.1 From 8d84bdff2177205be3ce97b4ecdc0247ae088606 Mon Sep 17 00:00:00 2001 From: Andrei Gramakov Date: Wed, 19 Feb 2020 12:45:29 +0100 Subject: add a number for esp32-s2 --- src/tusb_option.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/tusb_option.h b/src/tusb_option.h index d39dd1046..97f14532f 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -80,6 +80,8 @@ #define OPT_MCU_NUC121 800 #define OPT_MCU_NUC126 801 +#define OPT_MCU_ESP32S2 900 ///< Espressif ESP32-S2 + /** @} */ /** \defgroup group_supported_os Supported RTOS -- cgit v1.3.1 From b8ea0f0a6b11bff6a4bb3f63f09485b2445969de Mon Sep 17 00:00:00 2001 From: Chang Feng Date: Wed, 26 Feb 2020 13:07:15 +0800 Subject: Add langid support to descriptor string callback. Signed-off-by: Chang Feng --- src/device/usbd.c | 2 +- src/device/usbd.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 16670b944..68c5c5160 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -809,7 +809,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const return false; }else { - uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index); + uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex); TU_ASSERT(desc_str); // first byte of descriptor is its size diff --git a/src/device/usbd.h b/src/device/usbd.h index 847251caa..d80abf17c 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -91,7 +91,7 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index); // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const* tud_descriptor_string_cb(uint8_t index); +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); // Invoked when device is mounted (configured) TU_ATTR_WEAK void tud_mount_cb(void); -- cgit v1.3.1 From fee79d746604f671483f5872337ea366f2d2c1a2 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Mon, 2 Mar 2020 21:15:01 -0600 Subject: add CDC-ECM/RNDIS/CDC-EEM network device class with example --- .gitmodules | 5 +- examples/device/lwip_webserver/Makefile | 57 ++++ examples/device/lwip_webserver/src/arch/cc.h | 75 +++++ examples/device/lwip_webserver/src/lwipopts.h | 57 ++++ examples/device/lwip_webserver/src/main.c | 214 +++++++++++++ examples/device/lwip_webserver/src/tusb_config.h | 90 ++++++ .../device/lwip_webserver/src/usb_descriptors.c | 199 ++++++++++++ .../device/lwip_webserver/src/usb_descriptors.h | 28 ++ examples/rules.mk | 1 + lib/lwip | 1 + lib/networking/dhserver.c | 347 +++++++++++++++++++++ lib/networking/dhserver.h | 63 ++++ lib/networking/dnserver.c | 200 ++++++++++++ lib/networking/dnserver.h | 47 +++ lib/networking/ndis.h | 266 ++++++++++++++++ lib/networking/rndis_protocol.h | 307 ++++++++++++++++++ lib/networking/rndis_reports.c | 303 ++++++++++++++++++ src/class/net/net_device.c | 345 ++++++++++++++++++++ src/class/net/net_device.h | 84 +++++ src/device/usbd.c | 18 ++ src/device/usbd.h | 84 +++++ src/tusb.h | 4 + src/tusb_option.h | 12 + 23 files changed, 2806 insertions(+), 1 deletion(-) create mode 100644 examples/device/lwip_webserver/Makefile create mode 100644 examples/device/lwip_webserver/src/arch/cc.h create mode 100644 examples/device/lwip_webserver/src/lwipopts.h create mode 100644 examples/device/lwip_webserver/src/main.c create mode 100644 examples/device/lwip_webserver/src/tusb_config.h create mode 100644 examples/device/lwip_webserver/src/usb_descriptors.c create mode 100644 examples/device/lwip_webserver/src/usb_descriptors.h create mode 160000 lib/lwip create mode 100644 lib/networking/dhserver.c create mode 100644 lib/networking/dhserver.h create mode 100644 lib/networking/dnserver.c create mode 100644 lib/networking/dnserver.h create mode 100644 lib/networking/ndis.h create mode 100644 lib/networking/rndis_protocol.h create mode 100644 lib/networking/rndis_reports.c create mode 100644 src/class/net/net_device.c create mode 100644 src/class/net/net_device.h (limited to 'src') diff --git a/.gitmodules b/.gitmodules index 18b627bcf..0dda17d64 100644 --- a/.gitmodules +++ b/.gitmodules @@ -21,4 +21,7 @@ url = https://github.com/hathach/microchip_driver.git [submodule "hw/mcu/nuvoton"] path = hw/mcu/nuvoton - url = https://github.com/majbthrd/nuc_driver.git \ No newline at end of file + url = https://github.com/majbthrd/nuc_driver.git +[submodule "lib/lwip"] + path = lib/lwip + url = https://git.savannah.nongnu.org/git/lwip.git diff --git a/examples/device/lwip_webserver/Makefile b/examples/device/lwip_webserver/Makefile new file mode 100644 index 000000000..a153c30be --- /dev/null +++ b/examples/device/lwip_webserver/Makefile @@ -0,0 +1,57 @@ +include ../../../tools/top.mk +include ../../make.mk + +CFLAGS += \ + -DPBUF_POOL_SIZE=2 \ + -DTCP_WND=2*TCP_MSS \ + -DHTTPD_USE_CUSTOM_FSDATA=0 + +INC += \ + src \ + $(TOP)/hw \ + $(TOP)/lib/lwip/src/include \ + $(TOP)/lib/lwip/src/include/ipv4 \ + $(TOP)/lib/lwip/src/include/lwip/apps \ + $(TOP)/lib/networking + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += \ + lib/lwip/src/core/altcp.c \ + lib/lwip/src/core/altcp_alloc.c \ + lib/lwip/src/core/altcp_tcp.c \ + lib/lwip/src/core/def.c \ + lib/lwip/src/core/dns.c \ + lib/lwip/src/core/inet_chksum.c \ + lib/lwip/src/core/init.c \ + lib/lwip/src/core/ip.c \ + lib/lwip/src/core/mem.c \ + lib/lwip/src/core/memp.c \ + lib/lwip/src/core/netif.c \ + lib/lwip/src/core/pbuf.c \ + lib/lwip/src/core/raw.c \ + lib/lwip/src/core/stats.c \ + lib/lwip/src/core/sys.c \ + lib/lwip/src/core/tcp.c \ + lib/lwip/src/core/tcp_in.c \ + lib/lwip/src/core/tcp_out.c \ + lib/lwip/src/core/timeouts.c \ + lib/lwip/src/core/udp.c \ + lib/lwip/src/core/ipv4/autoip.c \ + lib/lwip/src/core/ipv4/dhcp.c \ + lib/lwip/src/core/ipv4/etharp.c \ + lib/lwip/src/core/ipv4/icmp.c \ + lib/lwip/src/core/ipv4/igmp.c \ + lib/lwip/src/core/ipv4/ip4.c \ + lib/lwip/src/core/ipv4/ip4_addr.c \ + lib/lwip/src/core/ipv4/ip4_frag.c \ + lib/lwip/src/netif/ethernet.c \ + lib/lwip/src/netif/slipif.c \ + lib/lwip/src/apps/http/httpd.c \ + lib/lwip/src/apps/http/fs.c \ + lib/networking/dhserver.c \ + lib/networking/dnserver.c \ + lib/networking/rndis_reports.c + +include ../../rules.mk diff --git a/examples/device/lwip_webserver/src/arch/cc.h b/examples/device/lwip_webserver/src/arch/cc.h new file mode 100644 index 000000000..56a0cacf7 --- /dev/null +++ b/examples/device/lwip_webserver/src/arch/cc.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CC_H__ +#define __CC_H__ + +//#include "cpu.h" + +typedef int sys_prot_t; + + + +/* define compiler specific symbols */ +#if defined (__ICCARM__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_USE_INCLUDES + +#elif defined (__CC_ARM) + +#define PACK_STRUCT_BEGIN __packed +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__GNUC__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__TASKING__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#endif + +#define LWIP_PLATFORM_ASSERT(x) do { if(!(x)) while(1); } while(0) + +#endif /* __CC_H__ */ diff --git a/examples/device/lwip_webserver/src/lwipopts.h b/examples/device/lwip_webserver/src/lwipopts.h new file mode 100644 index 000000000..23319592d --- /dev/null +++ b/examples/device/lwip_webserver/src/lwipopts.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ +#define NO_SYS 1 +#define MEM_ALIGNMENT 4 +#define LWIP_RAW 1 +#define LWIP_NETCONN 0 +#define LWIP_SOCKET 0 +#define LWIP_DHCP 0 +#define LWIP_ICMP 1 +#define LWIP_UDP 1 +#define LWIP_TCP 1 +#define ETH_PAD_SIZE 0 +#define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67)) + +#define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/) +#define TCP_SND_BUF (2 * TCP_MSS) + +#define ETHARP_SUPPORT_STATIC_ENTRIES 1 + +#define LWIP_HTTPD_CGI 0 +#define LWIP_HTTPD_SSI 0 +#define LWIP_HTTPD_SSI_INCLUDE_TAG 0 + +#endif /* __LWIPOPTS_H__ */ diff --git a/examples/device/lwip_webserver/src/main.c b/examples/device/lwip_webserver/src/main.c new file mode 100644 index 000000000..364a26788 --- /dev/null +++ b/examples/device/lwip_webserver/src/main.c @@ -0,0 +1,214 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Peter Lawrence + * + * influenced by lrndis https://github.com/fetisov/lrndis + * + * 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. + * + */ + +/* +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 + +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. + +The MCU appears to the host as IP address 192.168.7.1, and provides a DHCP server, DNS server, and web server. +*/ + +#include "bsp/board.h" +#include "tusb.h" + +#include "dhserver.h" +#include "dnserver.h" +#include "lwip/init.h" +#include "httpd.h" + +/* lwip context */ +static struct netif netif_data; + +/* shared between network_recv_callback() and service_traffic() */ +static struct pbuf *received_frame; + +/* this is used by this code, ./class/net/net_driver.c, and usb_descriptors.c */ +/* ideally speaking, this should be generated from the hardware's unique ID (if available) */ +const uint8_t network_mac_address[6] = {0x20,0x89,0x84,0x6A,0x96,0x00}; + +/* network parameters of this MCU */ +static const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, 7, 1); +static const ip_addr_t netmask = IPADDR4_INIT_BYTES(255, 255, 255, 0); +static const ip_addr_t gateway = IPADDR4_INIT_BYTES(0, 0, 0, 0); + +/* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ +static dhcp_entry_t entries[] = +{ + /* mac ip address subnet mask lease time */ + { {0}, {192, 168, 7, 2}, {255, 255, 255, 0}, 24 * 60 * 60 }, + { {0}, {192, 168, 7, 3}, {255, 255, 255, 0}, 24 * 60 * 60 }, + { {0}, {192, 168, 7, 4}, {255, 255, 255, 0}, 24 * 60 * 60 } +}; + +/* DHCP configuration parameters, leveraging "entries" above */ +static const dhcp_config_t dhcp_config = +{ + {192, 168, 7, 1}, 67, /* server address (self), port */ + {192, 168, 7, 1}, /* dns server (self) */ + "usb", /* dns suffix */ + TU_ARRAY_SIZE(entries), /* number of entries */ + entries /* pointer to entries */ +}; + +static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) +{ + (void)netif; + + for (;;) + { + /* if TinyUSB isn't ready, we must signal back to lwip that there is nothing we can do */ + if (!tud_ready()) + return ERR_USE; + + /* if the network driver can accept another packet, we make it happen */ + if (network_can_xmit()) + { + network_xmit(p); + return ERR_OK; + } + + /* transfer execution to TinyUSB in the hopes that it will finish transmitting the prior packet */ + tud_task(); + } +} + +static err_t output_fn(struct netif *netif, struct pbuf *p, const ip_addr_t *addr) +{ + return etharp_output(netif, p, addr); +} + +static err_t netif_init_cb(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + netif->mtu = CFG_TUD_NET_MTU; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; + netif->state = NULL; + netif->name[0] = 'E'; + netif->name[1] = 'X'; + netif->linkoutput = linkoutput_fn; + netif->output = output_fn; + return ERR_OK; +} + +static void init_lwip(void) +{ + struct netif *netif = &netif_data; + + lwip_init(); + netif->hwaddr_len = sizeof(network_mac_address); + memcpy(netif->hwaddr, network_mac_address, sizeof(network_mac_address)); + + netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); + netif_set_default(netif); +} + +/* handle any DNS requests from dns-server */ +bool dns_query_proc(const char *name, ip_addr_t *addr) +{ + if (0 == strcmp(name, "tiny.usb")) + { + *addr = ipaddr; + return true; + } + return false; +} + +bool network_recv_callback(struct pbuf *p) +{ + /* this shouldn't happen, but if we get another packet before + parsing the previous, we must signal our inability to accept it */ + if (received_frame) return false; + + /* store away the pointer for service_traffic() to later handle */ + received_frame = p; + return true; +} + +static void service_traffic(void) +{ + /* handle any packet received by network_recv_callback() */ + if (received_frame) + { + ethernet_input(received_frame, &netif_data); + pbuf_free(received_frame); + received_frame = NULL; + network_recv_renew(); + } +} + +void network_init_callback(void) +{ + /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ + if (received_frame) + { + pbuf_free(received_frame); + received_frame = NULL; + } +} + +int main(void) +{ + /* initialize TinyUSB */ + board_init(); + tusb_init(); + + /* initialize lwip, dhcp-server, dns-server, and http */ + init_lwip(); + while (!netif_is_up(&netif_data)); + while (dhserv_init(&dhcp_config) != ERR_OK); + while (dnserv_init(&ipaddr, 53, dns_query_proc) != ERR_OK); + httpd_init(); + + while (1) + { + tud_task(); + service_traffic(); + } + + return 0; +} + +/* lwip has provision for using a mutex, when applicable */ +sys_prot_t sys_arch_protect(void) +{ + return 0; +} +void sys_arch_unprotect(sys_prot_t pval) +{ + (void)pval; +} + +/* lwip needs a millisecond time source, and the TinyUSB board support code has one available */ +uint32_t sys_now(void) +{ + return board_millis(); +} diff --git a/examples/device/lwip_webserver/src/tusb_config.h b/examples/device/lwip_webserver/src/tusb_config.h new file mode 100644 index 000000000..329fc80b9 --- /dev/null +++ b/examples/device/lwip_webserver/src/tusb_config.h @@ -0,0 +1,90 @@ +/* + * 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 _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU + #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 +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#else +#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 +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#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 + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/lwip_webserver/src/usb_descriptors.c b/examples/device/lwip_webserver/src/usb_descriptors.c new file mode 100644 index 000000000..803c99c02 --- /dev/null +++ b/examples/device/lwip_webserver/src/usb_descriptors.c @@ -0,0 +1,199 @@ +/* + * 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. + * + */ + +#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] + */ +#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) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) | _PID_MAP(NET, 5) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + + .bDeviceClass = TUSB_CLASS_UNSPECIFIED, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ +enum +{ + ITF_NUM_CDC = 0, + ITF_NUM_CDC_DATA, + ITF_NUM_TOTAL +}; + +enum +{ + STR_LANGID = 0, + STR_MANUFACTURER, + STR_PRODUCT, + STR_ITFNAME, + STR_MAC, +}; + +#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 + +#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 ... + #define EPNUM_CDC 2 +#else + #define EPNUM_CDC 2 +#endif + +uint8_t const desc_configuration[] = +{ + // Interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, 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, STR_ITFNAME, STR_MAC, 0x81, 8, 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, STR_ITFNAME, 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, STR_ITFNAME, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE), +#endif +}; + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// 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; +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + [STR_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409) + [STR_MANUFACTURER] = "TinyUSB", // Manufacturer + [STR_PRODUCT] = "TinyUSB Device", // Product + [STR_ITFNAME] = // CDC-ECM Interface +#if CFG_TUD_NET == OPT_NET_ECM + "TinyUSB CDC-ECM", +#elif CFG_TUD_NET == OPT_NET_RNDIS + "TinyUSB RNDIS", +#elif CFG_TUD_NET == OPT_NET_EEM + "TinyUSB CDC-EEM", +#endif +}; + +static uint16_t _desc_str[32]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void)langid; + + unsigned chr_count = 0; + + if (STR_LANGID == index) + { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + } + else if (STR_MAC == index) + { + // Convert MAC address into UTF-16 + + for (unsigned i=0; i> 4) & 0xf]; + _desc_str[1+chr_count++] = "0123456789ABCDEF"[(network_mac_address[i] >> 0) & 0xf]; + } + } + else + { + // Convert ASCII string into UTF-16 + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + if ( chr_count > (TU_ARRAY_SIZE(_desc_str) - 1)) chr_count = TU_ARRAY_SIZE(_desc_str) - 1; + + for (unsigned i=0; i + * + * 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. + */ + +#include "dhserver.h" + +/* DHCP message type */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +/* DHCP options */ +enum DHCP_OPTIONS +{ + DHCP_PAD = 0, + DHCP_SUBNETMASK = 1, + DHCP_ROUTER = 3, + DHCP_DNSSERVER = 6, + DHCP_HOSTNAME = 12, + DHCP_DNSDOMAIN = 15, + DHCP_MTU = 26, + DHCP_BROADCAST = 28, + DHCP_PERFORMROUTERDISC = 31, + DHCP_STATICROUTE = 33, + DHCP_NISDOMAIN = 40, + DHCP_NISSERVER = 41, + DHCP_NTPSERVER = 42, + DHCP_VENDOR = 43, + DHCP_IPADDRESS = 50, + DHCP_LEASETIME = 51, + DHCP_OPTIONSOVERLOADED = 52, + DHCP_MESSAGETYPE = 53, + DHCP_SERVERID = 54, + DHCP_PARAMETERREQUESTLIST = 55, + DHCP_MESSAGE = 56, + DHCP_MAXMESSAGESIZE = 57, + DHCP_RENEWALTIME = 58, + DHCP_REBINDTIME = 59, + DHCP_CLASSID = 60, + DHCP_CLIENTID = 61, + DHCP_USERCLASS = 77, /* RFC 3004 */ + DHCP_FQDN = 81, + DHCP_DNSSEARCH = 119, /* RFC 3397 */ + DHCP_CSR = 121, /* RFC 3442 */ + DHCP_MSCSR = 249, /* MS code for RFC 3442 */ + DHCP_END = 255 +}; + +typedef struct +{ + uint8_t dp_op; /* packet opcode type */ + uint8_t dp_htype; /* hardware addr type */ + uint8_t dp_hlen; /* hardware addr length */ + uint8_t dp_hops; /* gateway hops */ + uint32_t dp_xid; /* transaction ID */ + uint16_t dp_secs; /* seconds since boot began */ + uint16_t dp_flags; + uint8_t dp_ciaddr[4]; /* client IP address */ + uint8_t dp_yiaddr[4]; /* 'your' IP address */ + uint8_t dp_siaddr[4]; /* server IP address */ + uint8_t dp_giaddr[4]; /* gateway IP address */ + uint8_t dp_chaddr[16]; /* client hardware address */ + uint8_t dp_legacy[192]; + uint8_t dp_magic[4]; + uint8_t dp_options[275]; /* options area */ +} DHCP_TYPE; + +DHCP_TYPE dhcp_data; +static struct udp_pcb *pcb = NULL; +static const dhcp_config_t *config = NULL; + +char magic_cookie[] = {0x63,0x82,0x53,0x63}; + +static uint32_t get_ip(const uint8_t *pnt) +{ + uint32_t result; + memcpy(&result, pnt, sizeof(result)); + return result; +} + +static void set_ip(uint8_t *pnt, uint32_t value) +{ + memcpy(pnt, &value, sizeof(value)); +} + +static dhcp_entry_t *entry_by_ip(uint32_t ip) +{ + int i; + for (i = 0; i < config->num_entry; i++) + if (get_ip(config->entries[i].addr) == ip) + return &config->entries[i]; + return NULL; +} + +static dhcp_entry_t *entry_by_mac(uint8_t *mac) +{ + int i; + for (i = 0; i < config->num_entry; i++) + if (memcmp(config->entries[i].mac, mac, 6) == 0) + return &config->entries[i]; + return NULL; +} + +static __inline bool is_vacant(dhcp_entry_t *entry) +{ + return memcmp("\0\0\0\0\0", entry->mac, 6) == 0; +} + +static dhcp_entry_t *vacant_address(void) +{ + int i; + for (i = 0; i < config->num_entry; i++) + if (is_vacant(config->entries + i)) + return config->entries + i; + return NULL; +} + +static __inline void free_entry(dhcp_entry_t *entry) +{ + memset(entry->mac, 0, 6); +} + +uint8_t *find_dhcp_option(uint8_t *attrs, int size, uint8_t attr) +{ + int i = 0; + while ((i + 1) < size) + { + int next = i + attrs[i + 1] + 2; + if (next > size) return NULL; + if (attrs[i] == attr) + return attrs + i; + i = next; + } + return NULL; +} + +int fill_options(void *dest, + uint8_t msg_type, + const char *domain, + uint32_t dns, + int lease_time, + uint32_t serverid, + uint32_t router, + uint32_t subnet) +{ + uint8_t *ptr = (uint8_t *)dest; + /* ACK message type */ + *ptr++ = 53; + *ptr++ = 1; + *ptr++ = msg_type; + + /* dhcp server identifier */ + *ptr++ = DHCP_SERVERID; + *ptr++ = 4; + set_ip(ptr, serverid); + ptr += 4; + + /* lease time */ + *ptr++ = DHCP_LEASETIME; + *ptr++ = 4; + *ptr++ = (lease_time >> 24) & 0xFF; + *ptr++ = (lease_time >> 16) & 0xFF; + *ptr++ = (lease_time >> 8) & 0xFF; + *ptr++ = (lease_time >> 0) & 0xFF; + + /* subnet mask */ + *ptr++ = DHCP_SUBNETMASK; + *ptr++ = 4; + set_ip(ptr, subnet); + ptr += 4; + + /* router */ + if (router != 0) + { + *ptr++ = DHCP_ROUTER; + *ptr++ = 4; + set_ip(ptr, router); + ptr += 4; + } + + /* domain name */ + if (domain != NULL) + { + int len = strlen(domain); + *ptr++ = DHCP_DNSDOMAIN; + *ptr++ = len; + memcpy(ptr, domain, len); + ptr += len; + } + + /* domain name server (DNS) */ + if (dns != 0) + { + *ptr++ = DHCP_DNSSERVER; + *ptr++ = 4; + set_ip(ptr, dns); + ptr += 4; + } + + /* end */ + *ptr++ = DHCP_END; + return ptr - (uint8_t *)dest; +} + +static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + uint8_t *ptr; + dhcp_entry_t *entry; + struct pbuf *pp; + + (void)arg; + (void)addr; + + unsigned n = p->len; + if (n > sizeof(dhcp_data)) n = sizeof(dhcp_data); + memcpy(&dhcp_data, p->payload, n); + switch (dhcp_data.dp_options[2]) + { + case DHCP_DISCOVER: + entry = entry_by_mac(dhcp_data.dp_chaddr); + if (entry == NULL) entry = vacant_address(); + if (entry == NULL) break; + + dhcp_data.dp_op = 2; /* reply */ + dhcp_data.dp_secs = 0; + dhcp_data.dp_flags = 0; + set_ip(dhcp_data.dp_yiaddr, get_ip(entry->addr)); + memcpy(dhcp_data.dp_magic, magic_cookie, 4); + + memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); + + fill_options(dhcp_data.dp_options, + DHCP_OFFER, + config->domain, + get_ip(config->dns), + entry->lease, + get_ip(config->addr), + get_ip(config->addr), + get_ip(entry->subnet)); + + pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); + if (pp == NULL) break; + memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); + udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); + pbuf_free(pp); + break; + + case DHCP_REQUEST: + /* 1. find requested ipaddr in option list */ + ptr = find_dhcp_option(dhcp_data.dp_options, sizeof(dhcp_data.dp_options), DHCP_IPADDRESS); + if (ptr == NULL) break; + if (ptr[1] != 4) break; + ptr += 2; + + /* 2. does hw-address registered? */ + entry = entry_by_mac(dhcp_data.dp_chaddr); + if (entry != NULL) free_entry(entry); + + /* 3. find requested ipaddr */ + entry = entry_by_ip(get_ip(ptr)); + if (entry == NULL) break; + if (!is_vacant(entry)) break; + + /* 4. fill struct fields */ + memcpy(dhcp_data.dp_yiaddr, ptr, 4); + dhcp_data.dp_op = 2; /* reply */ + dhcp_data.dp_secs = 0; + dhcp_data.dp_flags = 0; + memcpy(dhcp_data.dp_magic, magic_cookie, 4); + + /* 5. fill options */ + memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); + + fill_options(dhcp_data.dp_options, + DHCP_ACK, + config->domain, + get_ip(config->dns), + entry->lease, + get_ip(config->addr), + get_ip(config->addr), + get_ip(entry->subnet)); + + /* 6. send ACK */ + pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); + if (pp == NULL) break; + memcpy(entry->mac, dhcp_data.dp_chaddr, 6); + memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); + udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); + pbuf_free(pp); + break; + + default: + break; + } + pbuf_free(p); +} + +err_t dhserv_init(const dhcp_config_t *c) +{ + err_t err; + udp_init(); + dhserv_free(); + pcb = udp_new(); + if (pcb == NULL) + return ERR_MEM; + err = udp_bind(pcb, IP_ADDR_ANY, c->port); + if (err != ERR_OK) + { + dhserv_free(); + return err; + } + udp_recv(pcb, udp_recv_proc, NULL); + config = c; + return ERR_OK; +} + +void dhserv_free(void) +{ + if (pcb == NULL) return; + udp_remove(pcb); + pcb = NULL; +} diff --git a/lib/networking/dhserver.h b/lib/networking/dhserver.h new file mode 100644 index 000000000..901f6e351 --- /dev/null +++ b/lib/networking/dhserver.h @@ -0,0 +1,63 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * 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. + */ + +/* + * version: 1.0 demo (7.02.2015) + * brief: tiny dhcp ipv4 server using lwip (pcb) + * ref: https://lists.gnu.org/archive/html/lwip-users/2012-12/msg00016.html + */ + +#ifndef DHSERVER_H +#define DHSERVER_H + +#include +#include +#include +#include +#include "lwip/err.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +typedef struct dhcp_entry +{ + uint8_t mac[6]; + uint8_t addr[4]; + uint8_t subnet[4]; + uint32_t lease; +} dhcp_entry_t; + +typedef struct dhcp_config +{ + uint8_t addr[4]; + uint16_t port; + uint8_t dns[4]; + const char *domain; + int num_entry; + dhcp_entry_t *entries; +} dhcp_config_t; + +err_t dhserv_init(const dhcp_config_t *config); +void dhserv_free(void); + +#endif /* DHSERVER_H */ diff --git a/lib/networking/dnserver.c b/lib/networking/dnserver.c new file mode 100644 index 000000000..6df0bd0c4 --- /dev/null +++ b/lib/networking/dnserver.c @@ -0,0 +1,200 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * 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. + */ + +/* + * version: 1.0 demo (7.02.2015) + * brief: tiny dns ipv4 server using lwip (pcb) + */ + +#include "dnserver.h" + +#define DNS_MAX_HOST_NAME_LEN 128 + +static struct udp_pcb *pcb = NULL; +dns_query_proc_t query_proc = NULL; + +#pragma pack(push, 1) +typedef struct +{ +#if BYTE_ORDER == LITTLE_ENDIAN + uint8_t rd: 1, /* Recursion Desired */ + tc: 1, /* Truncation Flag */ + aa: 1, /* Authoritative Answer Flag */ + opcode: 4, /* Operation code */ + qr: 1; /* Query/Response Flag */ + uint8_t rcode: 4, /* Response Code */ + z: 3, /* Zero */ + ra: 1; /* Recursion Available */ +#else + uint8_t qr: 1, /* Query/Response Flag */ + opcode: 4, /* Operation code */ + aa: 1, /* Authoritative Answer Flag */ + tc: 1, /* Truncation Flag */ + rd: 1; /* Recursion Desired */ + uint8_t ra: 1, /* Recursion Available */ + z: 3, /* Zero */ + rcode: 4; /* Response Code */ +#endif +} dns_header_flags_t; + +typedef struct +{ + uint16_t id; + dns_header_flags_t flags; + uint16_t n_record[4]; +} dns_header_t; + +typedef struct dns_answer +{ + uint16_t name; + uint16_t type; + uint16_t Class; + uint32_t ttl; + uint16_t len; + uint32_t addr; +} dns_answer_t; +#pragma pack(pop) + +typedef struct dns_query +{ + char name[DNS_MAX_HOST_NAME_LEN]; + uint16_t type; + uint16_t Class; +} dns_query_t; + +static uint16_t get_uint16(const uint8_t *pnt) +{ + uint16_t result; + memcpy(&result, pnt, sizeof(result)); + return result; +} + +static int parse_next_query(void *data, int size, dns_query_t *query) +{ + int len; + int lables; + uint8_t *ptr; + + len = 0; + lables = 0; + ptr = (uint8_t *)data; + + while (true) + { + uint8_t lable_len; + if (size <= 0) return -1; + lable_len = *ptr++; + size--; + if (lable_len == 0) break; + if (lables > 0) + { + if (len == DNS_MAX_HOST_NAME_LEN) return -2; + query->name[len++] = '.'; + } + if (lable_len > size) return -1; + if (len + lable_len >= DNS_MAX_HOST_NAME_LEN) return -2; + memcpy(&query->name[len], ptr, lable_len); + len += lable_len; + ptr += lable_len; + size -= lable_len; + lables++; + } + + if (size < 4) return -1; + query->name[len] = 0; + query->type = get_uint16(ptr); + ptr += 2; + query->Class = get_uint16(ptr); + ptr += 2; + return ptr - (uint8_t *)data; +} + +static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + int len; + dns_header_t *header; + static dns_query_t query; + struct pbuf *out; + ip_addr_t host_addr; + dns_answer_t *answer; + + (void)arg; + + if (p->len <= sizeof(dns_header_t)) goto error; + header = (dns_header_t *)p->payload; + if (header->flags.qr != 0) goto error; + if (ntohs(header->n_record[0]) != 1) goto error; + + len = parse_next_query(header + 1, p->len - sizeof(dns_header_t), &query); + if (len < 0) goto error; + if (!query_proc(query.name, &host_addr)) goto error; + + len += sizeof(dns_header_t); + out = pbuf_alloc(PBUF_TRANSPORT, len + 16, PBUF_POOL); + if (out == NULL) goto error; + + memcpy(out->payload, p->payload, len); + header = (dns_header_t *)out->payload; + header->flags.qr = 1; + header->n_record[1] = htons(1); + answer = (struct dns_answer *)((uint8_t *)out->payload + len); + answer->name = htons(0xC00C); + answer->type = htons(1); + answer->Class = htons(1); + answer->ttl = htonl(32); + answer->len = htons(4); + answer->addr = host_addr.addr; + + udp_sendto(upcb, out, addr, port); + pbuf_free(out); + +error: + pbuf_free(p); +} + +err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t qp) +{ + err_t err; + udp_init(); + dnserv_free(); + pcb = udp_new(); + if (pcb == NULL) + return ERR_MEM; + err = udp_bind(pcb, bind, port); + if (err != ERR_OK) + { + dnserv_free(); + return err; + } + udp_recv(pcb, udp_recv_proc, NULL); + query_proc = qp; + return ERR_OK; +} + +void dnserv_free() +{ + if (pcb == NULL) return; + udp_remove(pcb); + pcb = NULL; +} diff --git a/lib/networking/dnserver.h b/lib/networking/dnserver.h new file mode 100644 index 000000000..130991f5f --- /dev/null +++ b/lib/networking/dnserver.h @@ -0,0 +1,47 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * 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. + */ + +/* + * version: 1.0 demo (7.02.2015) + * brief: tiny dns ipv4 server using lwip (pcb) + */ + +#ifndef DNSERVER +#define DNSERVER + +#include +#include +#include +#include +#include "lwip/def.h" +#include "lwip/err.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +typedef bool (*dns_query_proc_t)(const char *name, ip_addr_t *addr); + +err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t query_proc); +void dnserv_free(void); + +#endif diff --git a/lib/networking/ndis.h b/lib/networking/ndis.h new file mode 100644 index 000000000..1c737574c --- /dev/null +++ b/lib/networking/ndis.h @@ -0,0 +1,266 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ndis.h *************************************************************** + * + * \brief + * This file contains the possible external configuration of the USB. + * + * \addtogroup usbstick + * + * + ******************************************************************************/ + +/** + \ingroup usbstick + \defgroup RNDIS RNDIS Support + @{ + */ + +/* + * ndis.h + * + * Modified by Colin O'Flynn + * ntddndis.h modified by Benedikt Spranger + * + * Thanks to the cygwin development team, + * espacially to Casper S. Hornstrup + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef _LINUX_NDIS_H +#define _LINUX_NDIS_H + + +#define NDIS_STATUS_MULTICAST_FULL 0xC0010009 +#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A +#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B + +/* from drivers/net/sk98lin/h/skgepnmi.h */ +#define OID_PNP_CAPABILITIES 0xFD010100 +#define OID_PNP_SET_POWER 0xFD010101 +#define OID_PNP_QUERY_POWER 0xFD010102 +#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 +#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 +#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 + +enum NDIS_DEVICE_POWER_STATE { + NdisDeviceStateUnspecified = 0, + NdisDeviceStateD0, + NdisDeviceStateD1, + NdisDeviceStateD2, + NdisDeviceStateD3, + NdisDeviceStateMaximum +}; + +struct NDIS_PM_WAKE_UP_CAPABILITIES { + enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp; + enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp; + enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp; +}; + +/* NDIS_PNP_CAPABILITIES.Flags constants */ +#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001 +#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002 +#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 + +/* +struct NDIS_PNP_CAPABILITIES { + __le32 Flags; + struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; +}; + +struct NDIS_PM_PACKET_PATTERN { + __le32 Priority; + __le32 Reserved; + __le32 MaskSize; + __le32 PatternOffset; + __le32 PatternSize; + __le32 PatternFlags; +}; +*/ + +/* Required Object IDs (OIDs) */ +#define OID_GEN_SUPPORTED_LIST 0x00010101 +#define OID_GEN_HARDWARE_STATUS 0x00010102 +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_MEDIA_IN_USE 0x00010104 +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +#define OID_GEN_LINK_SPEED 0x00010107 +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +#define OID_GEN_VENDOR_ID 0x0001010C +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +#define OID_GEN_DRIVER_VERSION 0x00010110 +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 +#define OID_GEN_MAC_OPTIONS 0x00010113 +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 +#define OID_GEN_SUPPORTED_GUIDS 0x00010117 +#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 +#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 +#define OID_GEN_MACHINE_NAME 0x0001021A +#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B +#define OID_GEN_VLAN_ID 0x0001021C + +/* Optional OIDs */ +#define OID_GEN_MEDIA_CAPABILITIES 0x00010201 +#define OID_GEN_PHYSICAL_MEDIUM 0x00010202 + +/* Required statistics OIDs */ +#define OID_GEN_XMIT_OK 0x00020101 +#define OID_GEN_RCV_OK 0x00020102 +#define OID_GEN_XMIT_ERROR 0x00020103 +#define OID_GEN_RCV_ERROR 0x00020104 +#define OID_GEN_RCV_NO_BUFFER 0x00020105 + +/* Optional statistics OIDs */ +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C +#define OID_GEN_RCV_CRC_ERROR 0x0002020D +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E +#define OID_GEN_GET_TIME_CAPS 0x0002020F +#define OID_GEN_GET_NETCARD_TIME 0x00020210 +#define OID_GEN_NETCARD_LOAD 0x00020211 +#define OID_GEN_DEVICE_PROFILE 0x00020212 +#define OID_GEN_INIT_TIME_MS 0x00020213 +#define OID_GEN_RESET_COUNTS 0x00020214 +#define OID_GEN_MEDIA_SENSE_COUNTS 0x00020215 +#define OID_GEN_FRIENDLY_NAME 0x00020216 +#define OID_GEN_MINIPORT_INFO 0x00020217 +#define OID_GEN_RESET_VERIFY_PARAMETERS 0x00020218 + +/* IEEE 802.3 (Ethernet) OIDs */ +#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 + +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +#define OID_802_3_MULTICAST_LIST 0x01010103 +#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 +#define OID_802_3_MAC_OPTIONS 0x01010105 +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 +#define OID_802_3_XMIT_DEFERRED 0x01020201 +#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define OID_802_3_RCV_OVERRUN 0x01020203 +#define OID_802_3_XMIT_UNDERRUN 0x01020204 +#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 + +/* Wireless LAN OIDs */ +/* Mandatory */ +#define OID_802_11_BSSID 0x0D010101 /* Q S */ +#define OID_802_11_SSID 0x0D010102 /* Q S */ +#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 /* Q S */ +#define OID_802_11_RSSI 0x0D010206 /* Q I */ +#define OID_802_11_BSSID_LIST 0x0D010217 /* Q */ +#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A /* S */ +#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 /* Q S */ +#define OID_802_11_SUPPORTED_RATES 0x0D01020E /* Q */ +#define OID_802_11_CONFIGURATION 0x0D010211 /* Q S */ +#define OID_802_11_ADD_WEP 0x0D010113 /* S */ +#define OID_802_11_WEP_STATUS 0x0D01011B /* Q S */ +#define OID_802_11_REMOVE_WEP 0x0D010114 /* S */ +#define OID_802_11_DISASSOCIATE 0x0D010115 /* S */ +#define OID_802_11_AUTHENTICATION_MODE 0x0D010118 /* Q S */ +#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C /* S */ + + + +/* OID_GEN_MINIPORT_INFO constants */ +#define NDIS_MINIPORT_BUS_MASTER 0x00000001 +#define NDIS_MINIPORT_WDM_DRIVER 0x00000002 +#define NDIS_MINIPORT_SG_LIST 0x00000004 +#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY 0x00000008 +#define NDIS_MINIPORT_INDICATES_PACKETS 0x00000010 +#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE 0x00000020 +#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE 0x00000040 +#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS 0x00000080 +#define NDIS_MINIPORT_INTERMEDIATE_DRIVER 0x00000100 +#define NDIS_MINIPORT_IS_NDIS_5 0x00000200 +#define NDIS_MINIPORT_IS_CO 0x00000400 +#define NDIS_MINIPORT_DESERIALIZE 0x00000800 +#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING 0x00001000 +#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE 0x00002000 +#define NDIS_MINIPORT_NETBOOT_CARD 0x00004000 +#define NDIS_MINIPORT_PM_SUPPORTED 0x00008000 +#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00010000 +#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS 0x00020000 +#define NDIS_MINIPORT_HIDDEN 0x00040000 +#define NDIS_MINIPORT_SWENUM 0x00080000 +#define NDIS_MINIPORT_SURPRISE_REMOVE_OK 0x00100000 +#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND 0x00200000 +#define NDIS_MINIPORT_HARDWARE_DEVICE 0x00400000 +#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS 0x00800000 +#define NDIS_MINIPORT_64BITS_DMA 0x01000000 + +#define NDIS_MEDIUM_802_3 0x00000000 +#define NDIS_MEDIUM_802_5 0x00000001 +#define NDIS_MEDIUM_FDDI 0x00000002 +#define NDIS_MEDIUM_WAN 0x00000003 +#define NDIS_MEDIUM_LOCAL_TALK 0x00000004 +#define NDIS_MEDIUM_DIX 0x00000005 +#define NDIS_MEDIUM_ARCENT_RAW 0x00000006 +#define NDIS_MEDIUM_ARCENT_878_2 0x00000007 +#define NDIS_MEDIUM_ATM 0x00000008 +#define NDIS_MEDIUM_WIRELESS_LAN 0x00000009 +#define NDIS_MEDIUM_IRDA 0x0000000A +#define NDIS_MEDIUM_BPC 0x0000000B +#define NDIS_MEDIUM_CO_WAN 0x0000000C +#define NDIS_MEDIUM_1394 0x0000000D + +#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 +#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 +#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 +#define NDIS_PACKET_TYPE_SMT 0x00000040 +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 +#define NDIS_PACKET_TYPE_GROUP 0x00000100 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800 + +#define NDIS_MEDIA_STATE_CONNECTED 0x00000000 +#define NDIS_MEDIA_STATE_DISCONNECTED 0x00000001 + +#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 +#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 +#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 +#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 +#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 +#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 +#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040 +#define NDIS_MAC_OPTION_RESERVED 0x80000000 + +#endif /* _LINUX_NDIS_H */ + +/** @} */ diff --git a/lib/networking/rndis_protocol.h b/lib/networking/rndis_protocol.h new file mode 100644 index 000000000..b45860eeb --- /dev/null +++ b/lib/networking/rndis_protocol.h @@ -0,0 +1,307 @@ +/** + * \file rndis_protocol.h + * RNDIS Defines + * + * \author + * Colin O'Flynn + * + * \addtogroup usbstick + */ + +/* Copyright (c) 2008 Colin O'Flynn + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of the copyright holders nor the names of + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _RNDIS_H +#define _RNDIS_H + +/** + \addtogroup RNDIS + @{ + */ + +#include + +#define RNDIS_MAJOR_VERSION 1 +#define RNDIS_MINOR_VERSION 0 + +#define RNDIS_STATUS_SUCCESS 0X00000000 +#define RNDIS_STATUS_FAILURE 0XC0000001 +#define RNDIS_STATUS_INVALID_DATA 0XC0010015 +#define RNDIS_STATUS_NOT_SUPPORTED 0XC00000BB +#define RNDIS_STATUS_MEDIA_CONNECT 0X4001000B +#define RNDIS_STATUS_MEDIA_DISCONNECT 0X4001000C + + +/* Message set for Connectionless (802.3) Devices */ +#define REMOTE_NDIS_PACKET_MSG 0x00000001 +#define REMOTE_NDIS_INITIALIZE_MSG 0X00000002 +#define REMOTE_NDIS_HALT_MSG 0X00000003 +#define REMOTE_NDIS_QUERY_MSG 0X00000004 +#define REMOTE_NDIS_SET_MSG 0X00000005 +#define REMOTE_NDIS_RESET_MSG 0X00000006 +#define REMOTE_NDIS_INDICATE_STATUS_MSG 0X00000007 +#define REMOTE_NDIS_KEEPALIVE_MSG 0X00000008 +#define REMOTE_NDIS_INITIALIZE_CMPLT 0X80000002 +#define REMOTE_NDIS_QUERY_CMPLT 0X80000004 +#define REMOTE_NDIS_SET_CMPLT 0X80000005 +#define REMOTE_NDIS_RESET_CMPLT 0X80000006 +#define REMOTE_NDIS_KEEPALIVE_CMPLT 0X80000008 + +typedef uint32_t rndis_MessageType_t; +typedef uint32_t rndis_MessageLength_t; +typedef uint32_t rndis_RequestId_t; +typedef uint32_t rndis_MajorVersion_t; +typedef uint32_t rndis_MinorVersion_t; +typedef uint32_t rndis_MaxTransferSize_t; +typedef uint32_t rndis_Status_t; + + +/* Device Flags */ +#define RNDIS_DF_CONNECTIONLESS 0x00000001 +#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002 +typedef uint32_t rndis_DeviceFlags_t; + +/* Mediums */ +#define RNDIS_MEDIUM_802_3 0x00000000 +typedef uint32_t rndis_Medium_t; + + +typedef uint32_t rndis_MaxPacketsPerTransfer_t; +typedef uint32_t rndis_PacketAlignmentFactor_t; +typedef uint32_t rndis_AfListOffset_t; +typedef uint32_t rndis_AfListSize_t; + +/*** Remote NDIS Generic Message type ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + } rndis_generic_msg_t; + + +/*** Remote NDIS Initialize Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_MajorVersion_t MajorVersion; + rndis_MinorVersion_t MinorVersion; + rndis_MaxTransferSize_t MaxTransferSize; + } rndis_initialize_msg_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + rndis_MajorVersion_t MajorVersion; + rndis_MinorVersion_t MinorVersion; + rndis_DeviceFlags_t DeviceFlags; + rndis_Medium_t Medium; + rndis_MaxPacketsPerTransfer_t MaxPacketsPerTransfer; + rndis_MaxTransferSize_t MaxTransferSize; + rndis_PacketAlignmentFactor_t PacketAlignmentFactor; + rndis_AfListOffset_t AfListOffset; + rndis_AfListSize_t AfListSize; + } rndis_initialize_cmplt_t; + + +/*** Remote NDIS Halt Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + } rndis_halt_msg_t; + +typedef uint32_t rndis_Oid_t; +typedef uint32_t rndis_InformationBufferLength_t; +typedef uint32_t rndis_InformationBufferOffset_t; +typedef uint32_t rndis_DeviceVcHandle_t; + +/*** Remote NDIS Query Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Oid_t Oid; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + rndis_DeviceVcHandle_t DeviceVcHandle; + } rndis_query_msg_t; + +/* Response: */ + +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + } rndis_query_cmplt_t; + +/*** Remote NDIS Set Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Oid_t Oid; + rndis_InformationBufferLength_t InformationBufferLength; + rndis_InformationBufferOffset_t InformationBufferOffset; + rndis_DeviceVcHandle_t DeviceVcHandle; + } rndis_set_msg_t; + +/* Response */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + }rndis_set_cmplt_t; + +/* Information buffer layout for OID_GEN_RNDIS_CONFIG_PARAMETER */ +typedef uint32_t rndis_ParameterNameOffset_t; +typedef uint32_t rndis_ParameterNameLength_t; +typedef uint32_t rndis_ParameterType_t; +typedef uint32_t rndis_ParameterValueOffset_t; +typedef uint32_t rndis_ParameterValueLength_t; + +#define PARAMETER_TYPE_STRING 2 +#define PARAMETER_TYPE_NUMERICAL 0 + +typedef struct{ + rndis_ParameterNameOffset_t ParameterNameOffset; + rndis_ParameterNameLength_t ParameterNameLength; + rndis_ParameterType_t ParameterType; + rndis_ParameterValueOffset_t ParameterValueOffset; + rndis_ParameterValueLength_t ParameterValueLength; + }rndis_config_parameter_t; + +typedef uint32_t rndis_Reserved_t; + +/*** Remote NDIS Soft Reset Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Reserved_t Reserved; + } rndis_reset_msg_t; + +typedef uint32_t rndis_AddressingReset_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Status_t Status; + rndis_AddressingReset_t AddressingReset; + } rndis_reset_cmplt_t; + +/*** Remote NDIS Indicate Status Message ***/ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_Status_t Status; + rndis_Status_t StatusBufferLength; + rndis_Status_t StatusBufferOffset; + } rndis_indicate_status_t; + +typedef uint32_t rndis_DiagStatus_t; +typedef uint32_t rndis_ErrorOffset_t; + +typedef struct { + rndis_DiagStatus_t DiagStatus; + rndis_ErrorOffset_t ErrorOffset; + }rndis_diagnostic_info_t; + +/*** Remote NDIS Keepalive Message */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + }rndis_keepalive_msg_t; + +/* Response: */ +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_RequestId_t RequestId; + rndis_Status_t Status; + }rndis_keepalive_cmplt_t; + +/*** Remote NDIS Data Packet ***/ + +typedef uint32_t rndis_DataOffset_t; +typedef uint32_t rndis_DataLength_t; +typedef uint32_t rndis_OOBDataOffset_t; +typedef uint32_t rndis_OOBDataLength_t; +typedef uint32_t rndis_NumOOBDataElements_t; +typedef uint32_t rndis_PerPacketInfoOffset_t; +typedef uint32_t rndis_PerPacketInfoLength_t; + +typedef struct{ + rndis_MessageType_t MessageType; + rndis_MessageLength_t MessageLength; + rndis_DataOffset_t DataOffset; + rndis_DataLength_t DataLength; + rndis_OOBDataOffset_t OOBDataOffset; + rndis_OOBDataLength_t OOBDataLength; + rndis_NumOOBDataElements_t NumOOBDataElements; + rndis_PerPacketInfoOffset_t PerPacketInfoOffset; + rndis_PerPacketInfoLength_t PerPacketInfoLength; + rndis_DeviceVcHandle_t DeviceVcHandle; + rndis_Reserved_t Reserved; + }rndis_data_packet_t; + +typedef uint32_t rndis_ClassInformationOffset_t; +typedef uint32_t rndis_Size_t; +typedef uint32_t rndis_Type_t; + +typedef struct{ + rndis_Size_t Size; + rndis_Type_t Type; + rndis_ClassInformationOffset_t ClassInformationType; + }rndis_OOB_packet_t; + +#include "ndis.h" + +typedef enum rnids_state_e { + rndis_uninitialized, + rndis_initialized, + rndis_data_initialized + } rndis_state_t; + +typedef struct { + uint32_t txok; + uint32_t rxok; + uint32_t txbad; + uint32_t rxbad; +} usb_eth_stat_t; + +#endif /* _RNDIS_H */ + +/** @} */ diff --git a/lib/networking/rndis_reports.c b/lib/networking/rndis_reports.c new file mode 100644 index 000000000..535bdf851 --- /dev/null +++ b/lib/networking/rndis_reports.c @@ -0,0 +1,303 @@ +/* + The original version of this code was lrndis/usbd_rndis_core.c from https://github.com/fetisov/lrndis + It has since been overhauled to suit this application +*/ + +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 by Sergey Fetisov + * + * 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. + */ + +#include +#include +#include "class/net/net_device.h" +#include "rndis_protocol.h" +#include "netif/ethernet.h" + +#define RNDIS_LINK_SPEED 12000000 /* Link baudrate (12Mbit/s for USB-FS) */ +#define RNDIS_VENDOR "TinyUSB" /* NIC vendor name */ + +static const uint8_t *const station_hwaddr = network_mac_address; +static const uint8_t *const permanent_hwaddr = network_mac_address; + +static usb_eth_stat_t usb_eth_stat = { 0, 0, 0, 0 }; +static uint32_t oid_packet_filter = 0x0000000; +static rndis_state_t rndis_state; + +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t ndis_report[8] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + +static const uint32_t OIDSupportedList[] = +{ + OID_GEN_SUPPORTED_LIST, + OID_GEN_HARDWARE_STATUS, + OID_GEN_MEDIA_SUPPORTED, + OID_GEN_MEDIA_IN_USE, + OID_GEN_MAXIMUM_FRAME_SIZE, + OID_GEN_LINK_SPEED, + OID_GEN_TRANSMIT_BLOCK_SIZE, + OID_GEN_RECEIVE_BLOCK_SIZE, + OID_GEN_VENDOR_ID, + OID_GEN_VENDOR_DESCRIPTION, + OID_GEN_VENDOR_DRIVER_VERSION, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_PROTOCOL_OPTIONS, + OID_GEN_MAC_OPTIONS, + OID_GEN_MEDIA_CONNECT_STATUS, + OID_GEN_MAXIMUM_SEND_PACKETS, + OID_802_3_PERMANENT_ADDRESS, + OID_802_3_CURRENT_ADDRESS, + OID_802_3_MULTICAST_LIST, + OID_802_3_MAXIMUM_LIST_SIZE, + OID_802_3_MAC_OPTIONS +}; + +#define OID_LIST_LENGTH TU_ARRAY_SIZE(OIDSupportedList) +#define ENC_BUF_SIZE (OID_LIST_LENGTH * 4 + 32) + +static uint8_t *encapsulated_buffer; + +static void rndis_report(void) +{ + netd_report(ndis_report, sizeof(ndis_report)); +} + +static void rndis_query_cmplt32(int status, uint32_t data) +{ + rndis_query_cmplt_t *c; + c = (rndis_query_cmplt_t *)encapsulated_buffer; + c->MessageType = REMOTE_NDIS_QUERY_CMPLT; + c->MessageLength = sizeof(rndis_query_cmplt_t) + 4; + c->InformationBufferLength = 4; + c->InformationBufferOffset = 16; + c->Status = status; + memcpy(c + 1, &data, sizeof(data)); + rndis_report(); +} + +static void rndis_query_cmplt(int status, const void *data, int size) +{ + rndis_query_cmplt_t *c; + c = (rndis_query_cmplt_t *)encapsulated_buffer; + c->MessageType = REMOTE_NDIS_QUERY_CMPLT; + c->MessageLength = sizeof(rndis_query_cmplt_t) + size; + c->InformationBufferLength = size; + c->InformationBufferOffset = 16; + c->Status = status; + memcpy(c + 1, data, size); + rndis_report(); +} + +#define MAC_OPT NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \ + NDIS_MAC_OPTION_RECEIVE_SERIALIZED | \ + NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | \ + NDIS_MAC_OPTION_NO_LOOPBACK + +static const char *rndis_vendor = RNDIS_VENDOR; + +static void rndis_query(void) +{ + switch (((rndis_query_msg_t *)encapsulated_buffer)->Oid) + { + case OID_GEN_SUPPORTED_LIST: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, OIDSupportedList, 4 * OID_LIST_LENGTH); return; + case OID_GEN_VENDOR_DRIVER_VERSION: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0x00001000); return; + case OID_802_3_CURRENT_ADDRESS: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, &station_hwaddr, 6); return; + case OID_802_3_PERMANENT_ADDRESS: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, &permanent_hwaddr, 6); return; + case OID_GEN_MEDIA_SUPPORTED: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; + case OID_GEN_MEDIA_IN_USE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; + case OID_GEN_PHYSICAL_MEDIUM: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return; + case OID_GEN_HARDWARE_STATUS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_GEN_LINK_SPEED: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, RNDIS_LINK_SPEED / 100); return; + case OID_GEN_VENDOR_ID: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0x00FFFFFF); return; + case OID_GEN_VENDOR_DESCRIPTION: rndis_query_cmplt(RNDIS_STATUS_SUCCESS, rndis_vendor, strlen(rndis_vendor) + 1); return; + case OID_GEN_CURRENT_PACKET_FILTER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, oid_packet_filter); return; + case OID_GEN_MAXIMUM_FRAME_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU - SIZEOF_ETH_HDR); return; + case OID_GEN_MAXIMUM_TOTAL_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; + case OID_GEN_TRANSMIT_BLOCK_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; + case OID_GEN_RECEIVE_BLOCK_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, CFG_TUD_NET_MTU); return; + case OID_GEN_MEDIA_CONNECT_STATUS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, NDIS_MEDIA_STATE_CONNECTED); return; + case OID_GEN_RNDIS_CONFIG_PARAMETER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_802_3_MAXIMUM_LIST_SIZE: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 1); return; + case OID_802_3_MULTICAST_LIST: rndis_query_cmplt32(RNDIS_STATUS_NOT_SUPPORTED, 0); return; + case OID_802_3_MAC_OPTIONS: rndis_query_cmplt32(RNDIS_STATUS_NOT_SUPPORTED, 0); return; + case OID_GEN_MAC_OPTIONS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, /*MAC_OPT*/ 0); return; + case OID_802_3_RCV_ERROR_ALIGNMENT: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_802_3_XMIT_ONE_COLLISION: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_802_3_XMIT_MORE_COLLISIONS: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + case OID_GEN_XMIT_OK: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.txok); return; + case OID_GEN_RCV_OK: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.rxok); return; + case OID_GEN_RCV_ERROR: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.rxbad); return; + case OID_GEN_XMIT_ERROR: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, usb_eth_stat.txbad); return; + case OID_GEN_RCV_NO_BUFFER: rndis_query_cmplt32(RNDIS_STATUS_SUCCESS, 0); return; + default: rndis_query_cmplt(RNDIS_STATUS_FAILURE, NULL, 0); return; + } +} + +#define INFBUF ((uint32_t *)((uint8_t *)&(m->RequestId) + m->InformationBufferOffset)) + +static void rndis_handle_config_parm(const char *data, int keyoffset, int valoffset, int keylen, int vallen) +{ + (void)data; + (void)keyoffset; + (void)valoffset; + (void)keylen; + (void)vallen; +} + +static void rndis_packetFilter(uint32_t newfilter) +{ + (void)newfilter; +} + +static void rndis_handle_set_msg(void) +{ + rndis_set_cmplt_t *c; + rndis_set_msg_t *m; + rndis_Oid_t oid; + + c = (rndis_set_cmplt_t *)encapsulated_buffer; + m = (rndis_set_msg_t *)encapsulated_buffer; + + oid = m->Oid; + c->MessageType = REMOTE_NDIS_SET_CMPLT; + c->MessageLength = sizeof(rndis_set_cmplt_t); + c->Status = RNDIS_STATUS_SUCCESS; + + switch (oid) + { + /* Parameters set up in 'Advanced' tab */ + case OID_GEN_RNDIS_CONFIG_PARAMETER: + { + rndis_config_parameter_t *p; + char *ptr = (char *)m; + ptr += sizeof(rndis_generic_msg_t); + ptr += m->InformationBufferOffset; + p = (rndis_config_parameter_t *)ptr; + rndis_handle_config_parm(ptr, p->ParameterNameOffset, p->ParameterValueOffset, p->ParameterNameLength, p->ParameterValueLength); + } + break; + + /* Mandatory general OIDs */ + case OID_GEN_CURRENT_PACKET_FILTER: + oid_packet_filter = *INFBUF; + if (oid_packet_filter) + { + rndis_packetFilter(oid_packet_filter); + rndis_state = rndis_data_initialized; + } + else + { + rndis_state = rndis_initialized; + } + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + break; + + case OID_GEN_PROTOCOL_OPTIONS: + break; + + /* Mandatory 802_3 OIDs */ + case OID_802_3_MULTICAST_LIST: + break; + + /* Power Managment: fails for now */ + case OID_PNP_ADD_WAKE_UP_PATTERN: + case OID_PNP_REMOVE_WAKE_UP_PATTERN: + case OID_PNP_ENABLE_WAKE_UP: + default: + c->Status = RNDIS_STATUS_FAILURE; + break; + } + + /* c->MessageID is same as before */ + rndis_report(); + return; +} + +void rndis_class_set_handler(uint8_t *data, int size) +{ + encapsulated_buffer = data; + (void)size; + + switch (((rndis_generic_msg_t *)data)->MessageType) + { + case REMOTE_NDIS_INITIALIZE_MSG: + { + rndis_initialize_cmplt_t *m; + m = ((rndis_initialize_cmplt_t *)encapsulated_buffer); + /* m->MessageID is same as before */ + m->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT; + m->MessageLength = sizeof(rndis_initialize_cmplt_t); + m->MajorVersion = RNDIS_MAJOR_VERSION; + m->MinorVersion = RNDIS_MINOR_VERSION; + m->Status = RNDIS_STATUS_SUCCESS; + m->DeviceFlags = RNDIS_DF_CONNECTIONLESS; + m->Medium = RNDIS_MEDIUM_802_3; + m->MaxPacketsPerTransfer = 1; + m->MaxTransferSize = CFG_TUD_NET_MTU + sizeof(rndis_data_packet_t); + m->PacketAlignmentFactor = 0; + m->AfListOffset = 0; + m->AfListSize = 0; + rndis_state = rndis_initialized; + rndis_report(); + } + break; + + case REMOTE_NDIS_QUERY_MSG: + rndis_query(); + break; + + case REMOTE_NDIS_SET_MSG: + rndis_handle_set_msg(); + break; + + case REMOTE_NDIS_RESET_MSG: + { + rndis_reset_cmplt_t * m; + m = ((rndis_reset_cmplt_t *)encapsulated_buffer); + rndis_state = rndis_uninitialized; + m->MessageType = REMOTE_NDIS_RESET_CMPLT; + m->MessageLength = sizeof(rndis_reset_cmplt_t); + m->Status = RNDIS_STATUS_SUCCESS; + m->AddressingReset = 1; /* Make it look like we did something */ + /* m->AddressingReset = 0; - Windows halts if set to 1 for some reason */ + rndis_report(); + } + break; + + case REMOTE_NDIS_KEEPALIVE_MSG: + { + rndis_keepalive_cmplt_t * m; + m = (rndis_keepalive_cmplt_t *)encapsulated_buffer; + m->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT; + m->MessageLength = sizeof(rndis_keepalive_cmplt_t); + m->Status = RNDIS_STATUS_SUCCESS; + } + /* We have data to send back */ + rndis_report(); + break; + + default: + break; + } +} diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c new file mode 100644 index 000000000..422d435c6 --- /dev/null +++ b/src/class/net/net_device.c @@ -0,0 +1,345 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Peter Lawrence + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if ( TUSB_OPT_DEVICE_ENABLED && (CFG_TUD_NET != OPT_NET_NONE) ) + +#include "net_device.h" +#include "device/usbd_pvt.h" +#include "rndis_protocol.h" + +void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */ + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t itf_num; + uint8_t ep_notif; + uint8_t ep_in; + uint8_t ep_out; +} 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 + +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_RNDIS + CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t rndis_buf[128]; +#endif + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION static netd_interface_t _netd_itf; + +static bool can_xmit; + +void network_recv_renew(void) +{ + usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_out, received, sizeof(received)); +} + +static void do_in_xfer(uint8_t *buf, uint16_t len) +{ + can_xmit = false; + usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_in, buf, len); +} + +void netd_report(uint8_t *buf, uint16_t len) +{ + usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, buf, len); +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void netd_init(void) +{ + tu_memclr(&_netd_itf, sizeof(_netd_itf)); +} + +void netd_reset(uint8_t rhport) +{ + (void) rhport; + + netd_init(); +} + +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); + + // confirm interface hasn't already been allocated + TU_ASSERT(0 == _netd_itf.ep_in); + + //------------- first 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); + +#if CFG_TUD_NET != OPT_NET_EEM + // Communication Functional Descriptors + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) + { + (*p_length) += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + // notification endpoint (if any) + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) + { + TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + + _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + + (*p_length) += p_desc[DESC_OFFSET_LEN]; + 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 + + if (TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + { + // Open endpoint pair + 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); + } + + network_init_callback(); + + // we are ready to transmit a packet + can_xmit = true; + + // prepare for incoming packets + network_recv_renew(); + + return true; +} + +// Invoked when class request DATA stage is finished. +// return false to stall control endpoint (e.g Host send nonsense DATA) +bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (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) + { + rndis_class_set_handler(rndis_buf, request->wLength); + } +#endif + + return true; +} + +// 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); + + TU_VERIFY (_netd_itf.itf_num == request->wIndex); + +#if CFG_TUD_NET == OPT_NET_RNDIS + 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) + { + /* EEM Control Packet: discard it */ + network_recv_renew(); + } + else + { + /* EEM Data Packet */ + pnt += CFG_TUD_NET_PACKET_PREFIX_LEN; + size = hdr->length - 4; /* discard the unused CRC-32 */ + } +#endif + + 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 = network_recv_callback(p); + } + + if (!p || !accepted) + { + /* if a buffer couldn't be allocated or accepted by the callback, we must discard this packet */ + network_recv_renew(); + } + } +} + +bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) rhport; + (void) result; + + /* new packet received */ + if ( ep_addr == _netd_itf.ep_out ) + { + handle_incoming_packet(xferred_bytes); + } + + /* data transmission finished */ + if ( ep_addr == _netd_itf.ep_in ) + { + /* TinyUSB requires the class driver to implement ZLP (since ZLP usage is class-specific) */ + + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_NET_ENDPOINT_SIZE)) ) + { + do_in_xfer(NULL, 0); /* a ZLP is needed */ + } + else + { + /* we're finally finished */ + can_xmit = true; + } + } + + return true; +} + +bool network_can_xmit(void) +{ + return can_xmit; +} + +void network_xmit(struct pbuf *p) +{ + struct pbuf *q; + uint8_t *data; + uint16_t len; + + if (!can_xmit) + return; + + len = CFG_TUD_NET_PACKET_PREFIX_LEN; + data = transmitted + len; + + for(q = p; q != NULL; q = q->next) + { + memcpy(data, (char *)q->payload, q->len); + data += q->len; + 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 + + do_in_xfer(transmitted, len); +} + +#endif diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h new file mode 100644 index 000000000..c61efc86c --- /dev/null +++ b/src/class/net/net_device.h @@ -0,0 +1,84 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Peter Lawrence + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_NET_DEVICE_H_ +#define _TUSB_NET_DEVICE_H_ + +#include "common/tusb_common.h" +#include "device/usbd.h" +#include "class/cdc/cdc.h" +#include "lwip/pbuf.h" +#include "netif/ethernet.h" + +/* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ +#define CFG_TUD_NET_ENDPOINT_SIZE ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64) + +/* Maximum Tranmission Unit (in bytes) of the network, including Ethernet header */ +#define CFG_TUD_NET_MTU (1500 + SIZEOF_ETH_HDR) + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + +// client must provide this: initialize any network state back to the beginning +void network_init_callback(void); + +// client must provide this: return false if the packet buffer was not accepted +bool network_recv_callback(struct pbuf *p); + +// client must provide this: 48-bit MAC address +extern const uint8_t network_mac_address[6]; + +// indicate to network driver that client has finished with the packet provided to network_recv_callback() +void network_recv_renew(void); + +// poll network driver for its ability to accept another packet to transmit +bool network_can_xmit(void); + +// if network_can_xmit() returns true, network_xmit() can be called once +void network_xmit(struct pbuf *p); + +//--------------------------------------------------------------------+ +// INTERNAL USBD-CLASS DRIVER API +//--------------------------------------------------------------------+ +void netd_init (void); +void netd_reset (uint8_t rhport); +bool netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void netd_report (uint8_t *buf, uint16_t len); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_NET_DEVICE_H_ */ diff --git a/src/device/usbd.c b/src/device/usbd.c index 68c5c5160..32a89889e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -181,6 +181,24 @@ static usbd_class_driver_t const _usbd_driver[] = .sof = NULL }, #endif + + #if CFG_TUD_NET + { + .class_code = +#if CFG_TUD_NET == OPT_NET_RNDIS + TUD_RNDIS_ITF_CLASS, +#else + TUSB_CLASS_CDC, +#endif + .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 + }, + #endif }; enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; diff --git a/src/device/usbd.h b/src/device/usbd.h index d80abf17c..07163a013 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -326,6 +326,90 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +//------------- CDC-ECM -------------// + +// Length of template descriptor: 62 bytes +#define TUD_CDC_ECM_DESC_LEN (9+5+5+13+7+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) \ + /* 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 */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC-ECM Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* CDC-ECM Functional Descriptor */\ + 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,\ + /* 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 + + +//------------- RNDIS -------------// + +#if 0 + /* 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 +#else + /* Windows 7+ */ + #define TUD_RNDIS_ITF_CLASS 0xE0 + #define TUD_RNDIS_ITF_SUBCLASS 0x01 + #define TUD_RNDIS_ITF_PROTOCOL 0x03 +#endif + +// Length of template descriptor: 66 bytes +#define TUD_RNDIS_DESC_LEN (8+9+5+5+4+5+7+9+7+7) + +// RNDIS Descriptor Template +// Interface number, string index, EP notification address and size, EP data address (out, in) and size. +#define TUD_RNDIS_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ + /* CDC-ACM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ + /* CDC Call Management */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* ACM */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* 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,\ + /* 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 + + +//------------- 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/tusb.h b/src/tusb.h index 7dcddf645..55c105121 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -91,6 +91,10 @@ #if CFG_TUD_DFU_RT #include "class/dfu/dfu_rt_device.h" #endif + + #if CFG_TUD_NET + #include "class/net/net_device.h" + #endif #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 97f14532f..00d4a39dc 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -117,6 +117,15 @@ #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 @@ -204,6 +213,9 @@ #define CFG_TUD_DFU_RT 0 #endif +#ifndef CFG_TUD_NET + #define CFG_TUD_NET 0 +#endif //-------------------------------------------------------------------- // HOST OPTIONS -- cgit v1.3.1 From 4a4682a80a2bd3d6d607d5a960443656de32955d Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Tue, 3 Mar 2020 10:31:46 -0600 Subject: update net class to follow API naming convention --- examples/device/lwip_webserver/src/main.c | 20 ++++++++++---------- examples/device/lwip_webserver/src/usb_descriptors.c | 6 +++--- lib/networking/rndis_reports.c | 4 ++-- src/class/net/net_device.c | 16 ++++++++-------- src/class/net/net_device.h | 14 +++++++------- 5 files changed, 30 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/examples/device/lwip_webserver/src/main.c b/examples/device/lwip_webserver/src/main.c index 364a26788..c193aeb0f 100644 --- a/examples/device/lwip_webserver/src/main.c +++ b/examples/device/lwip_webserver/src/main.c @@ -48,12 +48,12 @@ The MCU appears to the host as IP address 192.168.7.1, and provides a DHCP serve /* lwip context */ static struct netif netif_data; -/* shared between network_recv_callback() and service_traffic() */ +/* shared between tud_network_recv_cb() and service_traffic() */ static struct pbuf *received_frame; /* this is used by this code, ./class/net/net_driver.c, and usb_descriptors.c */ /* ideally speaking, this should be generated from the hardware's unique ID (if available) */ -const uint8_t network_mac_address[6] = {0x20,0x89,0x84,0x6A,0x96,0x00}; +const uint8_t tud_network_mac_address[6] = {0x20,0x89,0x84,0x6A,0x96,0x00}; /* network parameters of this MCU */ static const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, 7, 1); @@ -90,9 +90,9 @@ static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) return ERR_USE; /* if the network driver can accept another packet, we make it happen */ - if (network_can_xmit()) + if (tud_network_can_xmit()) { - network_xmit(p); + tud_network_xmit(p); return ERR_OK; } @@ -124,8 +124,8 @@ static void init_lwip(void) struct netif *netif = &netif_data; lwip_init(); - netif->hwaddr_len = sizeof(network_mac_address); - memcpy(netif->hwaddr, network_mac_address, sizeof(network_mac_address)); + netif->hwaddr_len = sizeof(tud_network_mac_address); + memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); netif_set_default(netif); @@ -142,7 +142,7 @@ bool dns_query_proc(const char *name, ip_addr_t *addr) return false; } -bool network_recv_callback(struct pbuf *p) +bool tud_network_recv_cb(struct pbuf *p) { /* this shouldn't happen, but if we get another packet before parsing the previous, we must signal our inability to accept it */ @@ -155,17 +155,17 @@ bool network_recv_callback(struct pbuf *p) static void service_traffic(void) { - /* handle any packet received by network_recv_callback() */ + /* handle any packet received by tud_network_recv_cb() */ if (received_frame) { ethernet_input(received_frame, &netif_data); pbuf_free(received_frame); received_frame = NULL; - network_recv_renew(); + tud_network_recv_renew(); } } -void network_init_callback(void) +void tud_network_init_cb(void) { /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ if (received_frame) diff --git a/examples/device/lwip_webserver/src/usb_descriptors.c b/examples/device/lwip_webserver/src/usb_descriptors.c index 803c99c02..26f8aeba6 100644 --- a/examples/device/lwip_webserver/src/usb_descriptors.c +++ b/examples/device/lwip_webserver/src/usb_descriptors.c @@ -168,10 +168,10 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Convert MAC address into UTF-16 - for (unsigned i=0; i> 4) & 0xf]; - _desc_str[1+chr_count++] = "0123456789ABCDEF"[(network_mac_address[i] >> 0) & 0xf]; + _desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 4) & 0xf]; + _desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 0) & 0xf]; } } else diff --git a/lib/networking/rndis_reports.c b/lib/networking/rndis_reports.c index 535bdf851..9c470b621 100644 --- a/lib/networking/rndis_reports.c +++ b/lib/networking/rndis_reports.c @@ -36,8 +36,8 @@ #define RNDIS_LINK_SPEED 12000000 /* Link baudrate (12Mbit/s for USB-FS) */ #define RNDIS_VENDOR "TinyUSB" /* NIC vendor name */ -static const uint8_t *const station_hwaddr = network_mac_address; -static const uint8_t *const permanent_hwaddr = network_mac_address; +static const uint8_t *const station_hwaddr = tud_network_mac_address; +static const uint8_t *const permanent_hwaddr = tud_network_mac_address; static usb_eth_stat_t usb_eth_stat = { 0, 0, 0, 0 }; static uint32_t oid_packet_filter = 0x0000000; diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 422d435c6..c918e5874 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -74,7 +74,7 @@ CFG_TUSB_MEM_SECTION static netd_interface_t _netd_itf; static bool can_xmit; -void network_recv_renew(void) +void tud_network_recv_renew(void) { usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_out, received, sizeof(received)); } @@ -156,13 +156,13 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t (*p_length) += 2*sizeof(tusb_desc_endpoint_t); } - network_init_callback(); + tud_network_init_cb(); // we are ready to transmit a packet can_xmit = true; // prepare for incoming packets - network_recv_renew(); + tud_network_recv_renew(); return true; } @@ -237,7 +237,7 @@ static void handle_incoming_packet(uint32_t len) if (hdr->bmType) { /* EEM Control Packet: discard it */ - network_recv_renew(); + tud_network_recv_renew(); } else { @@ -256,13 +256,13 @@ static void handle_incoming_packet(uint32_t len) { memcpy(p->payload, pnt, size); p->len = size; - accepted = network_recv_callback(p); + 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 */ - network_recv_renew(); + tud_network_recv_renew(); } } } @@ -297,12 +297,12 @@ bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ return true; } -bool network_can_xmit(void) +bool tud_network_can_xmit(void) { return can_xmit; } -void network_xmit(struct pbuf *p) +void tud_network_xmit(struct pbuf *p) { struct pbuf *q; uint8_t *data; diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index c61efc86c..fee54163f 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -49,22 +49,22 @@ //--------------------------------------------------------------------+ // client must provide this: initialize any network state back to the beginning -void network_init_callback(void); +void tud_network_init_cb(void); // client must provide this: return false if the packet buffer was not accepted -bool network_recv_callback(struct pbuf *p); +bool tud_network_recv_cb(struct pbuf *p); // client must provide this: 48-bit MAC address -extern const uint8_t network_mac_address[6]; +extern const uint8_t tud_network_mac_address[6]; -// indicate to network driver that client has finished with the packet provided to network_recv_callback() -void network_recv_renew(void); +// indicate to network driver that client has finished with the packet provided to network_recv_cb() +void tud_network_recv_renew(void); // poll network driver for its ability to accept another packet to transmit -bool network_can_xmit(void); +bool tud_network_can_xmit(void); // if network_can_xmit() returns true, network_xmit() can be called once -void network_xmit(struct pbuf *p); +void tud_network_xmit(struct pbuf *p); //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API -- cgit v1.3.1 From d74facfd0aede63da35c067ae8b8f3e4ed29ac6f Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Wed, 4 Mar 2020 17:54:11 -0600 Subject: usbnet RNDIS correction --- src/class/net/net_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index c918e5874..d0d32e909 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -64,7 +64,7 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACK 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_RNDIS - CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t rndis_buf[128]; + CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t rndis_buf[120]; #endif //--------------------------------------------------------------------+ -- cgit v1.3.1 From 7aa5a53652270a06dc60e6293393755350bf7c85 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 8 Mar 2020 13:26:36 +0700 Subject: fix log printf --- src/device/usbd.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 32a89889e..335c68e8e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -264,6 +264,9 @@ static char const* const _usbd_driver_str[USBD_CLASS_DRIVER_COUNT] = #if CFG_TUD_USBTMC "USBTMC" #endif + #if CFG_TUD_NET + "NET" + #endif }; static char const* const _tusb_std_request_str[] = -- cgit v1.3.1 From c8247f0907040eb86c301e8bff8bb322fc9cb566 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 8 Mar 2020 14:20:28 +0700 Subject: fix zlp for nrf52840 --- src/device/usbd_control.c | 6 ++++-- src/portable/nordic/nrf5x/dcd_nrf5x.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 5a0ba412f..f0a4cf84a 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -96,6 +96,8 @@ static bool _data_stage_xact(uint8_t rhport) if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len); } + TU_LOG2(" XACT Control: 0x%02X, Bytes: %d\n", ep_addr, xact_len); + return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); } @@ -110,10 +112,10 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo { TU_ASSERT(buffer); + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); + // Data stage TU_ASSERT( _data_stage_xact(rhport) ); - - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); }else { // Status stage diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 59c2f36aa..2ce288d6c 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -276,8 +276,10 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->total_len = total_bytes; xfer->actual_len = 0; - // Control endpoint with zero-length packet --> status stage - if ( epnum == 0 && total_bytes == 0 ) + // Control endpoint with zero-length packet and opposite direction to 1st request byte --> status stage + bool const control_status = (epnum == 0 && total_bytes == 0 && dir != tu_edpt_dir(NRF_USBD->BMREQUESTTYPE)); + + if ( control_status ) { // Status Phase also require Easy DMA has to be free as well !!!! edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS); -- cgit v1.3.1 From e0cdab5bf7ab6c2f085a748f936afafbd94ca0d9 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 8 Mar 2020 16:28:21 +0700 Subject: fix stm32 fsdev epdesc --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 30 +++++++++++++-------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index a1f40d971..5eacbe655 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -323,29 +323,27 @@ void dcd_remote_wakeup(uint8_t rhport) remoteWakeCountdown = 4u; // required to be 1 to 15 ms, ESOF should trigger every 1ms. } -// I'm getting a weird warning about missing braces here that I don't -// know how to fix. -#if defined(__GNUC__) && (__GNUC__ >= 7) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wmissing-braces" -#endif static const tusb_desc_endpoint_t ep0OUT_desc = { - .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, - .bDescriptorType = TUSB_XFER_CONTROL, - .bEndpointAddress = 0x00 + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + + .bEndpointAddress = 0x00, + .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, + .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, + .bInterval = 0 }; static const tusb_desc_endpoint_t ep0IN_desc = { - .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, - .bDescriptorType = TUSB_XFER_CONTROL, - .bEndpointAddress = 0x80 -}; + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, -#if defined(__GNUC__) && (__GNUC__ >= 7) -#pragma GCC diagnostic pop -#endif + .bEndpointAddress = 0x80, + .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, + .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, + .bInterval = 0 +}; static void dcd_handle_bus_reset(void) { -- cgit v1.3.1 From 85a3315a998ce7c625796177a665e6f4cd373e73 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 9 Mar 2020 15:51:29 +0700 Subject: Adding lwip_webserver to ci - buil_al.py skip specific MCU if .skip.MCU_ exists - reduce stm32f070 heap & stack size to compile webserver --- examples/device/lwip_webserver/.skip.MCU_LPC11UXX | 0 examples/device/lwip_webserver/.skip.MCU_LPC13XX | 0 examples/device/lwip_webserver/.skip.MCU_NUC121 | 0 examples/device/lwip_webserver/.skip.MCU_STM32L0 | 0 hw/bsp/samg55xplained/samg55xplained.c | 3 +- hw/bsp/spresense/board.mk | 4 +- hw/bsp/stm32f070rbnucleo/stm32F070rbtx_flash.ld | 4 +- src/class/net/net_device.h | 2 + tools/build_all.py | 56 ++++++++++++++++------- tools/build_success.sh | 10 ---- 10 files changed, 48 insertions(+), 31 deletions(-) create mode 100644 examples/device/lwip_webserver/.skip.MCU_LPC11UXX create mode 100644 examples/device/lwip_webserver/.skip.MCU_LPC13XX create mode 100644 examples/device/lwip_webserver/.skip.MCU_NUC121 create mode 100644 examples/device/lwip_webserver/.skip.MCU_STM32L0 delete mode 100644 tools/build_success.sh (limited to 'src') diff --git a/examples/device/lwip_webserver/.skip.MCU_LPC11UXX b/examples/device/lwip_webserver/.skip.MCU_LPC11UXX new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/lwip_webserver/.skip.MCU_LPC13XX b/examples/device/lwip_webserver/.skip.MCU_LPC13XX new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/lwip_webserver/.skip.MCU_NUC121 b/examples/device/lwip_webserver/.skip.MCU_NUC121 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/lwip_webserver/.skip.MCU_STM32L0 b/examples/device/lwip_webserver/.skip.MCU_STM32L0 new file mode 100644 index 000000000..e69de29bb diff --git a/hw/bsp/samg55xplained/samg55xplained.c b/hw/bsp/samg55xplained/samg55xplained.c index a5e145734..66a3d137f 100644 --- a/hw/bsp/samg55xplained/samg55xplained.c +++ b/hw/bsp/samg55xplained/samg55xplained.c @@ -24,13 +24,14 @@ */ #include "sam.h" +#include "bsp/board.h" + #include "peripheral_clk_config.h" #include "hal/include/hal_init.h" #include "hal/include/hpl_usart_sync.h" #include "hpl/pmc/hpl_pmc.h" #include "hal/include/hal_gpio.h" -#include "bsp/board.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION diff --git a/hw/bsp/spresense/board.mk b/hw/bsp/spresense/board.mk index 2e88cf994..c6b5ce12a 100644 --- a/hw/bsp/spresense/board.mk +++ b/hw/bsp/spresense/board.mk @@ -1,5 +1,4 @@ CFLAGS += \ - -DCONFIG_WCHAR_BUILTIN \ -DCONFIG_HAVE_DOUBLE \ -Dmain=spresense_main \ -pipe \ @@ -14,6 +13,9 @@ CFLAGS += \ -fomit-frame-pointer \ -DCFG_TUSB_MCU=OPT_MCU_CXD56 \ +# lwip/src/core/raw.c:334:43: error: declaration of 'recv' shadows a global declaration +CFLAGS += -Wno-error=shadow + SPRESENSE_SDK = $(TOP)/hw/mcu/sony/cxd56/spresense-exported-sdk INC += \ diff --git a/hw/bsp/stm32f070rbnucleo/stm32F070rbtx_flash.ld b/hw/bsp/stm32f070rbnucleo/stm32F070rbtx_flash.ld index 7ae8e5960..59e18f375 100644 --- a/hw/bsp/stm32f070rbnucleo/stm32F070rbtx_flash.ld +++ b/hw/bsp/stm32f070rbnucleo/stm32F070rbtx_flash.ld @@ -55,8 +55,8 @@ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ _estack = 0x20004000; /* end of "RAM" Ram type memory */ -_Min_Heap_Size = 0x400; /* required amount of heap */ -_Min_Stack_Size = 0x600; /* required amount of stack */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ /* Memories definition */ MEMORY diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index fee54163f..71483364d 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -31,6 +31,8 @@ #include "common/tusb_common.h" #include "device/usbd.h" #include "class/cdc/cdc.h" + +// TODO should not include external files #include "lwip/pbuf.h" #include "netif/ethernet.h" diff --git a/tools/build_all.py b/tools/build_all.py index 97294a9a3..45ae8d4d5 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -1,5 +1,5 @@ import os -import shutil +import glob import sys import subprocess import time @@ -10,9 +10,8 @@ exit_status = 0 total_time = time.monotonic() +# 1st Argument is Example, build all examples if not existed all_examples = [] - -# build all example if input not existed if len(sys.argv) > 1: all_examples.append(sys.argv[1]) else: @@ -22,11 +21,17 @@ else: # TODO update freeRTOS example to work with all boards (only nrf52840 now) all_examples.remove("cdc_msc_hid_freertos") +all_examples.sort() +# 2nd Argument is Board, build all boards if not existed all_boards = [] -for entry in os.scandir("hw/bsp"): - if entry.is_dir(): - all_boards.append(entry.name) +if len(sys.argv) > 2: + all_boards.append(sys.argv[2]) +else: + for entry in os.scandir("hw/bsp"): + if entry.is_dir(): + all_boards.append(entry.name) +all_boards.sort() def build_example(example, board): @@ -35,6 +40,16 @@ def build_example(example, board): return subprocess.run("make -j 4 -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) +def skip_example(example, board): + ex_dir = 'examples/device/' + example + board_mk = 'hw/bsp/{}/board.mk'.format(board) + for skip_file in glob.iglob(ex_dir + '/.skip.MCU_*'): + mcu_cflag = '-DCFG_TUSB_MCU=OPT_' + os.path.basename(skip_file).split('.')[2] + with open(board_mk) as mk: + if mcu_cflag in mk.read(): + return 1 + + return 0 build_format = '| {:30} | {:30} | {:9} ' build_separator = '-' * 87 @@ -44,20 +59,27 @@ for example in all_examples: print(build_separator) for board in all_boards: start_time = time.monotonic() - build_result = build_example(example, board) - build_duration = time.monotonic() - start_time - if build_result.returncode == 0: - success = "\033[32msucceeded\033[0m" - success_count += 1 + # Check if board is skipped + if skip_example(example, board): + success = "\033[33mskipped\033[0m " + print((build_format + '| {:.2f}s |').format(example, board, success, 0)) else: - exit_status = build_result.returncode - success = "\033[31mfailed\033[0m " - fail_count += 1 + build_result = build_example(example, board) + + if build_result.returncode == 0: + success = "\033[32msucceeded\033[0m" + success_count += 1 + else: + exit_status = build_result.returncode + success = "\033[31mfailed\033[0m " + fail_count += 1 + + build_duration = time.monotonic() - start_time + print((build_format + '| {:.2f}s |').format(example, board, success, build_duration)) - print((build_format + '| {:.2f}s |').format(example, board, success, build_duration)) - if build_result.returncode != 0: - print(build_result.stdout.decode("utf-8")) + if build_result.returncode != 0: + print(build_result.stdout.decode("utf-8")) # FreeRTOS example # example = 'cdc_msc_hid_freertos' diff --git a/tools/build_success.sh b/tools/build_success.sh deleted file mode 100644 index df725bdce..000000000 --- a/tools/build_success.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -# Trigger mynewt-tinyusb-example repo each push -curl -s -X POST \ - -H "Content-Type: application/json" \ - -H "Accept: application/json" \ - -H "Travis-API-Version: 3" \ - -H "Authorization: token $TRAVIS_TOKEN" \ - -d '{ "request": { "branch":"master" }}' \ - https://api.travis-ci.com/repo/hathach%2Fmynewt-tinyusb-example/requests \ No newline at end of file -- cgit v1.3.1 From 7f6316dbe1c98d2f00ded0913176a85e871353fa Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sat, 14 Mar 2020 14:22:08 -0400 Subject: Use CRLF on UART. --- examples/device/board_test/src/main.c | 2 +- src/class/cdc/cdc_device.c | 6 +++--- src/class/msc/msc_device.c | 6 +++--- src/common/tusb_common.h | 2 +- src/common/tusb_verify.h | 4 ++-- src/device/usbd_control.c | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/examples/device/board_test/src/main.c b/examples/device/board_test/src/main.c index 865821745..584ff799d 100644 --- a/examples/device/board_test/src/main.c +++ b/examples/device/board_test/src/main.c @@ -42,7 +42,7 @@ enum { BLINK_UNPRESSED = 1000 }; -#define HELLO_STR "Hello from TinyUSB\n" +#define HELLO_STR "Hello from TinyUSB\r\n" int main(void) { diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index f63418dae..14b9a3153 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -335,12 +335,12 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request switch ( request->bRequest ) { case CDC_REQUEST_SET_LINE_CODING: - TU_LOG2(" Set Line Coding\n"); + TU_LOG2(" Set Line Coding\r\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); break; case CDC_REQUEST_GET_LINE_CODING: - TU_LOG2(" Get Line Coding\n"); + TU_LOG2(" Get Line Coding\r\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); break; @@ -356,7 +356,7 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request p_cdc->line_state = (uint8_t) request->wValue; - TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\n", dtr, rts); + TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); tud_control_status(rhport, request); diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 3ff0eba92..06cc9dbb6 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -407,7 +407,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_ASSERT( event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE ); - TU_LOG2(" SCSI Command: %s\n", lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); + TU_LOG2(" SCSI Command: %s\r\n", lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); // TU_LOG2_MEM(p_cbw, xferred_bytes, 2); p_csw->signature = MSC_CSW_SIGNATURE; @@ -480,7 +480,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t break; case MSC_STAGE_DATA: - TU_LOG2(" SCSI Data\n"); + TU_LOG2(" SCSI Data\r\n"); //TU_LOG2_MEM(_mscd_buf, xferred_bytes, 2); // OUT transfer, invoke callback if needed @@ -577,7 +577,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // Wait for the Status phase to complete if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) ) { - TU_LOG2(" SCSI Status: %u\n", p_csw->status); + TU_LOG2(" SCSI Status: %u\r\n", p_csw->status); // TU_LOG2_MEM(p_csw, xferred_bytes, 2); // Move to default CMD stage diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 5e6a8bb10..ef232a593 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -222,7 +222,7 @@ void tu_print_mem(void const *buf, uint16_t count, uint8_t indent); // Log with debug level 1 #define TU_LOG1 tu_printf #define TU_LOG1_MEM tu_print_mem -#define TU_LOG1_LOCATION() tu_printf("%s: %d:\n", __PRETTY_FUNCTION__, __LINE__) +#define TU_LOG1_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__) // Log with debug level 2 #if CFG_TUSB_DEBUG > 1 diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 1ad6d3fb0..74150d6c5 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -76,8 +76,8 @@ #if CFG_TUSB_DEBUG #include - #define _MESS_ERR(_err) printf("%s %d: failed, error = %s\n", __func__, __LINE__, tusb_strerr[_err]) - #define _MESS_FAILED() printf("%s %d: assert failed\n", __func__, __LINE__) + #define _MESS_ERR(_err) printf("%s %d: failed, error = %s\r\n", __func__, __LINE__, tusb_strerr[_err]) + #define _MESS_FAILED() printf("%s %d: assert failed\r\n", __func__, __LINE__) #else #define _MESS_ERR(_err) #define _MESS_FAILED() diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index f0a4cf84a..7c35fe768 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -63,7 +63,7 @@ static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t con // Opposite to endpoint in Data Phase uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", ep_addr, 0); + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", ep_addr, 0); // status direction is reversed to one in the setup packet // Note: Status must always be DATA1 @@ -96,7 +96,7 @@ static bool _data_stage_xact(uint8_t rhport) if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len); } - TU_LOG2(" XACT Control: 0x%02X, Bytes: %d\n", ep_addr, xact_len); + TU_LOG2(" XACT Control: 0x%02X, Bytes: %d\r\n", ep_addr, xact_len); return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); } @@ -112,7 +112,7 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo { TU_ASSERT(buffer); - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); + TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); // Data stage TU_ASSERT( _data_stage_xact(rhport) ); -- cgit v1.3.1 From 5e8ff1f7c2887abb5459b0d9d6812e2da437d4d0 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sun, 15 Mar 2020 16:05:45 -0500 Subject: usb RNDIS revision on @pigrew suggestions --- src/class/net/net_device.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index d0d32e909..7bb11d57c 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -198,7 +198,17 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request TU_VERIFY (_netd_itf.itf_num == request->wIndex); #if CFG_TUD_NET == OPT_NET_RNDIS - tud_control_xfer(rhport, request, rndis_buf, sizeof(rndis_buf)); + 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 -- cgit v1.3.1 From fb56c02a6f7cc03b2f9fd970a5b1bc772ccf4795 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sun, 15 Mar 2020 17:10:14 -0500 Subject: NUC505 : fix operation with net_lwip_webserver --- examples/device/net_lwip_webserver/src/tusb_config.h | 2 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index 329fc80b9..0b40fefab 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -39,7 +39,7 @@ #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 +#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) #else #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 2b6a66bc2..031bfc5e4 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -211,6 +211,7 @@ static void bus_reset(void) current_dma_xfer = NULL; } +#if 0 /* this must only be called by the ISR; it does its best to share the single DMA engine across all user EPs (IN and OUT) */ static void service_dma(void) { @@ -243,6 +244,7 @@ static void service_dma(void) return; } } +#endif /* centralized location for USBD interrupt enable bit masks */ static const uint32_t enabled_irqs = USBD_GINTEN_USBIEN_Msk | \ @@ -366,7 +368,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to for (int count = 0; count < total_bytes; count++) *buffer++ = USBD->CEPDAT_BYTE; - usb_control_send_zlp(); + dcd_event_xfer_complete(0, ep_addr, total_bytes, XFER_RESULT_SUCCESS, true); } } else @@ -465,6 +467,7 @@ void USBD_IRQHandler(void) if (bus_state & USBD_BUSINTSTS_DMADONEIF_Msk) { +#if 0 if (current_dma_xfer) { current_dma_xfer->dma_requested = false; @@ -480,6 +483,7 @@ void USBD_IRQHandler(void) current_dma_xfer = NULL; service_dma(); } +#endif } if (bus_state & USBD_BUSINTSTS_VBUSDETIF_Msk) @@ -597,7 +601,7 @@ void USBD_IRQHandler(void) if (out_ep) { -#if 1 +#if 0 xfer->dma_requested = true; service_dma(); #else -- cgit v1.3.1 From aafddfe637cf2dadf82075b59b18aad6a722caaa Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sun, 15 Mar 2020 18:32:02 -0500 Subject: following suggestion by @kasjer --- src/class/cdc/cdc_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 73eafab07..51c69423e 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -413,7 +413,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Though maybe the baudrate is not really important !!! if ( ep_addr == p_cdc->ep_in ) { - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) ) usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) && (0 == p_cdc->tx_ff.count) ) usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); } // nothing to do with notif endpoint for now -- cgit v1.3.1 From df05440d92f0d05532476df5f544d00751f03bce Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Mon, 16 Mar 2020 13:20:17 -0500 Subject: NUC505 : added comment on DMA choice --- src/portable/nuvoton/nuc505/dcd_nuc505.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 031bfc5e4..e05e73eff 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -33,6 +33,12 @@ nomenclature of EPA through EPL. */ +/* + Note on OPT_MCU_NUC505_USB_DMA: the author suggests against using this option. + The DMA functionality of the USBD peripheral does not appear to succeed with + transfer lengths that are longer (> 64 bytes) and are not a multiple of 4. +*/ + #include "tusb_option.h" #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC505) @@ -211,7 +217,7 @@ static void bus_reset(void) current_dma_xfer = NULL; } -#if 0 +#ifdef OPT_MCU_NUC505_USB_DMA /* this must only be called by the ISR; it does its best to share the single DMA engine across all user EPs (IN and OUT) */ static void service_dma(void) { @@ -467,7 +473,7 @@ void USBD_IRQHandler(void) if (bus_state & USBD_BUSINTSTS_DMADONEIF_Msk) { -#if 0 +#ifdef OPT_MCU_NUC505_USB_DMA if (current_dma_xfer) { current_dma_xfer->dma_requested = false; @@ -601,7 +607,7 @@ void USBD_IRQHandler(void) if (out_ep) { -#if 0 +#ifdef OPT_MCU_NUC505_USB_DMA xfer->dma_requested = true; service_dma(); #else -- cgit v1.3.1 From a39d170672cca9b0c05065971ea3070def4f4244 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 17 Mar 2020 10:40:45 +0700 Subject: follow up to pr #301 rename OPT_MCU_NUC505_USB_DMA to simply USE_DMA --- README.md | 2 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index 211dcc50a..19106db3e 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,13 @@ The stack supports the following MCUs: - **MicroChip:** SAMD21, SAMD51 (device only) - **Nordic:** nRF52840, nRF52833 +- **Nuvoton:** NUC120, NUC121/NUC125, NUC126, NUC505 - **NXP:** - LPC Series: 11Uxx, 13xx, 175x_6x, 177x_8x, 18xx, 40xx, 43xx, 51Uxx, 54xxx, 55xx - iMX RT Series: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064 - **Sony:** CXD56 - **ST:** STM32 series: L0, F0, F1, F2, F3, F4, F7, H7 (device only) - **[ValentyUSB](https://github.com/im-tomu/valentyusb)** eptri -- **Nuvoton:** NUC120, NUC121/NUC125, NUC126, NUC505 [Here is the list of supported Boards](docs/boards.md) that can be used with provided examples. diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index e05e73eff..ff2e5264d 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -33,12 +33,6 @@ nomenclature of EPA through EPL. */ -/* - Note on OPT_MCU_NUC505_USB_DMA: the author suggests against using this option. - The DMA functionality of the USBD peripheral does not appear to succeed with - transfer lengths that are longer (> 64 bytes) and are not a multiple of 4. -*/ - #include "tusb_option.h" #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC505) @@ -46,6 +40,14 @@ #include "device/dcd.h" #include "NUC505Series.h" +/* + The DMA functionality of the USBD peripheral does not appear to succeed with + transfer lengths that are longer (> 64 bytes) and are not a multiple of 4. + Disable for now, we could implement a walk-around if non-DMA slow the MCU down + too much. +*/ +#define USE_DMA 0 + /* rather important info unfortunately not provided by device include files */ #define USBD_BUF_SIZE 2048 /* how much USB buffer space there is */ #define USBD_MAX_DMA_LEN 0x1000 /* max bytes that can be DMAed at one time */ @@ -217,7 +219,7 @@ static void bus_reset(void) current_dma_xfer = NULL; } -#ifdef OPT_MCU_NUC505_USB_DMA +#if USE_DMA /* this must only be called by the ISR; it does its best to share the single DMA engine across all user EPs (IN and OUT) */ static void service_dma(void) { @@ -473,7 +475,7 @@ void USBD_IRQHandler(void) if (bus_state & USBD_BUSINTSTS_DMADONEIF_Msk) { -#ifdef OPT_MCU_NUC505_USB_DMA +#if USE_DMA if (current_dma_xfer) { current_dma_xfer->dma_requested = false; @@ -607,7 +609,7 @@ void USBD_IRQHandler(void) if (out_ep) { -#ifdef OPT_MCU_NUC505_USB_DMA +#if USE_DMA xfer->dma_requested = true; service_dma(); #else -- cgit v1.3.1 From a93548cfe9094893e147db0115958612e1606aa7 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 17 Mar 2020 23:39:53 +0700 Subject: update comment per review --- src/portable/nuvoton/nuc505/dcd_nuc505.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index ff2e5264d..8457e686b 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -41,11 +41,10 @@ #include "NUC505Series.h" /* - The DMA functionality of the USBD peripheral does not appear to succeed with - transfer lengths that are longer (> 64 bytes) and are not a multiple of 4. - Disable for now, we could implement a walk-around if non-DMA slow the MCU down - too much. -*/ + * The DMA functionality of the USBD peripheral does not appear to succeed with + * transfer lengths that are longer (> 64 bytes) and are not a multiple of 4. + * Keep disabled for now. + */ #define USE_DMA 0 /* rather important info unfortunately not provided by device include files */ -- cgit v1.3.1 From eaf767b0db141fe745b64abf2cfc7b8896391d1c Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sun, 22 Mar 2020 14:19:31 -0400 Subject: STM32FSDEV: Rewrite transfer ISR --- hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c | 5 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 259 +++++++++------------ .../st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h | 7 + 3 files changed, 121 insertions(+), 150 deletions(-) (limited to 'src') diff --git a/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c b/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c index 084d9a92d..56b3024e3 100644 --- a/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c +++ b/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c @@ -185,10 +185,7 @@ void HardFault_Handler (void) */ void assert_failed(char *file, uint32_t line) { - /* USER CODE BEGIN 6 */ - /* User can add his own implementation to report the file name and line number, - tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ - /* USER CODE END 6 */ + TU_LOG1("Assertion failed (%s:%ld)\r\n", file, line); } #endif /* USE_FULL_ASSERT */ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 5eacbe655..f962a4bee 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -184,7 +184,7 @@ 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 uint16_t dcd_ep_ctr_handler(void); +static void dcd_ep_ctr_handler(void); // Using a function due to better type checks @@ -363,163 +363,130 @@ static void dcd_handle_bus_reset(void) USB->DADDR = USB_DADDR_EF; // Set enable flag, and leaving the device address as zero. } -// FIXME: Defined to return uint16 so that ASSERT can be used, even though a return value is not needed. -static uint16_t dcd_ep_ctr_handler(void) +// Handle CTR interrupt for the TX/IN direction +// +// Upon call, (wIstr & USB_ISTR_DIR) == 0U +static void dcd_ep_ctr_tx_handler(uint32_t wIstr) { - uint32_t count=0U; - uint8_t EPindex; - __IO uint16_t wIstr; - __IO uint16_t wEPVal = 0U; + uint32_t EPindex = wIstr & USB_ISTR_EP_ID; + uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex); - // stack variables to pass to USBD + // Verify the CTR_TX bit is set. This was in the ST Micro code, + // but I'm not sure it's actually necessary? + if((wEPRegVal & USB_EP_CTR_TX) == 0U) + { + return; + } + + /* clear int flag */ + pcd_clear_tx_ep_ctr(USB, EPindex); + + xfer_ctl_t * xfer = xfer_ctl_ptr(EPindex,TUSB_DIR_IN); + if((xfer->total_len != xfer->queued_len)) /* TX not complete */ + { + dcd_transmit_packet(xfer, EPindex); + } + else /* TX Complete */ + { + dcd_event_xfer_complete(0, (uint8_t)(0x80 + EPindex), xfer->total_len, XFER_RESULT_SUCCESS, true); + } +} + +// Handle CTR interrupt for the RX/OUT direction +// +// Upon call, (wIstr & USB_ISTR_DIR) == 0U +static void dcd_ep_ctr_rx_handler(uint32_t wIstr) +{ + uint32_t EPindex = wIstr & USB_ISTR_EP_ID; + uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex); + uint32_t count = pcd_get_ep_rx_cnt(USB,EPindex); + + xfer_ctl_t *xfer = xfer_ctl_ptr(EPindex,TUSB_DIR_OUT); + + // Verify the CTR_RX bit is set. This was in the ST Micro code, + // but I'm not sure it's actually necessary? + if((wEPRegVal & USB_EP_CTR_RX) == 0U) + { + return; + } + + if((EPindex == 0U) && ((wEPRegVal & USB_EP_SETUP) != 0U)) /* Setup packet */ + { + // The setup_received function uses memcpy, so this must first copy the setup data into + // user memory, to allow for the 32-bit access that memcpy performs. + uint8_t userMemBuf[8]; + /* Get SETUP Packet*/ + if(count == 8) // Setup packet should always be 8 bytes. If not, ignore it, and try again. + { + // Must reset EP to NAK (in case it had been stalling) (though, maybe too late here) + pcd_set_ep_rx_status(USB,0u,USB_EP_RX_NAK); + pcd_set_ep_tx_status(USB,0u,USB_EP_TX_NAK); + dcd_read_packet_memory(userMemBuf, *pcd_ep_rx_address_ptr(USB,EPindex), 8); + dcd_event_setup_received(0, (uint8_t*)userMemBuf, true); + } + } + else + { + // Clear RX CTR interrupt flag + if(EPindex != 0u) + { + pcd_clear_rx_ep_ctr(USB, EPindex); + } + + if (count != 0U) + { + dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]), + *pcd_ep_rx_address_ptr(USB,EPindex), count); + xfer->queued_len = (uint16_t)(xfer->queued_len + count); + } + + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) + { + /* RX COMPLETE */ + dcd_event_xfer_complete(0, EPindex, xfer->queued_len, XFER_RESULT_SUCCESS, true); + // Though the host could still send, we don't know. + // Does the bulk pipe need to be reset to valid to allow for a ZLP? + } + else + { + uint32_t remaining = (uint32_t)xfer->total_len - (uint32_t)xfer->queued_len; + if(remaining >= xfer->max_packet_size) { + pcd_set_ep_rx_cnt(USB, EPindex,xfer->max_packet_size); + } else { + pcd_set_ep_rx_cnt(USB, EPindex,remaining); + } + pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID); + } + } + + // For EP0, prepare to receive another SETUP packet. + // Clear CTR last so that a new packet does not overwrite the packing being read. + // (Based on the docs, it seems SETUP will always be accepted after CTR is cleared) + if(EPindex == 0u) + { + // Always be prepared for a status packet... + pcd_set_ep_rx_cnt(USB, EPindex, CFG_TUD_ENDPOINT0_SIZE); + pcd_clear_rx_ep_ctr(USB, EPindex); + } +} + +static void dcd_ep_ctr_handler(void) +{ + uint32_t wIstr; /* stay in loop while pending interrupts */ while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U) { - /* extract highest priority endpoint index */ - EPindex = (uint8_t)(wIstr & USB_ISTR_EP_ID); - if (EPindex == 0U) + if ((wIstr & USB_ISTR_DIR) == 0U) /* TX/IN */ { - /* Decode and service control endpoint interrupt */ - - /* DIR bit = origin of the interrupt */ - if ((wIstr & USB_ISTR_DIR) == 0U) - { - /* DIR = 0 => IN int */ - /* DIR = 0 implies that (EP_CTR_TX = 1) always */ - pcd_clear_tx_ep_ctr(USB, 0); - - xfer_ctl_t * xfer = xfer_ctl_ptr(EPindex,TUSB_DIR_IN); - - if((xfer->total_len == xfer->queued_len)) - { - dcd_event_xfer_complete(0u, (uint8_t)(0x80 + EPindex), xfer->total_len, XFER_RESULT_SUCCESS, true); - - if(xfer->total_len == 0) // Probably a status message? - { - pcd_clear_rx_dtog(USB,EPindex); - } - } - else - { - dcd_transmit_packet(xfer,EPindex); - } - } - else - { - /* DIR = 1 & CTR_RX => SETUP or OUT int */ - /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */ - - xfer_ctl_t *xfer = xfer_ctl_ptr(EPindex,TUSB_DIR_OUT); - - //ep = &hpcd->OUT_ep[0]; - wEPVal = pcd_get_endpoint(USB, EPindex); - - if ((wEPVal & USB_EP_SETUP) != 0U) // SETUP - { - // The setup_received function uses memcpy, so this must first copy the setup data into - // user memory, to allow for the 32-bit access that memcpy performs. - uint8_t userMemBuf[8]; - /* Get SETUP Packet*/ - count = pcd_get_ep_rx_cnt(USB, EPindex); - if(count == 8) // Setup packet should always be 8 bytes. If not, ignore it, and try again. - { - // Must reset EP to NAK (in case it had been stalling) (though, maybe too late here) - pcd_set_ep_rx_status(USB,0u,USB_EP_RX_NAK); - pcd_set_ep_tx_status(USB,0u,USB_EP_TX_NAK); - dcd_read_packet_memory(userMemBuf, *pcd_ep_rx_address_ptr(USB,EPindex), 8); - dcd_event_setup_received(0, (uint8_t*)userMemBuf, true); - } - /* SETUP bit kept frozen while CTR_RX = 1*/ - pcd_clear_rx_ep_ctr(USB, EPindex); - } - else if ((wEPVal & USB_EP_CTR_RX) != 0U) // OUT - { - - pcd_clear_rx_ep_ctr(USB, EPindex); - - /* Get Control Data OUT Packet */ - count = pcd_get_ep_rx_cnt(USB,EPindex); - - if (count != 0U) - { - dcd_read_packet_memory(xfer->buffer, *pcd_ep_rx_address_ptr(USB,EPindex), count); - xfer->queued_len = (uint16_t)(xfer->queued_len + count); - } - - /* Process Control Data OUT status Packet*/ - dcd_event_xfer_complete(0, EPindex, xfer->total_len, XFER_RESULT_SUCCESS, true); - - pcd_set_ep_rx_cnt(USB, EPindex, CFG_TUD_ENDPOINT0_SIZE); - if(EPindex == 0u && xfer->total_len == 0u) - { - pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID);// Await next SETUP - } - } - } + dcd_ep_ctr_tx_handler(wIstr); } - else /* Decode and service non control endpoints interrupt */ + else /* RX/OUT*/ { - /* process related endpoint register */ - wEPVal = pcd_get_endpoint(USB, EPindex); - if ((wEPVal & USB_EP_CTR_RX) != 0U) // OUT - { - /* clear int flag */ - pcd_clear_rx_ep_ctr(USB, EPindex); - - xfer_ctl_t * xfer = xfer_ctl_ptr(EPindex,TUSB_DIR_OUT); - - //ep = &hpcd->OUT_ep[EPindex]; - - count = pcd_get_ep_rx_cnt(USB, EPindex); - if (count != 0U) - { - dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]), - *pcd_ep_rx_address_ptr(USB,EPindex), count); - } - - /*multi-packet on the NON control OUT endpoint */ - xfer->queued_len = (uint16_t)(xfer->queued_len + count); - - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { - /* RX COMPLETE */ - dcd_event_xfer_complete(0, EPindex, xfer->queued_len, XFER_RESULT_SUCCESS, true); - // Though the host could still send, we don't know. - // Does the bulk pipe need to be reset to valid to allow for a ZLP? - } - else - { - uint32_t remaining = (uint32_t)xfer->total_len - (uint32_t)xfer->queued_len; - if(remaining >= xfer->max_packet_size) { - pcd_set_ep_rx_cnt(USB, EPindex,xfer->max_packet_size); - } else { - pcd_set_ep_rx_cnt(USB, EPindex,remaining); - } - - pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID); - } - - } /* if((wEPVal & EP_CTR_RX) */ - - if ((wEPVal & USB_EP_CTR_TX) != 0U) // IN - { - /* clear int flag */ - pcd_clear_tx_ep_ctr(USB, EPindex); - - xfer_ctl_t * xfer = xfer_ctl_ptr(EPindex,TUSB_DIR_IN); - - if (xfer->queued_len != xfer->total_len) // data remaining in transfer? - { - dcd_transmit_packet(xfer, EPindex); - } else { - dcd_event_xfer_complete(0, (uint8_t)(0x80 + EPindex), xfer->total_len, XFER_RESULT_SUCCESS, true); - } - } + dcd_ep_ctr_rx_handler(wIstr); } } - return 0; } static void dcd_fs_irqHandler(void) { diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h index 36dca8cd8..4f2b2294e 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h @@ -310,6 +310,13 @@ static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpNum, ui pcd_set_endpoint(USBx, bEpNum, regVal); } /* pcd_set_ep_rx_status */ +static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpNum) +{ + uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); + return (regVal & USB_EPRX_STAT) >> (12u); +} /* pcd_get_ep_rx_status */ + + /** * @brief Toggles DTOG_RX / DTOG_TX bit in the endpoint register. * @param USBx USB peripheral instance register address. -- cgit v1.3.1 From 8a22eba7b4104e037fb10d86edfd9dd97421b156 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Mar 2020 15:24:30 +0700 Subject: add TODO note to remove tud_network_mac_address --- src/class/net/net_device.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 71483364d..67cd99933 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -57,6 +57,7 @@ void tud_network_init_cb(void); bool tud_network_recv_cb(struct pbuf *p); // client must provide this: 48-bit MAC address +// TODO removed later since it is not part of tinyusb stack extern const uint8_t tud_network_mac_address[6]; // indicate to network driver that client has finished with the packet provided to network_recv_cb() -- cgit v1.3.1 From 6b5157fd28a9495ee37fb2c84d29c1a61bb7c68b Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Tue, 24 Mar 2020 00:03:12 -0400 Subject: dcd_msp430x5xx: Add dummy dcd_edpt0_status_complete handler. Add comment which describes why it might be needed. --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 3a73cf9bf..d50fa17fe 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -1,8 +1,8 @@ /* * The MIT License (MIT) * - * Copyright (c) 2019 William D. Jones - * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2019-2020 William D. Jones + * Copyright (c) 2019-2020 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 @@ -384,6 +384,22 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) } } +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void) rhport; + (void) request; + + // FIXME: Per manual, we should be clearing the NAK bits of EP0 after the + // Status Phase of a control xfer is done, in preparation of another possible + // SETUP packet. However, from my own testing, SETUP packets _are_ correctly + // handled by the USB core without clearing the NAKs. + // + // Right now, clearing NAKs in this callbacks causes a direction mismatch + // between host and device on EP0. Figure out why and come back to this. + // USBOEPCNT_0 &= ~NAK; + // USBIEPCNT_0 &= ~NAK; +} + /*------------------------------------------------------------------*/ static void receive_packet(uint8_t ep_num) @@ -563,12 +579,6 @@ void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) // first place. When I first noticed the STALL, the only two places I // touched the NAK bits were in dcd_edpt_xfer() and to _set_ (sic) them in // bus_reset(). SETUP packet handling should've been unaffected. - // - // FIXME: Per manual, we should be clearing the NAK bits of EP0 after the - // Status Phase of a control xfer is done, in preparation of another - // possible SETUP packet. We don't do this right now, as there is no - // "Status Phase done" callback the driver can use. However, SETUP packets - // _are_ correctly handled by the USB core without clearing the NAKs. case USBVECINT_SETUP_PACKET_RECEIVED: break; -- cgit v1.3.1 From 6606cf289661909cfe238787bef7b91112d40f0d Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 27 Mar 2020 15:30:40 -0400 Subject: USBD: Use tud_control_xfer only for data --- src/device/usbd_control.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 4fd40c440..c61606f18 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -101,22 +101,29 @@ static bool _data_stage_xact(uint8_t rhport) return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); } +// Transmit data to/from the control endpoint. +// +// If the request's wLength is zero, a status packet is sent instead. bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len) { _ctrl_xfer.request = (*request); _ctrl_xfer.buffer = (uint8_t*) buffer; - _ctrl_xfer.total_xferred = 0; + _ctrl_xfer.total_xferred = 0U; _ctrl_xfer.data_len = tu_min16(len, request->wLength); - - if ( _ctrl_xfer.data_len ) + + if (request->wLength > 0U) { - TU_ASSERT(buffer); + if(_ctrl_xfer.data_len > 0U) + { + TU_ASSERT(buffer); + } TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); // Data stage TU_ASSERT( _data_stage_xact(rhport) ); - }else + } + else { // Status stage TU_ASSERT( _status_stage_xact(rhport, request) ); -- cgit v1.3.1 From 622a6c77a10b3b9278f78c9b597bdfd4efd1dd68 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Fri, 27 Mar 2020 20:30:57 -0500 Subject: usbnet: tweak CDC-ECM after MacOS testing --- examples/device/net_lwip_webserver/src/main.c | 6 +++++- .../device/net_lwip_webserver/src/usb_descriptors.c | 2 +- src/class/net/net_device.c | 20 ++++++++++++++++++-- 3 files changed, 24 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index c193aeb0f..fe904e8e8 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -53,7 +53,8 @@ static struct pbuf *received_frame; /* this is used by this code, ./class/net/net_driver.c, and usb_descriptors.c */ /* ideally speaking, this should be generated from the hardware's unique ID (if available) */ -const uint8_t tud_network_mac_address[6] = {0x20,0x89,0x84,0x6A,0x96,0x00}; +/* it is suggested that the first two bytes are 0x02,0x02 to indicate a link-local address */ +const uint8_t tud_network_mac_address[6] = {0x02,0x02,0x84,0x6A,0x96,0x00}; /* network parameters of this MCU */ static const ip_addr_t ipaddr = IPADDR4_INIT_BYTES(192, 168, 7, 1); @@ -124,8 +125,11 @@ static void init_lwip(void) struct netif *netif = &netif_data; lwip_init(); + + /* the lwip virtual MAC address must be different from the host's; to ensure this, we toggle the LSbit */ netif->hwaddr_len = sizeof(tud_network_mac_address); memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); + netif->hwaddr[5] ^= 0x01; netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); netif_set_default(netif); diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index c7a8cc767..a4eba205f 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -112,7 +112,7 @@ uint8_t const desc_configuration[] = #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, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), + 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), diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 7bb11d57c..68520625a 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -63,7 +63,15 @@ typedef struct 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_RNDIS +#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 */, + .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 @@ -197,7 +205,15 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request TU_VERIFY (_netd_itf.itf_num == request->wIndex); -#if CFG_TUD_NET == OPT_NET_RNDIS +#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)); + } +#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; -- cgit v1.3.1 From 87f313da48aa1df4fb0566d9ad26036f06418422 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Mon, 30 Mar 2020 13:34:56 -0500 Subject: add provision for multiple configurations --- examples/device/cdc_dual_ports/src/usb_descriptors.c | 4 ++-- examples/device/cdc_msc/src/usb_descriptors.c | 4 ++-- examples/device/cdc_msc_freertos/src/usb_descriptors.c | 4 ++-- examples/device/dfu_rt/src/usb_descriptors.c | 4 ++-- examples/device/hid_composite/src/usb_descriptors.c | 4 ++-- examples/device/hid_generic_inout/src/usb_descriptors.c | 4 ++-- examples/device/midi_test/src/usb_descriptors.c | 4 ++-- examples/device/msc_dual_lun/src/usb_descriptors.c | 4 ++-- examples/device/net_lwip_webserver/src/usb_descriptors.c | 4 ++-- examples/device/usbtmc/src/usb_descriptors.c | 4 ++-- examples/device/webusb_serial/src/usb_descriptors.c | 4 ++-- src/device/usbd.h | 6 +++--- test/test/device/msc/test_msc_device.c | 4 ++-- test/test/device/usbd/test_usbd.c | 8 ++++---- 14 files changed, 31 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index 1b1d171b1..b59f55d1b 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -93,8 +93,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, 64), diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 127008227..373928e2f 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -116,8 +116,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), diff --git a/examples/device/cdc_msc_freertos/src/usb_descriptors.c b/examples/device/cdc_msc_freertos/src/usb_descriptors.c index 127008227..373928e2f 100644 --- a/examples/device/cdc_msc_freertos/src/usb_descriptors.c +++ b/examples/device/cdc_msc_freertos/src/usb_descriptors.c @@ -116,8 +116,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), diff --git a/examples/device/dfu_rt/src/usb_descriptors.c b/examples/device/dfu_rt/src/usb_descriptors.c index 17b3fe87d..f96684b91 100644 --- a/examples/device/dfu_rt/src/usb_descriptors.c +++ b/examples/device/dfu_rt/src/usb_descriptors.c @@ -141,8 +141,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), #if CFG_TUD_CDC // Interface number, string index, EP notification address and size, EP data address (out, in) and size. diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index 19689c90b..a75bc5274 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -101,8 +101,8 @@ enum uint8_t const desc_configuration[] = { - // interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_BUFSIZE, 10) diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index 87611a432..8adb336a0 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -99,8 +99,8 @@ enum uint8_t const desc_configuration[] = { - // interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_BUFSIZE, 10) diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c index 949404826..3c2848e56 100644 --- a/examples/device/midi_test/src/usb_descriptors.c +++ b/examples/device/midi_test/src/usb_descriptors.c @@ -90,8 +90,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, EP Out & EP In address, EP size TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64) diff --git a/examples/device/msc_dual_lun/src/usb_descriptors.c b/examples/device/msc_dual_lun/src/usb_descriptors.c index 3b2615fd4..90f7083d2 100644 --- a/examples/device/msc_dual_lun/src/usb_descriptors.c +++ b/examples/device/msc_dual_lun/src/usb_descriptors.c @@ -98,8 +98,8 @@ enum uint8_t const desc_configuration[] = { - // interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index a4eba205f..e398a5d4b 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -107,8 +107,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100, 1), #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. diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index 92b1dce61..e22665706 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -165,8 +165,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), #if CFG_TUD_CDC // Interface number, string index, EP notification address and size, EP data address (out, in) and size. diff --git a/examples/device/webusb_serial/src/usb_descriptors.c b/examples/device/webusb_serial/src/usb_descriptors.c index 2925a66c4..386ca7458 100644 --- a/examples/device/webusb_serial/src/usb_descriptors.c +++ b/examples/device/webusb_serial/src/usb_descriptors.c @@ -95,8 +95,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, 64), diff --git a/src/device/usbd.h b/src/device/usbd.h index 07163a013..71829322b 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -156,9 +156,9 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re //------------- Configuration -------------// #define TUD_CONFIG_DESC_LEN (9) -// Interface count, string index, total length, attribute, power in mA -#define TUD_CONFIG_DESCRIPTOR(_itfcount, _stridx, _total_len, _attribute, _power_ma) \ - 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, 1, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 +// Interface count, string index, total length, attribute, power in mA, config number +#define TUD_CONFIG_DESCRIPTOR(_itfcount, _stridx, _total_len, _attribute, _power_ma, config_num) \ + 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 //------------- CDC -------------// diff --git a/test/test/device/msc/test_msc_device.c b/test/test/device/msc/test_msc_device.c index 43a8e7438..8f807183f 100644 --- a/test/test/device/msc/test_msc_device.c +++ b/test/test/device/msc/test_msc_device.c @@ -62,8 +62,8 @@ enum uint8_t const data_desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EDPT_MSC_OUT, EDPT_MSC_IN, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), diff --git a/test/test/device/usbd/test_usbd.c b/test/test/device/usbd/test_usbd.c index af30aaf8f..96afd8b43 100644 --- a/test/test/device/usbd/test_usbd.c +++ b/test/test/device/usbd/test_usbd.c @@ -73,8 +73,8 @@ tusb_desc_device_t const data_desc_device = uint8_t const data_desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(0, 0, TUD_CONFIG_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(0, 0, TUD_CONFIG_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), }; tusb_control_request_t const req_get_desc_device = @@ -211,8 +211,8 @@ void test_usbd_control_in_zlp(void) // ZLP must be return uint8_t zlp_desc_configuration[CFG_TUD_ENDOINT0_SIZE*2] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(0, 0, CFG_TUD_ENDOINT0_SIZE*2, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + // Interface count, string index, total length, attribute, power in mA, config number + TUD_CONFIG_DESCRIPTOR(0, 0, CFG_TUD_ENDOINT0_SIZE*2, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), }; desc_configuration = zlp_desc_configuration; -- cgit v1.3.1 From 794212d44e38a05d8b747e43942595d214ee5b0b Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Tue, 31 Mar 2020 10:53:47 -0500 Subject: revise argument order for TUD_CONFIG_DESCRIPTOR macro --- examples/device/cdc_dual_ports/src/usb_descriptors.c | 4 ++-- examples/device/cdc_msc/src/usb_descriptors.c | 4 ++-- examples/device/cdc_msc_freertos/src/usb_descriptors.c | 4 ++-- examples/device/dfu_rt/src/usb_descriptors.c | 4 ++-- examples/device/hid_composite/src/usb_descriptors.c | 4 ++-- examples/device/hid_generic_inout/src/usb_descriptors.c | 4 ++-- examples/device/midi_test/src/usb_descriptors.c | 4 ++-- examples/device/msc_dual_lun/src/usb_descriptors.c | 4 ++-- examples/device/net_lwip_webserver/src/usb_descriptors.c | 4 ++-- examples/device/usbtmc/src/usb_descriptors.c | 4 ++-- examples/device/webusb_serial/src/usb_descriptors.c | 4 ++-- src/device/usbd.h | 4 ++-- test/test/device/msc/test_msc_device.c | 4 ++-- test/test/device/usbd/test_usbd.c | 8 ++++---- 14 files changed, 30 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index b59f55d1b..03800d693 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -93,8 +93,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // 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), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, 64), diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 373928e2f..7b22d46a7 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -116,8 +116,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // 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), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), diff --git a/examples/device/cdc_msc_freertos/src/usb_descriptors.c b/examples/device/cdc_msc_freertos/src/usb_descriptors.c index 373928e2f..7b22d46a7 100644 --- a/examples/device/cdc_msc_freertos/src/usb_descriptors.c +++ b/examples/device/cdc_msc_freertos/src/usb_descriptors.c @@ -116,8 +116,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // 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), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), diff --git a/examples/device/dfu_rt/src/usb_descriptors.c b/examples/device/dfu_rt/src/usb_descriptors.c index f96684b91..5cd661b2b 100644 --- a/examples/device/dfu_rt/src/usb_descriptors.c +++ b/examples/device/dfu_rt/src/usb_descriptors.c @@ -141,8 +141,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // 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. diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index a75bc5274..6bde2ff7a 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -101,8 +101,8 @@ enum uint8_t const desc_configuration[] = { - // interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // 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), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_BUFSIZE, 10) diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index 8adb336a0..5c769c9c9 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -99,8 +99,8 @@ enum uint8_t const desc_configuration[] = { - // interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // 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), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_BUFSIZE, 10) diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c index 3c2848e56..72ab1416c 100644 --- a/examples/device/midi_test/src/usb_descriptors.c +++ b/examples/device/midi_test/src/usb_descriptors.c @@ -90,8 +90,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // 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), // Interface number, string index, EP Out & EP In address, EP size TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64) diff --git a/examples/device/msc_dual_lun/src/usb_descriptors.c b/examples/device/msc_dual_lun/src/usb_descriptors.c index 90f7083d2..9128c4f75 100644 --- a/examples/device/msc_dual_lun/src/usb_descriptors.c +++ b/examples/device/msc_dual_lun/src/usb_descriptors.c @@ -98,8 +98,8 @@ enum uint8_t const desc_configuration[] = { - // interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // 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), // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index e398a5d4b..6ce36cfef 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -107,8 +107,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100, 1), + // 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), #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. diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index e22665706..675140260 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -165,8 +165,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // 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. diff --git a/examples/device/webusb_serial/src/usb_descriptors.c b/examples/device/webusb_serial/src/usb_descriptors.c index 386ca7458..1a2df76ca 100644 --- a/examples/device/webusb_serial/src/usb_descriptors.c +++ b/examples/device/webusb_serial/src/usb_descriptors.c @@ -95,8 +95,8 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // 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), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, 64), diff --git a/src/device/usbd.h b/src/device/usbd.h index 71829322b..beeec7e1c 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -156,8 +156,8 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re //------------- Configuration -------------// #define TUD_CONFIG_DESC_LEN (9) -// Interface count, string index, total length, attribute, power in mA, config number -#define TUD_CONFIG_DESCRIPTOR(_itfcount, _stridx, _total_len, _attribute, _power_ma, config_num) \ +// Config number, interface count, string index, total length, attribute, power in mA +#define TUD_CONFIG_DESCRIPTOR(config_num, _itfcount, _stridx, _total_len, _attribute, _power_ma) \ 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 //------------- CDC -------------// diff --git a/test/test/device/msc/test_msc_device.c b/test/test/device/msc/test_msc_device.c index 8f807183f..095c28170 100644 --- a/test/test/device/msc/test_msc_device.c +++ b/test/test/device/msc/test_msc_device.c @@ -62,8 +62,8 @@ enum uint8_t const data_desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // 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), // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EDPT_MSC_OUT, EDPT_MSC_IN, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), diff --git a/test/test/device/usbd/test_usbd.c b/test/test/device/usbd/test_usbd.c index 96afd8b43..06372b2e4 100644 --- a/test/test/device/usbd/test_usbd.c +++ b/test/test/device/usbd/test_usbd.c @@ -73,8 +73,8 @@ tusb_desc_device_t const data_desc_device = uint8_t const data_desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(0, 0, TUD_CONFIG_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, 0, 0, TUD_CONFIG_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), }; tusb_control_request_t const req_get_desc_device = @@ -211,8 +211,8 @@ void test_usbd_control_in_zlp(void) // ZLP must be return uint8_t zlp_desc_configuration[CFG_TUD_ENDOINT0_SIZE*2] = { - // Interface count, string index, total length, attribute, power in mA, config number - TUD_CONFIG_DESCRIPTOR(0, 0, CFG_TUD_ENDOINT0_SIZE*2, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100, 1), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, 0, 0, CFG_TUD_ENDOINT0_SIZE*2, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), }; desc_configuration = zlp_desc_configuration; -- cgit v1.3.1 From a3e50242b9239e1fc0c10d15651222fb3ae3f6d1 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 1 Apr 2020 17:07:28 +0700 Subject: add dcd_esp32s2 skip esp32s2_saola for make build since idf use cmake --- examples/device/cdc_msc_freertos/src/main.c | 17 +- examples/rules.mk | 4 +- src/portable/espressif/esp32s2/dcd_esp32s2.c | 749 +++++++++++++++++++++++++++ tools/build_all.py | 3 +- 4 files changed, 768 insertions(+), 5 deletions(-) create mode 100644 src/portable/espressif/esp32s2/dcd_esp32s2.c (limited to 'src') diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index 704d0803b..514ffa724 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -56,12 +56,12 @@ StaticTimer_t static_blink; TimerHandle_t blink_tm; // static task for usbd -#define USBD_STACK_SIZE 150 +#define USBD_STACK_SIZE (3*(configMINIMAL_STACK_SIZE/2)) StackType_t stack_usbd[USBD_STACK_SIZE]; StaticTask_t static_task_usbd; // static task for cdc -#define CDC_STACK_SZIE 128 +#define CDC_STACK_SZIE configMINIMAL_STACK_SIZE StackType_t stack_cdc[CDC_STACK_SZIE]; StaticTask_t static_task_cdc; @@ -71,6 +71,11 @@ void usb_device_task(void* param); void cdc_task(void* params); /*------------- MAIN -------------*/ +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 +// ESP32S2 entry function is app_main() +#define main app_main +#endif + int main(void) { board_init(); @@ -89,8 +94,16 @@ int main(void) (void) xTaskCreateStatic( cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, stack_cdc, &static_task_cdc); #endif +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 + // skip starting scheduler for ESP32 S2 (already started) + while(1) + { + vTaskSuspend(NULL); + } +#else vTaskStartScheduler(); NVIC_SystemReset(); +#endif return 0; } diff --git a/examples/rules.mk b/examples/rules.mk index 0343391cb..55c70af4b 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -15,14 +15,14 @@ SRC_C += \ src/common/tusb_fifo.c \ src/device/usbd.c \ src/device/usbd_control.c \ - src/class/msc/msc_device.c \ src/class/cdc/cdc_device.c \ src/class/dfu/dfu_rt_device.c \ src/class/hid/hid_device.c \ src/class/midi/midi_device.c \ + src/class/msc/msc_device.c \ + src/class/net/net_device.c \ src/class/usbtmc/usbtmc_device.c \ src/class/vendor/vendor_device.c \ - src/class/net/net_device.c \ src/portable/$(VENDOR)/$(CHIP_FAMILY)/dcd_$(CHIP_FAMILY).c # TinyUSB stack include diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c new file mode 100644 index 000000000..e4e8e30fe --- /dev/null +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -0,0 +1,749 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Additions Copyright (c) 2020, Espressif Systems (Shanghai) Co. Ltd. + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +// Espressif +#include "driver/periph_ctrl.h" +#include "freertos/xtensa_api.h" +#include "esp_intr_alloc.h" +#include "esp_log.h" +#include "esp32s2/rom/gpio.h" +#include "soc/dport_reg.h" +#include "soc/gpio_sig_map.h" +#include "soc/usb_periph.h" +#include "tusb_config.h" +// TinyUSB +#include "tusb_option.h" +//#include "descriptors_control.h" +#include "device/dcd.h" + + +#define USB_EP_DIRECTIONS 2 +#define USB_MAX_EP_NUM 16 + +typedef struct { + uint8_t *buffer; + uint16_t total_len; + uint16_t queued_len; + uint16_t max_size; + bool short_packet; +} xfer_ctl_t; + +static const char *TAG = "TUSB:DCD"; +static intr_handle_t usb_ih; +static volatile TU_ATTR_ALIGNED(4) uint32_t _setup_packet[6]; +static uint8_t s_setup_phase = 0; /* 00 - got setup, + 01 - got done setup, + 02 - setup cmd sent*/ + +#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] +static xfer_ctl_t xfer_status[USB_MAX_EP_NUM][USB_EP_DIRECTIONS]; + +static inline void readyfor1setup_pkg(int ep_num) +{ + USB0.out_ep_reg[ep_num].doeptsiz |= (1 << USB_SUPCNT0_S); // doeptsiz 29:30 will decremented on every setup received +} + +// Setup the control endpoint 0. +static void bus_reset(void) +{ + + for (int ep_num = 0; ep_num < USB_OUT_EP_NUM; ep_num++) { + USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK + } + + USB0.dcfg &= ~USB_DEVADDR_M; // reset address + + // Peripheral FIFO architecture + // + // --------------- 320 ( 1280 bytes ) + // | IN FIFO 3 | + // --------------- y + x + 16 + GRXFSIZ + // | IN FIFO 2 | + // --------------- x + 16 + GRXFSIZ + // | IN FIFO 1 | + // --------------- 16 + GRXFSIZ + // | IN FIFO 0 | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // FIFO sizes are set up by the following rules (each word 32-bits): + // All EP OUT shared a unique OUT FIFO which uses (based on page 1354 of Rev 17 of reference manual): + // * 10 locations in hardware for setup packets + setup control words + // (up to 3 setup packets). + // * 2 locations for OUT endpoint control words. + // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) + // * 1 location for global NAK (not required/used here). + // + // It is recommended to allocate 2 times the largest packet size, therefore + // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 50 + USB0.grstctl |= 0x10 << USB_TXFNUM_S; // fifo 0x10, + USB0.grstctl |= USB_TXFFLSH_M; // Flush fifo + USB0.grxfsiz = 50; + + USB0.gintmsk = USB_MODEMISMSK_M | + USB_SOFMSK_M | + USB_RXFLVIMSK_M | + USB_ERLYSUSPMSK_M | + USB_USBSUSPMSK_M | + USB_USBRSTMSK_M | + USB_ENUMDONEMSK_M | + USB_IEPINTMSK_M | + USB_OEPINTMSK_M | + USB_RESETDETMSK_M | + USB_DISCONNINTMSK_M; + + USB0.daintmsk |= USB_OUTEPMSK0_M | USB_INEPMSK0_M; + USB0.doepmsk |= USB_SETUPMSK_M | USB_XFERCOMPLMSK; + USB0.diepmsk |= USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M; + + USB0.gnptxfsiz = 16 << USB_NPTXFDEP_S; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) + + readyfor1setup_pkg(0); +} + +static void enum_done_processing(void) +{ + + ESP_EARLY_LOGV(TAG, "dcd_int_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); + // On current silicon on the Full Speed core, speed is fixed to Full Speed. + // However, keep for debugging and in case Low Speed is ever supported. + uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); + + // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL + if (enum_spd == 0x03) { // Full-Speed (PHY on 48 MHz) + USB0.in_ep_reg[0].diepctl &= ~USB_D_MPS0_V; // 64 bytes + USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall + xfer_status[0][TUSB_DIR_OUT].max_size = 64; + xfer_status[0][TUSB_DIR_IN].max_size = 64; + } else { + USB0.in_ep_reg[0].diepctl |= USB_D_MPS0_V; // 8 bytes + USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall + xfer_status[0][TUSB_DIR_OUT].max_size = 8; + xfer_status[0][TUSB_DIR_IN].max_size = 8; + } + + USB0.gintmsk |= USB_SOFMSK_M; // SOF unmask +} + + + + +/*------------------------------------------------------------------*/ +/* Controller API + *------------------------------------------------------------------*/ +void dcd_init(uint8_t rhport) +{ + ESP_LOGV(TAG, "DCD init - Start"); + + // A. Disconnect + ESP_LOGV(TAG, "DCD init - Soft DISCONNECT and Setting up"); + USB0.dctl |= USB_SFTDISCON_M; // Soft disconnect + + // B. Programming DCFG + /* If USB host misbehaves during status portion of control xfer + (non zero-length packet), send STALL back and discard. Full speed. */ + USB0.dcfg |= USB_NZSTSOUTHSHK_M | // NonZero .... STALL + (3 << 0); // dev speed: fullspeed 1.1 on 48 mhz // TODO no value in usb_reg.h (IDF-1476) + + USB0.gahbcfg |= USB_NPTXFEMPLVL_M | USB_GLBLLNTRMSK_M; // Global interruptions ON + USB0.gusbcfg |= USB_FORCEDEVMODE_M; // force devmode + + USB0.gotgctl &= ~(USB_BVALIDOVVAL_M | USB_BVALIDOVEN_M | USB_VBVALIDOVVAL_M); //no overrides +#ifdef CONFIG_IDF_TARGET_ESP32S2BETA // needed for beta chip only + //C. chip 7.2.2 hack + ESP_LOGV(TAG, "DCD init - chip ESP32-S2 beta hack"); + USB0.gotgctl = (0 << USB_BVALIDOVVAL_S); //B override value + ets_delay_us(20); + USB0.gotgctl = (0 << USB_BVALIDOVVAL_S) | (1 << USB_BVALIDOVEN_S); //B override value & enable + ets_delay_us(20); +#endif + + // C. Setting SNAKs, then connect + for (int n = 0; n < USB_OUT_EP_NUM; n++) { + USB0.out_ep_reg[n].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK + } + ESP_LOGV(TAG, "DCD init - Soft CONNECT"); + USB0.dctl &= ~USB_SFTDISCON_M; // Connect + + // D. Interruption masking + USB0.gintmsk = 0; //mask all + USB0.gotgint = ~0U; //clear OTG ints + USB0.gintsts = ~0U; //clear pending ints + USB0.gintmsk = USB_MODEMISMSK_M | + USB_SOFMSK_M | + USB_RXFLVIMSK_M | + USB_ERLYSUSPMSK_M | + USB_USBSUSPMSK_M | + USB_USBRSTMSK_M | + USB_ENUMDONEMSK_M | + USB_RESETDETMSK_M | + USB_DISCONNINTMSK_M; + ets_delay_us(100); +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void)rhport; + ESP_LOGV(TAG, "DCD init - Set address : %u", dev_addr); + USB0.dcfg |= ((dev_addr & USB_DEVADDR_V) << USB_DEVADDR_S); + // Response with status after changing device address + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} + +void dcd_set_config(uint8_t rhport, uint8_t config_num) +{ + (void)rhport; + (void)config_num; + // Nothing to do +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void)rhport; +} + +/*------------------------------------------------------------------*/ +/* DCD Endpoint port + *------------------------------------------------------------------*/ + +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) +{ + + ESP_LOGV(TAG, "DCD endpoint opened"); + (void)rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); + + // Unsupported endpoint numbers/size. + if ((desc_edpt->wMaxPacketSize.size > 64) || (epnum > 3)) { + return false; + } + + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + xfer->max_size = desc_edpt->wMaxPacketSize.size; + + if (dir == TUSB_DIR_OUT) { + out_ep[epnum].doepctl |= USB_USBACTEP0_M | + desc_edpt->bmAttributes.xfer << USB_EPTYPE0_S | + desc_edpt->wMaxPacketSize.size << USB_MPS0_S; + USB0.daintmsk |= (1 << (16 + epnum)); + } else { + // Peripheral FIFO architecture (Rev18 RM 29.11) + // + // --------------- 320 ( 1280 bytes ) + // | IN FIFO 3 | + // --------------- y + x + 16 + GRXFSIZ + // | IN FIFO 2 | + // --------------- x + 16 + GRXFSIZ + // | IN FIFO 1 | + // --------------- 16 + GRXFSIZ + // | IN FIFO 0 | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // Since OUT FIFO = 50, FIFO 0 = 16, average of FIFOx = (312-50-16) / 3 = 82 ~ 80 + in_ep[epnum].diepctl |= USB_D_USBACTEP1_M | + (epnum - 1) << USB_D_TXFNUM1_S | + desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | + desc_edpt->wMaxPacketSize.size << 0; + USB0.daintmsk |= (1 << (0 + epnum)); + + // Both TXFD and TXSA are in unit of 32-bit words + uint16_t const fifo_size = 80; + uint32_t const fifo_offset = (USB0.grxfsiz & USB_NPTXFDEP_V) + 16 + fifo_size * (epnum - 1); + USB0.dieptxf[epnum - 1] = (80 << USB_NPTXFDEP_S) | fifo_offset; + } + return true; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +{ + + (void)rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->short_packet = false; + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint8_t short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if (short_packet_size > 0 || (total_bytes == 0)) { + num_packets++; + } + + ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", + epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), + num_packets, total_bytes); + + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them + // here. + if (dir == TUSB_DIR_IN) { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + int bytes2fifo_left = total_bytes; + uint32_t val; // 32 bit val from 4 buff addresses + + USB0.in_ep_reg[epnum].diepint = ~0U; // clear all ints + USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; + USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK + while (bytes2fifo_left > 0) { // TODO move it to ep_in_handle (IDF-1475) + /* ATTENTION! In cases when CFG_TUD_ENDOINT0_SIZE, CFG_TUD_CDC_EPSIZE, CFG_TUD_MIDI_EPSIZE or + CFG_TUD_MSC_BUFSIZE < 4 next line can be a cause of an error.*/ + val = (*(buffer + 3) << 24) | + (*(buffer + 2) << 16) | + (*(buffer + 1) << 8) | + (*(buffer + 0) << 0); + ESP_LOGV(TAG, "Transfer 0x%08x -> FIFO%d", val, epnum); + USB0.fifo[epnum][0] = val; //copy and next buffer address + buffer += 4; + bytes2fifo_left -= 4; + } + // USB0.dtknqr4_fifoemptymsk |= (1 << epnum); + } else { + // Each complete packet for OUT xfers triggers XFRC. + USB0.out_ep_reg[epnum].doeptsiz = USB_PKTCNT0_M | + ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; + } + return true; +} + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if (dir == TUSB_DIR_IN) { + // Only disable currently enabled non-control endpoint + if ((epnum == 0) || !(in_ep[epnum].diepctl & USB_D_EPENA1_M)) { + in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M); + } else { + // Stop transmitting packets and NAK IN xfers. + in_ep[epnum].diepctl |= USB_DI_SNAK1_M; + while ((in_ep[epnum].diepint & USB_DI_SNAK1_M) == 0) + ; + + // Disable the endpoint. Note that both SNAK and STALL are set here. + in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M | + USB_D_EPDIS1_M); + while ((in_ep[epnum].diepint & USB_D_EPDISBLD0_M) == 0) + ; + in_ep[epnum].diepint = USB_D_EPDISBLD0_M; + } + + // Flush the FIFO, and wait until we have confirmed it cleared. + USB0.grstctl |= ((epnum - 1) << USB_TXFNUM_S); + USB0.grstctl |= USB_TXFFLSH_M; + while ((USB0.grstctl & USB_TXFFLSH_M) != 0) + ; + } else { + // Only disable currently enabled non-control endpoint + if ((epnum == 0) || !(out_ep[epnum].doepctl & USB_EPENA0_M)) { + out_ep[epnum].doepctl |= USB_STALL0_M; + } else { + // Asserting GONAK is required to STALL an OUT endpoint. + // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt + // anyway, and it can't be cleared by user code. If this while loop never + // finishes, we have bigger problems than just the stack. + USB0.dctl |= USB_SGOUTNAK_M; + while ((USB0.gintsts & USB_GOUTNAKEFF_M) == 0) + ; + + // Ditto here- disable the endpoint. Note that only STALL and not SNAK + // is set here. + out_ep[epnum].doepctl |= (USB_STALL0_M | USB_EPDIS0_M); + while ((out_ep[epnum].doepint & USB_EPDISBLD0_M) == 0) + ; + out_ep[epnum].doepint = USB_EPDISBLD0_M; + + // Allow other OUT endpoints to keep receiving. + USB0.dctl |= USB_CGOUTNAK_M; + } + } +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if (dir == TUSB_DIR_IN) { + in_ep[epnum].diepctl &= ~USB_D_STALL1_M; + + uint8_t eptype = (in_ep[epnum].diepctl & USB_D_EPTYPE1_M) >> USB_D_EPTYPE1_S; + // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt + // and bulk endpoints. + if (eptype == 2 || eptype == 3) { + in_ep[epnum].diepctl |= USB_DI_SETD0PID1_M; + } + } else { + out_ep[epnum].doepctl &= ~USB_STALL1_M; + + uint8_t eptype = (out_ep[epnum].doepctl & USB_EPTYPE1_M) >> USB_EPTYPE1_S; + // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt + // and bulk endpoints. + if (eptype == 2 || eptype == 3) { + out_ep[epnum].doepctl |= USB_DO_SETD0PID1_M; + } + } +} + +/*------------------------------------------------------------------*/ + +static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ uint16_t xfer_size) +{ + ESP_EARLY_LOGV(TAG, "USB - receive_packet"); + uint32_t *rx_fifo = USB0.fifo[0]; + + // See above TODO + // uint16_t remaining = (out_ep->DOEPTSIZ & UsbDOEPTSIZ_XFRSIZ_Msk) >> UsbDOEPTSIZ_XFRSIZ_Pos; + // xfer->queued_len = xfer->total_len - remaining; + + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint16_t to_recv_size; + + if (remaining <= xfer->max_size) { + // Avoid buffer overflow. + to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; + } else { + // Room for full packet, choose recv_size based on what the microcontroller + // claims. + to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; + } + + uint8_t to_recv_rem = to_recv_size % 4; + uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; + + // Do not assume xfer buffer is aligned. + uint8_t *base = (xfer->buffer + xfer->queued_len); + + // This for loop always runs at least once- skip if less than 4 bytes + // to collect. + if (to_recv_size >= 4) { + for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { + uint32_t tmp = (*rx_fifo); + base[i] = tmp & 0x000000FF; + base[i + 1] = (tmp & 0x0000FF00) >> 8; + base[i + 2] = (tmp & 0x00FF0000) >> 16; + base[i + 3] = (tmp & 0xFF000000) >> 24; + } + } + + // Do not read invalid bytes from RX FIFO. + if (to_recv_rem != 0) { + uint32_t tmp = (*rx_fifo); + uint8_t *last_32b_bound = base + to_recv_size_aligned; + + last_32b_bound[0] = tmp & 0x000000FF; + if (to_recv_rem > 1) { + last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; + } + if (to_recv_rem > 2) { + last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; + } + } + + xfer->queued_len += xfer_size; + + // Per USB spec, a short OUT packet (including length 0) is always + // indicative of the end of a transfer (at least for ctl, bulk, int). + xfer->short_packet = (xfer_size < xfer->max_size); +} + +static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, uint8_t fifo_num) +{ + + ESP_EARLY_LOGV(TAG, "USB - transmit_packet"); + uint32_t *tx_fifo = USB0.fifo[0]; + + uint16_t remaining = (in_ep->dieptsiz & 0x7FFFFU) >> USB_D_XFERSIZE0_S; + xfer->queued_len = xfer->total_len - remaining; + + uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; + uint8_t to_xfer_rem = to_xfer_size % 4; + uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; + + // Buffer might not be aligned to 32b, so we need to force alignment + // by copying to a temp var. + uint8_t *base = (xfer->buffer + xfer->queued_len); + + // This for loop always runs at least once- skip if less than 4 bytes + // to send off. + if (to_xfer_size >= 4) { + for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { + uint32_t tmp = base[i] | (base[i + 1] << 8) | + (base[i + 2] << 16) | (base[i + 3] << 24); + (*tx_fifo) = tmp; + } + } + + // Do not read beyond end of buffer if not divisible by 4. + if (to_xfer_rem != 0) { + uint32_t tmp = 0; + uint8_t *last_32b_bound = base + to_xfer_size_aligned; + + tmp |= last_32b_bound[0]; + if (to_xfer_rem > 1) { + tmp |= (last_32b_bound[1] << 8); + } + if (to_xfer_rem > 2) { + tmp |= (last_32b_bound[2] << 16); + } + + (*tx_fifo) = tmp; + } +} + +static void read_rx_fifo(void) +{ + // Pop control word off FIFO (completed xfers will have 2 control words, + // we only pop one ctl word each interrupt). + volatile uint32_t ctl_word = USB0.grxstsp; + uint8_t pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S; + uint8_t epnum = (ctl_word & USB_CHNUM_M) >> USB_CHNUM_S; + uint16_t bcnt = (ctl_word & USB_BCNT_M) >> USB_BCNT_S; + switch (pktsts) { + case 0x01: // Global OUT NAK (Interrupt) + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Global OUT NAK"); + break; + case 0x02: { // Out packet recvd + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet"); + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + receive_packet(xfer, bcnt); + } + break; + case 0x03: // Out packet done (Interrupt) + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet done"); + break; + case 0x04: // Setup packet done (Interrupt) + if (s_setup_phase == 0) { // only if setup is started + s_setup_phase = 1; + ESP_EARLY_LOGV(TAG, "TUSB IRQ - setup_phase 1"); //finished + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); + } + + break; + case 0x06: { // Setup packet recvd + s_setup_phase = 0; + ESP_EARLY_LOGV(TAG, "TUSB IRQ - setup_phase 0"); // new setup process + // For some reason, it's possible to get a mismatch between + // how many setup packets were received versus the location + // of the Setup packet done word. This leads to situations + // where stale setup packets are in the RX FIFO that were received + // after the core loaded the Setup packet done word. Workaround by + // only accepting one setup packet at a time for now. + _setup_packet[0] = (USB0.grxstsp); + _setup_packet[1] = (USB0.grxstsp); + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", + _setup_packet[0], _setup_packet[1]); + } + break; + default: // Invalid, do something here, like breakpoint? + break; + } +} + +static void handle_epout_ints(void) +{ + // GINTSTS will be cleared with DAINT == 0 + // DAINT for a given EP clears when DOEPINTx is cleared. + // DOEPINT will be cleared when DAINT's out bits are cleared. + for (int n = 0; n < USB_OUT_EP_NUM; n++) { + xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); + if (USB0.daint & (1 << (16 + n))) { + // SETUP packet Setup Phase done. + if ((USB0.out_ep_reg[n].doepint & USB_SETUP0_M)) { + USB0.out_ep_reg[n].doepint |= USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear + if (s_setup_phase == 1) { // only if setup is done, but not handled + s_setup_phase = 2; + ESP_EARLY_LOGV(TAG, "TUSB IRQ - setup_phase 2"); // sending to a handling queue + ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP OUT - Setup Phase done (irq-s 0x%08x)", USB0.out_ep_reg[n].doepint); + dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); + } + readyfor1setup_pkg(0); + } + + // OUT XFER complete (single packet).q + if (USB0.out_ep_reg[n].doepint & USB_XFERCOMPL0_M) { + + ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP OUT - XFER complete (single packet)"); + USB0.out_ep_reg[n].doepint = USB_XFERCOMPL0_M; + + // Transfer complete if short packet or total len is transferred + if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { + xfer->short_packet = false; + dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); + } else { + // Schedule another packet to be received. + USB0.out_ep_reg[n].doeptsiz = USB_PKTCNT0_M | + ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[n].doepctl |= USB_EPENA0_M | USB_CNAK0_M; + } + } + } + } +} + +static void handle_epin_ints(void) +{ + + // GINTSTS will be cleared with DAINT == 0 + // DAINT for a given EP clears when DIEPINTx is cleared. + // IEPINT will be cleared when DAINT's out bits are cleared. + for (uint32_t n = 0; n < USB_IN_EP_NUM; n++) { + xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN]; + + if (USB0.daint & (1 << (0 + n))) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP IN %u", n); + // IN XFER complete (entire xfer). + if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER complete!"); + USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M; + // USB0.dtknqr4_fifoemptymsk &= ~(1 << n); // Turn off TXFE b/c xfer inactive. + dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + } + + // XFER FIFO empty + if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER FIFO empty!"); + USB0.in_ep_reg[n].diepint = USB_D_TXFEMP0_M; + transmit_packet(xfer, &USB0.in_ep_reg[n], n); + } + } + } +} + + +static void dcd_int_handler(void) +{ + uint32_t int_status = USB0.gintsts; + uint32_t int_msk = USB0.gintmsk; + + if (int_status & USB_DISCONNINT_M) { + ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); + USB0.gintsts = USB_DISCONNINT_M; + } + + if (int_status & USB_USBRST_M) { + + ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); + USB0.gintsts = USB_USBRST_M; + bus_reset(); + } + + if (int_status & USB_RESETDET_M) { + ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset while suspend"); + USB0.gintsts = USB_RESETDET_M; + bus_reset(); + } + + if (int_status & USB_ENUMDONE_M) { + // ENUMDNE detects speed of the link. For full-speed, we + // always expect the same value. This interrupt is considered + // the end of reset. + USB0.gintsts = USB_ENUMDONE_M; + enum_done_processing(); + dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + } + + if (int_status & USB_SOF_M) { + USB0.gintsts = USB_SOF_M; + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); // do nothing actually + } + + if ((int_status & USB_RXFLVI_M) & (int_msk & USB_RXFLVIMSK_M)) { + ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); + read_rx_fifo(); + } + + // OUT endpoint interrupt handling. + if (int_status & USB_OEPINT_M) { + ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); + handle_epout_ints(); + } + + // IN endpoint interrupt handling. + if (int_status & USB_IEPINT_M) { + ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); + handle_epin_ints(); + } + + // Without handling + USB0.gintsts |= USB_CURMOD_INT_M | + USB_MODEMIS_M | + USB_OTGINT_M | + USB_NPTXFEMP_M | + USB_GINNAKEFF_M | + USB_GOUTNAKEFF | + USB_ERLYSUSP_M | + USB_USBSUSP_M | + USB_ISOOUTDROP_M | + USB_EOPF_M | + USB_EPMIS_M | + USB_INCOMPISOIN_M | + USB_INCOMPIP_M | + USB_FETSUSP_M | + USB_PTXFEMP_M; +} + +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); +} + +void dcd_int_disable(uint8_t rhport) +{ + (void)rhport; + esp_intr_free(usb_ih); +} diff --git a/tools/build_all.py b/tools/build_all.py index 0437bcaac..65f41422f 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -27,7 +27,8 @@ if len(sys.argv) > 2: all_boards.append(sys.argv[2]) else: for entry in os.scandir("hw/bsp"): - if entry.is_dir(): + # Skip board without board.mk e.g esp32s2 + if entry.is_dir() and os.path.exists(entry.path + "/board.mk"): all_boards.append(entry.name) all_boards.sort() -- cgit v1.3.1 From 0d5f3c7f04a6b66d46164b4d4dab22fd4124622b Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 2 Apr 2020 23:00:47 -0400 Subject: Set OSAL_TIMEOUT_WAIT_FOREVER to be a const, to avoid a pedantic gcc warning about signedness. --- src/osal/osal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/osal/osal.h b/src/osal/osal.h index 8b7527a7e..16ad34f3c 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -40,9 +40,10 @@ enum { OSAL_TIMEOUT_NOTIMEOUT = 0, // return immediately OSAL_TIMEOUT_NORMAL = 10, // default timeout - OSAL_TIMEOUT_WAIT_FOREVER = 0xFFFFFFFFUL }; +static const uint32_t OSAL_TIMEOUT_WAIT_FOREVER = 0xFFFFFFFFUL; + #define OSAL_TIMEOUT_CONTROL_XFER OSAL_TIMEOUT_WAIT_FOREVER typedef void (*osal_task_func_t)( void * ); -- cgit v1.3.1 From 55fd9fe392d9aa63c27ba39275c9fd7e5dd37049 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 2 Apr 2020 23:16:28 -0400 Subject: Typo of usbtmc. --- examples/device/usbtmc/src/usbtmc_app.c | 2 +- src/class/usbtmc/usbtmc_device.c | 2 +- src/class/usbtmc/usbtmc_device.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 0e39b4227..8f87a6dca 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -303,7 +303,7 @@ bool tud_usbtmc_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp) void tud_usbtmc_bulkIn_clearFeature_cb(void) { } -void tud_usmtmc_bulkOut_clearFeature_cb(void) +void tud_usbtmc_bulkOut_clearFeature_cb(void) { tud_usbtmc_start_bus_read(); } diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 916422752..92d8d34ef 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -590,7 +590,7 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r criticalEnter(); usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us criticalLeave(); - tud_usmtmc_bulkOut_clearFeature_cb(); + tud_usbtmc_bulkOut_clearFeature_cb(); } else if (ep_addr == usbtmc_state.ep_bulk_in) { diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index 4c52989c2..e231dd72d 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -69,7 +69,7 @@ void tud_usbtmc_open_cb(uint8_t interface_id); bool tud_usbtmc_msgBulkOut_start_cb(usbtmc_msg_request_dev_dep_out const * msgHeader); // transfer_complete does not imply that a message is complete. bool tud_usbtmc_msg_data_cb( void *data, size_t len, bool transfer_complete); -void tud_usmtmc_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer +void tud_usbtmc_bulkOut_clearFeature_cb(void); // Notice to clear and abort the pending BULK out transfer bool tud_usbtmc_msgBulkIn_request_cb(usbtmc_msg_request_dev_dep_in const * request); bool tud_usbtmc_msgBulkIn_complete_cb(void); -- cgit v1.3.1 From 84a9715958663e1056376b7d2b1369310db2eca6 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 2 Apr 2020 23:22:48 -0400 Subject: tu_verify: Change some define functions use do-while statement. --- src/common/tusb_verify.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 74150d6c5..fee291df6 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -79,8 +79,8 @@ #define _MESS_ERR(_err) printf("%s %d: failed, error = %s\r\n", __func__, __LINE__, tusb_strerr[_err]) #define _MESS_FAILED() printf("%s %d: assert failed\r\n", __func__, __LINE__) #else - #define _MESS_ERR(_err) - #define _MESS_FAILED() + #define _MESS_ERR(_err) do {} while (0) + #define _MESS_FAILED() do {} while (0) #endif // Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 @@ -94,7 +94,7 @@ #if defined(__riscv) #define TU_BREAKPOINT() do { __asm("ebreak\n"); } while(0) #else - #define TU_BREAKPOINT() + #define TU_BREAKPOINT() do {} while (0) #endif #endif -- cgit v1.3.1 From 1e7c3cf95eb4c1e078a9083277b2abbbda5e19bf Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 3 Apr 2020 17:09:38 +0700 Subject: update dcd esp32s2 fifo allocation to match current dcd synopsys --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 116 ++++++++++++++++----------- 1 file changed, 69 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index e4e8e30fe..b2593383c 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -26,6 +26,10 @@ * This file is part of the TinyUSB stack. */ +#include "tusb_option.h" + +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 && TUSB_OPT_DEVICE_ENABLED + // Espressif #include "driver/periph_ctrl.h" #include "freertos/xtensa_api.h" @@ -35,15 +39,12 @@ #include "soc/dport_reg.h" #include "soc/gpio_sig_map.h" #include "soc/usb_periph.h" -#include "tusb_config.h" -// TinyUSB -#include "tusb_option.h" -//#include "descriptors_control.h" -#include "device/dcd.h" +#include "device/dcd.h" -#define USB_EP_DIRECTIONS 2 -#define USB_MAX_EP_NUM 16 +// FIFO size in bytes TODO need confirmation from Espressif +#define EP_MAX USB_OUT_EP_NUM +#define EP_FIFO_SIZE 1280 typedef struct { uint8_t *buffer; @@ -61,7 +62,7 @@ static uint8_t s_setup_phase = 0; /* 00 - got setup, 02 - setup cmd sent*/ #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] -static xfer_ctl_t xfer_status[USB_MAX_EP_NUM][USB_EP_DIRECTIONS]; +static xfer_ctl_t xfer_status[EP_MAX][2]; static inline void readyfor1setup_pkg(int ep_num) { @@ -78,34 +79,37 @@ static void bus_reset(void) USB0.dcfg &= ~USB_DEVADDR_M; // reset address + // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture // - // --------------- 320 ( 1280 bytes ) - // | IN FIFO 3 | + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO MAX | + // --------------- + // | ... | // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | + // | IN FIFO 2 | // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | + // | IN FIFO 1 | // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | + // | IN FIFO 0 | // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | + // | OUT FIFO | + // | ( Shared ) | // --------------- 0 // - // FIFO sizes are set up by the following rules (each word 32-bits): - // All EP OUT shared a unique OUT FIFO which uses (based on page 1354 of Rev 17 of reference manual): - // * 10 locations in hardware for setup packets + setup control words - // (up to 3 setup packets). - // * 2 locations for OUT endpoint control words. - // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) - // * 1 location for global NAK (not required/used here). + // According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits): + // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN // - // It is recommended to allocate 2 times the largest packet size, therefore - // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 50 + // - All EP OUT shared a unique OUT FIFO which uses + // * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets). + // * 2 locations for OUT endpoint control words. + // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) + // * 1 location for global NAK (not required/used here). + // * It is recommended to allocate 2 times the largest packet size, therefore + // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 USB0.grstctl |= 0x10 << USB_TXFNUM_S; // fifo 0x10, USB0.grstctl |= USB_TXFFLSH_M; // Flush fifo - USB0.grxfsiz = 50; + USB0.grxfsiz = 52; USB0.gintmsk = USB_MODEMISMSK_M | USB_SOFMSK_M | @@ -123,7 +127,8 @@ static void bus_reset(void) USB0.doepmsk |= USB_SETUPMSK_M | USB_XFERCOMPLMSK; USB0.diepmsk |= USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M; - USB0.gnptxfsiz = 16 << USB_NPTXFDEP_S; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) + // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) + USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); readyfor1setup_pkg(0); } @@ -245,10 +250,8 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - // Unsupported endpoint numbers/size. - if ((desc_edpt->wMaxPacketSize.size > 64) || (epnum > 3)) { - return false; - } + TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 64); + TU_ASSERT(epnum < EP_MAX); xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = desc_edpt->wMaxPacketSize.size; @@ -259,33 +262,44 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) desc_edpt->wMaxPacketSize.size << USB_MPS0_S; USB0.daintmsk |= (1 << (16 + epnum)); } else { - // Peripheral FIFO architecture (Rev18 RM 29.11) + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture // - // --------------- 320 ( 1280 bytes ) - // | IN FIFO 3 | + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO MAX | + // --------------- + // | ... | // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | + // | IN FIFO 2 | // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | + // | IN FIFO 1 | // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | + // | IN FIFO 0 | // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | + // | OUT FIFO | + // | ( Shared ) | // --------------- 0 // - // Since OUT FIFO = 50, FIFO 0 = 16, average of FIFOx = (312-50-16) / 3 = 82 ~ 80 + // Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints + // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1) + // - Offset: GRXFSIZ + 16 + Size*(epnum-1) + // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". + in_ep[epnum].diepctl |= USB_D_USBACTEP1_M | - (epnum - 1) << USB_D_TXFNUM1_S | + epnum << USB_D_TXFNUM1_S | desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | desc_edpt->wMaxPacketSize.size << 0; USB0.daintmsk |= (1 << (0 + epnum)); - // Both TXFD and TXSA are in unit of 32-bit words - uint16_t const fifo_size = 80; - uint32_t const fifo_offset = (USB0.grxfsiz & USB_NPTXFDEP_V) + 16 + fifo_size * (epnum - 1); - USB0.dieptxf[epnum - 1] = (80 << USB_NPTXFDEP_S) | fifo_offset; + // Both TXFD and TXSA are in unit of 32-bit words. + // IN FIFO 0 was configured during enumeration, hence the "+ 16". + uint16_t const allocated_size = (USB0.grxfsiz & 0x0000ffff) + 16; + uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_MAX-1); + uint32_t const fifo_offset = allocated_size + fifo_size*(epnum-1); + + // DIEPTXF starts at FIFO #1. + USB0.dieptxf[epnum - 1] = (fifo_size << USB_NPTXFDEP_S) | fifo_offset; } return true; } @@ -320,12 +334,14 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to // here. if (dir == TUSB_DIR_IN) { // A full IN transfer (multiple packets, possibly) triggers XFRC. - int bytes2fifo_left = total_bytes; - uint32_t val; // 32 bit val from 4 buff addresses - USB0.in_ep_reg[epnum].diepint = ~0U; // clear all ints USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK + +#if 1 + //int bytes2fifo_left = tu_min16(total_bytes, xfer->max_size); + int bytes2fifo_left = total_bytes; + uint32_t val; // 32 bit val from 4 buff addresses while (bytes2fifo_left > 0) { // TODO move it to ep_in_handle (IDF-1475) /* ATTENTION! In cases when CFG_TUD_ENDOINT0_SIZE, CFG_TUD_CDC_EPSIZE, CFG_TUD_MIDI_EPSIZE or CFG_TUD_MSC_BUFSIZE < 4 next line can be a cause of an error.*/ @@ -338,7 +354,10 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to buffer += 4; bytes2fifo_left -= 4; } +#else +// transmit_packet(xfer, &USB0.in_ep_reg[epnum], epnum); // USB0.dtknqr4_fifoemptymsk |= (1 << epnum); +#endif } else { // Each complete packet for OUT xfers triggers XFRC. USB0.out_ep_reg[epnum].doeptsiz = USB_PKTCNT0_M | @@ -747,3 +766,6 @@ void dcd_int_disable(uint8_t rhport) (void)rhport; esp_intr_free(usb_ih); } + +#endif // OPT_MCU_ESP32S2 + -- cgit v1.3.1 From c2606c021386588675cba1e7dfee01b9488e8175 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 5 Apr 2020 18:22:16 +0700 Subject: allow application to implement its own os --- src/osal/osal.h | 2 ++ src/tusb_option.h | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/osal/osal.h b/src/osal/osal.h index 8b7527a7e..94c71e7d9 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -53,6 +53,8 @@ typedef void (*osal_task_func_t)( void * ); #include "osal_freertos.h" #elif CFG_TUSB_OS == OPT_OS_MYNEWT #include "osal_mynewt.h" +#elif CFG_TUSB_OS == OPT_OS_CUSTOM + #include "tusb_os_custom.h" // implemented by application #else #error OS is not supported yet #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 4a9d05712..6e2a2f125 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -93,9 +93,10 @@ /** \defgroup group_supported_os Supported RTOS * \ref CFG_TUSB_OS must be defined to one of these * @{ */ -#define OPT_OS_NONE 1 ///< No RTOS -#define OPT_OS_FREERTOS 2 ///< FreeRTOS -#define OPT_OS_MYNEWT 3 ///< Mynewt OS +#define OPT_OS_NONE 1 ///< No RTOS +#define OPT_OS_FREERTOS 2 ///< FreeRTOS +#define OPT_OS_MYNEWT 3 ///< Mynewt OS +#define OPT_OS_CUSTOM 4 ///< Custom OS is implemented by application /** @} */ -- cgit v1.3.1 From 2d6d298302be2d39374c36e7889341dee944d542 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 14:11:45 +0700 Subject: move irqhandler to application tud_isr() must be called by application to forward the irqhandle to the stack --- examples/device/board_test/Makefile | 6 +++ .../circuitplayground_express.c | 10 ++++ hw/bsp/ea4088qs/ea4088qs.c | 32 +++++++------ hw/bsp/feather_m0_express/feather_m0_express.c | 8 ++++ hw/bsp/feather_m4_express/feather_m4_express.c | 23 +++++++++ .../feather_nrf52840_express.c | 1 + hw/bsp/itsybitsy_m0/itsybitsy_m0.c | 8 ++++ hw/bsp/itsybitsy_m4/itsybitsy_m4.c | 23 +++++++++ hw/bsp/metro_m0_express/metro_m0_express.c | 8 ++++ hw/bsp/metro_m4_express/metro_m4_express.c | 23 +++++++++ hw/bsp/seeeduino_xiao/seeeduino_xiao.c | 8 ++++ src/device/dcd.h | 2 +- src/portable/microchip/samd/dcd_samd.c | 54 +--------------------- 13 files changed, 138 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/examples/device/board_test/Makefile b/examples/device/board_test/Makefile index 5a455078e..ce34c7ccd 100644 --- a/examples/device/board_test/Makefile +++ b/examples/device/board_test/Makefile @@ -9,4 +9,10 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +# board_test example is special example that doesn't enable device or host stack +# This can cause some TinyUSB API missing, this hack to allow us to fill those API +# to pass the compilation process +CFLAGS += \ + -D"tud_isr(x)= " \ + include ../../rules.mk diff --git a/hw/bsp/circuitplayground_express/circuitplayground_express.c b/hw/bsp/circuitplayground_express/circuitplayground_express.c index cdd75580a..5ddf1c624 100644 --- a/hw/bsp/circuitplayground_express/circuitplayground_express.c +++ b/hw/bsp/circuitplayground_express/circuitplayground_express.c @@ -35,6 +35,14 @@ #include "hpl_pm_config.h" #include "hpl/pm/hpl_pm_base.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_Handler(void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ @@ -134,6 +142,7 @@ int board_uart_write(void const * buf, int len) } #if CFG_TUSB_OS == OPT_OS_NONE + volatile uint32_t system_ticks = 0; void SysTick_Handler (void) { @@ -144,4 +153,5 @@ uint32_t board_millis(void) { return system_ticks; } + #endif diff --git a/hw/bsp/ea4088qs/ea4088qs.c b/hw/bsp/ea4088qs/ea4088qs.c index 83b2d6b1e..3d4ce0367 100644 --- a/hw/bsp/ea4088qs/ea4088qs.c +++ b/hw/bsp/ea4088qs/ea4088qs.c @@ -27,6 +27,23 @@ #include "chip.h" #include "../board.h" +//--------------------------------------------------------------------+ +// USB Interrupt Handler +//--------------------------------------------------------------------+ +void USB_IRQHandler(void) +{ + #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST + tuh_isr(0); + #endif + + #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE + tud_isr(0); + #endif +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ #define LED_PORT 2 #define LED_PIN 19 @@ -113,21 +130,6 @@ void board_init(void) LPC_USB->StCtrl = 0x3; } -//--------------------------------------------------------------------+ -// USB Interrupt Handler -//--------------------------------------------------------------------+ -void USB_IRQHandler(void) -{ - #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); - #endif - - #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); - #endif -} - - //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ diff --git a/hw/bsp/feather_m0_express/feather_m0_express.c b/hw/bsp/feather_m0_express/feather_m0_express.c index df81940f2..b373b829e 100644 --- a/hw/bsp/feather_m0_express/feather_m0_express.c +++ b/hw/bsp/feather_m0_express/feather_m0_express.c @@ -35,6 +35,14 @@ #include "hpl_pm_config.h" #include "hpl/pm/hpl_pm_base.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_Handler(void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ diff --git a/hw/bsp/feather_m4_express/feather_m4_express.c b/hw/bsp/feather_m4_express/feather_m4_express.c index 60939c99b..be8cc810b 100644 --- a/hw/bsp/feather_m4_express/feather_m4_express.c +++ b/hw/bsp/feather_m4_express/feather_m4_express.c @@ -32,6 +32,29 @@ #include "hpl/gclk/hpl_gclk_base.h" #include "hpl_mclk_config.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_0_Handler (void) +{ + tud_isr(0); +} + +void USB_1_Handler (void) +{ + tud_isr(0); +} + +void USB_2_Handler (void) +{ + tud_isr(0); +} + +void USB_3_Handler (void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ diff --git a/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c b/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c index 5dc3a4c40..a790b125d 100644 --- a/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c +++ b/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c @@ -92,6 +92,7 @@ void board_init(void) nrfx_uarte_init(&_uart_id, &uart_cfg, NULL); //uart_handler); + //------------- USB -------------// #if TUSB_OPT_DEVICE_ENABLED // Priorities 0, 1, 4 (nRF52) are reserved for SoftDevice // 2 is highest for application diff --git a/hw/bsp/itsybitsy_m0/itsybitsy_m0.c b/hw/bsp/itsybitsy_m0/itsybitsy_m0.c index dd7d4da04..ba31493ee 100644 --- a/hw/bsp/itsybitsy_m0/itsybitsy_m0.c +++ b/hw/bsp/itsybitsy_m0/itsybitsy_m0.c @@ -35,6 +35,14 @@ #include "hpl_pm_config.h" #include "hpl/pm/hpl_pm_base.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_Handler(void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ diff --git a/hw/bsp/itsybitsy_m4/itsybitsy_m4.c b/hw/bsp/itsybitsy_m4/itsybitsy_m4.c index 43432d3e3..0b9cc89e0 100644 --- a/hw/bsp/itsybitsy_m4/itsybitsy_m4.c +++ b/hw/bsp/itsybitsy_m4/itsybitsy_m4.c @@ -32,6 +32,29 @@ #include "hpl/gclk/hpl_gclk_base.h" #include "hpl_mclk_config.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_0_Handler (void) +{ + tud_isr(0); +} + +void USB_1_Handler (void) +{ + tud_isr(0); +} + +void USB_2_Handler (void) +{ + tud_isr(0); +} + +void USB_3_Handler (void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ diff --git a/hw/bsp/metro_m0_express/metro_m0_express.c b/hw/bsp/metro_m0_express/metro_m0_express.c index df81940f2..b373b829e 100644 --- a/hw/bsp/metro_m0_express/metro_m0_express.c +++ b/hw/bsp/metro_m0_express/metro_m0_express.c @@ -35,6 +35,14 @@ #include "hpl_pm_config.h" #include "hpl/pm/hpl_pm_base.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_Handler(void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ diff --git a/hw/bsp/metro_m4_express/metro_m4_express.c b/hw/bsp/metro_m4_express/metro_m4_express.c index 11a95b408..c735fa64d 100644 --- a/hw/bsp/metro_m4_express/metro_m4_express.c +++ b/hw/bsp/metro_m4_express/metro_m4_express.c @@ -32,6 +32,29 @@ #include "hpl/gclk/hpl_gclk_base.h" #include "hpl_mclk_config.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_0_Handler (void) +{ + tud_isr(0); +} + +void USB_1_Handler (void) +{ + tud_isr(0); +} + +void USB_2_Handler (void) +{ + tud_isr(0); +} + +void USB_3_Handler (void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ diff --git a/hw/bsp/seeeduino_xiao/seeeduino_xiao.c b/hw/bsp/seeeduino_xiao/seeeduino_xiao.c index a3602d66e..799c56261 100644 --- a/hw/bsp/seeeduino_xiao/seeeduino_xiao.c +++ b/hw/bsp/seeeduino_xiao/seeeduino_xiao.c @@ -35,6 +35,14 @@ #include "hpl_pm_config.h" #include "hpl/pm/hpl_pm_base.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_Handler(void) +{ + tud_isr(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ diff --git a/src/device/dcd.h b/src/device/dcd.h index 143a2de34..5e1181d1b 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -89,7 +89,7 @@ typedef struct TU_ATTR_ALIGNED(4) void dcd_init (uint8_t rhport); // Interrupt Handler -void dcd_isr (uint8_t rhport); +void dcd_isr (uint8_t rhport) TU_ATTR_USED; // Enable device interrupt void dcd_int_enable (uint8_t rhport); diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 148995520..9f91e3f96 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -324,7 +324,7 @@ void dcd_isr (uint8_t rhport) uint32_t int_status = USB->DEVICE.INTFLAG.reg & USB->DEVICE.INTENSET.reg; - /*------------- Interrupt Processing -------------*/ + // Start of Frame if ( int_status & USB_DEVICE_INTFLAG_SOF ) { USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_SOF; @@ -357,6 +357,7 @@ void dcd_isr (uint8_t rhport) dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } + // Enable of Reset if ( int_status & USB_DEVICE_INTFLAG_EORST ) { USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_EORST; @@ -381,55 +382,4 @@ void dcd_isr (uint8_t rhport) maybe_transfer_complete(); } -#if CFG_TUSB_MCU == OPT_MCU_SAMD51 - -/* - *------------------------------------------------------------------*/ -/* USB_EORSM_DNRSM, USB_EORST_RST, USB_LPMSUSP_DDISC, USB_LPM_DCONN, -USB_MSOF, USB_RAMACER, USB_RXSTP_TXSTP_0, USB_RXSTP_TXSTP_1, -USB_RXSTP_TXSTP_2, USB_RXSTP_TXSTP_3, USB_RXSTP_TXSTP_4, -USB_RXSTP_TXSTP_5, USB_RXSTP_TXSTP_6, USB_RXSTP_TXSTP_7, -USB_STALL0_STALL_0, USB_STALL0_STALL_1, USB_STALL0_STALL_2, -USB_STALL0_STALL_3, USB_STALL0_STALL_4, USB_STALL0_STALL_5, -USB_STALL0_STALL_6, USB_STALL0_STALL_7, USB_STALL1_0, USB_STALL1_1, -USB_STALL1_2, USB_STALL1_3, USB_STALL1_4, USB_STALL1_5, USB_STALL1_6, -USB_STALL1_7, USB_SUSPEND, USB_TRFAIL0_TRFAIL_0, USB_TRFAIL0_TRFAIL_1, -USB_TRFAIL0_TRFAIL_2, USB_TRFAIL0_TRFAIL_3, USB_TRFAIL0_TRFAIL_4, -USB_TRFAIL0_TRFAIL_5, USB_TRFAIL0_TRFAIL_6, USB_TRFAIL0_TRFAIL_7, -USB_TRFAIL1_PERR_0, USB_TRFAIL1_PERR_1, USB_TRFAIL1_PERR_2, -USB_TRFAIL1_PERR_3, USB_TRFAIL1_PERR_4, USB_TRFAIL1_PERR_5, -USB_TRFAIL1_PERR_6, USB_TRFAIL1_PERR_7, USB_UPRSM, USB_WAKEUP */ -void USB_0_Handler(void) { - dcd_isr(0); -} - -/* USB_SOF_HSOF */ -void USB_1_Handler(void) { - dcd_isr(0); -} - -// Bank zero is for OUT and SETUP transactions. -/* USB_TRCPT0_0, USB_TRCPT0_1, USB_TRCPT0_2, -USB_TRCPT0_3, USB_TRCPT0_4, USB_TRCPT0_5, -USB_TRCPT0_6, USB_TRCPT0_7 */ -void USB_2_Handler(void) { - dcd_isr(0); -} - -// Bank one is used for IN transactions. -/* USB_TRCPT1_0, USB_TRCPT1_1, USB_TRCPT1_2, -USB_TRCPT1_3, USB_TRCPT1_4, USB_TRCPT1_5, -USB_TRCPT1_6, USB_TRCPT1_7 */ -void USB_3_Handler(void) { - dcd_isr(0); -} - -#elif CFG_TUSB_MCU == OPT_MCU_SAMD21 - -void USB_Handler(void) { - dcd_isr(0); -} - -#endif - #endif -- cgit v1.3.1 From 050de0ec33752d0a24b53c9e18d82161185d0176 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 16:32:55 +0700 Subject: fix issue and typo with In token when Fifo empty fix transmit packet endpoint's fifo --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 45 ++++++++-------------------- 1 file changed, 12 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index b2593383c..3361bde36 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -57,9 +57,9 @@ typedef struct { static const char *TAG = "TUSB:DCD"; static intr_handle_t usb_ih; static volatile TU_ATTR_ALIGNED(4) uint32_t _setup_packet[6]; -static uint8_t s_setup_phase = 0; /* 00 - got setup, - 01 - got done setup, - 02 - setup cmd sent*/ +static volatile uint8_t s_setup_phase = 0; /* 00 - got setup, + 01 - got done setup, + 02 - setup cmd sent*/ #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] static xfer_ctl_t xfer_status[EP_MAX][2]; @@ -125,7 +125,7 @@ static void bus_reset(void) USB0.daintmsk |= USB_OUTEPMSK0_M | USB_INEPMSK0_M; USB0.doepmsk |= USB_SETUPMSK_M | USB_XFERCOMPLMSK; - USB0.diepmsk |= USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M; + USB0.diepmsk |= USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); @@ -334,30 +334,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to // here. if (dir == TUSB_DIR_IN) { // A full IN transfer (multiple packets, possibly) triggers XFRC. - USB0.in_ep_reg[epnum].diepint = ~0U; // clear all ints USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK - -#if 1 - //int bytes2fifo_left = tu_min16(total_bytes, xfer->max_size); - int bytes2fifo_left = total_bytes; - uint32_t val; // 32 bit val from 4 buff addresses - while (bytes2fifo_left > 0) { // TODO move it to ep_in_handle (IDF-1475) - /* ATTENTION! In cases when CFG_TUD_ENDOINT0_SIZE, CFG_TUD_CDC_EPSIZE, CFG_TUD_MIDI_EPSIZE or - CFG_TUD_MSC_BUFSIZE < 4 next line can be a cause of an error.*/ - val = (*(buffer + 3) << 24) | - (*(buffer + 2) << 16) | - (*(buffer + 1) << 8) | - (*(buffer + 0) << 0); - ESP_LOGV(TAG, "Transfer 0x%08x -> FIFO%d", val, epnum); - USB0.fifo[epnum][0] = val; //copy and next buffer address - buffer += 4; - bytes2fifo_left -= 4; - } -#else -// transmit_packet(xfer, &USB0.in_ep_reg[epnum], epnum); - // USB0.dtknqr4_fifoemptymsk |= (1 << epnum); -#endif + USB0.dtknqr4_fifoemptymsk |= (1 << epnum); } else { // Each complete packet for OUT xfers triggers XFRC. USB0.out_ep_reg[epnum].doeptsiz = USB_PKTCNT0_M | @@ -521,9 +500,8 @@ static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, uint8_t fifo_num) { - ESP_EARLY_LOGV(TAG, "USB - transmit_packet"); - uint32_t *tx_fifo = USB0.fifo[0]; + volatile uint32_t *tx_fifo = USB0.fifo[fifo_num]; uint16_t remaining = (in_ep->dieptsiz & 0x7FFFFU) >> USB_D_XFERSIZE0_S; xfer->queued_len = xfer->total_len - remaining; @@ -567,10 +545,11 @@ static void read_rx_fifo(void) { // Pop control word off FIFO (completed xfers will have 2 control words, // we only pop one ctl word each interrupt). - volatile uint32_t ctl_word = USB0.grxstsp; + uint32_t ctl_word = USB0.grxstsp; uint8_t pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S; uint8_t epnum = (ctl_word & USB_CHNUM_M) >> USB_CHNUM_S; uint16_t bcnt = (ctl_word & USB_BCNT_M) >> USB_BCNT_S; + switch (pktsts) { case 0x01: // Global OUT NAK (Interrupt) ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Global OUT NAK"); @@ -668,12 +647,12 @@ static void handle_epin_ints(void) if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER complete!"); USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M; - // USB0.dtknqr4_fifoemptymsk &= ~(1 << n); // Turn off TXFE b/c xfer inactive. + USB0.dtknqr4_fifoemptymsk &= ~(1 << n); // Turn off TXFE b/c xfer inactive. dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); } // XFER FIFO empty - if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { + if (USB0.in_ep_reg[n].diepint & USB_D_TXFEMP0_M) { ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER FIFO empty!"); USB0.in_ep_reg[n].diepint = USB_D_TXFEMP0_M; transmit_packet(xfer, &USB0.in_ep_reg[n], n); @@ -685,8 +664,8 @@ static void handle_epin_ints(void) static void dcd_int_handler(void) { - uint32_t int_status = USB0.gintsts; - uint32_t int_msk = USB0.gintmsk; + const uint32_t int_status = USB0.gintsts; + const uint32_t int_msk = USB0.gintmsk; if (int_status & USB_DISCONNINT_M) { ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); -- cgit v1.3.1 From c026236824e95d9409136cd48481b69e2cea56dc Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 16:33:04 +0700 Subject: house keeping --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index ddd99d7f1..125aa351c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -421,7 +421,7 @@ void tud_task (void) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Endpoint: 0x%02X, Bytes: %ld\r\n", ep_addr, event.xfer_complete.len); + TU_LOG2(" Endpoint: 0x%02X, Bytes: %lu\r\n", ep_addr, event.xfer_complete.len); _usbd_dev.ep_status[epnum][ep_dir].busy = false; -- cgit v1.3.1 From dc4bf02dcb8198c9647e13bc0f5b4e5fcdeef618 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 17:04:49 +0700 Subject: mass rename tud_isr to tud_irq_handler --- examples/device/board_test/Makefile | 2 +- hw/bsp/circuitplayground_express/circuitplayground_express.c | 2 +- hw/bsp/ea4088qs/ea4088qs.c | 2 +- hw/bsp/ea4357/ea4357.c | 4 ++-- hw/bsp/feather_m0_express/feather_m0_express.c | 2 +- hw/bsp/feather_m4_express/feather_m4_express.c | 8 ++++---- hw/bsp/itsybitsy_m0/itsybitsy_m0.c | 2 +- hw/bsp/itsybitsy_m4/itsybitsy_m4.c | 8 ++++---- hw/bsp/lpcxpresso1769/lpcxpresso1769.c | 2 +- hw/bsp/mbed1768/mbed1768.c | 2 +- hw/bsp/mcb1800/mcb1800.c | 4 ++-- hw/bsp/metro_m0_express/metro_m0_express.c | 2 +- hw/bsp/metro_m4_express/metro_m4_express.c | 8 ++++---- hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c | 2 +- hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c | 2 +- hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c | 2 +- hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c | 4 ++-- hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c | 4 ++-- hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c | 4 ++-- hw/bsp/ngx4330/ngx4330.c | 4 ++-- hw/bsp/samg55xplained/samg55xplained.c | 2 +- hw/bsp/seeeduino_xiao/seeeduino_xiao.c | 2 +- hw/bsp/teensy_40/teensy40.c | 4 ++-- src/device/usbd.h | 2 +- 24 files changed, 40 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/examples/device/board_test/Makefile b/examples/device/board_test/Makefile index ce34c7ccd..66d8571cf 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_isr(x)= " \ + -D"tud_irq_handler(x)= " \ include ../../rules.mk diff --git a/hw/bsp/circuitplayground_express/circuitplayground_express.c b/hw/bsp/circuitplayground_express/circuitplayground_express.c index 5ddf1c624..0e2583383 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_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/ea4088qs/ea4088qs.c b/hw/bsp/ea4088qs/ea4088qs.c index 3d4ce0367..756c9d384 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_isr(0); + tud_irq_handler(0); #endif } diff --git a/hw/bsp/ea4357/ea4357.c b/hw/bsp/ea4357/ea4357.c index f5d2a199e..87b19260e 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_isr(0); + tud_irq_handler(0); #endif } @@ -251,7 +251,7 @@ void USB1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_isr(1); + tud_irq_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 b373b829e..83b20793e 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_isr(0); + tud_irq_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 be8cc810b..8b4764cd0 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_isr(0); + tud_irq_handler(0); } void USB_1_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_2_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_3_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/itsybitsy_m0/itsybitsy_m0.c b/hw/bsp/itsybitsy_m0/itsybitsy_m0.c index ba31493ee..93661b899 100644 --- a/hw/bsp/itsybitsy_m0/itsybitsy_m0.c +++ b/hw/bsp/itsybitsy_m0/itsybitsy_m0.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/itsybitsy_m4/itsybitsy_m4.c b/hw/bsp/itsybitsy_m4/itsybitsy_m4.c index 0b9cc89e0..3ae9565c9 100644 --- a/hw/bsp/itsybitsy_m4/itsybitsy_m4.c +++ b/hw/bsp/itsybitsy_m4/itsybitsy_m4.c @@ -37,22 +37,22 @@ //--------------------------------------------------------------------+ void USB_0_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_1_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_2_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_3_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c index 76755e89f..9d955a763 100644 --- a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c +++ b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c @@ -153,7 +153,7 @@ void USB_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } diff --git a/hw/bsp/mbed1768/mbed1768.c b/hw/bsp/mbed1768/mbed1768.c index 66cf44a0e..cda508803 100644 --- a/hw/bsp/mbed1768/mbed1768.c +++ b/hw/bsp/mbed1768/mbed1768.c @@ -145,7 +145,7 @@ void USB_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } diff --git a/hw/bsp/mcb1800/mcb1800.c b/hw/bsp/mcb1800/mcb1800.c index 6d5284869..e172bbfb0 100644 --- a/hw/bsp/mcb1800/mcb1800.c +++ b/hw/bsp/mcb1800/mcb1800.c @@ -182,7 +182,7 @@ void USB0_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } @@ -193,7 +193,7 @@ void USB1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_isr(1); + tud_irq_handler(1); #endif } //--------------------------------------------------------------------+ diff --git a/hw/bsp/metro_m0_express/metro_m0_express.c b/hw/bsp/metro_m0_express/metro_m0_express.c index b373b829e..83b20793e 100644 --- a/hw/bsp/metro_m0_express/metro_m0_express.c +++ b/hw/bsp/metro_m0_express/metro_m0_express.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/metro_m4_express/metro_m4_express.c b/hw/bsp/metro_m4_express/metro_m4_express.c index c735fa64d..61b270de0 100644 --- a/hw/bsp/metro_m4_express/metro_m4_express.c +++ b/hw/bsp/metro_m4_express/metro_m4_express.c @@ -37,22 +37,22 @@ //--------------------------------------------------------------------+ void USB_0_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_1_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_2_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } void USB_3_Handler (void) { - tud_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c b/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c index a76e2d9b6..d061c0e04 100644 --- a/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c +++ b/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c @@ -125,7 +125,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } diff --git a/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c b/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c index 955344884..874e4517e 100644 --- a/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c +++ b/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c @@ -125,7 +125,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } diff --git a/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c b/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c index 708397f7f..17727c0ab 100644 --- a/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c +++ b/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c @@ -124,7 +124,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } diff --git a/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c b/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c index a21dcdbfc..ed29be4d3 100644 --- a/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c +++ b/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c @@ -128,7 +128,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } @@ -139,7 +139,7 @@ void USB_OTG2_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_isr(1); + tud_irq_handler(1); #endif } diff --git a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c index a21dcdbfc..ed29be4d3 100644 --- a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c +++ b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c @@ -128,7 +128,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } @@ -139,7 +139,7 @@ void USB_OTG2_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_isr(1); + tud_irq_handler(1); #endif } diff --git a/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c b/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c index a21dcdbfc..ed29be4d3 100644 --- a/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c +++ b/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c @@ -128,7 +128,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } @@ -139,7 +139,7 @@ void USB_OTG2_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_isr(1); + tud_irq_handler(1); #endif } diff --git a/hw/bsp/ngx4330/ngx4330.c b/hw/bsp/ngx4330/ngx4330.c index e1bafff8d..a789a8819 100644 --- a/hw/bsp/ngx4330/ngx4330.c +++ b/hw/bsp/ngx4330/ngx4330.c @@ -229,7 +229,7 @@ void USB0_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } @@ -240,7 +240,7 @@ void USB1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_isr(1); + tud_irq_handler(1); #endif } diff --git a/hw/bsp/samg55xplained/samg55xplained.c b/hw/bsp/samg55xplained/samg55xplained.c index 1eb5105b9..4f894a2bc 100644 --- a/hw/bsp/samg55xplained/samg55xplained.c +++ b/hw/bsp/samg55xplained/samg55xplained.c @@ -100,7 +100,7 @@ void board_init(void) void UDP_Handler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } diff --git a/hw/bsp/seeeduino_xiao/seeeduino_xiao.c b/hw/bsp/seeeduino_xiao/seeeduino_xiao.c index 799c56261..d8dbd2b1c 100644 --- a/hw/bsp/seeeduino_xiao/seeeduino_xiao.c +++ b/hw/bsp/seeeduino_xiao/seeeduino_xiao.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_isr(0); + tud_irq_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/teensy_40/teensy40.c b/hw/bsp/teensy_40/teensy40.c index 7c2bee539..9e49ed19c 100644 --- a/hw/bsp/teensy_40/teensy40.c +++ b/hw/bsp/teensy_40/teensy40.c @@ -129,7 +129,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_isr(0); + tud_irq_handler(0); #endif } @@ -140,7 +140,7 @@ void USB_OTG2_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_isr(1); + tud_irq_handler(1); #endif } diff --git a/src/device/usbd.h b/src/device/usbd.h index beeec7e1c..683366f98 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_isr dcd_isr +#define tud_irq_handler dcd_isr // Check if device is connected and configured bool tud_mounted(void); -- cgit v1.3.1 From fb05451a26ebafd67de27271fd22b85d36fa3c62 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 17:24:22 +0700 Subject: mass rename dcd_isr() to dcd_irq_handler() --- src/device/dcd.h | 2 +- src/device/usbd.h | 2 +- src/portable/microchip/samd/dcd_samd.c | 2 +- src/portable/microchip/samg/dcd_samg.c | 2 +- src/portable/nuvoton/nuc120/dcd_nuc120.c | 2 +- src/portable/nuvoton/nuc121/dcd_nuc121.c | 2 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 2 +- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 2 +- src/portable/nxp/transdimension/dcd_transdimension.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index 5e1181d1b..7e976e0ed 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -89,7 +89,7 @@ typedef struct TU_ATTR_ALIGNED(4) void dcd_init (uint8_t rhport); // Interrupt Handler -void dcd_isr (uint8_t rhport) TU_ATTR_USED; +void dcd_irq_handler (uint8_t rhport) TU_ATTR_USED; // Enable device interrupt void dcd_int_enable (uint8_t rhport); diff --git a/src/device/usbd.h b/src/device/usbd.h index 683366f98..2bb9821ed 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_isr +#define tud_irq_handler dcd_irq_handler // Check if device is connected and configured bool tud_mounted(void); diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 9f91e3f96..420526bfa 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -318,7 +318,7 @@ void maybe_transfer_complete(void) { } -void dcd_isr (uint8_t rhport) +void dcd_irq_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 882072521..93d9029d6 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -333,7 +333,7 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) //--------------------------------------------------------------------+ // ISR //--------------------------------------------------------------------+ -void dcd_isr(uint8_t rhport) +void dcd_irq_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/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 4e1db24a4..f85af6d1e 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -424,7 +424,7 @@ void USBD_IRQHandler(void) USBD->INTSTS = status & enabled_irqs; } -void dcd_isr(uint8_t rhport) +void dcd_irq_handler(uint8_t rhport) { (void) rhport; USBD_IRQHandler(); diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 25d723d96..fbc2361a8 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -440,7 +440,7 @@ void USBD_IRQHandler(void) USBD->INTSTS = status & enabled_irqs; } -void dcd_isr(uint8_t rhport) +void dcd_irq_handler(uint8_t rhport) { (void) rhport; USBD_IRQHandler(); diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 8457e686b..c448577ae 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -641,7 +641,7 @@ void USBD_IRQHandler(void) } } -void dcd_isr(uint8_t rhport) +void dcd_irq_handler(uint8_t rhport) { (void) rhport; USBD_IRQHandler(); diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 89a4ba3f8..884260f31 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -495,7 +495,7 @@ static void dd_complete_isr(uint8_t rhport, uint8_t ep_id) } // main USB IRQ handler -void dcd_isr(uint8_t rhport) +void dcd_irq_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/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index d400a30e3..2872f1435 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -492,7 +492,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t //--------------------------------------------------------------------+ // ISR //--------------------------------------------------------------------+ -void dcd_isr(uint8_t rhport) +void dcd_irq_handler(uint8_t rhport) { dcd_registers_t* const dcd_reg = _dcd_controller[rhport].regs; -- cgit v1.3.1 From 4179334aca5b4085912f895ac2e5e8586efefd67 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 17:35:11 +0700 Subject: call tud_irq_handler() for all nrf5x board --- hw/bsp/adafruit_clue/adafruit_clue.c | 9 +++++++++ hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c | 8 ++++++++ hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c | 8 ++++++++ hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c | 8 ++++++++ hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c | 8 ++++++++ hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c | 8 ++++++++ hw/bsp/pca10056/pca10056.c | 8 ++++++++ hw/bsp/pca10059/pca10059.c | 8 ++++++++ hw/bsp/pca10100/pca10100.c | 8 ++++++++ hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c | 8 ++++++++ src/device/dcd.h | 2 +- src/portable/nordic/nrf5x/dcd_nrf5x.c | 4 +++- 12 files changed, 85 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/hw/bsp/adafruit_clue/adafruit_clue.c b/hw/bsp/adafruit_clue/adafruit_clue.c index 67b5ffda4..7b090dd45 100644 --- a/hw/bsp/adafruit_clue/adafruit_clue.c +++ b/hw/bsp/adafruit_clue/adafruit_clue.c @@ -35,6 +35,15 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c b/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c index 941716c2f..a3ab49a5d 100644 --- a/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c +++ b/hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c @@ -36,6 +36,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c b/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c index 30742ab9f..17e619704 100644 --- a/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c +++ b/hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c @@ -35,6 +35,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c b/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c index a790b125d..e36615ee1 100644 --- a/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c +++ b/hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c @@ -36,6 +36,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c b/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c index 473abc2d1..fb4ef9af2 100644 --- a/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c +++ b/hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c @@ -35,6 +35,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c b/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c index 86f02d3e7..99db842ac 100644 --- a/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c +++ b/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c @@ -35,6 +35,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/pca10056/pca10056.c b/hw/bsp/pca10056/pca10056.c index 8d9764c3a..ec34dbb9e 100644 --- a/hw/bsp/pca10056/pca10056.c +++ b/hw/bsp/pca10056/pca10056.c @@ -36,6 +36,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/pca10059/pca10059.c b/hw/bsp/pca10059/pca10059.c index e0f4bc930..72a85a9fa 100644 --- a/hw/bsp/pca10059/pca10059.c +++ b/hw/bsp/pca10059/pca10059.c @@ -35,6 +35,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/pca10100/pca10100.c b/hw/bsp/pca10100/pca10100.c index 8d9764c3a..ec34dbb9e 100644 --- a/hw/bsp/pca10100/pca10100.c +++ b/hw/bsp/pca10100/pca10100.c @@ -36,6 +36,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c b/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c index 8bb5a1739..62e6fa045 100644 --- a/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c +++ b/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c @@ -35,6 +35,14 @@ #include "nrf_soc.h" #endif +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ diff --git a/src/device/dcd.h b/src/device/dcd.h index 7e976e0ed..dbdc19dd3 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -89,7 +89,7 @@ typedef struct TU_ATTR_ALIGNED(4) void dcd_init (uint8_t rhport); // Interrupt Handler -void dcd_irq_handler (uint8_t rhport) TU_ATTR_USED; +void dcd_irq_handler(uint8_t rhport) TU_ATTR_USED; // Enable device interrupt void dcd_int_enable (uint8_t rhport); diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 2ce288d6c..e54f475ec 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -359,8 +359,10 @@ void bus_reset(void) _dcd.xfer[0][TUSB_DIR_OUT].mps = MAX_PACKET_SIZE; } -void USBD_IRQHandler(void) +void dcd_irq_handler(uint8_t rhport) { + (void) rhport; + uint32_t const inten = NRF_USBD->INTEN; uint32_t int_status = 0; -- cgit v1.3.1 From 138965d1d13113c90eae7f2e6c04168754337934 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 17:43:56 +0700 Subject: add tud_irq_handler() to all NUC board --- hw/bsp/nutiny_nuc121s/nutiny_nuc121.c | 11 +++++++++++ hw/bsp/nutiny_nuc125s/nutiny_nuc125.c | 11 +++++++++++ hw/bsp/nutiny_nuc126v/nutiny_nuc126.c | 12 ++++++++++++ hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c | 11 +++++++++++ hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c | 11 +++++++++++ src/portable/nuvoton/nuc120/dcd_nuc120.c | 10 +++------- src/portable/nuvoton/nuc121/dcd_nuc121.c | 10 +++------- src/portable/nuvoton/nuc505/dcd_nuc505.c | 10 +++------- 8 files changed, 65 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/hw/bsp/nutiny_nuc121s/nutiny_nuc121.c b/hw/bsp/nutiny_nuc121s/nutiny_nuc121.c index dfa67206b..115c88165 100644 --- a/hw/bsp/nutiny_nuc121s/nutiny_nuc121.c +++ b/hw/bsp/nutiny_nuc121s/nutiny_nuc121.c @@ -29,6 +29,17 @@ #include "clk.h" #include "sys.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT PB #define LED_PIN 4 #define LED_PIN_IO PB4 diff --git a/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c b/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c index dfa67206b..115c88165 100644 --- a/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c +++ b/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c @@ -29,6 +29,17 @@ #include "clk.h" #include "sys.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT PB #define LED_PIN 4 #define LED_PIN_IO PB4 diff --git a/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c b/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c index bdc154559..214873f8c 100644 --- a/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c +++ b/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c @@ -29,6 +29,18 @@ #include "clk.h" #include "sys.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT PC #define LED_PIN 9 #define LED_PIN_IO PC9 diff --git a/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c b/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c index 0650a4e3a..906d44454 100644 --- a/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c +++ b/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c @@ -29,6 +29,17 @@ #include "clk.h" #include "sys.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT PB #define LED_PIN 0 #define LED_PIN_IO PB0 diff --git a/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c b/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c index 3a341de9a..9018e698d 100644 --- a/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c +++ b/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c @@ -27,6 +27,17 @@ #include "bsp/board.h" #include "NUC505Series.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USBD_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT PC #define LED_PIN 3 #define LED_STATE_ON 0 diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index f85af6d1e..e7bb4d431 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -306,8 +306,10 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) ep->CFG |= USBD_CFG_CSTALL_Msk; } -void USBD_IRQHandler(void) +void dcd_irq_handler(uint8_t rhport) { + (void) rhport; + uint32_t status = USBD->INTSTS; uint32_t state = USBD->ATTR & 0xf; @@ -424,10 +426,4 @@ void USBD_IRQHandler(void) USBD->INTSTS = status & enabled_irqs; } -void dcd_irq_handler(uint8_t rhport) -{ - (void) rhport; - USBD_IRQHandler(); -} - #endif diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index fbc2361a8..e9fbc2220 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -312,8 +312,10 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) ep->CFG |= USBD_CFG_CSTALL_Msk; } -void USBD_IRQHandler(void) +void dcd_irq_handler(uint8_t rhport) { + (void) rhport; + uint32_t status = USBD->INTSTS; #ifdef SUPPORT_LPM uint32_t state = USBD->ATTR & 0x300f; @@ -440,10 +442,4 @@ void USBD_IRQHandler(void) USBD->INTSTS = status & enabled_irqs; } -void dcd_irq_handler(uint8_t rhport) -{ - (void) rhport; - USBD_IRQHandler(); -} - #endif diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index c448577ae..bb010a408 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -430,8 +430,10 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) } } -void USBD_IRQHandler(void) +void dcd_irq_handler(uint8_t rhport) { + (void) rhport; + uint32_t status = USBD->GINTSTS; /* USB interrupt */ @@ -641,10 +643,4 @@ void USBD_IRQHandler(void) } } -void dcd_irq_handler(uint8_t rhport) -{ - (void) rhport; - USBD_IRQHandler(); -} - #endif -- cgit v1.3.1 From 06377a341b6bc78e107554427b9278233d77c026 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 18:00:37 +0700 Subject: add tud_irq_handler() for all lpc ip3511 (13, 15, 11) --- hw/bsp/lpcxpresso11u37/lpcxpresso11u37.c | 11 ++++++++++ hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c | 11 ++++++++++ hw/bsp/lpcxpresso1347/lpcxpresso1347.c | 11 ++++++++++ hw/bsp/lpcxpresso1549/lpcxpresso1549.c | 11 ++++++++++ hw/bsp/lpcxpresso1769/lpcxpresso1769.c | 31 +++++++++++++++------------- hw/bsp/lpcxpresso51u68/lpcxpresso51u68.c | 11 ++++++++++ hw/bsp/lpcxpresso54114/lpcxpresso54114.c | 11 ++++++++++ hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c | 16 ++++++++++++++ src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 6 +++--- 9 files changed, 102 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/hw/bsp/lpcxpresso11u37/lpcxpresso11u37.c b/hw/bsp/lpcxpresso11u37/lpcxpresso11u37.c index 546dd3d13..6f2ae80e8 100644 --- a/hw/bsp/lpcxpresso11u37/lpcxpresso11u37.c +++ b/hw/bsp/lpcxpresso11u37/lpcxpresso11u37.c @@ -27,6 +27,17 @@ #include "chip.h" #include "../board.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//---------------------------------------------------------------- ----+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT 1 #define LED_PIN 24 #define LED_STATE_ON 0 diff --git a/hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c b/hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c index d062de7c3..193df3bb1 100644 --- a/hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c +++ b/hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c @@ -27,6 +27,17 @@ #include "chip.h" #include "../board.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT 2 #define LED_PIN 17 #define LED_STATE_ON 0 diff --git a/hw/bsp/lpcxpresso1347/lpcxpresso1347.c b/hw/bsp/lpcxpresso1347/lpcxpresso1347.c index cc1a8deae..14a0009e4 100644 --- a/hw/bsp/lpcxpresso1347/lpcxpresso1347.c +++ b/hw/bsp/lpcxpresso1347/lpcxpresso1347.c @@ -27,6 +27,17 @@ #include "chip.h" #include "../board.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT 0 #define LED_PIN 7 diff --git a/hw/bsp/lpcxpresso1549/lpcxpresso1549.c b/hw/bsp/lpcxpresso1549/lpcxpresso1549.c index 5f806d851..2ae8d7506 100644 --- a/hw/bsp/lpcxpresso1549/lpcxpresso1549.c +++ b/hw/bsp/lpcxpresso1549/lpcxpresso1549.c @@ -27,6 +27,17 @@ #include "chip.h" #include "../board.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT 0 #define LED_PIN 25 diff --git a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c index 9d955a763..3b5c9dcab 100644 --- a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c +++ b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c @@ -27,6 +27,23 @@ #include "chip.h" #include "../board.h" +//--------------------------------------------------------------------+ +// USB Interrupt Handler +//--------------------------------------------------------------------+ +void USB_IRQHandler(void) +{ + #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST + tuh_isr(0); + #endif + + #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE + tud_irq_handler(0); + #endif +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT 0 #define LED_PIN 22 #define LED_STATE_ON 1 @@ -143,20 +160,6 @@ void board_init(void) #endif } -//--------------------------------------------------------------------+ -// USB Interrupt Handler -//--------------------------------------------------------------------+ -void USB_IRQHandler(void) -{ - #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); - #endif - - #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); - #endif -} - //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ diff --git a/hw/bsp/lpcxpresso51u68/lpcxpresso51u68.c b/hw/bsp/lpcxpresso51u68/lpcxpresso51u68.c index 11b190b92..2a314388d 100644 --- a/hw/bsp/lpcxpresso51u68/lpcxpresso51u68.c +++ b/hw/bsp/lpcxpresso51u68/lpcxpresso51u68.c @@ -30,6 +30,17 @@ #include "fsl_power.h" #include "fsl_iocon.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB0_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT 0 #define LED_PIN 29 #define LED_STATE_ON 0 diff --git a/hw/bsp/lpcxpresso54114/lpcxpresso54114.c b/hw/bsp/lpcxpresso54114/lpcxpresso54114.c index d86af58c8..847accb67 100644 --- a/hw/bsp/lpcxpresso54114/lpcxpresso54114.c +++ b/hw/bsp/lpcxpresso54114/lpcxpresso54114.c @@ -30,6 +30,17 @@ #include "fsl_power.h" #include "fsl_iocon.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB0_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT 0 #define LED_PIN 29 #define LED_STATE_ON 0 diff --git a/hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c b/hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c index e595634a7..31519dc8f 100644 --- a/hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c +++ b/hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c @@ -30,6 +30,22 @@ #include "fsl_power.h" #include "fsl_iocon.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB0_IRQHandler(void) +{ + tud_irq_handler(0); +} + +void USB1_IRQHandler(void) +{ + tud_irq_handler(1); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT 1 #define LED_PIN 6 #define LED_STATE_ON 0 diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 5b2bd83e9..9af8e6019 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -49,13 +49,11 @@ // LPC 11Uxx, 13xx, 15xx use lpcopen #include "chip.h" #define DCD_REGS LPC_USB - #define DCD_IRQHandler USB_IRQHandler #elif CFG_TUSB_MCU == OPT_MCU_LPC51UXX || CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ CFG_TUSB_MCU == OPT_MCU_LPC55XX // TODO 55xx has dual usb controllers #include "fsl_device_registers.h" #define DCD_REGS USB0 - #define DCD_IRQHandler USB0_IRQHandler #endif @@ -335,8 +333,10 @@ static void process_xfer_isr(uint32_t int_status) } } -void DCD_IRQHandler(void) +void dcd_irq_handler(uint8_t rhport) { + (void) rhport; // TODO support multiple USB on supported mcu such as LPC55s69 + uint32_t const cmd_stat = DCD_REGS->DEVCMDSTAT; uint32_t int_status = DCD_REGS->INTSTAT & DCD_REGS->INTEN; -- cgit v1.3.1 From 22a9b05834504471a4446f45e5f8153a8f99d9fa Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 19:49:25 +0700 Subject: rename dcd_int_handler to dcd_irq_handler for consistency with other port --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 3361bde36..df4cbf445 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -136,7 +136,7 @@ static void bus_reset(void) static void enum_done_processing(void) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); // On current silicon on the Full Speed core, speed is fixed to Full Speed. // However, keep for debugging and in case Low Speed is ever supported. uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); @@ -662,25 +662,25 @@ static void handle_epin_ints(void) } -static void dcd_int_handler(void) +void dcd_irq_handler(void) { const uint32_t int_status = USB0.gintsts; const uint32_t int_msk = USB0.gintmsk; if (int_status & USB_DISCONNINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - disconnected"); USB0.gintsts = USB_DISCONNINT_M; } if (int_status & USB_USBRST_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - reset"); USB0.gintsts = USB_USBRST_M; bus_reset(); } if (int_status & USB_RESETDET_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset while suspend"); + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - reset while suspend"); USB0.gintsts = USB_RESETDET_M; bus_reset(); } @@ -700,19 +700,19 @@ static void dcd_int_handler(void) } if ((int_status & USB_RXFLVI_M) & (int_msk & USB_RXFLVIMSK_M)) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - rx!"); read_rx_fifo(); } // OUT endpoint interrupt handling. if (int_status & USB_OEPINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - OUT endpoint!"); handle_epout_ints(); } // IN endpoint interrupt handling. if (int_status & USB_IEPINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - IN endpoint!"); handle_epin_ints(); } @@ -737,7 +737,7 @@ static void dcd_int_handler(void) 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_irq_handler, NULL, &usb_ih); } void dcd_int_disable(uint8_t rhport) -- cgit v1.3.1 From 06e87b47a29a0d8c304a08cd1f8bb1ad2168880f Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 Apr 2020 21:28:02 +0700 Subject: revert name to dcd_init_handler() since the function signature is different --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index df4cbf445..3361bde36 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -136,7 +136,7 @@ static void bus_reset(void) static void enum_done_processing(void) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); + ESP_EARLY_LOGV(TAG, "dcd_int_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); // On current silicon on the Full Speed core, speed is fixed to Full Speed. // However, keep for debugging and in case Low Speed is ever supported. uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); @@ -662,25 +662,25 @@ static void handle_epin_ints(void) } -void dcd_irq_handler(void) +static void dcd_int_handler(void) { const uint32_t int_status = USB0.gintsts; const uint32_t int_msk = USB0.gintmsk; if (int_status & USB_DISCONNINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - disconnected"); + ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); USB0.gintsts = USB_DISCONNINT_M; } if (int_status & USB_USBRST_M) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - reset"); + ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); USB0.gintsts = USB_USBRST_M; bus_reset(); } if (int_status & USB_RESETDET_M) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - reset while suspend"); + ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset while suspend"); USB0.gintsts = USB_RESETDET_M; bus_reset(); } @@ -700,19 +700,19 @@ void dcd_irq_handler(void) } if ((int_status & USB_RXFLVI_M) & (int_msk & USB_RXFLVIMSK_M)) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - rx!"); + ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); read_rx_fifo(); } // OUT endpoint interrupt handling. if (int_status & USB_OEPINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - OUT endpoint!"); + ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); handle_epout_ints(); } // IN endpoint interrupt handling. if (int_status & USB_IEPINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - IN endpoint!"); + ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); handle_epin_ints(); } @@ -737,7 +737,7 @@ void dcd_irq_handler(void) void dcd_int_enable(uint8_t rhport) { (void)rhport; - esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t)dcd_irq_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) -- cgit v1.3.1 From 06d7fdc22897f04d152b1746644ca9733e44fa54 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sun, 5 Apr 2020 11:29:24 -0400 Subject: Use #define for OSAL_TIMEOUT_WAIT_FOREVER. --- src/osal/osal.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/osal/osal.h b/src/osal/osal.h index 16ad34f3c..c35cf7721 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -36,13 +36,12 @@ #include "common/tusb_common.h" -enum -{ - OSAL_TIMEOUT_NOTIMEOUT = 0, // return immediately - OSAL_TIMEOUT_NORMAL = 10, // default timeout -}; - -static const uint32_t OSAL_TIMEOUT_WAIT_FOREVER = 0xFFFFFFFFUL; +// Return immediately +#define OSAL_TIMEOUT_NOTIMEOUT (0) +// Default timeout +#define OSAL_TIMEOUT_NORMAL (10) +// Wait forever +#define OSAL_TIMEOUT_WAIT_FOREVER (UINT32_MAX) #define OSAL_TIMEOUT_CONTROL_XFER OSAL_TIMEOUT_WAIT_FOREVER -- cgit v1.3.1 From ccb65fcf6a6e3724f88e94df167665c3231dc3df Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Tue, 7 Apr 2020 10:51:55 -0500 Subject: nuvoton: add dcd_disconnect() dcd_connect() --- src/portable/nuvoton/nuc120/dcd_nuc120.c | 12 ++++++++++++ src/portable/nuvoton/nuc121/dcd_nuc121.c | 12 ++++++++++++ src/portable/nuvoton/nuc505/dcd_nuc505.c | 17 +++++++++++++++++ 3 files changed, 41 insertions(+) (limited to 'src') diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 4e1db24a4..ba593ba06 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -430,4 +430,16 @@ void dcd_isr(uint8_t rhport) USBD_IRQHandler(); } +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + usb_detach(); +} + +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + usb_attach(); +} + #endif diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 25d723d96..e7cb3dcd9 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -446,4 +446,16 @@ void dcd_isr(uint8_t rhport) USBD_IRQHandler(); } +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + usb_detach(); +} + +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + usb_attach(); +} + #endif diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 8457e686b..de842eeb2 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -126,6 +126,11 @@ static void usb_attach(void) USBD->PHYCTL |= USBD_PHYCTL_DPPUEN_Msk; } +static void usb_detach(void) +{ + USBD->PHYCTL &= ~USBD_PHYCTL_DPPUEN_Msk; +} + static void usb_control_send_zlp(void) { USBD->CEPINTSTS = USBD_CEPINTSTS_STSDONEIF_Msk; @@ -647,4 +652,16 @@ void dcd_isr(uint8_t rhport) USBD_IRQHandler(); } +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + usb_detach(); +} + +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + usb_attach(); +} + #endif -- cgit v1.3.1 From 7b7a78ab2e89a8f147bbe7210923a72560b601d8 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 8 Apr 2020 15:29:12 +0700 Subject: disable SOF interrupt since it is not used for now --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 3361bde36..4cd682e12 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -42,6 +42,10 @@ #include "device/dcd.h" +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#define USE_SOF 0 + // FIFO size in bytes TODO need confirmation from Espressif #define EP_MAX USB_OUT_EP_NUM #define EP_FIFO_SIZE 1280 @@ -112,7 +116,7 @@ static void bus_reset(void) USB0.grxfsiz = 52; USB0.gintmsk = USB_MODEMISMSK_M | - USB_SOFMSK_M | + /* USB_SOFMSK_M | */ USB_RXFLVIMSK_M | USB_ERLYSUSPMSK_M | USB_USBSUSPMSK_M | @@ -154,7 +158,7 @@ static void enum_done_processing(void) xfer_status[0][TUSB_DIR_IN].max_size = 8; } - USB0.gintmsk |= USB_SOFMSK_M; // SOF unmask +// USB0.gintmsk |= USB_SOFMSK_M; // SOF unmask } @@ -202,7 +206,7 @@ void dcd_init(uint8_t rhport) USB0.gotgint = ~0U; //clear OTG ints USB0.gintsts = ~0U; //clear pending ints USB0.gintmsk = USB_MODEMISMSK_M | - USB_SOFMSK_M | + /*USB_SOFMSK_M |*/ USB_RXFLVIMSK_M | USB_ERLYSUSPMSK_M | USB_USBSUSPMSK_M | -- cgit v1.3.1 From 880595433ce6b75428dca30b72b41d865a4b89f4 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 8 Apr 2020 15:41:16 +0700 Subject: use macro for easy enable/disable SOF --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 4cd682e12..8a11f57b0 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -116,7 +116,9 @@ static void bus_reset(void) USB0.grxfsiz = 52; USB0.gintmsk = USB_MODEMISMSK_M | - /* USB_SOFMSK_M | */ +#if USE_SOF + USB_SOFMSK_M | +#endif USB_RXFLVIMSK_M | USB_ERLYSUSPMSK_M | USB_USBSUSPMSK_M | @@ -157,8 +159,6 @@ static void enum_done_processing(void) xfer_status[0][TUSB_DIR_OUT].max_size = 8; xfer_status[0][TUSB_DIR_IN].max_size = 8; } - -// USB0.gintmsk |= USB_SOFMSK_M; // SOF unmask } @@ -206,7 +206,9 @@ void dcd_init(uint8_t rhport) USB0.gotgint = ~0U; //clear OTG ints USB0.gintsts = ~0U; //clear pending ints USB0.gintmsk = USB_MODEMISMSK_M | - /*USB_SOFMSK_M |*/ +#if USE_SOF + USB_SOFMSK_M | +#endif USB_RXFLVIMSK_M | USB_ERLYSUSPMSK_M | USB_USBSUSPMSK_M | @@ -698,10 +700,12 @@ static void dcd_int_handler(void) dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); } +#if USE_SOF if (int_status & USB_SOF_M) { USB0.gintsts = USB_SOF_M; dcd_event_bus_signal(0, DCD_EVENT_SOF, true); // do nothing actually } +#endif if ((int_status & USB_RXFLVI_M) & (int_msk & USB_RXFLVIMSK_M)) { ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); -- cgit v1.3.1 From 9014ca55284d755d15c39cd4f721ee60ac239c40 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 8 Apr 2020 16:26:14 +0700 Subject: move irq for stm32 fsdev --- hw/bsp/adafruit_clue/adafruit_clue.c | 7 ++-- hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c | 14 +++++-- hw/bsp/stm32f072disco/stm32f072disco.c | 12 +++++- hw/bsp/stm32f103bluepill/stm32f103bluepill.c | 22 ++++++++++- hw/bsp/stm32f303disco/stm32f303disco.c | 34 +++++++++++++++- hw/bsp/stm32l0538disco/stm32l0538disco.c | 12 +++++- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 56 ++------------------------- 7 files changed, 93 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/hw/bsp/adafruit_clue/adafruit_clue.c b/hw/bsp/adafruit_clue/adafruit_clue.c index 7b090dd45..54b822fc9 100644 --- a/hw/bsp/adafruit_clue/adafruit_clue.c +++ b/hw/bsp/adafruit_clue/adafruit_clue.c @@ -43,10 +43,9 @@ void USBD_IRQHandler(void) tud_irq_handler(0); } - -/*------------------------------------------------------------------*/ -/* MACRO TYPEDEF CONSTANT ENUM - *------------------------------------------------------------------*/ +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define _PINNUM(port, pin) ((port)*32 + (pin)) #define LED_PIN _PINNUM(1, 1) diff --git a/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c b/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c index b4d97aff8..132da8aee 100644 --- a/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c +++ b/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c @@ -25,9 +25,19 @@ */ #include "../board.h" - #include "stm32f0xx_hal.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT GPIOA #define LED_PIN GPIO_PIN_5 #define LED_STATE_ON 1 @@ -56,8 +66,6 @@ static void all_rcc_clk_enable(void) void board_init(void) { - - /* Configure the system clock to 48 MHz */ RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_OscInitTypeDef RCC_OscInitStruct; diff --git a/hw/bsp/stm32f072disco/stm32f072disco.c b/hw/bsp/stm32f072disco/stm32f072disco.c index 7128eb4d9..9a3a354ef 100644 --- a/hw/bsp/stm32f072disco/stm32f072disco.c +++ b/hw/bsp/stm32f072disco/stm32f072disco.c @@ -25,9 +25,19 @@ */ #include "../board.h" - #include "stm32f0xx_hal.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT GPIOC #define LED_PIN GPIO_PIN_6 #define LED_STATE_ON 1 diff --git a/hw/bsp/stm32f103bluepill/stm32f103bluepill.c b/hw/bsp/stm32f103bluepill/stm32f103bluepill.c index e68bdd1bf..dbb58032c 100644 --- a/hw/bsp/stm32f103bluepill/stm32f103bluepill.c +++ b/hw/bsp/stm32f103bluepill/stm32f103bluepill.c @@ -25,9 +25,29 @@ */ #include "../board.h" - #include "stm32f1xx_hal.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_HP_IRQHandler(void) +{ + tud_irq_handler(0); +} + +void USB_LP_IRQHandler(void) +{ + tud_irq_handler(0); +} + +void USBWakeUp_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT GPIOC #define LED_PIN GPIO_PIN_13 #define LED_STATE_ON 0 diff --git a/hw/bsp/stm32f303disco/stm32f303disco.c b/hw/bsp/stm32f303disco/stm32f303disco.c index 44a342e04..444472a79 100644 --- a/hw/bsp/stm32f303disco/stm32f303disco.c +++ b/hw/bsp/stm32f303disco/stm32f303disco.c @@ -25,9 +25,41 @@ */ #include "../board.h" - #include "stm32f3xx_hal.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ + +// USB defaults to using interrupts 19, 20, and 42 (based on SYSCFG_CFGR1.USB_IT_RMP) +// FIXME: Do all three need to be handled, or just the LP one? +// USB high-priority interrupt (Channel 19): Triggered only by a correct +// transfer event for isochronous and double-buffer bulk transfer to reach +// the highest possible transfer rate. +void USB_HP_CAN_TX_IRQHandler(void) +{ + tud_irq_handler(0); +} + +// USB low-priority interrupt (Channel 20): Triggered by all USB events +// (Correct transfer, USB reset, etc.). The firmware has to check the +// interrupt source before serving the interrupt. +void USB_LP_CAN_RX0_IRQHandler(void) +{ + tud_irq_handler(0); +} + +// USB wakeup interrupt (Channel 42): Triggered by the wakeup event from the USB +// Suspend mode. +void USBWakeUp_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + #define LED_PORT GPIOE #define LED_PIN GPIO_PIN_9 #define LED_STATE_ON 1 diff --git a/hw/bsp/stm32l0538disco/stm32l0538disco.c b/hw/bsp/stm32l0538disco/stm32l0538disco.c index 2d9b49951..0bfb1f845 100644 --- a/hw/bsp/stm32l0538disco/stm32l0538disco.c +++ b/hw/bsp/stm32l0538disco/stm32l0538disco.c @@ -25,9 +25,19 @@ */ #include "../board.h" - #include "stm32l0xx_hal.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT GPIOA #define LED_PIN GPIO_PIN_5 #define LED_STATE_ON 1 diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index f962a4bee..21cd44396 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -489,7 +489,9 @@ static void dcd_ep_ctr_handler(void) } } -static void dcd_fs_irqHandler(void) { +void dcd_irq_handler(uint8_t rhport) { + + (void) rhport; uint32_t int_status = USB->ISTR; //const uint32_t handled_ints = USB_ISTR_CTR | USB_ISTR_RESET | USB_ISTR_WKUP @@ -804,57 +806,5 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN return true; } - -// Interrupt handlers -#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 -void USB_IRQHandler(void) -{ - dcd_fs_irqHandler(); -} - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F1 -void USB_HP_IRQHandler(void) -{ - dcd_fs_irqHandler(); -} -void USB_LP_IRQHandler(void) -{ - dcd_fs_irqHandler(); -} -void USBWakeUp_IRQHandler(void) -{ - dcd_fs_irqHandler(); -} - -#elif (CFG_TUSB_MCU) == (OPT_MCU_STM32F3) -// USB defaults to using interrupts 19, 20, and 42 (based on SYSCFG_CFGR1.USB_IT_RMP) -// FIXME: Do all three need to be handled, or just the LP one? -// USB high-priority interrupt (Channel 19): Triggered only by a correct -// transfer event for isochronous and double-buffer bulk transfer to reach -// the highest possible transfer rate. -void USB_HP_CAN_TX_IRQHandler(void) -{ - dcd_fs_irqHandler(); -} - -// USB low-priority interrupt (Channel 20): Triggered by all USB events -// (Correct transfer, USB reset, etc.). The firmware has to check the -// interrupt source before serving the interrupt. -void USB_LP_CAN_RX0_IRQHandler(void) -{ - dcd_fs_irqHandler(); -} - -// USB wakeup interrupt (Channel 42): Triggered by the wakeup event from the USB -// Suspend mode. -void USBWakeUp_IRQHandler(void) -{ - dcd_fs_irqHandler(); -} - -#else - #error Which IRQ handler do you need? -#endif - #endif -- cgit v1.3.1 From 8f17945b6792a326f8dee6abbd49af84a1791209 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 8 Apr 2020 16:37:09 +0700 Subject: move irq for stm32 synopsys --- hw/bsp/feather_stm32f405/feather_stm32f405.c | 12 ++++++++++++ hw/bsp/pyboardv11/pyboardv11.c | 12 ++++++++++++ hw/bsp/stm32f207nucleo/stm32f207nucleo.c | 12 ++++++++++++ hw/bsp/stm32f401blackpill/stm32f401blackpill.c | 12 ++++++++++++ hw/bsp/stm32f407disco/stm32f407disco.c | 12 ++++++++++++ hw/bsp/stm32f411blackpill/stm32f411blackpill.c | 12 ++++++++++++ hw/bsp/stm32f411disco/stm32f411disco.c | 13 ++++++++++++- hw/bsp/stm32f412disco/stm32f412disco.c | 12 ++++++++++++ hw/bsp/stm32f767nucleo/stm32f767nucleo.c | 12 ++++++++++++ hw/bsp/stm32h743nucleo/stm32h743nucleo.c | 12 ++++++++++++ hw/bsp/stm32l476disco/stm32l476disco.c | 12 ++++++++++++ src/portable/st/synopsys/dcd_synopsys.c | 5 ++++- 12 files changed, 136 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/hw/bsp/feather_stm32f405/feather_stm32f405.c b/hw/bsp/feather_stm32f405/feather_stm32f405.c index 16036750c..bdd216272 100644 --- a/hw/bsp/feather_stm32f405/feather_stm32f405.c +++ b/hw/bsp/feather_stm32f405/feather_stm32f405.c @@ -29,6 +29,18 @@ #include "stm32f4xx.h" #include "stm32f4xx_hal_conf.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void OTG_FS_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + // Blue LED is chosen because the other LEDs are connected to ST-LINK lines. #define LED_PORT GPIOC #define LED_PIN GPIO_PIN_1 diff --git a/hw/bsp/pyboardv11/pyboardv11.c b/hw/bsp/pyboardv11/pyboardv11.c index aa8301b44..e6f45b339 100644 --- a/hw/bsp/pyboardv11/pyboardv11.c +++ b/hw/bsp/pyboardv11/pyboardv11.c @@ -29,6 +29,18 @@ #include "stm32f4xx.h" #include "stm32f4xx_hal_conf.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void OTG_FS_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + // Blue LED is chosen because the other LEDs are connected to ST-LINK lines. #define LED_PORT GPIOB #define LED_PIN GPIO_PIN_4 diff --git a/hw/bsp/stm32f207nucleo/stm32f207nucleo.c b/hw/bsp/stm32f207nucleo/stm32f207nucleo.c index 29e69cc88..3d1765e8b 100644 --- a/hw/bsp/stm32f207nucleo/stm32f207nucleo.c +++ b/hw/bsp/stm32f207nucleo/stm32f207nucleo.c @@ -28,6 +28,18 @@ #include "stm32f2xx_hal.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void OTG_FS_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + #define LED_PORT GPIOB #define LED_PIN GPIO_PIN_14 #define LED_STATE_ON 1 diff --git a/hw/bsp/stm32f401blackpill/stm32f401blackpill.c b/hw/bsp/stm32f401blackpill/stm32f401blackpill.c index 5d3375f01..90507e178 100644 --- a/hw/bsp/stm32f401blackpill/stm32f401blackpill.c +++ b/hw/bsp/stm32f401blackpill/stm32f401blackpill.c @@ -29,6 +29,18 @@ #include "stm32f4xx.h" #include "stm32f4xx_hal_conf.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void OTG_FS_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + #define LED_PORT GPIOC #define LED_PIN GPIO_PIN_13 #define LED_STATE_ON 1 diff --git a/hw/bsp/stm32f407disco/stm32f407disco.c b/hw/bsp/stm32f407disco/stm32f407disco.c index c6cc5e9aa..d317ae7df 100644 --- a/hw/bsp/stm32f407disco/stm32f407disco.c +++ b/hw/bsp/stm32f407disco/stm32f407disco.c @@ -28,6 +28,18 @@ #include "stm32f4xx_hal.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void OTG_FS_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + #define LED_PORT GPIOD #define LED_PIN GPIO_PIN_14 #define LED_STATE_ON 1 diff --git a/hw/bsp/stm32f411blackpill/stm32f411blackpill.c b/hw/bsp/stm32f411blackpill/stm32f411blackpill.c index 3dd74fc71..0d085b20e 100644 --- a/hw/bsp/stm32f411blackpill/stm32f411blackpill.c +++ b/hw/bsp/stm32f411blackpill/stm32f411blackpill.c @@ -28,6 +28,18 @@ #include "stm32f4xx_hal.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void OTG_FS_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + #define LED_PORT GPIOC #define LED_PIN GPIO_PIN_13 #define LED_STATE_ON 1 diff --git a/hw/bsp/stm32f411disco/stm32f411disco.c b/hw/bsp/stm32f411disco/stm32f411disco.c index 8f97eff01..3f95afb09 100644 --- a/hw/bsp/stm32f411disco/stm32f411disco.c +++ b/hw/bsp/stm32f411disco/stm32f411disco.c @@ -25,9 +25,20 @@ */ #include "../board.h" - #include "stm32f4xx_hal.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void OTG_FS_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + // Orange LED #define LED_PORT GPIOD #define LED_PIN GPIO_PIN_13 diff --git a/hw/bsp/stm32f412disco/stm32f412disco.c b/hw/bsp/stm32f412disco/stm32f412disco.c index f64fa3f01..be0731fb6 100644 --- a/hw/bsp/stm32f412disco/stm32f412disco.c +++ b/hw/bsp/stm32f412disco/stm32f412disco.c @@ -28,6 +28,18 @@ #include "stm32f4xx_hal.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void OTG_FS_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + #define LED_PORT GPIOE #define LED_PIN GPIO_PIN_2 #define LED_STATE_ON 0 diff --git a/hw/bsp/stm32f767nucleo/stm32f767nucleo.c b/hw/bsp/stm32f767nucleo/stm32f767nucleo.c index 7a24bfa71..b9025a42c 100644 --- a/hw/bsp/stm32f767nucleo/stm32f767nucleo.c +++ b/hw/bsp/stm32f767nucleo/stm32f767nucleo.c @@ -29,6 +29,18 @@ #include "stm32f7xx_hal.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void OTG_FS_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + #define LED_PORT GPIOB #define LED_PIN GPIO_PIN_14 #define LED_STATE_ON 1 diff --git a/hw/bsp/stm32h743nucleo/stm32h743nucleo.c b/hw/bsp/stm32h743nucleo/stm32h743nucleo.c index 593b6e50e..9a758988c 100644 --- a/hw/bsp/stm32h743nucleo/stm32h743nucleo.c +++ b/hw/bsp/stm32h743nucleo/stm32h743nucleo.c @@ -29,6 +29,18 @@ #include "stm32h7xx_hal.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void OTG_FS_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + #define LED_PORT GPIOB #define LED_PIN GPIO_PIN_0 #define LED_STATE_ON 1 diff --git a/hw/bsp/stm32l476disco/stm32l476disco.c b/hw/bsp/stm32l476disco/stm32l476disco.c index db755c18d..65c544137 100644 --- a/hw/bsp/stm32l476disco/stm32l476disco.c +++ b/hw/bsp/stm32l476disco/stm32l476disco.c @@ -28,6 +28,18 @@ #include "stm32l4xx_hal.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void OTG_FS_IRQHandler(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + #define LED_PORT GPIOB #define LED_PIN GPIO_PIN_2 #define LED_STATE_ON 1 diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index c16211a9d..dc752b37a 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -656,7 +656,10 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType } } -void OTG_FS_IRQHandler(void) { +void dcd_irq_handler(uint8_t rhport) { + + (void) rhport; + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE; USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE; -- cgit v1.3.1 From e879ad1e6f6535768ebcf05f02f30a8266518276 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 8 Apr 2020 16:42:36 +0700 Subject: move irq from msp430 --- hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c | 11 +++++++++++ src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 4 +++- 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c b/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c index bcae4b09e..621d21d55 100644 --- a/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c +++ b/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c @@ -28,6 +28,17 @@ #include "msp430.h" +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) +{ + tud_irq_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #define LED_PORT P1OUT #define LED_PIN BIT0 #define LED_STATE_ON 1 diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index d50fa17fe..edccec33f 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -539,8 +539,10 @@ static void handle_setup_packet(void) dcd_event_setup_received(0, (uint8_t*) &_setup_packet[0], true); } -void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) +void dcd_irq_handler(uint8_t rhport) { + (void) rhport; + // Setup is special- reading USBVECINT to handle setup packets is done to // stop hardware-generated NAKs on EP0. uint8_t setup_status = USBIFG & SETUPIFG; -- cgit v1.3.1 From 40e23672ff192b3d0ab1312987ecc94d4e0de0e7 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 8 Apr 2020 16:47:20 +0700 Subject: rename hal_dcd_isr to dcd_irq_handler for fomu --- hw/bsp/fomu/board.mk | 5 ----- hw/bsp/fomu/fomu.c | 8 +++----- src/portable/valentyusb/eptri/dcd_eptri.c | 2 +- src/portable/valentyusb/eptri/hal_eptri.c | 33 ------------------------------- 4 files changed, 4 insertions(+), 44 deletions(-) delete mode 100644 src/portable/valentyusb/eptri/hal_eptri.c (limited to 'src') diff --git a/hw/bsp/fomu/board.mk b/hw/bsp/fomu/board.mk index 403a7fb95..ffd0158c9 100644 --- a/hw/bsp/fomu/board.mk +++ b/hw/bsp/fomu/board.mk @@ -14,11 +14,6 @@ BSP_DIR = hw/bsp/fomu # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/fomu.ld -# TODO remove later -SRC_C += src/portable/$(VENDOR)/$(CHIP_FAMILY)/hal_$(CHIP_FAMILY).c - -SRC_C += - SRC_S += hw/bsp/fomu/crt0-vexriscv.S INC += \ diff --git a/hw/bsp/fomu/fomu.c b/hw/bsp/fomu/fomu.c index 519c63630..404b72333 100644 --- a/hw/bsp/fomu/fomu.c +++ b/hw/bsp/fomu/fomu.c @@ -26,7 +26,7 @@ #include #include -#include "common/tusb_common.h" +#include "../board.h" #include "csr.h" #include "irq.h" @@ -34,8 +34,6 @@ // Board porting API //--------------------------------------------------------------------+ -void hal_dcd_isr(uint8_t rhport); - void fomu_error(uint32_t line) { (void)line; @@ -65,7 +63,7 @@ void isr(void) #if CFG_TUSB_RHPORT0_MODE == OPT_MODE_DEVICE if (irqs & (1 << USB_INTERRUPT)) { - hal_dcd_isr(0); + tud_irq_handler(0); } #endif if (irqs & (1 << TIMER0_INTERRUPT)) { @@ -114,4 +112,4 @@ uint32_t board_millis(void) { return system_ticks; } -#endif \ No newline at end of file +#endif diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index f1b79dcfd..1054e71d6 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -613,7 +613,7 @@ static void handle_setup(void) usb_setup_ev_pending_write(1); } -void hal_dcd_isr(uint8_t rhport) +void dcd_irq_handler(uint8_t rhport) { (void)rhport; uint8_t next_ev; diff --git a/src/portable/valentyusb/eptri/hal_eptri.c b/src/portable/valentyusb/eptri/hal_eptri.c deleted file mode 100644 index 72453affa..000000000 --- a/src/portable/valentyusb/eptri/hal_eptri.c +++ /dev/null @@ -1,33 +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. - * - * This file is part of the TinyUSB stack. - */ - -#include "common/tusb_common.h" - -#if (CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI) - -// No HAL-specific stuff here! - -#endif -- cgit v1.3.1 From 11201f1a06396d4ab8302f2bb5ce579cb4ae7a6c Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 9 Apr 2020 11:42:42 +0700 Subject: adding dcd_connect/disconnect --- src/device/dcd.h | 6 ++++++ src/device/usbd.h | 14 ++++++++++++++ 2 files changed, 20 insertions(+) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index 143a2de34..487ddb3b6 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -106,6 +106,12 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num); // Wake up host void dcd_remote_wakeup(uint8_t rhport); +// disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; + +// connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) TU_ATTR_WEAK; + //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index beeec7e1c..817af20e3 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -65,6 +65,20 @@ static inline bool tud_ready(void) // Remote wake up host, only if suspended and enabled by host bool tud_remote_wakeup(void); +static inline bool tud_disconnect(void) +{ + TU_VERIFY(dcd_disconnect); + dcd_disconnect(TUD_OPT_RHPORT); + return true; +} + +static inline bool tud_connect(void) +{ + TU_VERIFY(dcd_connect); + dcd_connect(TUD_OPT_RHPORT); + return true; +} + // Carry out Data and Status stage of control transfer // - If len = 0, it is equivalent to sending status only // - If len > wLength : it will be truncated -- cgit v1.3.1 From c1f3fbbc03256d303d5ce355bd0cf87a0d3c4f4c Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 9 Apr 2020 11:47:02 +0700 Subject: implement dcd connect/disconnect for samd and nrf --- src/portable/microchip/samd/dcd_samd.c | 15 ++++++++++++++- src/portable/nordic/nrf5x/dcd_nrf5x.c | 14 ++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 148995520..c3d2985d4 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -154,10 +154,23 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num) void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; - USB->DEVICE.CTRLB.bit.UPRSM = 1; } +// disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + USB->DEVICE.CTRLB.reg |= USB_DEVICE_CTRLB_DETACH; +} + +// connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + USB->DEVICE.CTRLB.reg &= ~USB_DEVICE_CTRLB_DETACH; +} + /*------------------------------------------------------------------*/ /* DCD Endpoint port *------------------------------------------------------------------*/ diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 2ce288d6c..c0dddef83 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -237,6 +237,20 @@ void dcd_remote_wakeup(uint8_t rhport) // We may manually raise DCD_EVENT_RESUME event here } +// disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + NRF_USBD->USBPULLUP = 0; +} + +// connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + NRF_USBD->USBPULLUP = 1; +} + //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ -- cgit v1.3.1 From d6578823bb405cacbda13a044b66ba0a4f16a3d4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 9 Apr 2020 12:00:45 +0700 Subject: rename static function for dcd_cxd56 to prevent conflict --- src/portable/sony/cxd56/dcd_cxd56.c | 38 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 638b2f979..320b7237e 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -46,22 +46,22 @@ struct usbdcd_driver_s static struct usbdcd_driver_s usbdcd_driver; static struct usbdev_s *usbdev; -static int dcd_bind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); -static void dcd_unbind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); -static int dcd_setup(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev, - FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, size_t outlen); -static void dcd_disconnect(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); -static void dcd_suspend(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); -static void dcd_resume(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); +static int _dcd_bind (FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); +static void _dcd_unbind (FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); +static int _dcd_setup (FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev, + FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, size_t outlen); +static void _dcd_disconnect (FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); +static void _dcd_suspend (FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); +static void _dcd_resume (FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); static const struct usbdevclass_driverops_s g_driverops = { - dcd_bind, /* bind */ - dcd_unbind, /* unbind */ - dcd_setup, /* setup */ - dcd_disconnect, /* disconnect */ - dcd_suspend, /* suspend */ - dcd_resume, /* resume */ + _dcd_bind, /* bind */ + _dcd_unbind, /* unbind */ + _dcd_setup, /* setup */ + _dcd_disconnect, /* disconnect */ + _dcd_suspend, /* suspend */ + _dcd_resume, /* resume */ }; static void usbdcd_ep0incomplete(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req) @@ -86,7 +86,7 @@ static void usbdcd_ep0incomplete(FAR struct usbdev_ep_s *ep, FAR struct usbdev_r } } -static int dcd_bind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) +static int _dcd_bind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) { (void) driver; @@ -111,13 +111,13 @@ static int dcd_bind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s return 0; } -static void dcd_unbind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) +static void _dcd_unbind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) { (void) driver; (void) dev; } -static int dcd_setup(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev, +static int _dcd_setup(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev, FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, size_t outlen) { (void) driver; @@ -130,7 +130,7 @@ static int dcd_setup(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_ return 0; } -static void dcd_disconnect(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) +static void _dcd_disconnect(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) { (void) driver; @@ -138,7 +138,7 @@ static void dcd_disconnect(FAR struct usbdevclass_driver_s *driver, FAR struct u DEV_CONNECT(dev); } -static void dcd_suspend(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) +static void _dcd_suspend(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) { (void) driver; (void) dev; @@ -146,7 +146,7 @@ static void dcd_suspend(FAR struct usbdevclass_driver_s *driver, FAR struct usbd dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } -static void dcd_resume(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) +static void _dcd_resume(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) { (void) driver; (void) dev; -- cgit v1.3.1 From 715c4dbbf8fe7c6bb83013df626a201928704b30 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Wed, 8 Apr 2020 11:51:33 -0400 Subject: stm32fsdev: Implement dcd_connect. --- docs/porting.md | 6 ++++++ src/device/dcd.h | 8 ++++---- src/device/usbd.c | 1 + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 24 ++++++++++++++++++------ src/portable/template/dcd_template.c | 14 ++++++++++++++ test/test/device/msc/test_msc_device.c | 1 + test/test/device/usbd/test_usbd.c | 1 + 7 files changed, 45 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/docs/porting.md b/docs/porting.md index deb1b9efb..7d7d4cdb1 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -62,6 +62,8 @@ All of the code for the low-level device API is in `src/portable//CNTR |= USB_CNTR_RESETM | USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; dcd_handle_bus_reset(); + + // Data-line pull-up is left disconnected. +} - // And finally enable pull-up, which may trigger the RESET IRQ if the host is connected. - // (if this MCU has an internal pullup) +// Define only on MCU with internal pull-up so BSP can override (needed on MCU without internal pull-up) #if defined(USB_BCDR_DPPU) - USB->BCDR |= USB_BCDR_DPPU; -#else - // FIXME: callback to the user to ask them to twiddle a GPIO to disable/enable D+??? -#endif +TU_ATTR_WEAK +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + USB->BCDR &= ~(USB_BCDR_DPPU); +} + +TU_ATTR_WEAK +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + USB->BCDR |= USB_BCDR_DPPU; } +#endif + // Enable device interrupt void dcd_int_enable (uint8_t rhport) { diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 102910509..d29c98e55 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -45,6 +45,20 @@ void dcd_init (uint8_t rhport) (void) rhport; } +#if HAS_INTERNAL_PULLUP +// Enable internal D+/D- pullup +void dcd_connect(uint8_t rhport) TU_ATTR_WEAK +{ + (void) rhport; +} + +// Disable internal D+/D- pullup +void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK +{ + (void) rhport; +} +#endif + // Enable device interrupt void dcd_int_enable (uint8_t rhport) { diff --git a/test/test/device/msc/test_msc_device.c b/test/test/device/msc/test_msc_device.c index 095c28170..62a36d3e3 100644 --- a/test/test/device/msc/test_msc_device.c +++ b/test/test/device/msc/test_msc_device.c @@ -199,6 +199,7 @@ void setUp(void) if ( !tusb_inited() ) { dcd_init_Expect(rhport); + dcd_connect_Expect(rhport); tusb_init(); } diff --git a/test/test/device/usbd/test_usbd.c b/test/test/device/usbd/test_usbd.c index 06372b2e4..1bb32c1e5 100644 --- a/test/test/device/usbd/test_usbd.c +++ b/test/test/device/usbd/test_usbd.c @@ -127,6 +127,7 @@ void setUp(void) { mscd_init_Expect(); dcd_init_Expect(rhport); + dcd_connect_Expect(rhport); tusb_init(); } } -- cgit v1.3.1 From 1b3d1b52c9351391f62dea374345c8de7f985b0f Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Apr 2020 13:54:50 +0700 Subject: fix uint32_t format with log --- src/device/usbd.c | 2 +- src/tusb.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 125aa351c..397a681ed 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -421,7 +421,7 @@ void tud_task (void) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Endpoint: 0x%02X, Bytes: %lu\r\n", ep_addr, event.xfer_complete.len); + TU_LOG2(" Endpoint: 0x%02X, Bytes: %u\r\n", ep_addr, (unsigned int) event.xfer_complete.len); _usbd_dev.ep_status[epnum][ep_dir].busy = false; diff --git a/src/tusb.c b/src/tusb.c index 8e0022f4d..8f234455f 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -96,9 +96,9 @@ void tu_print_mem(void const *buf, uint16_t count, uint8_t indent) char format[] = "%00lX"; format[2] += 2*size; - const uint8_t item_per_line = 16 / size; + const uint8_t item_per_line = 16 / size; - for(uint32_t i=0; i Date: Fri, 10 Apr 2020 14:04:18 +0700 Subject: try to fix racing condition with setup --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 145 +++++++++++++++++---------- 1 file changed, 93 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 8a11f57b0..3aebd824e 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -60,18 +60,23 @@ typedef struct { static const char *TAG = "TUSB:DCD"; static intr_handle_t usb_ih; -static volatile TU_ATTR_ALIGNED(4) uint32_t _setup_packet[6]; -static volatile uint8_t s_setup_phase = 0; /* 00 - got setup, - 01 - got done setup, - 02 - setup cmd sent*/ + + +static uint32_t _setup_packet[2]; #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] static xfer_ctl_t xfer_status[EP_MAX][2]; +#if 0 +static volatile uint8_t s_setup_phase = 0; /* 00 - got setup, + 01 - got done setup, + 02 - setup cmd sent*/ + static inline void readyfor1setup_pkg(int ep_num) { USB0.out_ep_reg[ep_num].doeptsiz |= (1 << USB_SUPCNT0_S); // doeptsiz 29:30 will decremented on every setup received } +#endif // Setup the control endpoint 0. static void bus_reset(void) @@ -83,6 +88,10 @@ static void bus_reset(void) USB0.dcfg &= ~USB_DEVADDR_M; // reset address + USB0.daintmsk |= USB_OUTEPMSK0_M | USB_INEPMSK0_M; + USB0.doepmsk |= USB_SETUPMSK_M | USB_XFERCOMPLMSK; + USB0.diepmsk |= USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; + // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture // @@ -115,28 +124,16 @@ static void bus_reset(void) USB0.grstctl |= USB_TXFFLSH_M; // Flush fifo USB0.grxfsiz = 52; - USB0.gintmsk = USB_MODEMISMSK_M | -#if USE_SOF - USB_SOFMSK_M | -#endif - USB_RXFLVIMSK_M | - USB_ERLYSUSPMSK_M | - USB_USBSUSPMSK_M | - USB_USBRSTMSK_M | - USB_ENUMDONEMSK_M | - USB_IEPINTMSK_M | - USB_OEPINTMSK_M | - USB_RESETDETMSK_M | - USB_DISCONNINTMSK_M; - - USB0.daintmsk |= USB_OUTEPMSK0_M | USB_INEPMSK0_M; - USB0.doepmsk |= USB_SETUPMSK_M | USB_XFERCOMPLMSK; - USB0.diepmsk |= USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; - // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); +#if 0 readyfor1setup_pkg(0); +#else + USB0.out_ep_reg[0].doeptsiz |= USB_SUPCNT0_M; +#endif + + USB0.gintmsk |= USB_IEPINTMSK_M | USB_OEPINTMSK_M; } static void enum_done_processing(void) @@ -162,13 +159,13 @@ static void enum_done_processing(void) } - - /*------------------------------------------------------------------*/ /* Controller API *------------------------------------------------------------------*/ void dcd_init(uint8_t rhport) { + (void)rhport; + ESP_LOGV(TAG, "DCD init - Start"); // A. Disconnect @@ -198,9 +195,7 @@ void dcd_init(uint8_t rhport) for (int n = 0; n < USB_OUT_EP_NUM; n++) { USB0.out_ep_reg[n].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK } - ESP_LOGV(TAG, "DCD init - Soft CONNECT"); - USB0.dctl &= ~USB_SFTDISCON_M; // Connect - + // D. Interruption masking USB0.gintmsk = 0; //mask all USB0.gotgint = ~0U; //clear OTG ints @@ -216,6 +211,10 @@ 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 + ets_delay_us(100); } @@ -240,6 +239,18 @@ 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) +{ + USB0.dctl &= ~USB_SFTDISCON_M; +} + /*------------------------------------------------------------------*/ /* DCD Endpoint port *------------------------------------------------------------------*/ @@ -312,7 +323,6 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { - (void)rhport; uint8_t const epnum = tu_edpt_number(ep_addr); @@ -447,7 +457,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ uint16_t xfer_size) { ESP_EARLY_LOGV(TAG, "USB - receive_packet"); - uint32_t *rx_fifo = USB0.fifo[0]; + volatile uint32_t *rx_fifo = USB0.fifo[0]; // See above TODO // uint16_t remaining = (out_ep->DOEPTSIZ & UsbDOEPTSIZ_XFRSIZ_Msk) >> UsbDOEPTSIZ_XFRSIZ_Pos; @@ -549,35 +559,47 @@ static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, static void read_rx_fifo(void) { + volatile uint32_t *rx_fifo = USB0.fifo[0]; + // Pop control word off FIFO (completed xfers will have 2 control words, // we only pop one ctl word each interrupt). - uint32_t ctl_word = USB0.grxstsp; - uint8_t pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S; - uint8_t epnum = (ctl_word & USB_CHNUM_M) >> USB_CHNUM_S; - uint16_t bcnt = (ctl_word & USB_BCNT_M) >> USB_BCNT_S; + uint32_t const ctl_word = USB0.grxstsp; + uint8_t const pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S; + uint8_t const epnum = (ctl_word & USB_CHNUM_M ) >> USB_CHNUM_S; + uint16_t const bcnt = (ctl_word & USB_BCNT_M ) >> USB_BCNT_S; switch (pktsts) { - case 0x01: // Global OUT NAK (Interrupt) + case 0x01: // Global OUT NAK (Interrupt) ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Global OUT NAK"); break; - case 0x02: { // Out packet recvd + + case 0x02: { // Out packet recvd ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet"); xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); receive_packet(xfer, bcnt); - } - break; - case 0x03: // Out packet done (Interrupt) + } + break; + + case 0x03: // Out packet done (Interrupt) ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet done"); break; - case 0x04: // Setup packet done (Interrupt) + + case 0x04: // Step 2: Setup transaction completed (Interrupt) + // After this event, OEPINT interrupt will occur with SETUP bit set +#if 0 if (s_setup_phase == 0) { // only if setup is started - s_setup_phase = 1; - ESP_EARLY_LOGV(TAG, "TUSB IRQ - setup_phase 1"); //finished - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); + s_setup_phase = 1; + ESP_EARLY_LOGV(TAG, "TUSB IRQ - setup_phase 1"); //finished + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); } +#else + USB0.out_ep_reg[epnum].doeptsiz |= USB_SUPCNT0_M; +#endif break; - case 0x06: { // Setup packet recvd + + case 0x06: { // Step1: Setup data packet received +#if 0 s_setup_phase = 0; ESP_EARLY_LOGV(TAG, "TUSB IRQ - setup_phase 0"); // new setup process // For some reason, it's possible to get a mismatch between @@ -588,11 +610,18 @@ static void read_rx_fifo(void) // only accepting one setup packet at a time for now. _setup_packet[0] = (USB0.grxstsp); _setup_packet[1] = (USB0.grxstsp); - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", - _setup_packet[0], _setup_packet[1]); - } - break; - default: // Invalid, do something here, like breakpoint? + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", _setup_packet[0], _setup_packet[1]); +#else + // We can receive up to three setup packets in succession, but + // only the last one is valid. Therefore we just overwrite it + _setup_packet[0] = (*rx_fifo); + _setup_packet[1] = (*rx_fifo); +#endif + } + break; + + default: // Invalid, do something here, like breakpoint? + TU_BREAKPOINT(); break; } } @@ -604,9 +633,11 @@ static void handle_epout_ints(void) // DOEPINT will be cleared when DAINT's out bits are cleared. for (int n = 0; n < USB_OUT_EP_NUM; n++) { xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); + if (USB0.daint & (1 << (16 + n))) { // SETUP packet Setup Phase done. if ((USB0.out_ep_reg[n].doepint & USB_SETUP0_M)) { +#if 0 USB0.out_ep_reg[n].doepint |= USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear if (s_setup_phase == 1) { // only if setup is done, but not handled s_setup_phase = 2; @@ -615,6 +646,10 @@ static void handle_epout_ints(void) dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); } readyfor1setup_pkg(0); +#else + USB0.out_ep_reg[n].doepint = USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear + dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); +#endif } // OUT XFER complete (single packet).q @@ -668,18 +703,21 @@ static void handle_epin_ints(void) } -static void dcd_int_handler(void) +static void dcd_int_handler(void* arg) { + (void) arg; + const uint32_t int_status = USB0.gintsts; - const uint32_t int_msk = USB0.gintmsk; + //const uint32_t int_msk = USB0.gintmsk; if (int_status & USB_DISCONNINT_M) { ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); USB0.gintsts = USB_DISCONNINT_M; + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); } if (int_status & USB_USBRST_M) { - + // start of reset ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); USB0.gintsts = USB_USBRST_M; bus_reset(); @@ -707,9 +745,12 @@ static void dcd_int_handler(void) } #endif - if ((int_status & USB_RXFLVI_M) & (int_msk & USB_RXFLVIMSK_M)) { + if ((int_status & USB_RXFLVI_M) /*& (int_msk & USB_RXFLVIMSK_M)*/) { ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); + USB0.gintmsk &= ~USB_RXFLVIMSK_M; read_rx_fifo(); + USB0.gintmsk |= USB_RXFLVIMSK_M; + USB0.gintsts = USB_RXFLVI_M; } // OUT endpoint interrupt handling. -- cgit v1.3.1 From d122d7de88819b744c192c2b3ab76b2a3d6cfda8 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Apr 2020 14:45:55 +0700 Subject: remove commented code --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 57 +++------------------------- 1 file changed, 6 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 3aebd824e..ed01c7877 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -67,17 +67,6 @@ static uint32_t _setup_packet[2]; #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] static xfer_ctl_t xfer_status[EP_MAX][2]; -#if 0 -static volatile uint8_t s_setup_phase = 0; /* 00 - got setup, - 01 - got done setup, - 02 - setup cmd sent*/ - -static inline void readyfor1setup_pkg(int ep_num) -{ - USB0.out_ep_reg[ep_num].doeptsiz |= (1 << USB_SUPCNT0_S); // doeptsiz 29:30 will decremented on every setup received -} -#endif - // Setup the control endpoint 0. static void bus_reset(void) { @@ -127,11 +116,8 @@ static void bus_reset(void) // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); -#if 0 - readyfor1setup_pkg(0); -#else + // Ready to receive SETUP packet USB0.out_ep_reg[0].doeptsiz |= USB_SUPCNT0_M; -#endif USB0.gintmsk |= USB_IEPINTMSK_M | USB_OEPINTMSK_M; } @@ -559,8 +545,6 @@ static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, static void read_rx_fifo(void) { - volatile uint32_t *rx_fifo = USB0.fifo[0]; - // Pop control word off FIFO (completed xfers will have 2 control words, // we only pop one ctl word each interrupt). uint32_t const ctl_word = USB0.grxstsp; @@ -586,37 +570,19 @@ static void read_rx_fifo(void) case 0x04: // Step 2: Setup transaction completed (Interrupt) // After this event, OEPINT interrupt will occur with SETUP bit set -#if 0 - if (s_setup_phase == 0) { // only if setup is started - s_setup_phase = 1; - ESP_EARLY_LOGV(TAG, "TUSB IRQ - setup_phase 1"); //finished - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); - } -#else + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); USB0.out_ep_reg[epnum].doeptsiz |= USB_SUPCNT0_M; -#endif - break; case 0x06: { // Step1: Setup data packet received -#if 0 - s_setup_phase = 0; - ESP_EARLY_LOGV(TAG, "TUSB IRQ - setup_phase 0"); // new setup process - // For some reason, it's possible to get a mismatch between - // how many setup packets were received versus the location - // of the Setup packet done word. This leads to situations - // where stale setup packets are in the RX FIFO that were received - // after the core loaded the Setup packet done word. Workaround by - // only accepting one setup packet at a time for now. - _setup_packet[0] = (USB0.grxstsp); - _setup_packet[1] = (USB0.grxstsp); - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", _setup_packet[0], _setup_packet[1]); -#else + volatile uint32_t *rx_fifo = USB0.fifo[0]; + // We can receive up to three setup packets in succession, but // only the last one is valid. Therefore we just overwrite it _setup_packet[0] = (*rx_fifo); _setup_packet[1] = (*rx_fifo); -#endif + + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", _setup_packet[0], _setup_packet[1]); } break; @@ -637,19 +603,8 @@ static void handle_epout_ints(void) if (USB0.daint & (1 << (16 + n))) { // SETUP packet Setup Phase done. if ((USB0.out_ep_reg[n].doepint & USB_SETUP0_M)) { -#if 0 - USB0.out_ep_reg[n].doepint |= USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear - if (s_setup_phase == 1) { // only if setup is done, but not handled - s_setup_phase = 2; - ESP_EARLY_LOGV(TAG, "TUSB IRQ - setup_phase 2"); // sending to a handling queue - ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP OUT - Setup Phase done (irq-s 0x%08x)", USB0.out_ep_reg[n].doepint); - dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); - } - readyfor1setup_pkg(0); -#else USB0.out_ep_reg[n].doepint = USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); -#endif } // OUT XFER complete (single packet).q -- cgit v1.3.1 From cec747776dd08452e2cd446262e407c60f4bfd7a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Apr 2020 14:47:02 +0700 Subject: rename dcd_init_handler to dcd_irq_handler to consistent with other ports --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index ed01c7877..27312824e 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -125,7 +125,7 @@ static void bus_reset(void) static void enum_done_processing(void) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); // On current silicon on the Full Speed core, speed is fixed to Full Speed. // However, keep for debugging and in case Low Speed is ever supported. uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); @@ -658,28 +658,28 @@ static void handle_epin_ints(void) } -static void dcd_int_handler(void* arg) +void dcd_irq_handler(uint32_t rhport) { - (void) arg; + (void) rhport; const uint32_t int_status = USB0.gintsts; //const uint32_t int_msk = USB0.gintmsk; if (int_status & USB_DISCONNINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - disconnected"); USB0.gintsts = USB_DISCONNINT_M; dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); } if (int_status & USB_USBRST_M) { // start of reset - ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - reset"); USB0.gintsts = USB_USBRST_M; bus_reset(); } if (int_status & USB_RESETDET_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset while suspend"); + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - reset while suspend"); USB0.gintsts = USB_RESETDET_M; bus_reset(); } @@ -701,7 +701,7 @@ static void dcd_int_handler(void* arg) #endif if ((int_status & USB_RXFLVI_M) /*& (int_msk & USB_RXFLVIMSK_M)*/) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - rx!"); USB0.gintmsk &= ~USB_RXFLVIMSK_M; read_rx_fifo(); USB0.gintmsk |= USB_RXFLVIMSK_M; @@ -710,13 +710,13 @@ static void dcd_int_handler(void* arg) // OUT endpoint interrupt handling. if (int_status & USB_OEPINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - OUT endpoint!"); handle_epout_ints(); } // IN endpoint interrupt handling. if (int_status & USB_IEPINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - IN endpoint!"); handle_epin_ints(); } @@ -741,7 +741,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_irq_handler, NULL, &usb_ih); } void dcd_int_disable(uint8_t rhport) -- cgit v1.3.1 From 933e3cdfc754c42936e5be7e84bf1c55f77b8bd0 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Apr 2020 15:01:12 +0700 Subject: change indent from 4 -> 2 spaces --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 1078 +++++++++++++------------- 1 file changed, 540 insertions(+), 538 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 27312824e..e0a2c2454 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -70,78 +70,76 @@ static xfer_ctl_t xfer_status[EP_MAX][2]; // Setup the control endpoint 0. static void bus_reset(void) { - - for (int ep_num = 0; ep_num < USB_OUT_EP_NUM; ep_num++) { - USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK - } - - USB0.dcfg &= ~USB_DEVADDR_M; // reset address - - USB0.daintmsk |= USB_OUTEPMSK0_M | USB_INEPMSK0_M; - USB0.doepmsk |= USB_SETUPMSK_M | USB_XFERCOMPLMSK; - USB0.diepmsk |= USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; - - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | - // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits): - // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN - // - // - All EP OUT shared a unique OUT FIFO which uses - // * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets). - // * 2 locations for OUT endpoint control words. - // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) - // * 1 location for global NAK (not required/used here). - // * It is recommended to allocate 2 times the largest packet size, therefore - // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 - USB0.grstctl |= 0x10 << USB_TXFNUM_S; // fifo 0x10, - USB0.grstctl |= USB_TXFFLSH_M; // Flush fifo - USB0.grxfsiz = 52; - - // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); - - // Ready to receive SETUP packet - USB0.out_ep_reg[0].doeptsiz |= USB_SUPCNT0_M; - - USB0.gintmsk |= USB_IEPINTMSK_M | USB_OEPINTMSK_M; + for (int ep_num = 0; ep_num < USB_OUT_EP_NUM; ep_num++) { + USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK + } + + USB0.dcfg &= ~USB_DEVADDR_M; // reset address + + USB0.daintmsk |= USB_OUTEPMSK0_M | USB_INEPMSK0_M; + USB0.doepmsk |= USB_SETUPMSK_M | USB_XFERCOMPLMSK; + USB0.diepmsk |= USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; + + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO MAX | + // --------------- + // | ... | + // --------------- y + x + 16 + GRXFSIZ + // | IN FIFO 2 | + // --------------- x + 16 + GRXFSIZ + // | IN FIFO 1 | + // --------------- 16 + GRXFSIZ + // | IN FIFO 0 | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits): + // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN + // + // - All EP OUT shared a unique OUT FIFO which uses + // * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets). + // * 2 locations for OUT endpoint control words. + // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) + // * 1 location for global NAK (not required/used here). + // * It is recommended to allocate 2 times the largest packet size, therefore + // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 + USB0.grstctl |= 0x10 << USB_TXFNUM_S; // fifo 0x10, + USB0.grstctl |= USB_TXFFLSH_M; // Flush fifo + USB0.grxfsiz = 52; + + // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) + USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); + + // Ready to receive SETUP packet + USB0.out_ep_reg[0].doeptsiz |= USB_SUPCNT0_M; + + USB0.gintmsk |= USB_IEPINTMSK_M | USB_OEPINTMSK_M; } static void enum_done_processing(void) { - - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); - // On current silicon on the Full Speed core, speed is fixed to Full Speed. - // However, keep for debugging and in case Low Speed is ever supported. - uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); - - // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL - if (enum_spd == 0x03) { // Full-Speed (PHY on 48 MHz) - USB0.in_ep_reg[0].diepctl &= ~USB_D_MPS0_V; // 64 bytes - USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; - } else { - USB0.in_ep_reg[0].diepctl |= USB_D_MPS0_V; // 8 bytes - USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall - xfer_status[0][TUSB_DIR_OUT].max_size = 8; - xfer_status[0][TUSB_DIR_IN].max_size = 8; - } + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); + // On current silicon on the Full Speed core, speed is fixed to Full Speed. + // However, keep for debugging and in case Low Speed is ever supported. + uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); + + // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL + if (enum_spd == 0x03) { // Full-Speed (PHY on 48 MHz) + USB0.in_ep_reg[0].diepctl &= ~USB_D_MPS0_V; // 64 bytes + USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall + xfer_status[0][TUSB_DIR_OUT].max_size = 64; + xfer_status[0][TUSB_DIR_IN].max_size = 64; + } else { + USB0.in_ep_reg[0].diepctl |= USB_D_MPS0_V; // 8 bytes + USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall + xfer_status[0][TUSB_DIR_OUT].max_size = 8; + xfer_status[0][TUSB_DIR_IN].max_size = 8; + } } @@ -150,79 +148,79 @@ static void enum_done_processing(void) *------------------------------------------------------------------*/ void dcd_init(uint8_t rhport) { - (void)rhport; + (void)rhport; - ESP_LOGV(TAG, "DCD init - Start"); + ESP_LOGV(TAG, "DCD init - Start"); - // A. Disconnect - ESP_LOGV(TAG, "DCD init - Soft DISCONNECT and Setting up"); - USB0.dctl |= USB_SFTDISCON_M; // Soft disconnect + // A. Disconnect + ESP_LOGV(TAG, "DCD init - Soft DISCONNECT and Setting up"); + USB0.dctl |= USB_SFTDISCON_M; // Soft disconnect - // B. Programming DCFG - /* If USB host misbehaves during status portion of control xfer + // B. Programming DCFG + /* If USB host misbehaves during status portion of control xfer (non zero-length packet), send STALL back and discard. Full speed. */ - USB0.dcfg |= USB_NZSTSOUTHSHK_M | // NonZero .... STALL - (3 << 0); // dev speed: fullspeed 1.1 on 48 mhz // TODO no value in usb_reg.h (IDF-1476) + USB0.dcfg |= USB_NZSTSOUTHSHK_M | // NonZero .... STALL + (3 << 0); // dev speed: fullspeed 1.1 on 48 mhz // TODO no value in usb_reg.h (IDF-1476) - USB0.gahbcfg |= USB_NPTXFEMPLVL_M | USB_GLBLLNTRMSK_M; // Global interruptions ON - USB0.gusbcfg |= USB_FORCEDEVMODE_M; // force devmode + USB0.gahbcfg |= USB_NPTXFEMPLVL_M | USB_GLBLLNTRMSK_M; // Global interruptions ON + USB0.gusbcfg |= USB_FORCEDEVMODE_M; // force devmode - USB0.gotgctl &= ~(USB_BVALIDOVVAL_M | USB_BVALIDOVEN_M | USB_VBVALIDOVVAL_M); //no overrides + USB0.gotgctl &= ~(USB_BVALIDOVVAL_M | USB_BVALIDOVEN_M | USB_VBVALIDOVVAL_M); //no overrides #ifdef CONFIG_IDF_TARGET_ESP32S2BETA // needed for beta chip only - //C. chip 7.2.2 hack - ESP_LOGV(TAG, "DCD init - chip ESP32-S2 beta hack"); - USB0.gotgctl = (0 << USB_BVALIDOVVAL_S); //B override value - ets_delay_us(20); - USB0.gotgctl = (0 << USB_BVALIDOVVAL_S) | (1 << USB_BVALIDOVEN_S); //B override value & enable - ets_delay_us(20); + //C. chip 7.2.2 hack + ESP_LOGV(TAG, "DCD init - chip ESP32-S2 beta hack"); + USB0.gotgctl = (0 << USB_BVALIDOVVAL_S); //B override value + ets_delay_us(20); + USB0.gotgctl = (0 << USB_BVALIDOVVAL_S) | (1 << USB_BVALIDOVEN_S); //B override value & enable + ets_delay_us(20); #endif - // C. Setting SNAKs, then connect - for (int n = 0; n < USB_OUT_EP_NUM; n++) { - USB0.out_ep_reg[n].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK - } - - // D. Interruption masking - USB0.gintmsk = 0; //mask all - USB0.gotgint = ~0U; //clear OTG ints - USB0.gintsts = ~0U; //clear pending ints - USB0.gintmsk = USB_MODEMISMSK_M | -#if USE_SOF - USB_SOFMSK_M | -#endif - USB_RXFLVIMSK_M | - USB_ERLYSUSPMSK_M | - USB_USBSUSPMSK_M | - USB_USBRSTMSK_M | - USB_ENUMDONEMSK_M | - USB_RESETDETMSK_M | - USB_DISCONNINTMSK_M; - - ESP_LOGV(TAG, "DCD init - Soft CONNECT"); - USB0.dctl &= ~USB_SFTDISCON_M; // Connect - - ets_delay_us(100); + // C. Setting SNAKs, then connect + for (int n = 0; n < USB_OUT_EP_NUM; n++) { + USB0.out_ep_reg[n].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK + } + + // D. Interruption masking + USB0.gintmsk = 0; //mask all + USB0.gotgint = ~0U; //clear OTG ints + USB0.gintsts = ~0U; //clear pending ints + USB0.gintmsk = USB_MODEMISMSK_M | + #if USE_SOF + USB_SOFMSK_M | + #endif + USB_RXFLVIMSK_M | + USB_ERLYSUSPMSK_M | + USB_USBSUSPMSK_M | + USB_USBRSTMSK_M | + USB_ENUMDONEMSK_M | + USB_RESETDETMSK_M | + USB_DISCONNINTMSK_M; + + ESP_LOGV(TAG, "DCD init - Soft CONNECT"); + USB0.dctl &= ~USB_SFTDISCON_M; // Connect + + ets_delay_us(100); } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { - (void)rhport; - ESP_LOGV(TAG, "DCD init - Set address : %u", dev_addr); - USB0.dcfg |= ((dev_addr & USB_DEVADDR_V) << USB_DEVADDR_S); - // Response with status after changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + (void)rhport; + ESP_LOGV(TAG, "DCD init - Set address : %u", dev_addr); + USB0.dcfg |= ((dev_addr & USB_DEVADDR_V) << USB_DEVADDR_S); + // Response with status after changing device address + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } void dcd_set_config(uint8_t rhport, uint8_t config_num) { - (void)rhport; - (void)config_num; - // Nothing to do + (void)rhport; + (void)config_num; + // Nothing to do } void dcd_remote_wakeup(uint8_t rhport) { - (void)rhport; + (void)rhport; } // disconnect by disabling internal pull-up resistor on D+/D- @@ -243,511 +241,515 @@ void dcd_connect(uint8_t rhport) bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) { + ESP_LOGV(TAG, "DCD endpoint opened"); + (void)rhport; - ESP_LOGV(TAG, "DCD endpoint opened"); - (void)rhport; + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); + TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 64); + TU_ASSERT(epnum < EP_MAX); - TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 64); - TU_ASSERT(epnum < EP_MAX); + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + xfer->max_size = desc_edpt->wMaxPacketSize.size; - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); - xfer->max_size = desc_edpt->wMaxPacketSize.size; - - if (dir == TUSB_DIR_OUT) { - out_ep[epnum].doepctl |= USB_USBACTEP0_M | - desc_edpt->bmAttributes.xfer << USB_EPTYPE0_S | - desc_edpt->wMaxPacketSize.size << USB_MPS0_S; - USB0.daintmsk |= (1 << (16 + epnum)); - } else { - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | - // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints - // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1) - // - Offset: GRXFSIZ + 16 + Size*(epnum-1) - // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". - - in_ep[epnum].diepctl |= USB_D_USBACTEP1_M | - epnum << USB_D_TXFNUM1_S | - desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | - desc_edpt->wMaxPacketSize.size << 0; - USB0.daintmsk |= (1 << (0 + epnum)); - - // Both TXFD and TXSA are in unit of 32-bit words. - // IN FIFO 0 was configured during enumeration, hence the "+ 16". - uint16_t const allocated_size = (USB0.grxfsiz & 0x0000ffff) + 16; - uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_MAX-1); - uint32_t const fifo_offset = allocated_size + fifo_size*(epnum-1); - - // DIEPTXF starts at FIFO #1. - USB0.dieptxf[epnum - 1] = (fifo_size << USB_NPTXFDEP_S) | fifo_offset; - } - return true; + if (dir == TUSB_DIR_OUT) { + out_ep[epnum].doepctl |= USB_USBACTEP0_M | + desc_edpt->bmAttributes.xfer << USB_EPTYPE0_S | + desc_edpt->wMaxPacketSize.size << USB_MPS0_S; + USB0.daintmsk |= (1 << (16 + epnum)); + } else { + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO MAX | + // --------------- + // | ... | + // --------------- y + x + 16 + GRXFSIZ + // | IN FIFO 2 | + // --------------- x + 16 + GRXFSIZ + // | IN FIFO 1 | + // --------------- 16 + GRXFSIZ + // | IN FIFO 0 | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints + // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1) + // - Offset: GRXFSIZ + 16 + Size*(epnum-1) + // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". + + in_ep[epnum].diepctl |= USB_D_USBACTEP1_M | + epnum << USB_D_TXFNUM1_S | + desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | + desc_edpt->wMaxPacketSize.size << 0; + USB0.daintmsk |= (1 << (0 + epnum)); + + // Both TXFD and TXSA are in unit of 32-bit words. + // IN FIFO 0 was configured during enumeration, hence the "+ 16". + uint16_t const allocated_size = (USB0.grxfsiz & 0x0000ffff) + 16; + uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_MAX-1); + uint32_t const fifo_offset = allocated_size + fifo_size*(epnum-1); + + // DIEPTXF starts at FIFO #1. + USB0.dieptxf[epnum - 1] = (fifo_size << USB_NPTXFDEP_S) | fifo_offset; + } + return true; } bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { - (void)rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = buffer; - xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->short_packet = false; - - uint16_t num_packets = (total_bytes / xfer->max_size); - uint8_t short_packet_size = total_bytes % xfer->max_size; - - // Zero-size packet is special case. - if (short_packet_size > 0 || (total_bytes == 0)) { - num_packets++; - } - - ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", - epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), - num_packets, total_bytes); - - // IN and OUT endpoint xfers are interrupt-driven, we just schedule them - // here. - if (dir == TUSB_DIR_IN) { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; - USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK - USB0.dtknqr4_fifoemptymsk |= (1 << epnum); - } else { - // Each complete packet for OUT xfers triggers XFRC. - USB0.out_ep_reg[epnum].doeptsiz = USB_PKTCNT0_M | - ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; - } - return true; + (void)rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->short_packet = false; + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint8_t short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if (short_packet_size > 0 || (total_bytes == 0)) { + num_packets++; + } + + ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", + epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), + num_packets, total_bytes); + + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them + // here. + if (dir == TUSB_DIR_IN) { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; + USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK + USB0.dtknqr4_fifoemptymsk |= (1 << epnum); + } else { + // Each complete packet for OUT xfers triggers XFRC. + USB0.out_ep_reg[epnum].doeptsiz = USB_PKTCNT0_M | + ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; + } + return true; } void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { - (void)rhport; + (void)rhport; - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - if (dir == TUSB_DIR_IN) { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(in_ep[epnum].diepctl & USB_D_EPENA1_M)) { - in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M); - } else { - // Stop transmitting packets and NAK IN xfers. - in_ep[epnum].diepctl |= USB_DI_SNAK1_M; - while ((in_ep[epnum].diepint & USB_DI_SNAK1_M) == 0) - ; - - // Disable the endpoint. Note that both SNAK and STALL are set here. - in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M | - USB_D_EPDIS1_M); - while ((in_ep[epnum].diepint & USB_D_EPDISBLD0_M) == 0) - ; - in_ep[epnum].diepint = USB_D_EPDISBLD0_M; - } + if (dir == TUSB_DIR_IN) { + // Only disable currently enabled non-control endpoint + if ((epnum == 0) || !(in_ep[epnum].diepctl & USB_D_EPENA1_M)) { + in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M); + } else { + // Stop transmitting packets and NAK IN xfers. + in_ep[epnum].diepctl |= USB_DI_SNAK1_M; + while ((in_ep[epnum].diepint & USB_DI_SNAK1_M) == 0) + ; + + // Disable the endpoint. Note that both SNAK and STALL are set here. + in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M | + USB_D_EPDIS1_M); + while ((in_ep[epnum].diepint & USB_D_EPDISBLD0_M) == 0) + ; + in_ep[epnum].diepint = USB_D_EPDISBLD0_M; + } - // Flush the FIFO, and wait until we have confirmed it cleared. - USB0.grstctl |= ((epnum - 1) << USB_TXFNUM_S); - USB0.grstctl |= USB_TXFFLSH_M; - while ((USB0.grstctl & USB_TXFFLSH_M) != 0) - ; + // Flush the FIFO, and wait until we have confirmed it cleared. + USB0.grstctl |= ((epnum - 1) << USB_TXFNUM_S); + USB0.grstctl |= USB_TXFFLSH_M; + while ((USB0.grstctl & USB_TXFFLSH_M) != 0) + ; + } else { + // Only disable currently enabled non-control endpoint + if ((epnum == 0) || !(out_ep[epnum].doepctl & USB_EPENA0_M)) { + out_ep[epnum].doepctl |= USB_STALL0_M; } else { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(out_ep[epnum].doepctl & USB_EPENA0_M)) { - out_ep[epnum].doepctl |= USB_STALL0_M; - } else { - // Asserting GONAK is required to STALL an OUT endpoint. - // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt - // anyway, and it can't be cleared by user code. If this while loop never - // finishes, we have bigger problems than just the stack. - USB0.dctl |= USB_SGOUTNAK_M; - while ((USB0.gintsts & USB_GOUTNAKEFF_M) == 0) - ; - - // Ditto here- disable the endpoint. Note that only STALL and not SNAK - // is set here. - out_ep[epnum].doepctl |= (USB_STALL0_M | USB_EPDIS0_M); - while ((out_ep[epnum].doepint & USB_EPDISBLD0_M) == 0) - ; - out_ep[epnum].doepint = USB_EPDISBLD0_M; - - // Allow other OUT endpoints to keep receiving. - USB0.dctl |= USB_CGOUTNAK_M; - } + // Asserting GONAK is required to STALL an OUT endpoint. + // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt + // anyway, and it can't be cleared by user code. If this while loop never + // finishes, we have bigger problems than just the stack. + USB0.dctl |= USB_SGOUTNAK_M; + while ((USB0.gintsts & USB_GOUTNAKEFF_M) == 0) + ; + + // Ditto here- disable the endpoint. Note that only STALL and not SNAK + // is set here. + out_ep[epnum].doepctl |= (USB_STALL0_M | USB_EPDIS0_M); + while ((out_ep[epnum].doepint & USB_EPDISBLD0_M) == 0) + ; + out_ep[epnum].doepint = USB_EPDISBLD0_M; + + // Allow other OUT endpoints to keep receiving. + USB0.dctl |= USB_CGOUTNAK_M; } + } } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + (void)rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - if (dir == TUSB_DIR_IN) { - in_ep[epnum].diepctl &= ~USB_D_STALL1_M; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - uint8_t eptype = (in_ep[epnum].diepctl & USB_D_EPTYPE1_M) >> USB_D_EPTYPE1_S; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt - // and bulk endpoints. - if (eptype == 2 || eptype == 3) { - in_ep[epnum].diepctl |= USB_DI_SETD0PID1_M; - } - } else { - out_ep[epnum].doepctl &= ~USB_STALL1_M; + if (dir == TUSB_DIR_IN) { + in_ep[epnum].diepctl &= ~USB_D_STALL1_M; - uint8_t eptype = (out_ep[epnum].doepctl & USB_EPTYPE1_M) >> USB_EPTYPE1_S; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt - // and bulk endpoints. - if (eptype == 2 || eptype == 3) { - out_ep[epnum].doepctl |= USB_DO_SETD0PID1_M; - } + uint8_t eptype = (in_ep[epnum].diepctl & USB_D_EPTYPE1_M) >> USB_D_EPTYPE1_S; + // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt + // and bulk endpoints. + if (eptype == 2 || eptype == 3) { + in_ep[epnum].diepctl |= USB_DI_SETD0PID1_M; + } + } else { + out_ep[epnum].doepctl &= ~USB_STALL1_M; + + uint8_t eptype = (out_ep[epnum].doepctl & USB_EPTYPE1_M) >> USB_EPTYPE1_S; + // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt + // and bulk endpoints. + if (eptype == 2 || eptype == 3) { + out_ep[epnum].doepctl |= USB_DO_SETD0PID1_M; } + } } /*------------------------------------------------------------------*/ static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ uint16_t xfer_size) { - ESP_EARLY_LOGV(TAG, "USB - receive_packet"); - volatile uint32_t *rx_fifo = USB0.fifo[0]; - - // See above TODO - // uint16_t remaining = (out_ep->DOEPTSIZ & UsbDOEPTSIZ_XFRSIZ_Msk) >> UsbDOEPTSIZ_XFRSIZ_Pos; - // xfer->queued_len = xfer->total_len - remaining; - - uint16_t remaining = xfer->total_len - xfer->queued_len; - uint16_t to_recv_size; - - if (remaining <= xfer->max_size) { - // Avoid buffer overflow. - to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; - } else { - // Room for full packet, choose recv_size based on what the microcontroller - // claims. - to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; - } - - uint8_t to_recv_rem = to_recv_size % 4; - uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; - - // Do not assume xfer buffer is aligned. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to collect. - if (to_recv_size >= 4) { - for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { - uint32_t tmp = (*rx_fifo); - base[i] = tmp & 0x000000FF; - base[i + 1] = (tmp & 0x0000FF00) >> 8; - base[i + 2] = (tmp & 0x00FF0000) >> 16; - base[i + 3] = (tmp & 0xFF000000) >> 24; - } + ESP_EARLY_LOGV(TAG, "USB - receive_packet"); + volatile uint32_t *rx_fifo = USB0.fifo[0]; + + // See above TODO + // uint16_t remaining = (out_ep->DOEPTSIZ & UsbDOEPTSIZ_XFRSIZ_Msk) >> UsbDOEPTSIZ_XFRSIZ_Pos; + // xfer->queued_len = xfer->total_len - remaining; + + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint16_t to_recv_size; + + if (remaining <= xfer->max_size) { + // Avoid buffer overflow. + to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; + } else { + // Room for full packet, choose recv_size based on what the microcontroller + // claims. + to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; + } + + uint8_t to_recv_rem = to_recv_size % 4; + uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; + + // Do not assume xfer buffer is aligned. + uint8_t *base = (xfer->buffer + xfer->queued_len); + + // This for loop always runs at least once- skip if less than 4 bytes + // to collect. + if (to_recv_size >= 4) { + for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { + uint32_t tmp = (*rx_fifo); + base[i] = tmp & 0x000000FF; + base[i + 1] = (tmp & 0x0000FF00) >> 8; + base[i + 2] = (tmp & 0x00FF0000) >> 16; + base[i + 3] = (tmp & 0xFF000000) >> 24; } + } - // Do not read invalid bytes from RX FIFO. - if (to_recv_rem != 0) { - uint32_t tmp = (*rx_fifo); - uint8_t *last_32b_bound = base + to_recv_size_aligned; + // Do not read invalid bytes from RX FIFO. + if (to_recv_rem != 0) { + uint32_t tmp = (*rx_fifo); + uint8_t *last_32b_bound = base + to_recv_size_aligned; - last_32b_bound[0] = tmp & 0x000000FF; - if (to_recv_rem > 1) { - last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; - } - if (to_recv_rem > 2) { - last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; - } + last_32b_bound[0] = tmp & 0x000000FF; + if (to_recv_rem > 1) { + last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; } + if (to_recv_rem > 2) { + last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; + } + } - xfer->queued_len += xfer_size; + xfer->queued_len += xfer_size; - // Per USB spec, a short OUT packet (including length 0) is always - // indicative of the end of a transfer (at least for ctl, bulk, int). - xfer->short_packet = (xfer_size < xfer->max_size); + // Per USB spec, a short OUT packet (including length 0) is always + // indicative of the end of a transfer (at least for ctl, bulk, int). + xfer->short_packet = (xfer_size < xfer->max_size); } static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, uint8_t fifo_num) { - ESP_EARLY_LOGV(TAG, "USB - transmit_packet"); - volatile uint32_t *tx_fifo = USB0.fifo[fifo_num]; - - uint16_t remaining = (in_ep->dieptsiz & 0x7FFFFU) >> USB_D_XFERSIZE0_S; - xfer->queued_len = xfer->total_len - remaining; - - uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; - uint8_t to_xfer_rem = to_xfer_size % 4; - uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; - - // Buffer might not be aligned to 32b, so we need to force alignment - // by copying to a temp var. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to send off. - if (to_xfer_size >= 4) { - for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { - uint32_t tmp = base[i] | (base[i + 1] << 8) | - (base[i + 2] << 16) | (base[i + 3] << 24); - (*tx_fifo) = tmp; - } + ESP_EARLY_LOGV(TAG, "USB - transmit_packet"); + volatile uint32_t *tx_fifo = USB0.fifo[fifo_num]; + + uint16_t remaining = (in_ep->dieptsiz & 0x7FFFFU) >> USB_D_XFERSIZE0_S; + xfer->queued_len = xfer->total_len - remaining; + + uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; + uint8_t to_xfer_rem = to_xfer_size % 4; + uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; + + // Buffer might not be aligned to 32b, so we need to force alignment + // by copying to a temp var. + uint8_t *base = (xfer->buffer + xfer->queued_len); + + // This for loop always runs at least once- skip if less than 4 bytes + // to send off. + if (to_xfer_size >= 4) { + for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { + uint32_t tmp = base[i] | (base[i + 1] << 8) | + (base[i + 2] << 16) | (base[i + 3] << 24); + (*tx_fifo) = tmp; } + } - // Do not read beyond end of buffer if not divisible by 4. - if (to_xfer_rem != 0) { - uint32_t tmp = 0; - uint8_t *last_32b_bound = base + to_xfer_size_aligned; + // Do not read beyond end of buffer if not divisible by 4. + if (to_xfer_rem != 0) { + uint32_t tmp = 0; + uint8_t *last_32b_bound = base + to_xfer_size_aligned; - tmp |= last_32b_bound[0]; - if (to_xfer_rem > 1) { - tmp |= (last_32b_bound[1] << 8); - } - if (to_xfer_rem > 2) { - tmp |= (last_32b_bound[2] << 16); - } - - (*tx_fifo) = tmp; + tmp |= last_32b_bound[0]; + if (to_xfer_rem > 1) { + tmp |= (last_32b_bound[1] << 8); + } + if (to_xfer_rem > 2) { + tmp |= (last_32b_bound[2] << 16); } + + (*tx_fifo) = tmp; + } } static void read_rx_fifo(void) { - // Pop control word off FIFO (completed xfers will have 2 control words, - // we only pop one ctl word each interrupt). - uint32_t const ctl_word = USB0.grxstsp; - uint8_t const pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S; - uint8_t const epnum = (ctl_word & USB_CHNUM_M ) >> USB_CHNUM_S; - uint16_t const bcnt = (ctl_word & USB_BCNT_M ) >> USB_BCNT_S; - - switch (pktsts) { - case 0x01: // Global OUT NAK (Interrupt) - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Global OUT NAK"); - break; - - case 0x02: { // Out packet recvd - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet"); - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - receive_packet(xfer, bcnt); - } + // Pop control word off FIFO (completed xfers will have 2 control words, + // we only pop one ctl word each interrupt). + uint32_t const ctl_word = USB0.grxstsp; + uint8_t const pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S; + uint8_t const epnum = (ctl_word & USB_CHNUM_M ) >> USB_CHNUM_S; + uint16_t const bcnt = (ctl_word & USB_BCNT_M ) >> USB_BCNT_S; + + switch (pktsts) { + case 0x01: // Global OUT NAK (Interrupt) + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Global OUT NAK"); break; - case 0x03: // Out packet done (Interrupt) - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet done"); - break; + case 0x02: { // Out packet recvd + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet"); + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + receive_packet(xfer, bcnt); + } + break; - case 0x04: // Step 2: Setup transaction completed (Interrupt) - // After this event, OEPINT interrupt will occur with SETUP bit set - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); - USB0.out_ep_reg[epnum].doeptsiz |= USB_SUPCNT0_M; - break; + case 0x03: // Out packet done (Interrupt) + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet done"); + break; - case 0x06: { // Step1: Setup data packet received - volatile uint32_t *rx_fifo = USB0.fifo[0]; + case 0x04: // Step 2: Setup transaction completed (Interrupt) + // After this event, OEPINT interrupt will occur with SETUP bit set + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); + USB0.out_ep_reg[epnum].doeptsiz |= USB_SUPCNT0_M; + break; - // We can receive up to three setup packets in succession, but - // only the last one is valid. Therefore we just overwrite it - _setup_packet[0] = (*rx_fifo); - _setup_packet[1] = (*rx_fifo); + case 0x06: { // Step1: Setup data packet received + volatile uint32_t *rx_fifo = USB0.fifo[0]; - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", _setup_packet[0], _setup_packet[1]); - } - break; + // We can receive up to three setup packets in succession, but + // only the last one is valid. Therefore we just overwrite it + _setup_packet[0] = (*rx_fifo); + _setup_packet[1] = (*rx_fifo); - default: // Invalid, do something here, like breakpoint? - TU_BREAKPOINT(); - break; + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", _setup_packet[0], _setup_packet[1]); } + break; + + default: // Invalid, do something here, like breakpoint? + TU_BREAKPOINT(); + break; + } } static void handle_epout_ints(void) { - // GINTSTS will be cleared with DAINT == 0 - // DAINT for a given EP clears when DOEPINTx is cleared. - // DOEPINT will be cleared when DAINT's out bits are cleared. - for (int n = 0; n < USB_OUT_EP_NUM; n++) { - xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); - - if (USB0.daint & (1 << (16 + n))) { - // SETUP packet Setup Phase done. - if ((USB0.out_ep_reg[n].doepint & USB_SETUP0_M)) { - USB0.out_ep_reg[n].doepint = USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear - dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); - } - - // OUT XFER complete (single packet).q - if (USB0.out_ep_reg[n].doepint & USB_XFERCOMPL0_M) { - - ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP OUT - XFER complete (single packet)"); - USB0.out_ep_reg[n].doepint = USB_XFERCOMPL0_M; - - // Transfer complete if short packet or total len is transferred - if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { - xfer->short_packet = false; - dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); - } else { - // Schedule another packet to be received. - USB0.out_ep_reg[n].doeptsiz = USB_PKTCNT0_M | - ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[n].doepctl |= USB_EPENA0_M | USB_CNAK0_M; - } - } + // GINTSTS will be cleared with DAINT == 0 + // DAINT for a given EP clears when DOEPINTx is cleared. + // DOEPINT will be cleared when DAINT's out bits are cleared. + for (int n = 0; n < USB_OUT_EP_NUM; n++) { + xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); + + if (USB0.daint & (1 << (16 + n))) { + // SETUP packet Setup Phase done. + if ((USB0.out_ep_reg[n].doepint & USB_SETUP0_M)) { + USB0.out_ep_reg[n].doepint = USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear + dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); + } + + // OUT XFER complete (single packet).q + if (USB0.out_ep_reg[n].doepint & USB_XFERCOMPL0_M) { + + ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP OUT - XFER complete (single packet)"); + USB0.out_ep_reg[n].doepint = USB_XFERCOMPL0_M; + + // Transfer complete if short packet or total len is transferred + if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { + xfer->short_packet = false; + dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); + } else { + // Schedule another packet to be received. + USB0.out_ep_reg[n].doeptsiz = USB_PKTCNT0_M | + ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[n].doepctl |= USB_EPENA0_M | USB_CNAK0_M; } + } } + } } static void handle_epin_ints(void) { + // GINTSTS will be cleared with DAINT == 0 + // DAINT for a given EP clears when DIEPINTx is cleared. + // IEPINT will be cleared when DAINT's out bits are cleared. + for (uint32_t n = 0; n < USB_IN_EP_NUM; n++) { + xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN]; + + if (USB0.daint & (1 << (0 + n))) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP IN %u", n); + // IN XFER complete (entire xfer). + if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER complete!"); + USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M; + USB0.dtknqr4_fifoemptymsk &= ~(1 << n); // Turn off TXFE b/c xfer inactive. + dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + } - // GINTSTS will be cleared with DAINT == 0 - // DAINT for a given EP clears when DIEPINTx is cleared. - // IEPINT will be cleared when DAINT's out bits are cleared. - for (uint32_t n = 0; n < USB_IN_EP_NUM; n++) { - xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN]; - - if (USB0.daint & (1 << (0 + n))) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP IN %u", n); - // IN XFER complete (entire xfer). - if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER complete!"); - USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M; - USB0.dtknqr4_fifoemptymsk &= ~(1 << n); // Turn off TXFE b/c xfer inactive. - dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - - // XFER FIFO empty - if (USB0.in_ep_reg[n].diepint & USB_D_TXFEMP0_M) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER FIFO empty!"); - USB0.in_ep_reg[n].diepint = USB_D_TXFEMP0_M; - transmit_packet(xfer, &USB0.in_ep_reg[n], n); - } - } + // XFER FIFO empty + if (USB0.in_ep_reg[n].diepint & USB_D_TXFEMP0_M) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER FIFO empty!"); + USB0.in_ep_reg[n].diepint = USB_D_TXFEMP0_M; + transmit_packet(xfer, &USB0.in_ep_reg[n], n); + } } + } } void dcd_irq_handler(uint32_t rhport) { - (void) rhport; - - const uint32_t int_status = USB0.gintsts; - //const uint32_t int_msk = USB0.gintmsk; - - if (int_status & USB_DISCONNINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - disconnected"); - USB0.gintsts = USB_DISCONNINT_M; - dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); - } - - if (int_status & USB_USBRST_M) { - // start of reset - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - reset"); - USB0.gintsts = USB_USBRST_M; - bus_reset(); - } - - if (int_status & USB_RESETDET_M) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - reset while suspend"); - USB0.gintsts = USB_RESETDET_M; - bus_reset(); - } - - if (int_status & USB_ENUMDONE_M) { - // ENUMDNE detects speed of the link. For full-speed, we - // always expect the same value. This interrupt is considered - // the end of reset. - USB0.gintsts = USB_ENUMDONE_M; - enum_done_processing(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); - } + (void) rhport; + + const uint32_t int_status = USB0.gintsts; + //const uint32_t int_msk = USB0.gintmsk; + + if (int_status & USB_DISCONNINT_M) { + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - disconnected"); + USB0.gintsts = USB_DISCONNINT_M; + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + } + + if (int_status & USB_USBRST_M) { + // start of reset + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - reset"); + USB0.gintsts = USB_USBRST_M; + bus_reset(); + } + + if (int_status & USB_RESETDET_M) { + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - reset while suspend"); + USB0.gintsts = USB_RESETDET_M; + bus_reset(); + } + + if (int_status & USB_ENUMDONE_M) { + // ENUMDNE detects speed of the link. For full-speed, we + // always expect the same value. This interrupt is considered + // the end of reset. + USB0.gintsts = USB_ENUMDONE_M; + enum_done_processing(); + dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + } #if USE_SOF - if (int_status & USB_SOF_M) { - USB0.gintsts = USB_SOF_M; - dcd_event_bus_signal(0, DCD_EVENT_SOF, true); // do nothing actually - } + if (int_status & USB_SOF_M) { + USB0.gintsts = USB_SOF_M; + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); // do nothing actually + } #endif - if ((int_status & USB_RXFLVI_M) /*& (int_msk & USB_RXFLVIMSK_M)*/) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - rx!"); - USB0.gintmsk &= ~USB_RXFLVIMSK_M; - read_rx_fifo(); - USB0.gintmsk |= USB_RXFLVIMSK_M; - USB0.gintsts = USB_RXFLVI_M; - } - - // OUT endpoint interrupt handling. - if (int_status & USB_OEPINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - OUT endpoint!"); - handle_epout_ints(); - } - - // IN endpoint interrupt handling. - if (int_status & USB_IEPINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - IN endpoint!"); - handle_epin_ints(); - } - - // Without handling - USB0.gintsts |= USB_CURMOD_INT_M | - USB_MODEMIS_M | - USB_OTGINT_M | - USB_NPTXFEMP_M | - USB_GINNAKEFF_M | - USB_GOUTNAKEFF | - USB_ERLYSUSP_M | - USB_USBSUSP_M | - USB_ISOOUTDROP_M | - USB_EOPF_M | - USB_EPMIS_M | - USB_INCOMPISOIN_M | - USB_INCOMPIP_M | - USB_FETSUSP_M | - USB_PTXFEMP_M; + if (int_status & USB_RXFLVI_M) { + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - rx!"); + + // disable RXFLVI interrupt until we read data from FIFO + USB0.gintmsk &= ~USB_RXFLVIMSK_M; + + read_rx_fifo(); + + // re-enable RXFLVI + USB0.gintmsk |= USB_RXFLVIMSK_M; + + USB0.gintsts = USB_RXFLVI_M; + } + + // OUT endpoint interrupt handling. + if (int_status & USB_OEPINT_M) { + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - OUT endpoint!"); + handle_epout_ints(); + } + + // IN endpoint interrupt handling. + if (int_status & USB_IEPINT_M) { + ESP_EARLY_LOGV(TAG, "dcd_irq_handler - IN endpoint!"); + handle_epin_ints(); + } + + // Without handling + USB0.gintsts |= USB_CURMOD_INT_M | + USB_MODEMIS_M | + USB_OTGINT_M | + USB_NPTXFEMP_M | + USB_GINNAKEFF_M | + USB_GOUTNAKEFF | + USB_ERLYSUSP_M | + USB_USBSUSP_M | + USB_ISOOUTDROP_M | + USB_EOPF_M | + USB_EPMIS_M | + USB_INCOMPISOIN_M | + USB_INCOMPIP_M | + USB_FETSUSP_M | + USB_PTXFEMP_M; } -void dcd_int_enable(uint8_t rhport) +void dcd_int_enable (uint8_t rhport) { - (void)rhport; - esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t)dcd_irq_handler, NULL, &usb_ih); + (void) rhport; + esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) dcd_irq_handler, NULL, &usb_ih); } -void dcd_int_disable(uint8_t rhport) +void dcd_int_disable (uint8_t rhport) { - (void)rhport; - esp_intr_free(usb_ih); + (void) rhport; + esp_intr_free(usb_ih); } #endif // OPT_MCU_ESP32S2 -- cgit v1.3.1 From c0695b4b55ba0a01117d7e9f544735c117fcb14b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Apr 2020 15:13:12 +0700 Subject: clear USB_RXFLVI_M before read_rx_fifo() more format clean up --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index e0a2c2454..d34e1c123 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -362,22 +362,18 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) } else { // Stop transmitting packets and NAK IN xfers. in_ep[epnum].diepctl |= USB_DI_SNAK1_M; - while ((in_ep[epnum].diepint & USB_DI_SNAK1_M) == 0) - ; + while ((in_ep[epnum].diepint & USB_DI_SNAK1_M) == 0) ; // Disable the endpoint. Note that both SNAK and STALL are set here. - in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M | - USB_D_EPDIS1_M); - while ((in_ep[epnum].diepint & USB_D_EPDISBLD0_M) == 0) - ; + in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M | USB_D_EPDIS1_M); + while ((in_ep[epnum].diepint & USB_D_EPDISBLD0_M) == 0) ; in_ep[epnum].diepint = USB_D_EPDISBLD0_M; } // Flush the FIFO, and wait until we have confirmed it cleared. USB0.grstctl |= ((epnum - 1) << USB_TXFNUM_S); USB0.grstctl |= USB_TXFFLSH_M; - while ((USB0.grstctl & USB_TXFFLSH_M) != 0) - ; + while ((USB0.grstctl & USB_TXFFLSH_M) != 0) ; } else { // Only disable currently enabled non-control endpoint if ((epnum == 0) || !(out_ep[epnum].doepctl & USB_EPENA0_M)) { @@ -388,14 +384,12 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) // anyway, and it can't be cleared by user code. If this while loop never // finishes, we have bigger problems than just the stack. USB0.dctl |= USB_SGOUTNAK_M; - while ((USB0.gintsts & USB_GOUTNAKEFF_M) == 0) - ; + while ((USB0.gintsts & USB_GOUTNAKEFF_M) == 0) ; // Ditto here- disable the endpoint. Note that only STALL and not SNAK // is set here. out_ep[epnum].doepctl |= (USB_STALL0_M | USB_EPDIS0_M); - while ((out_ep[epnum].doepint & USB_EPDISBLD0_M) == 0) - ; + while ((out_ep[epnum].doepint & USB_EPDISBLD0_M) == 0) ; out_ep[epnum].doepint = USB_EPDISBLD0_M; // Allow other OUT endpoints to keep receiving. @@ -698,6 +692,7 @@ void dcd_irq_handler(uint32_t rhport) if (int_status & USB_RXFLVI_M) { ESP_EARLY_LOGV(TAG, "dcd_irq_handler - rx!"); + USB0.gintsts = USB_RXFLVI_M; // disable RXFLVI interrupt until we read data from FIFO USB0.gintmsk &= ~USB_RXFLVIMSK_M; @@ -706,8 +701,6 @@ void dcd_irq_handler(uint32_t rhport) // re-enable RXFLVI USB0.gintmsk |= USB_RXFLVIMSK_M; - - USB0.gintsts = USB_RXFLVI_M; } // OUT endpoint interrupt handling. -- cgit v1.3.1 From 30945ab9f3f7c96725e1cabbe084836b48a113b5 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Apr 2020 15:27:23 +0700 Subject: revert name to dcd_int_handler due to function prototype warning --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index d34e1c123..328ec2fb9 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -123,7 +123,7 @@ static void bus_reset(void) static void enum_done_processing(void) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); + ESP_EARLY_LOGV(TAG, "dcd_int_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); // On current silicon on the Full Speed core, speed is fixed to Full Speed. // However, keep for debugging and in case Low Speed is ever supported. uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); @@ -648,28 +648,28 @@ static void handle_epin_ints(void) } -void dcd_irq_handler(uint32_t rhport) +static void dcd_int_handler(void* arg) { - (void) rhport; + (void) arg; const uint32_t int_status = USB0.gintsts; //const uint32_t int_msk = USB0.gintmsk; if (int_status & USB_DISCONNINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - disconnected"); + ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); USB0.gintsts = USB_DISCONNINT_M; dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); } if (int_status & USB_USBRST_M) { // start of reset - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - reset"); + ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); USB0.gintsts = USB_USBRST_M; bus_reset(); } if (int_status & USB_RESETDET_M) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - reset while suspend"); + ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset while suspend"); USB0.gintsts = USB_RESETDET_M; bus_reset(); } @@ -691,7 +691,7 @@ void dcd_irq_handler(uint32_t rhport) #endif if (int_status & USB_RXFLVI_M) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - rx!"); + ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); USB0.gintsts = USB_RXFLVI_M; // disable RXFLVI interrupt until we read data from FIFO @@ -705,13 +705,13 @@ void dcd_irq_handler(uint32_t rhport) // OUT endpoint interrupt handling. if (int_status & USB_OEPINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - OUT endpoint!"); + ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); handle_epout_ints(); } // IN endpoint interrupt handling. if (int_status & USB_IEPINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_irq_handler - IN endpoint!"); + ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); handle_epin_ints(); } @@ -736,7 +736,7 @@ void dcd_irq_handler(uint32_t rhport) void dcd_int_enable (uint8_t rhport) { (void) rhport; - esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) dcd_irq_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) -- cgit v1.3.1 From 978eec73b350ae5a52e47036c0dec163172944fa Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Apr 2020 15:39:59 +0700 Subject: remove 100us delay at the end of dcd_init() --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 328ec2fb9..26895c204 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -198,8 +198,6 @@ void dcd_init(uint8_t rhport) ESP_LOGV(TAG, "DCD init - Soft CONNECT"); USB0.dctl &= ~USB_SFTDISCON_M; // Connect - - ets_delay_us(100); } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) -- cgit v1.3.1 From c545cfc0bc9c4828c4b60515014386f770622166 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Apr 2020 15:42:50 +0700 Subject: Correct dedicated FIFO SRAM size to 1024 add note for up to 5 active IN endpoints (including EP0 IN) --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 26895c204..099f3af3e 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -46,9 +46,13 @@ // We disable SOF for now until needed later on #define USE_SOF 0 -// FIFO size in bytes TODO need confirmation from Espressif +// Max number of bi-directional endpoints including EP0 +// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0 +// We should probably prohibit enabling Endpoint IN > 4 (not done yet) #define EP_MAX USB_OUT_EP_NUM -#define EP_FIFO_SIZE 1280 + +// FIFO size in bytes +#define EP_FIFO_SIZE 1024 typedef struct { uint8_t *buffer; -- cgit v1.3.1 From 8953bc9255712cace4eb3e66b1e89961952bb639 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Apr 2020 20:25:53 +0700 Subject: added comment note for beta chip walkaround --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 099f3af3e..d1e670358 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -170,7 +170,17 @@ void dcd_init(uint8_t rhport) USB0.gusbcfg |= USB_FORCEDEVMODE_M; // force devmode USB0.gotgctl &= ~(USB_BVALIDOVVAL_M | USB_BVALIDOVEN_M | USB_VBVALIDOVVAL_M); //no overrides -#ifdef CONFIG_IDF_TARGET_ESP32S2BETA // needed for beta chip only + +#ifdef CONFIG_IDF_TARGET_ESP32S2BETA + // needed for beta chip only + // there was a bug in the phy logic that made the chip reset as soon as it transmitted anything. + // Setting the B override value made it ignore resets (any resets, generated by the faulty logic or not), + // which 'fixed' the problem well enough to test usb with it. + // Also, do note that the beta silicon run was very small and software support for it is not in mainstream esp-idf, + // as such you may consider phasing out support for it alltogether somewhere in the future + + // TODO we could safely remove this later (maybe after 2020) + //C. chip 7.2.2 hack ESP_LOGV(TAG, "DCD init - chip ESP32-S2 beta hack"); USB0.gotgctl = (0 << USB_BVALIDOVVAL_S); //B override value -- cgit v1.3.1 From 5bd9d14fc14d9130d7d879800bd46e4ca08e3d5f Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Fri, 10 Apr 2020 10:23:56 -0400 Subject: stm32fsdev: set dcd_connect API definitions to strong, Modify documentation. --- docs/porting.md | 4 ++-- src/device/dcd.h | 4 ++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/docs/porting.md b/docs/porting.md index 7d7d4cdb1..d3408aebd 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -62,7 +62,7 @@ All of the code for the low-level device API is in `src/portable//BCDR &= ~(USB_BCDR_DPPU); } -TU_ATTR_WEAK +// Enable internal D+ PU void dcd_connect(uint8_t rhport) { (void) rhport; -- cgit v1.3.1 From a37a56acd3ca70e0330d68da866d56faf00e82ce Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 Apr 2020 23:38:36 +0700 Subject: remove CONFIG_IDF_TARGET_ESP32S2BETA per review --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index d1e670358..de9ef6b6d 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -168,27 +168,8 @@ void dcd_init(uint8_t rhport) USB0.gahbcfg |= USB_NPTXFEMPLVL_M | USB_GLBLLNTRMSK_M; // Global interruptions ON USB0.gusbcfg |= USB_FORCEDEVMODE_M; // force devmode - USB0.gotgctl &= ~(USB_BVALIDOVVAL_M | USB_BVALIDOVEN_M | USB_VBVALIDOVVAL_M); //no overrides -#ifdef CONFIG_IDF_TARGET_ESP32S2BETA - // needed for beta chip only - // there was a bug in the phy logic that made the chip reset as soon as it transmitted anything. - // Setting the B override value made it ignore resets (any resets, generated by the faulty logic or not), - // which 'fixed' the problem well enough to test usb with it. - // Also, do note that the beta silicon run was very small and software support for it is not in mainstream esp-idf, - // as such you may consider phasing out support for it alltogether somewhere in the future - - // TODO we could safely remove this later (maybe after 2020) - - //C. chip 7.2.2 hack - ESP_LOGV(TAG, "DCD init - chip ESP32-S2 beta hack"); - USB0.gotgctl = (0 << USB_BVALIDOVVAL_S); //B override value - ets_delay_us(20); - USB0.gotgctl = (0 << USB_BVALIDOVVAL_S) | (1 << USB_BVALIDOVEN_S); //B override value & enable - ets_delay_us(20); -#endif - // C. Setting SNAKs, then connect for (int n = 0; n < USB_OUT_EP_NUM; n++) { USB0.out_ep_reg[n].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK -- cgit v1.3.1 From ae1314f1c77bb043789d54bf8a7fa30ff7efd1e2 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 11 Apr 2020 12:55:45 +0700 Subject: fix incorrect setup packet also increase usbd stack in example when debug is enabled --- examples/device/cdc_msc_freertos/src/main.c | 8 +++++++- src/portable/espressif/esp32s2/dcd_esp32s2.c | 8 +++----- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index f093d8ea0..77184ff58 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -56,7 +56,13 @@ StaticTimer_t blinky_tmdef; TimerHandle_t blinky_tm; // static task for usbd -#define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) +// Increase stack size when debug log is enabled +#if CFG_TUSB_DEBUG + #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE) +#else + #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) +#endif + StackType_t usb_device_stack[USBD_STACK_SIZE]; StaticTask_t usb_device_taskdef; diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index de9ef6b6d..126f3ea20 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -331,9 +331,8 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to USB0.dtknqr4_fifoemptymsk |= (1 << epnum); } else { // Each complete packet for OUT xfers triggers XFRC. - USB0.out_ep_reg[epnum].doeptsiz = USB_PKTCNT0_M | - ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; + USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; } return true; } @@ -603,8 +602,7 @@ static void handle_epout_ints(void) dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); } else { // Schedule another packet to be received. - USB0.out_ep_reg[n].doeptsiz = USB_PKTCNT0_M | - ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[n].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); USB0.out_ep_reg[n].doepctl |= USB_EPENA0_M | USB_CNAK0_M; } } -- cgit v1.3.1 From bb3bbcc00bfa641d285b28931ceb8bd04c3f7651 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sun, 12 Apr 2020 15:41:18 -0500 Subject: usbnet: OS-agnostic (Windows/Linux/macOS) network driver --- examples/device/net_lwip_webserver/src/main.c | 11 +- .../device/net_lwip_webserver/src/tusb_config.h | 3 +- .../net_lwip_webserver/src/usb_descriptors.c | 61 ++++-- src/class/net/net_device.c | 218 ++++++++++++++------- src/class/net/net_device.h | 2 + src/device/usbd.c | 38 +++- src/device/usbd.h | 12 +- src/tusb_option.h | 5 +- 8 files changed, 237 insertions(+), 113 deletions(-) (limited to 'src') diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index fe904e8e8..c6af96ea8 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -26,13 +26,14 @@ */ /* -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 +depending on the value of CFG_TUD_NET (tusb_config.h), this can be a RNDIS+CDC-ECM or CDC-EEM USB virtual network adapter -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 +OPT_NET_RNDIS_ECM : RNDIS should be valid on Linux and Windows hosts, and CDC-ECM should be valid on Linux and MacOS hosts +OPT_NET_EEM : 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. +OPT_NET_RNDIS_ECM should be the best choice, as it makes for a hopefully universal solution. + +You *must* customize tusb_config.h to set the CFG_TUD_NET definition to the type of these network option. 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..d8c750d5c 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -79,8 +79,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_RNDIS_ECM //#define CFG_TUD_NET OPT_NET_EEM #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..39c542eca 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -63,13 +63,17 @@ tusb_desc_device_t const desc_device = .idVendor = 0xCafe, .idProduct = USB_PID, - .bcdDevice = 0x0100, + .bcdDevice = 0x0101, .iManufacturer = STRID_MANUFACTURER, .iProduct = STRID_PRODUCT, .iSerialNumber = STRID_SERIAL, +#if CFG_TUD_NET == OPT_NET_EEM .bNumConfigurations = 0x01 +#else + .bNumConfigurations = 0x02 +#endif }; // Invoked when received GET DEVICE DESCRIPTOR @@ -85,16 +89,23 @@ uint8_t const * tud_descriptor_device_cb(void) enum { ITF_NUM_CDC = 0, +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM ITF_NUM_CDC_DATA, +#endif 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) +enum +{ + CONFIG_NUM_DEFAULT = 1, + CONFIG_NUM_ALTERNATE = 2, +}; + +#if CFG_TUD_NET == OPT_NET_EEM + #define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_EEM_DESC_LEN) +#else + #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) #endif #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX @@ -105,30 +116,42 @@ enum #define EPNUM_CDC 2 #endif -uint8_t const desc_configuration[] = +static uint8_t const main_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), + TUD_CONFIG_DESCRIPTOR(CONFIG_NUM_DEFAULT, 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 +#if 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), +#else + // 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), #endif }; +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM +static uint8_t const alt_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(CONFIG_NUM_ALTERNATE, 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), +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { +#if CFG_TUD_NET == OPT_NET_EEM (void) index; // for multiple configurations - return desc_configuration; + return main_configuration; +#else + return (0 == index) ? main_configuration : alt_configuration; +#endif } //--------------------------------------------------------------------+ @@ -141,8 +164,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/src/class/net/net_device.c b/src/class/net/net_device.c index 68520625a..19bc5d2d6 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -41,39 +41,57 @@ void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networ typedef struct { uint8_t itf_num; +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM uint8_t ep_notif; + bool ecm_mode; +#endif uint8_t ep_in; uint8_t ep_out; } 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 +#if 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 +#else + #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) + #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 #endif 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 @@ -95,7 +113,9 @@ static void do_in_xfer(uint8_t *buf, uint16_t len) void netd_report(uint8_t *buf, uint16_t len) { +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, buf, len); +#endif } //--------------------------------------------------------------------+ @@ -106,6 +126,10 @@ void netd_init(void) tu_memclr(&_netd_itf, sizeof(_netd_itf)); } +void netd_init_data(void) +{ +} + void netd_reset(uint8_t rhport) { (void) rhport; @@ -113,21 +137,26 @@ void netd_reset(uint8_t rhport) netd_init(); } +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM 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); +#if CFG_TUD_NET == OPT_NET_EEM + TU_VERIFY (CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL == itf_desc->bInterfaceSubClass); +#else + _netd_itf.ecm_mode = (CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass); + TU_VERIFY ( (TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass) || _netd_itf.ecm_mode ); +#endif // confirm interface hasn't already been allocated - TU_ASSERT(0 == _netd_itf.ep_in); + TU_ASSERT(0 == _netd_itf.ep_notif); - //------------- first Interface -------------// + //------------- 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); -#if CFG_TUD_NET != OPT_NET_EEM // Communication Functional Descriptors while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) { @@ -143,18 +172,28 @@ 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_desc = tu_desc_next(p_desc); } - //------------- second Interface -------------// - if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && + return true; +} +#endif + +bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +{ + // confirm interface hasn't already been allocated + TU_ASSERT(0 == _netd_itf.ep_in); + + uint8_t const * p_desc = tu_desc_next( itf_desc ); + (*p_length) = sizeof(tusb_desc_interface_t); + + //------------- Data Interface -------------// + while ( (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 if (TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { @@ -184,18 +223,25 @@ bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * reques // Handle class request only TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM TU_VERIFY (_netd_itf.itf_num == request->wIndex); -#if CFG_TUD_NET == OPT_NET_RNDIS - if (request->bmRequestType_bit.direction == TUSB_DIR_OUT) + if ( !_netd_itf.ecm_mode && (request->bmRequestType_bit.direction == TUSB_DIR_OUT) ) { - rndis_class_set_handler(rndis_buf, request->wLength); + 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) @@ -205,28 +251,32 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request TU_VERIFY (_netd_itf.itf_num == request->wIndex); -#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)); - } -#elif CFG_TUD_NET == OPT_NET_RNDIS - if (request->bmRequestType_bit.direction == TUSB_DIR_IN) +#if CFG_TUD_NET == OPT_NET_EEM + (void)rhport; +#else + if (_netd_itf.ecm_mode) { - 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); + /* 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 { - tud_control_xfer(rhport, request, rndis_buf, sizeof(rndis_buf)); + 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)); + } } -#else - (void)rhport; #endif return true; @@ -244,18 +294,7 @@ 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 +#if CFG_TUD_NET == OPT_NET_EEM struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)pnt; (void)len; @@ -271,26 +310,45 @@ static void handle_incoming_packet(uint32_t len) pnt += CFG_TUD_NET_PACKET_PREFIX_LEN; size = hdr->length - 4; /* discard the unused CRC-32 */ } +#else + if (_netd_itf.ecm_mode) + { + size = len; + } + else + { + 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 +378,13 @@ bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ } } +#if CFG_TUD_NET == OPT_NET_RNDIS_ECM + if ( _netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif) ) + { + if (sizeof(notify.ecm_buf.header) == xferred_bytes) ecm_report(false); + } +#endif + return true; } @@ -337,7 +402,11 @@ void tud_network_xmit(struct pbuf *p) if (!can_xmit) return; +#if CFG_TUD_NET == OPT_NET_EEM len = CFG_TUD_NET_PACKET_PREFIX_LEN; +#else + len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; +#endif data = transmitted + len; for(q = p; q != NULL; q = q->next) @@ -347,14 +416,7 @@ 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 +#if 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; @@ -363,6 +425,16 @@ void tud_network_xmit(struct pbuf *p) 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 */ +#else + 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); + } #endif do_in_xfer(transmitted, len); diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 67cd99933..6914ed050 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -73,8 +73,10 @@ void tud_network_xmit(struct pbuf *p); // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ void netd_init (void); +void netd_init_data (void); void netd_reset (uint8_t rhport); bool netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +bool netd_open_data (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); diff --git a/src/device/usbd.c b/src/device/usbd.c index 2adac429c..9d15ea4a4 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -184,21 +184,47 @@ static usbd_class_driver_t const _usbd_driver[] = #endif #if CFG_TUD_NET +#if CFG_TUD_NET != OPT_NET_EEM + /* RNDIS management interface */ { - .class_code = -#if CFG_TUD_NET == OPT_NET_RNDIS - TUD_RNDIS_ITF_CLASS, -#else - TUSB_CLASS_CDC, + .class_code = TUD_RNDIS_ITF_CLASS, + .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, + }, #endif + /* CDC-ECM management interface; CDC-EEM data interface */ + { + .class_code = TUSB_CLASS_CDC, .init = netd_init, .reset = netd_reset, +#if CFG_TUD_NET == OPT_NET_EEM + .open = netd_open_data, +#else .open = netd_open, +#endif .control_request = netd_control_request, .control_complete = netd_control_complete, .xfer_cb = netd_xfer_cb, - .sof = NULL + .sof = NULL, }, + /* RNDIS/CDC-ECM data interface */ +#if CFG_TUD_NET != OPT_NET_EEM + { + .class_code = TUSB_CLASS_CDC_DATA, + .init = netd_init_data, + .reset = NULL, + .open = netd_open_data, + .control_request = NULL, + .control_complete = NULL, + .xfer_cb = netd_xfer_cb, + .sof = NULL, + }, +#endif #endif }; diff --git a/src/device/usbd.h b/src/device/usbd.h index 817af20e3..756f5b161 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -342,8 +342,8 @@ 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 (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. @@ -358,8 +358,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,7 +374,7 @@ 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 diff --git a/src/tusb_option.h b/src/tusb_option.h index 6e2a2f125..c2394880f 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -128,9 +128,8 @@ * \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 +#define OPT_NET_RNDIS_ECM 1 ///< RNDIS+CDC-ECM +#define OPT_NET_EEM 2 ///< CDC-EEM /** @} */ #ifndef CFG_TUSB_RHPORT0_MODE -- cgit v1.3.1 From 0eeaccaf46c28444cc0830895559652cf5638c60 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Sun, 12 Apr 2020 21:07:17 -0400 Subject: Skeleton, and initial stm32fsdev implementation (that leaks memory) --- docs/porting.md | 7 +++ src/device/dcd.h | 6 ++- src/device/usbd.c | 61 +++++++++++++++++++++++++++ src/device/usbd.h | 2 + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 37 +++++++++++++++- 5 files changed, 111 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/docs/porting.md b/docs/porting.md index ccafa7999..de300c080 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -119,6 +119,13 @@ 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. After calling this, the device should not respond to any packets directed towards this endpoint. Implementation is optional, and is to be called from USBD in a non-interrupt context. +This function is used for implementing alternate settings. + +When called, this function need to abort any transfers in progress through this endpoint, before returning. + ##### 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/src/device/dcd.h b/src/device/dcd.h index 487ddb3b6..f48530227 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -66,7 +66,7 @@ typedef struct TU_ATTR_ALIGNED(4) // USBD_EVT_XFER_COMPLETE struct { - uint8_t ep_addr; + uint8_t ep_addr; ///< 0xFF signifies that the transfer was aborted. uint8_t result; uint32_t len; }xfer_complete; @@ -123,6 +123,10 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re // Configure endpoint's registers according to descriptor bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +// Close an endpoint. +// Since it is weak, caller must TU_ASSERT this function's existence before calling it. +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; + // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); diff --git a/src/device/usbd.c b/src/device/usbd.c index 397a681ed..e46532567 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -420,6 +420,11 @@ void tud_task (void) uint8_t const ep_addr = event.xfer_complete.ep_addr; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); + + if(ep_addr == 0xFF) // aborted transfer + { + break; + } TU_LOG2(" Endpoint: 0x%02X, Bytes: %u\r\n", ep_addr, (unsigned int) event.xfer_complete.len); @@ -1036,4 +1041,60 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) return _usbd_dev.ep_status[epnum][dir].stalled; } +/** + * Remove queued xfer complete messages from event queue, + * for a particular ep. + */ +static void usbd_abort_transfers(uint8_t rhport, uint8_t ep_addr) +{ + dcd_event_t ev_sentinal = + { + .event_id = DCD_EVENT_COUNT, ///< This is an invalid event ID. + }; + dcd_event_t event; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); + + dcd_int_disable(rhport); + // Queue sentinal element + TU_ASSERT(osal_queue_send(_usbd_q, &ev_sentinal, true), /**/); + + TU_ASSERT(osal_queue_receive(_usbd_q, &event), /**/); + + while(event.event_id != DCD_EVENT_COUNT) + { + if((event.rhport == rhport) && (event.event_id == DCD_EVENT_XFER_COMPLETE) + && (event.xfer_complete.ep_addr == ep_addr)) + { + _usbd_dev.ep_status[epnum][ep_dir].busy = false; + event.xfer_complete.ep_addr = 0xFF; // Mark transfer as invalid + } + TU_ASSERT(osal_queue_send(_usbd_q, &event, true), /**/); + TU_ASSERT(osal_queue_receive(_usbd_q, &event), /**/); + } + + dcd_int_enable(rhport); +} + +/** + * tud_edpt_close will disable an endpoint, and clear all pending transfers + * through the particular endpoint. + * + * It must be called from the usb task (i.e. from the control request + * handler while handling SET_ALTERNATE). + */ +void tud_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); + + /* Now, in progress transfers have to be expunged */ + usbd_abort_transfers(rhport, ep_addr); + + return; +} + #endif diff --git a/src/device/usbd.h b/src/device/usbd.h index 817af20e3..2447c2082 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -79,6 +79,8 @@ static inline bool tud_connect(void) return true; } +void tud_edpt_close(uint8_t rhport, uint8_t ep_addr); + // Carry out Data and Status stage of control transfer // - If len = 0, it is equivalent to sending status only // - If len > wLength : it will be truncated diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index f962a4bee..fa044e2d6 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -69,7 +69,6 @@ * - 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. @@ -623,6 +622,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc if(dir == TUSB_DIR_IN) { + // FIXME: use pma_alloc to allocate memory dynamically *pcd_ep_tx_address_ptr(USB, epnum) = ep_buf_ptr; pcd_set_ep_tx_cnt(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); pcd_clear_tx_dtog(USB, epnum); @@ -630,6 +630,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc } else { + // FIXME: use pma_alloc to allocate memory dynamically *pcd_ep_rx_address_ptr(USB, epnum) = ep_buf_ptr; pcd_set_ep_rx_cnt(USB, epnum, p_endpoint_desc->wMaxPacketSize.size); pcd_clear_rx_dtog(USB, epnum); @@ -642,6 +643,40 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc return true; } +/** + * Close an endpoint. + * + * This function should be called with interrupts enabled, though + * this implementation should be valid with them disabled, too. + * 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); + +#ifndef NDEBUG + TU_ASSERT(epnum < MAX_EP_COUNT, /**/); +#endif + + //uint16_t memptr; + + if(dir == TUSB_DIR_IN) + { + pcd_set_ep_tx_status(USB,epnum,USB_EP_TX_DIS); + //memptr = *pcd_ep_tx_address_ptr(USB, epnum); + } + else + { + pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_DIS); + //memptr = *pcd_ep_rx_address_ptr(USB, epnum); + } + + // FIXME: Free memory + // pma_free(memptr); +} + // Currently, single-buffered, and only 64 bytes at a time (max) static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix) -- cgit v1.3.1 From f4df82939955d86f6c2e826e1bc9f4b5bb713df8 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 13 Apr 2020 17:04:18 +0700 Subject: lpc17xx move set configdevice into set address for removing dcd_set_config() --- src/device/usbd.c | 2 -- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 2adac429c..55d6aa7eb 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -542,8 +542,6 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { uint8_t const cfg_num = (uint8_t) p_request->wValue; - dcd_set_config(rhport, cfg_num); - if ( !_usbd_dev.configured && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); _usbd_dev.configured = cfg_num ? 1 : 0; diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 884260f31..1d755ce63 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -205,13 +205,15 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); sie_write(SIE_CMDCODE_SET_ADDRESS, 1, 0x80 | dev_addr); // 7th bit is : device_enable + + // Also Set Configure Device to enable non-control endpoint response + sie_write(SIE_CMDCODE_CONFIGURE_DEVICE, 1, 1); } void dcd_set_config(uint8_t rhport, uint8_t config_num) { (void) rhport; (void) config_num; - sie_write(SIE_CMDCODE_CONFIGURE_DEVICE, 1, 1); } void dcd_remote_wakeup(uint8_t rhport) @@ -273,6 +275,7 @@ static uint8_t control_ep_read(void * buffer, uint8_t len) //--------------------------------------------------------------------+ // DCD Endpoint Port //--------------------------------------------------------------------+ + bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { (void) rhport; -- cgit v1.3.1 From f8e7487355c1d48517211a2316fbbc8566a1532d Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Mon, 13 Apr 2020 09:25:16 -0400 Subject: edpt_close: Updated based on feedback. --- docs/porting.md | 7 ++-- src/device/usbd.c | 10 +++-- src/device/usbd.h | 2 - src/device/usbd_pvt.h | 1 + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 60 ++++++++++++++++++--------- 5 files changed, 52 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/docs/porting.md b/docs/porting.md index de300c080..9561dfaf7 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -121,10 +121,11 @@ Also make sure to enable endpoint specific interrupts. ##### dcd_edpt_close -Close an endpoint. After calling this, the device should not respond to any packets directed towards this endpoint. Implementation is optional, and is to be called from USBD in a non-interrupt context. -This function is used for implementing alternate settings. +Close an endpoint. his function is used for implementing alternate settings. -When called, this function need to abort any transfers in progress through this endpoint, before returning. +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 diff --git a/src/device/usbd.c b/src/device/usbd.c index e46532567..71f5454ee 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1044,6 +1044,8 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) /** * Remove queued xfer complete messages from event queue, * for a particular ep. + * + * Must be called with interrupts enabled. */ static void usbd_abort_transfers(uint8_t rhport, uint8_t ep_addr) { @@ -1077,13 +1079,13 @@ static void usbd_abort_transfers(uint8_t rhport, uint8_t ep_addr) } /** - * tud_edpt_close will disable an endpoint, and clear all pending transfers + * usbd_edpt_close will disable an endpoint, and clear all pending transfers * through the particular endpoint. * - * It must be called from the usb task (i.e. from the control request - * handler while handling SET_ALTERNATE). + * It must be called from the usb task (e.g. from the control request + * handler while handling SET_ALTERNATE), with interrupts enabled. */ -void tud_edpt_close(uint8_t rhport, uint8_t ep_addr) +void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { TU_ASSERT(dcd_edpt_close, /**/); diff --git a/src/device/usbd.h b/src/device/usbd.h index 2447c2082..817af20e3 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -79,8 +79,6 @@ static inline bool tud_connect(void) return true; } -void tud_edpt_close(uint8_t rhport, uint8_t ep_addr); - // Carry out Data and Status stage of control transfer // - If len = 0, it is equivalent to sending status only // - If len > wLength : it will be truncated 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/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index fa044e2d6..13e54443f 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -63,8 +63,10 @@ * 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 as fixed 64 bytes. + * - Smaller can be requested: + * - Must be a multiple of 8 bytes + * - All EP must have identical buffer size. * - No isochronous endpoints * - Endpoint index is the ID of the endpoint * - This means that priority is given to endpoints with lower ID numbers @@ -130,21 +132,29 @@ * 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 +# if (PMA_LENGTH == 512U) +# define MAX_EP_COUNT 4U +# else +# define MAX_EP_COUNT 8U +# endif #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 # define DCD_STM32_BTABLE_LENGTH (PMA_LENGTH - DCD_STM32_BTABLE_BASE) #endif +// Below is used by the static PMA allocator +#define DCD_STM32_PMA_ALLOC_SIZE 64U + /*************************************************** * Checks, structs, defines, function definitions, etc. */ @@ -156,6 +166,11 @@ TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_LENGTH))<=(PMA_LEN TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligned to 8 bytes"); +// With static allocation of 64 bytes per endpoint, ensure there is enough packet buffer space +TU_VERIFY_STATIC(((MAX_EP_COUNT*2u*DCD_STM32_PMA_ALLOC_SIZE) <= DCD_STM32_BTABLE_LENGTH), "Packed buffer not long enough for count of endpoints"); + +TU_VERIFY_STATIC((DCD_STM32_PMA_ALLOC_SIZE % 8) == 0, "Packet buffer allocation must be a multiple of 8 bytes"); + // One of these for every EP IN & OUT, uses a bit of RAM.... typedef struct { @@ -178,7 +193,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); @@ -355,7 +369,6 @@ 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_edpt_open (0, &ep0OUT_desc); dcd_edpt_open (0, &ep0IN_desc); @@ -577,6 +590,22 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re } } +/*** + * Allocate a section of PMA + * Currently statitically allocates 64 bytes for each EP. + * + * stm32fsdev have 512 or 1024 bytes of packet RAM, and support 16 EP (8 in and 8 out), + * Static checks above have verified that there is enough packet memory space, so + * this should NEVER fail. + */ +static uint16_t dcd_pma_alloc(uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + return ((2*epnum + dir) * DCD_STM32_PMA_ALLOC_SIZE); +} + // The STM32F0 doesn't seem to like |= or &= to manipulate the EP#R registers, // so I'm using the #define from HAL here, instead. @@ -590,6 +619,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc TU_ASSERT(p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); TU_ASSERT(epnum < MAX_EP_COUNT); + TU_ASSERT(epMaxPktSize <= DCD_STM32_PMA_ALLOC_SIZE); // Set type switch(p_endpoint_desc->bmAttributes.xfer) { @@ -623,7 +653,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc if(dir == TUSB_DIR_IN) { // FIXME: use pma_alloc to allocate memory dynamically - *pcd_ep_tx_address_ptr(USB, epnum) = ep_buf_ptr; + *pcd_ep_tx_address_ptr(USB, epnum) = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress); 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); @@ -631,14 +661,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc else { // FIXME: use pma_alloc to allocate memory dynamically - *pcd_ep_rx_address_ptr(USB, epnum) = ep_buf_ptr; + *pcd_ep_rx_address_ptr(USB, epnum) = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress); 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; } @@ -646,8 +675,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc /** * Close an endpoint. * - * This function should be called with interrupts enabled, though - * this implementation should be valid with them disabled, too. + * 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) @@ -660,21 +689,14 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ASSERT(epnum < MAX_EP_COUNT, /**/); #endif - //uint16_t memptr; - if(dir == TUSB_DIR_IN) { pcd_set_ep_tx_status(USB,epnum,USB_EP_TX_DIS); - //memptr = *pcd_ep_tx_address_ptr(USB, epnum); } else { pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_DIS); - //memptr = *pcd_ep_rx_address_ptr(USB, epnum); } - - // FIXME: Free memory - // pma_free(memptr); } // Currently, single-buffered, and only 64 bytes at a time (max) -- cgit v1.3.1 From de208b31cf648c03670f34ff615a0f7ac6b566f3 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Mon, 13 Apr 2020 11:05:34 -0400 Subject: edpt_close: Remove item from queue instead of modifying it. --- src/device/dcd.h | 2 +- src/device/usbd.c | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index f48530227..99e623358 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -66,7 +66,7 @@ typedef struct TU_ATTR_ALIGNED(4) // USBD_EVT_XFER_COMPLETE struct { - uint8_t ep_addr; ///< 0xFF signifies that the transfer was aborted. + uint8_t ep_addr; uint8_t result; uint32_t len; }xfer_complete; diff --git a/src/device/usbd.c b/src/device/usbd.c index 71f5454ee..386401d9a 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -420,11 +420,6 @@ void tud_task (void) uint8_t const ep_addr = event.xfer_complete.ep_addr; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); - - if(ep_addr == 0xFF) // aborted transfer - { - break; - } TU_LOG2(" Endpoint: 0x%02X, Bytes: %u\r\n", ep_addr, (unsigned int) event.xfer_complete.len); @@ -1069,9 +1064,11 @@ static void usbd_abort_transfers(uint8_t rhport, uint8_t ep_addr) && (event.xfer_complete.ep_addr == ep_addr)) { _usbd_dev.ep_status[epnum][ep_dir].busy = false; - event.xfer_complete.ep_addr = 0xFF; // Mark transfer as invalid } - TU_ASSERT(osal_queue_send(_usbd_q, &event, true), /**/); + else + { + TU_ASSERT(osal_queue_send(_usbd_q, &event, true), /**/); + } TU_ASSERT(osal_queue_receive(_usbd_q, &event), /**/); } @@ -1087,7 +1084,6 @@ static void usbd_abort_transfers(uint8_t rhport, uint8_t ep_addr) */ 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); -- cgit v1.3.1 From bbc59f1ceb73131b5fc2158cdd3483b61408d59d Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Mon, 13 Apr 2020 13:11:45 -0400 Subject: stm32fsdev: add static assert for PMA size bigger than EP0 size. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 30 +++++++++++++++++---------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 13e54443f..defdfe057 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -136,9 +136,9 @@ // (8u here would mean 8 IN and 8 OUT) #ifndef MAX_EP_COUNT # if (PMA_LENGTH == 512U) -# define MAX_EP_COUNT 4U +# define MAX_EP_COUNT 3U # else -# define MAX_EP_COUNT 8U +# define MAX_EP_COUNT 7U # endif #endif @@ -153,7 +153,9 @@ #endif // Below is used by the static PMA allocator -#define DCD_STM32_PMA_ALLOC_SIZE 64U +#ifndef DCD_STM32_PMA_ALLOC_SIZE +# define DCD_STM32_PMA_ALLOC_SIZE 64U +#endif /*************************************************** * Checks, structs, defines, function definitions, etc. @@ -167,10 +169,13 @@ TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_LENGTH))<=(PMA_LEN TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligned to 8 bytes"); // With static allocation of 64 bytes per endpoint, ensure there is enough packet buffer space -TU_VERIFY_STATIC(((MAX_EP_COUNT*2u*DCD_STM32_PMA_ALLOC_SIZE) <= DCD_STM32_BTABLE_LENGTH), "Packed buffer not long enough for count of endpoints"); +// 8 bytes are required for control data for each EP. +TU_VERIFY_STATIC(((MAX_EP_COUNT*2u*DCD_STM32_PMA_ALLOC_SIZE + 8*MAX_EP_COUNT) <= DCD_STM32_BTABLE_LENGTH), "Packed buffer not long enough for count of endpoints"); TU_VERIFY_STATIC((DCD_STM32_PMA_ALLOC_SIZE % 8) == 0, "Packet buffer allocation must be a multiple of 8 bytes"); +TU_VERIFY_STATIC(CFG_TUD_ENDPOINT0_SIZE <= DCD_STM32_PMA_ALLOC_SIZE,"EP0 size is more than PMA allocation size"); + // One of these for every EP IN & OUT, uses a bit of RAM.... typedef struct { @@ -598,12 +603,18 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re * Static checks above have verified that there is enough packet memory space, so * this should NEVER fail. */ -static uint16_t dcd_pma_alloc(uint8_t ep_addr) +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); + + (void)length; - return ((2*epnum + dir) * DCD_STM32_PMA_ALLOC_SIZE); + TU_ASSERT(length <= DCD_STM32_PMA_ALLOC_SIZE); + + uint16_t addr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT; // Each EP needs 8 bytes to store control data + addr += ((2*epnum + dir) * DCD_STM32_PMA_ALLOC_SIZE); + return addr; } // The STM32F0 doesn't seem to like |= or &= to manipulate the EP#R registers, @@ -619,7 +630,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc TU_ASSERT(p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); TU_ASSERT(epnum < MAX_EP_COUNT); - TU_ASSERT(epMaxPktSize <= DCD_STM32_PMA_ALLOC_SIZE); // Set type switch(p_endpoint_desc->bmAttributes.xfer) { @@ -652,16 +662,14 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc if(dir == TUSB_DIR_IN) { - // FIXME: use pma_alloc to allocate memory dynamically - *pcd_ep_tx_address_ptr(USB, epnum) = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress); + *pcd_ep_tx_address_ptr(USB, epnum) = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress, p_endpoint_desc->wMaxPacketSize.size); 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 { - // FIXME: use pma_alloc to allocate memory dynamically - *pcd_ep_rx_address_ptr(USB, epnum) = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress); + *pcd_ep_rx_address_ptr(USB, epnum) = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress, p_endpoint_desc->wMaxPacketSize.size); 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); -- cgit v1.3.1 From 593fe154eca8e70b02beb0e5a2872e690ae74296 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 14 Apr 2020 18:00:59 +0700 Subject: adding subclass & protocol to class driver structure --- src/common/tusb_types.h | 7 +++++++ src/device/usbd.c | 56 +++++++++++++++++++++++++++++++++++++------------ src/device/usbd.h | 14 ++++++------- 3 files changed, 57 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index c37c19bad..70d0db942 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -139,6 +139,7 @@ typedef enum TUSB_REQ_RCPT_OTHER } tusb_request_recipient_t; +// https://www.usb.org/defined-class-codes typedef enum { TUSB_CLASS_UNSPECIFIED = 0 , @@ -176,6 +177,12 @@ typedef enum MISC_PROTOCOL_IAD = 1 }misc_protocol_type_t; +typedef enum +{ + APP_SUBCLASS_USBTMC = 0x03, + APP_SUBCLASS_DFU_RUNTIME = 0x01 +} app_subclass_type_t; + typedef enum { DEVICE_CAPABILITY_WIRELESS_USB = 0x01, diff --git a/src/device/usbd.c b/src/device/usbd.c index 9d15ea4a4..06fe1f23c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -73,8 +73,11 @@ enum { DRVID_INVALID = 0xFFu }; //--------------------------------------------------------------------+ // Class Driver //--------------------------------------------------------------------+ -typedef struct { +typedef struct +{ uint8_t class_code; + uint8_t subclass; // 0xFF support all values of subclass + uint8_t protocol; // 0xFF support all values of protocol void (* init ) (void); void (* reset ) (uint8_t rhport); @@ -90,6 +93,9 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_CDC { .class_code = TUSB_CLASS_CDC, + .subclass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, + .protocol = 0xFF, // all protocols + .init = cdcd_init, .reset = cdcd_reset, .open = cdcd_open, @@ -103,6 +109,9 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_MSC { .class_code = TUSB_CLASS_MSC, + .subclass = MSC_SUBCLASS_SCSI, + .protocol = MSC_PROTOCOL_BOT, + .init = mscd_init, .reset = mscd_reset, .open = mscd_open, @@ -116,6 +125,9 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_HID { .class_code = TUSB_CLASS_HID, + .subclass = 0xFF, // all subclass + .protocol = 0xFF, // all protocol + .init = hidd_init, .reset = hidd_reset, .open = hidd_open, @@ -129,6 +141,9 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_MIDI { .class_code = TUSB_CLASS_AUDIO, + .subclass = AUDIO_SUBCLASS_CONTROL, + .protocol = AUDIO_PROTOCOL_V1, + .init = midid_init, .open = midid_open, .reset = midid_reset, @@ -142,6 +157,9 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_VENDOR { .class_code = TUSB_CLASS_VENDOR_SPECIFIC, + .subclass = 0xFF, // all subclass + .protocol = 0xFF, // all protocol + .init = vendord_init, .reset = vendord_reset, .open = vendord_open, @@ -153,12 +171,11 @@ 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 + .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, + .subclass = APP_SUBCLASS_USBTMC, + .protocol = 0xFF, // all protocol + .init = usbtmcd_init_cb, .reset = usbtmcd_reset_cb, .open = usbtmcd_open_cb, @@ -171,8 +188,10 @@ 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 + .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, + .subclass = APP_SUBCLASS_DFU_RUNTIME, + .protocol = DFU_PROTOCOL_RT, + .init = dfu_rtd_init, .reset = dfu_rtd_reset, .open = dfu_rtd_open, @@ -183,11 +202,14 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif - #if CFG_TUD_NET -#if CFG_TUD_NET != OPT_NET_EEM +#if CFG_TUD_NET + #if CFG_TUD_NET != OPT_NET_EEM /* RNDIS management interface */ { .class_code = TUD_RNDIS_ITF_CLASS, + .subclass = TUD_RNDIS_ITF_SUBCLASS, + .protocol = TUD_RNDIS_ITF_PROTOCOL, + .init = netd_init, .reset = netd_reset, .open = netd_open, @@ -196,10 +218,14 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, -#endif + #endif + /* CDC-ECM management interface; CDC-EEM data interface */ { .class_code = TUSB_CLASS_CDC, + .subclass = CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, + .protocol = 0x00, + .init = netd_init, .reset = netd_reset, #if CFG_TUD_NET == OPT_NET_EEM @@ -212,10 +238,14 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, + /* RNDIS/CDC-ECM data interface */ -#if CFG_TUD_NET != OPT_NET_EEM + #if CFG_TUD_NET != OPT_NET_EEM { .class_code = TUSB_CLASS_CDC_DATA, + .subclass = 0x00, + .protocol = 0x00, + .init = netd_init_data, .reset = NULL, .open = netd_open_data, @@ -224,8 +254,8 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, -#endif #endif +#endif }; enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; diff --git a/src/device/usbd.h b/src/device/usbd.h index dbc94bc35..7b04ef9a7 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -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) @@ -377,7 +377,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re #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 -- cgit v1.3.1 From b90b00d43b18e1bed81c81e87ec148479ab1e696 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 14 Apr 2020 18:35:50 +0700 Subject: complete adding subclass and protocol to driver id --- src/device/usbd.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 06fe1f23c..c0e17c058 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -273,6 +273,8 @@ static osal_queue_t _usbd_q; // Prototypes //--------------------------------------------------------------------+ static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); +static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf); + static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); static bool process_set_config(uint8_t rhport, uint8_t cfg_num); static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); @@ -793,14 +795,10 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - tusb_desc_interface_t* desc_itf = (tusb_desc_interface_t*) p_desc; + tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) 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; - } + // Find driver id for the interface + uint8_t drv_id = find_driver_id(desc_itf); TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT ); // Interface number must not be used already TODO alternate interface @@ -824,6 +822,24 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) return true; } +// Helper to find class driver id for an interface +// return 0xFF if not found +static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf) +{ + for (uint8_t drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) + { + usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + if ( (driver->class_code == desc_itf->bInterfaceClass) && // match class code + (driver->subclass == desc_itf->bInterfaceSubClass || driver->subclass == 0xFF) && // match subclass or 0xFF from driver + (driver->protocol == desc_itf->bInterfaceProtocol || driver->protocol == 0xFF)) // match protocol or 0xFF from driver + { + return drv_id; + } + } + + return DRVID_INVALID; +} + // Helper marking endpoint of interface belongs to class driver static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) { -- cgit v1.3.1 From ae6014627408ec938d94a7d2796abd54dfff6b1f Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 14 Apr 2020 22:35:34 +0700 Subject: use explicit all_subclass and all_protocol since 0xFF is stil valid --- src/device/usbd.c | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index c0e17c058..c1ef482e2 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -79,6 +79,12 @@ typedef struct uint8_t subclass; // 0xFF support all values of subclass uint8_t protocol; // 0xFF support all values of protocol + struct TU_ATTR_PACKED + { + uint8_t all_subclass : 1; + uint8_t all_protocol : 1; + }; + void (* init ) (void); void (* reset ) (uint8_t rhport); bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); @@ -94,7 +100,9 @@ static usbd_class_driver_t const _usbd_driver[] = { .class_code = TUSB_CLASS_CDC, .subclass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, - .protocol = 0xFF, // all protocols + .protocol = 0x00, + .all_subclass = 0, + .all_protocol = 1, .init = cdcd_init, .reset = cdcd_reset, @@ -111,6 +119,8 @@ static usbd_class_driver_t const _usbd_driver[] = .class_code = TUSB_CLASS_MSC, .subclass = MSC_SUBCLASS_SCSI, .protocol = MSC_PROTOCOL_BOT, + .all_subclass = 0, + .all_protocol = 0, .init = mscd_init, .reset = mscd_reset, @@ -125,8 +135,10 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_HID { .class_code = TUSB_CLASS_HID, - .subclass = 0xFF, // all subclass - .protocol = 0xFF, // all protocol + .subclass = 0x00, + .protocol = 0x00, + .all_subclass = 1, + .all_protocol = 1, .init = hidd_init, .reset = hidd_reset, @@ -143,6 +155,8 @@ static usbd_class_driver_t const _usbd_driver[] = .class_code = TUSB_CLASS_AUDIO, .subclass = AUDIO_SUBCLASS_CONTROL, .protocol = AUDIO_PROTOCOL_V1, + .all_subclass = 0, + .all_protocol = 0, .init = midid_init, .open = midid_open, @@ -157,8 +171,10 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_VENDOR { .class_code = TUSB_CLASS_VENDOR_SPECIFIC, - .subclass = 0xFF, // all subclass - .protocol = 0xFF, // all protocol + .subclass = 0x00, + .protocol = 0x00, + .all_subclass = 1, + .all_protocol = 1, .init = vendord_init, .reset = vendord_reset, @@ -174,7 +190,9 @@ static usbd_class_driver_t const _usbd_driver[] = { .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, .subclass = APP_SUBCLASS_USBTMC, - .protocol = 0xFF, // all protocol + .protocol = 0x00, + .all_subclass = 0, + .all_protocol = 1, .init = usbtmcd_init_cb, .reset = usbtmcd_reset_cb, @@ -191,6 +209,8 @@ static usbd_class_driver_t const _usbd_driver[] = .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, .subclass = APP_SUBCLASS_DFU_RUNTIME, .protocol = DFU_PROTOCOL_RT, + .all_subclass = 0, + .all_protocol = 0, .init = dfu_rtd_init, .reset = dfu_rtd_reset, @@ -209,6 +229,8 @@ static usbd_class_driver_t const _usbd_driver[] = .class_code = TUD_RNDIS_ITF_CLASS, .subclass = TUD_RNDIS_ITF_SUBCLASS, .protocol = TUD_RNDIS_ITF_PROTOCOL, + .all_subclass = 0, + .all_protocol = 0, .init = netd_init, .reset = netd_reset, @@ -225,6 +247,8 @@ static usbd_class_driver_t const _usbd_driver[] = .class_code = TUSB_CLASS_CDC, .subclass = CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, .protocol = 0x00, + .all_subclass = 0, + .all_protocol = 0, .init = netd_init, .reset = netd_reset, @@ -245,6 +269,8 @@ static usbd_class_driver_t const _usbd_driver[] = .class_code = TUSB_CLASS_CDC_DATA, .subclass = 0x00, .protocol = 0x00, + .all_subclass = 0, + .all_protocol = 0, .init = netd_init_data, .reset = NULL, @@ -829,9 +855,9 @@ static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf) for (uint8_t drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) { usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; - if ( (driver->class_code == desc_itf->bInterfaceClass) && // match class code - (driver->subclass == desc_itf->bInterfaceSubClass || driver->subclass == 0xFF) && // match subclass or 0xFF from driver - (driver->protocol == desc_itf->bInterfaceProtocol || driver->protocol == 0xFF)) // match protocol or 0xFF from driver + if ( (driver->class_code == desc_itf->bInterfaceClass) && // match class code + (driver->subclass == desc_itf->bInterfaceSubClass || driver->all_subclass ) && // match subclass or driver support all + (driver->protocol == desc_itf->bInterfaceProtocol || driver->all_protocol)) // match protocol or driver support all { return drv_id; } -- cgit v1.3.1 From 3ef6e33533c533ef52336fae66e784b7d85e612f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 00:59:56 +0700 Subject: use class driver open() for interface support detection tested with dfu_runtime --- examples/device/dfu_rt/src/main.h | 5 -- examples/device/dfu_rt/src/usb_descriptors.c | 71 +--------------------------- src/class/dfu/dfu_rt_device.c | 4 +- src/class/dfu/dfu_rt_device.h | 2 +- src/device/usbd.c | 37 +++++++++++++-- 5 files changed, 38 insertions(+), 81 deletions(-) delete mode 100644 examples/device/dfu_rt/src/main.h (limited to 'src') 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/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/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/device/usbd.c b/src/device/usbd.c index c1ef482e2..eea344c3b 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -76,8 +76,8 @@ enum { DRVID_INVALID = 0xFFu }; typedef struct { uint8_t class_code; - uint8_t subclass; // 0xFF support all values of subclass - uint8_t protocol; // 0xFF support all values of protocol + uint8_t subclass; + uint8_t protocol; struct TU_ATTR_PACKED { @@ -299,7 +299,7 @@ static osal_queue_t _usbd_q; // Prototypes //--------------------------------------------------------------------+ static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); -static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf); +//static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf); static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); static bool process_set_config(uint8_t rhport, uint8_t cfg_num); @@ -346,6 +346,9 @@ static char const* const _usbd_driver_str[USBD_CLASS_DRIVER_COUNT] = #if CFG_TUD_VENDOR "Vendor", #endif + #if CFG_TUD_DFU_RT + "DFU Runtime", + #endif #if CFG_TUD_USBTMC "USBTMC" #endif @@ -823,6 +826,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; +#if 0 // Find driver id for the interface uint8_t drv_id = find_driver_id(desc_itf); TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT ); @@ -835,8 +839,31 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) 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) ); +#else + uint8_t drv_id; + uint16_t itf_len; + + for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) + { + usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + + itf_len = 0; + if ( driver->open(rhport, desc_itf, &itf_len) ) + { + // 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; - mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, itf_len, drv_id); + TU_LOG2(" itf_len = %d \r\n", itf_len); + break; + } + } + + // Assert if cannot find a driver + TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && itf_len >= sizeof(tusb_desc_interface_t) ); +#endif + + mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, itf_len, drv_id); // TODO refactor p_desc += itf_len; // next interface } @@ -848,6 +875,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) return true; } +#if 0 // Helper to find class driver id for an interface // return 0xFF if not found static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf) @@ -865,6 +893,7 @@ static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf) return DRVID_INVALID; } +#endif // Helper marking endpoint of interface belongs to class driver static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) -- cgit v1.3.1 From 8614dcece7792aab34431156c499f778baafa7c3 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 01:01:07 +0700 Subject: tested with hid --- src/class/hid/hid_device.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 7cb35f1ce..ca00cb942 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(desc_itf->bInterfaceClass == TUSB_CLASS_HID); + uint8_t const *p_desc = (uint8_t const *) desc_itf; // Find available interface -- cgit v1.3.1 From 7fa8d872916789fc5876c2e6bfae0d5a4d6fe379 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Tue, 14 Apr 2020 21:10:43 -0500 Subject: usbnet: remove CDC-EEM --- examples/device/net_lwip_webserver/src/main.c | 9 +-- .../device/net_lwip_webserver/src/tusb_config.h | 3 +- .../net_lwip_webserver/src/usb_descriptors.c | 28 +-------- src/class/net/net_device.c | 69 +--------------------- src/device/usbd.c | 10 +--- src/tusb_option.h | 8 --- 6 files changed, 10 insertions(+), 117 deletions(-) (limited to 'src') diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index 26c6401e6..b672ca3bb 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -26,14 +26,9 @@ */ /* -depending on the value of CFG_TUD_NET (tusb_config.h), this can be a RNDIS+CDC-ECM 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 -OPT_NET_RNDIS_ECM : RNDIS should be valid on Linux and Windows hosts, and CDC-ECM should be valid on Linux and MacOS hosts -OPT_NET_EEM : CDC-EEM should be valid on Linux hosts - -OPT_NET_RNDIS_ECM should be the best choice, as it makes for a hopefully universal solution. - -You *must* customize tusb_config.h to set the CFG_TUD_NET definition to the type of these network option. +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 d8c750d5c..a959968bc 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -79,8 +79,7 @@ #define CFG_TUD_HID 0 #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 -#define CFG_TUD_NET OPT_NET_RNDIS_ECM -//#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 39c542eca..3e61112e2 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -30,7 +30,7 @@ * 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) | \ @@ -69,11 +69,7 @@ tusb_desc_device_t const desc_device = .iProduct = STRID_PRODUCT, .iSerialNumber = STRID_SERIAL, -#if CFG_TUD_NET == OPT_NET_EEM - .bNumConfigurations = 0x01 -#else .bNumConfigurations = 0x02 -#endif }; // Invoked when received GET DEVICE DESCRIPTOR @@ -89,9 +85,7 @@ uint8_t const * tud_descriptor_device_cb(void) enum { ITF_NUM_CDC = 0, -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM ITF_NUM_CDC_DATA, -#endif ITF_NUM_TOTAL }; @@ -101,12 +95,8 @@ enum CONFIG_NUM_ALTERNATE = 2, }; -#if CFG_TUD_NET == OPT_NET_EEM - #define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_EEM_DESC_LEN) -#else - #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) -#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 @@ -121,16 +111,10 @@ static uint8_t const main_configuration[] = // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(CONFIG_NUM_DEFAULT, ITF_NUM_TOTAL, 0, MAIN_CONFIG_TOTAL_LEN, 0, 100), -#if 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), -#else // 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), -#endif }; -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM static uint8_t const alt_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA @@ -139,19 +123,13 @@ static uint8_t const alt_configuration[] = // 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), }; -#endif // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { -#if CFG_TUD_NET == OPT_NET_EEM - (void) index; // for multiple configurations - return main_configuration; -#else return (0 == index) ? main_configuration : alt_configuration; -#endif } //--------------------------------------------------------------------+ diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 19bc5d2d6..777d0da98 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" @@ -41,21 +41,14 @@ void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networ typedef struct { uint8_t itf_num; -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM uint8_t ep_notif; bool ecm_mode; -#endif uint8_t ep_in; uint8_t ep_out; } netd_interface_t; -#if CFG_TUD_NET == OPT_NET_EEM - #define CFG_TUD_NET_PACKET_PREFIX_LEN 2 - #define CFG_TUD_NET_PACKET_SUFFIX_LEN 4 -#else - #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) - #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 -#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]; @@ -113,9 +106,7 @@ static void do_in_xfer(uint8_t *buf, uint16_t len) void netd_report(uint8_t *buf, uint16_t len) { -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, buf, len); -#endif } //--------------------------------------------------------------------+ @@ -137,16 +128,11 @@ void netd_reset(uint8_t rhport) netd_init(); } -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { // sanity check the descriptor -#if CFG_TUD_NET == OPT_NET_EEM - TU_VERIFY (CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL == itf_desc->bInterfaceSubClass); -#else _netd_itf.ecm_mode = (CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass); TU_VERIFY ( (TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass) || _netd_itf.ecm_mode ); -#endif // confirm interface hasn't already been allocated TU_ASSERT(0 == _netd_itf.ep_notif); @@ -176,7 +162,6 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t return true; } -#endif bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { @@ -223,14 +208,12 @@ bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * reques // Handle class request only TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM TU_VERIFY (_netd_itf.itf_num == request->wIndex); if ( !_netd_itf.ecm_mode && (request->bmRequestType_bit.direction == TUSB_DIR_OUT) ) { rndis_class_set_handler(notify.rndis_buf, request->wLength); } -#endif return true; } @@ -251,9 +234,6 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request TU_VERIFY (_netd_itf.itf_num == request->wIndex); -#if CFG_TUD_NET == OPT_NET_EEM - (void)rhport; -#else if (_netd_itf.ecm_mode) { /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ @@ -277,40 +257,15 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); } } -#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_EEM - struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)pnt; - - (void)len; - - if (hdr->bmType) - { - /* EEM Control Packet: discard it */ - tud_network_recv_renew(); - } - else - { - /* EEM Data Packet */ - pnt += CFG_TUD_NET_PACKET_PREFIX_LEN; - size = hdr->length - 4; /* discard the unused CRC-32 */ - } -#else if (_netd_itf.ecm_mode) { size = len; @@ -326,7 +281,6 @@ static void handle_incoming_packet(uint32_t len) size = r->DataLength; } } -#endif bool accepted = false; @@ -378,12 +332,10 @@ bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ } } -#if CFG_TUD_NET == OPT_NET_RNDIS_ECM if ( _netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif) ) { if (sizeof(notify.ecm_buf.header) == xferred_bytes) ecm_report(false); } -#endif return true; } @@ -402,11 +354,7 @@ void tud_network_xmit(struct pbuf *p) if (!can_xmit) return; -#if CFG_TUD_NET == OPT_NET_EEM - len = CFG_TUD_NET_PACKET_PREFIX_LEN; -#else len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; -#endif data = transmitted + len; for(q = p; q != NULL; q = q->next) @@ -416,16 +364,6 @@ void tud_network_xmit(struct pbuf *p) len += q->len; } -#if 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 */ -#else if (!_netd_itf.ecm_mode) { rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted; @@ -435,7 +373,6 @@ void tud_network_xmit(struct pbuf *p) hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset); hdr->DataLength = len - sizeof(rndis_data_packet_t); } -#endif do_in_xfer(transmitted, len); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 9d15ea4a4..651cbbc7d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -184,7 +184,6 @@ static usbd_class_driver_t const _usbd_driver[] = #endif #if CFG_TUD_NET -#if CFG_TUD_NET != OPT_NET_EEM /* RNDIS management interface */ { .class_code = TUD_RNDIS_ITF_CLASS, @@ -196,24 +195,18 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, -#endif - /* CDC-ECM management interface; CDC-EEM data interface */ + /* CDC-ECM management interface */ { .class_code = TUSB_CLASS_CDC, .init = netd_init, .reset = netd_reset, -#if CFG_TUD_NET == OPT_NET_EEM - .open = netd_open_data, -#else .open = netd_open, -#endif .control_request = netd_control_request, .control_complete = netd_control_complete, .xfer_cb = netd_xfer_cb, .sof = NULL, }, /* RNDIS/CDC-ECM data interface */ -#if CFG_TUD_NET != OPT_NET_EEM { .class_code = TUSB_CLASS_CDC_DATA, .init = netd_init_data, @@ -224,7 +217,6 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, -#endif #endif }; diff --git a/src/tusb_option.h b/src/tusb_option.h index c2394880f..0826a5aab 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -124,14 +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_RNDIS_ECM 1 ///< RNDIS+CDC-ECM -#define OPT_NET_EEM 2 ///< CDC-EEM -/** @} */ - #ifndef CFG_TUSB_RHPORT0_MODE #define CFG_TUSB_RHPORT0_MODE OPT_MODE_NONE #endif -- cgit v1.3.1 From bae570f7c7ab16fcd727dde7e41bd182ade18d71 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 01:01:31 +0700 Subject: tested with midi --- src/class/midi/midi_device.c | 46 +++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 16 deletions(-) (limited to 'src') 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); -- cgit v1.3.1 From e713b534fa563509cad81807fbe11937dfcca8fb Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 10:30:34 +0700 Subject: test ok with cdc and msc --- src/class/cdc/cdc_device.c | 8 ++++---- src/class/hid/hid_device.c | 2 +- src/class/msc/msc_device.c | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 14b9a3153..04c73da78 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -223,11 +223,11 @@ void cdcd_reset(uint8_t rhport) bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { // Only support ACM subclass - TU_ASSERT ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->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; diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index ca00cb942..cbdc5bece 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -160,7 +160,7 @@ 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(desc_itf->bInterfaceClass == TUSB_CLASS_HID); + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); uint8_t const *p_desc = (uint8_t const *) desc_itf; 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; -- cgit v1.3.1 From c1c9ca5629270e545c54d5e2983b77a5c3821a4e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 10:37:31 +0700 Subject: test with tmc --- src/class/usbtmc/usbtmc_device.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') 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; -- cgit v1.3.1 From 490771a094baaa9ead60c7ea2e7c4a594d322825 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 10:39:01 +0700 Subject: test vendor --- src/class/vendor/vendor_device.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') 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 Date: Wed, 15 Apr 2020 11:06:35 +0700 Subject: remove class_code/subclass/protocol from driver structure, add name for logging --- src/device/usbd.c | 129 +++++++++++++++++------------------------------------- 1 file changed, 40 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index f9c52d841..4db6cd671 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -73,17 +73,17 @@ enum { DRVID_INVALID = 0xFFu }; //--------------------------------------------------------------------+ // Class Driver //--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + #define DRIVER_NAME(_name) .name = _name, +#else + #define DRIVER_NAME(_name) +#endif + typedef struct { - uint8_t class_code; - uint8_t subclass; - uint8_t protocol; - - struct TU_ATTR_PACKED - { - uint8_t all_subclass : 1; - uint8_t all_protocol : 1; - }; + #if CFG_TUSB_DEBUG >= 2 + char const* name; + #endif void (* init ) (void); void (* reset ) (uint8_t rhport); @@ -98,12 +98,7 @@ static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_CDC { - .class_code = TUSB_CLASS_CDC, - .subclass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, - .protocol = 0x00, - .all_subclass = 0, - .all_protocol = 1, - + DRIVER_NAME("CDC") .init = cdcd_init, .reset = cdcd_reset, .open = cdcd_open, @@ -116,12 +111,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_MSC { - .class_code = TUSB_CLASS_MSC, - .subclass = MSC_SUBCLASS_SCSI, - .protocol = MSC_PROTOCOL_BOT, - .all_subclass = 0, - .all_protocol = 0, - + DRIVER_NAME("MSC") .init = mscd_init, .reset = mscd_reset, .open = mscd_open, @@ -134,12 +124,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_HID { - .class_code = TUSB_CLASS_HID, - .subclass = 0x00, - .protocol = 0x00, - .all_subclass = 1, - .all_protocol = 1, - + DRIVER_NAME("HID") .init = hidd_init, .reset = hidd_reset, .open = hidd_open, @@ -152,12 +137,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_MIDI { - .class_code = TUSB_CLASS_AUDIO, - .subclass = AUDIO_SUBCLASS_CONTROL, - .protocol = AUDIO_PROTOCOL_V1, - .all_subclass = 0, - .all_protocol = 0, - + DRIVER_NAME("MIDI") .init = midid_init, .open = midid_open, .reset = midid_reset, @@ -170,12 +150,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_VENDOR { - .class_code = TUSB_CLASS_VENDOR_SPECIFIC, - .subclass = 0x00, - .protocol = 0x00, - .all_subclass = 1, - .all_protocol = 1, - + DRIVER_NAME("VENDOR") .init = vendord_init, .reset = vendord_reset, .open = vendord_open, @@ -188,12 +163,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_USBTMC { - .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, - .subclass = APP_SUBCLASS_USBTMC, - .protocol = 0x00, - .all_subclass = 0, - .all_protocol = 1, - + DRIVER_NAME("TMC") .init = usbtmcd_init_cb, .reset = usbtmcd_reset_cb, .open = usbtmcd_open_cb, @@ -206,12 +176,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_DFU_RT { - .class_code = TUSB_CLASS_APPLICATION_SPECIFIC, - .subclass = APP_SUBCLASS_DFU_RUNTIME, - .protocol = DFU_PROTOCOL_RT, - .all_subclass = 0, - .all_protocol = 0, - + DRIVER_NAME("DFU-RT") .init = dfu_rtd_init, .reset = dfu_rtd_reset, .open = dfu_rtd_open, @@ -225,7 +190,12 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_NET /* RNDIS management interface */ { - .class_code = TUD_RNDIS_ITF_CLASS, +// .class_code = TUD_RNDIS_ITF_CLASS, +// .subclass = TUD_RNDIS_ITF_SUBCLASS, +// .protocol = TUD_RNDIS_ITF_PROTOCOL, +// .all_subclass = 0, +// .all_protocol = 0, + DRIVER_NAME("RNDIS") .init = netd_init, .reset = netd_reset, .open = netd_open, @@ -236,7 +206,13 @@ static usbd_class_driver_t const _usbd_driver[] = }, /* CDC-ECM management interface */ { - .class_code = TUSB_CLASS_CDC, +// .class_code = TUSB_CLASS_CDC, +// .subclass = CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, +// .protocol = 0x00, +// .all_subclass = 0, +// .all_protocol = 0, + + DRIVER_NAME("CDC-ECM") .init = netd_init, .reset = netd_reset, .open = netd_open, @@ -247,7 +223,12 @@ static usbd_class_driver_t const _usbd_driver[] = }, /* RNDIS/CDC-ECM data interface */ { - .class_code = TUSB_CLASS_CDC_DATA, +// .class_code = TUSB_CLASS_CDC_DATA, +// .subclass = 0x00, +// .protocol = 0x00, +// .all_subclass = 0, +// .all_protocol = 0, + DRIVER_NAME("CDC-DATA") .init = netd_init_data, .reset = NULL, .open = netd_open_data, @@ -303,35 +284,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_DFU_RT - "DFU Runtime", - #endif - #if CFG_TUD_USBTMC - "USBTMC" - #endif - #if CFG_TUD_NET - "NET" - #endif -}; - static char const* const _tusb_std_request_str[] = { "Get Status" , @@ -388,7 +340,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(); } @@ -497,7 +449,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); } } @@ -542,7 +494,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); } @@ -811,7 +763,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) _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_LOG2(" %s open\r\n", _usbd_driver[drv_id].name); TU_ASSERT( _usbd_driver[drv_id].open(rhport, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); #else @@ -827,9 +779,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { // Interface number must not be used already TODO alternate interface 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; - - TU_LOG2(" itf_len = %d \r\n", itf_len); break; } } -- cgit v1.3.1 From 1faa3b2768f625ffcc06429b7266c88e11605bfc Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 11:41:26 +0700 Subject: tested usbnet, completely remove class code --- src/class/net/net_device.c | 17 ++++++++++++++--- src/device/usbd.c | 18 ++---------------- 2 files changed, 16 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 777d0da98..8d0cb5d37 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -130,13 +130,22 @@ 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 - _netd_itf.ecm_mode = (CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass); - TU_VERIFY ( (TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass) || _netd_itf.ecm_mode ); + 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_notif); + // sanity check the descriptor + _netd_itf.ecm_mode = is_ecm; + //------------- Management Interface -------------// _netd_itf.itf_num = itf_desc->bInterfaceNumber; @@ -165,6 +174,8 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { + TU_VERIFY(TUSB_CLASS_CDC_DATA == itf_desc->bInterfaceClass); + // confirm interface hasn't already been allocated TU_ASSERT(0 == _netd_itf.ep_in); diff --git a/src/device/usbd.c b/src/device/usbd.c index 4db6cd671..0f60117ee 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -190,11 +190,6 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_NET /* RNDIS management interface */ { -// .class_code = TUD_RNDIS_ITF_CLASS, -// .subclass = TUD_RNDIS_ITF_SUBCLASS, -// .protocol = TUD_RNDIS_ITF_PROTOCOL, -// .all_subclass = 0, -// .all_protocol = 0, DRIVER_NAME("RNDIS") .init = netd_init, .reset = netd_reset, @@ -204,14 +199,9 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, + /* CDC-ECM management interface */ { -// .class_code = TUSB_CLASS_CDC, -// .subclass = CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, -// .protocol = 0x00, -// .all_subclass = 0, -// .all_protocol = 0, - DRIVER_NAME("CDC-ECM") .init = netd_init, .reset = netd_reset, @@ -221,13 +211,9 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, + /* RNDIS/CDC-ECM data interface */ { -// .class_code = TUSB_CLASS_CDC_DATA, -// .subclass = 0x00, -// .protocol = 0x00, -// .all_subclass = 0, -// .all_protocol = 0, DRIVER_NAME("CDC-DATA") .init = netd_init_data, .reset = NULL, -- cgit v1.3.1 From 3bfb402d8ce0fda082f77d4e552537a51f93375c Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 11:44:12 +0700 Subject: clean up --- src/device/usbd.c | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 0f60117ee..eabe24be0 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -739,29 +739,15 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; -#if 0 - // Find driver id for the interface - uint8_t drv_id = find_driver_id(desc_itf); - 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[drv_id].name); - TU_ASSERT( _usbd_driver[drv_id].open(rhport, desc_itf, &itf_len) ); - TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); -#else uint8_t drv_id; - uint16_t itf_len; + 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]; - itf_len = 0; - if ( driver->open(rhport, desc_itf, &itf_len) ) + drv_len = 0; + if ( driver->open(rhport, desc_itf, &drv_len) ) { // Interface number must not be used already TODO alternate interface TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); @@ -771,13 +757,12 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } } - // Assert if cannot find a driver - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && itf_len >= sizeof(tusb_desc_interface_t) ); -#endif + // 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, itf_len, drv_id); // TODO refactor + mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor - p_desc += itf_len; // next interface + p_desc += drv_len; // next interface } } -- cgit v1.3.1 From 93ffe317b262df34afe74e216017411ac70324b5 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 13:53:50 +0700 Subject: clean up --- src/device/usbd.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index eabe24be0..4587a2cc7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -241,8 +241,6 @@ static osal_queue_t _usbd_q; // Prototypes //--------------------------------------------------------------------+ static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); -//static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf); - static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); static bool process_set_config(uint8_t rhport, uint8_t cfg_num); static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); @@ -772,26 +770,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) return true; } -#if 0 -// Helper to find class driver id for an interface -// return 0xFF if not found -static uint8_t find_driver_id(tusb_desc_interface_t const * desc_itf) -{ - for (uint8_t drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) - { - usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; - if ( (driver->class_code == desc_itf->bInterfaceClass) && // match class code - (driver->subclass == desc_itf->bInterfaceSubClass || driver->all_subclass ) && // match subclass or driver support all - (driver->protocol == desc_itf->bInterfaceProtocol || driver->all_protocol)) // match protocol or driver support all - { - return drv_id; - } - } - - return DRVID_INVALID; -} -#endif - // Helper marking endpoint of interface belongs to class driver static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) { -- cgit v1.3.1 From b03b9eb93991c561610a01c379154e7db55e9f4b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 15:14:26 +0700 Subject: change cdc template protocol to None --- src/class/cdc/cdc_host.c | 2 +- src/device/usbd.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') 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/device/usbd.h b/src/device/usbd.h index 7b04ef9a7..acefb6943 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -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 */\ -- cgit v1.3.1 From 0b39168dc25ad970a9829ada2c0e6af26cb0d1ed Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 15:40:53 +0700 Subject: add IAD for CDC ECM, remove EEM descriptor template --- src/device/usbd.h | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index acefb6943..3b409e70b 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -343,11 +343,13 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re //------------- CDC-ECM -------------// // Length of template descriptor: 71 bytes -#define TUD_CDC_ECM_DESC_LEN (9+5+5+13+7+9+9+7+7) +#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 */\ @@ -410,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 -- cgit v1.3.1 From d315393fbb39ab6a70ea2c636d28305d9777ff97 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 16:18:24 +0700 Subject: use IAD to assign itf2drv mapping correctly merge net_data back into net driver --- src/class/cdc/cdc_device.c | 4 +- src/class/net/net_device.c | 30 ++++----------- src/class/net/net_device.h | 2 - src/device/usbd.c | 92 ++++++++++++++++++++++------------------------ 4 files changed, 53 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 04c73da78..95b14ba54 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -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/net/net_device.c b/src/class/net/net_device.c index 8d0cb5d37..8bbce2305 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -117,10 +117,6 @@ void netd_init(void) tu_memclr(&_netd_itf, sizeof(_netd_itf)); } -void netd_init_data(void) -{ -} - void netd_reset(uint8_t rhport) { (void) rhport; @@ -166,32 +162,21 @@ 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); } - return true; -} - -bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) -{ - TU_VERIFY(TUSB_CLASS_CDC_DATA == itf_desc->bInterfaceClass); - - // confirm interface hasn't already been allocated - TU_ASSERT(0 == _netd_itf.ep_in); - - uint8_t const * p_desc = tu_desc_next( itf_desc ); - (*p_length) = sizeof(tusb_desc_interface_t); - //------------- Data Interface -------------// - while ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) + // TODO extract Alt Interface 0 & 1 + while ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && + (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // next to endpoint descriptor + (*p_length) += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); - (*p_length) += sizeof(tusb_desc_interface_t); } - if (TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { // Open endpoint pair TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) ); @@ -207,6 +192,7 @@ bool netd_open_data(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint // prepare for incoming packets tud_network_recv_renew(); + return true; } diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 6914ed050..67cd99933 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -73,10 +73,8 @@ void tud_network_xmit(struct pbuf *p); // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ void netd_init (void); -void netd_init_data (void); void netd_reset (uint8_t rhport); bool netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool netd_open_data (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); diff --git a/src/device/usbd.c b/src/device/usbd.c index 4587a2cc7..ad5a32f92 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -188,9 +188,8 @@ static usbd_class_driver_t const _usbd_driver[] = #endif #if CFG_TUD_NET - /* RNDIS management interface */ { - DRIVER_NAME("RNDIS") + DRIVER_NAME("NET") .init = netd_init, .reset = netd_reset, .open = netd_open, @@ -199,30 +198,6 @@ static usbd_class_driver_t const _usbd_driver[] = .xfer_cb = netd_xfer_cb, .sof = NULL, }, - - /* CDC-ECM management interface */ - { - DRIVER_NAME("CDC-ECM") - .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, - }, - - /* RNDIS/CDC-ECM data interface */ - { - DRIVER_NAME("CDC-DATA") - .init = netd_init_data, - .reset = NULL, - .open = netd_open_data, - .control_request = NULL, - .control_complete = NULL, - .xfer_cb = netd_xfer_cb, - .sof = NULL, - }, #endif }; @@ -611,9 +586,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const case TUSB_REQ_SET_INTERFACE: { uint8_t const alternate = (uint8_t) p_request->wValue; + (void) alternate; // TODO not support alternate interface yet - TU_ASSERT(alternate == 0); +// TU_ASSERT(alternate == 0); tud_control_status(rhport, p_request); } break; @@ -727,41 +703,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) ); + desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc; + p_desc = tu_desc_next(p_desc); // next to Interface + } - tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; + TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - uint8_t drv_id; - uint16_t drv_len; + 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++) + 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) ) { - usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + // Interface number must not be used already + TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); - drv_len = 0; - if ( driver->open(rhport, desc_itf, &drv_len) ) + 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) { - // Interface number must not be used already TODO alternate interface - 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; - break; + // 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) ); + // 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 + mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor - p_desc += drv_len; // next interface - } + p_desc += drv_len; // next interface } // invoke callback -- cgit v1.3.1 From caa1dceed97d841ca4176d96e324de976948f327 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 17:51:02 +0700 Subject: implement alternate setInterface() request mostly forward these request (recipient = interface) to class driver. --- src/class/net/net_device.c | 158 +++++++++++++++++++++++++++++++++------------ src/device/usbd.c | 37 +---------- 2 files changed, 118 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 8bbce2305..575a15edd 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -40,11 +40,20 @@ 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; - bool ecm_mode; 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; #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) @@ -145,8 +154,8 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t //------------- 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 ); // Communication Functional Descriptors while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) @@ -167,31 +176,44 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t } //------------- Data Interface -------------// - // TODO extract Alt Interface 0 & 1 - while ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) + // - 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)); + + do { - // next to endpoint descriptor + 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)) ); - if (TUSB_DESC_ENDPOINT == 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 + // 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(); - tud_network_init_cb(); + // we are ready to transmit a packet + can_xmit = true; - // we are ready to transmit a packet - can_xmit = true; - - // prepare for incoming packets - tud_network_recv_renew(); + // prepare for incoming packets + tud_network_recv_renew(); + } + (*p_length) += 2*sizeof(tusb_desc_endpoint_t); return true; } @@ -226,33 +248,83 @@ static void ecm_report(bool nc) // 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: + tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); + break; + + case TUSB_REQ_SET_INTERFACE: + { + // Request to enable/disable network activities on ACM-ECM only + TU_ASSERT(_netd_itf.ecm_mode); + + _netd_itf.itf_data_alt = (uint8_t) request->wValue; + + 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 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; - TU_VERIFY (_netd_itf.itf_num == request->wIndex); + // unsupported request + default: return false; + } + break; - 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)); - } + 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; } return true; diff --git a/src/device/usbd.c b/src/device/usbd.c index ad5a32f92..1df850165 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -571,40 +571,9 @@ 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) - { - 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; - - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const alternate = (uint8_t) p_request->wValue; - (void) alternate; - - // 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)); - } + // all requests to Interface (STD or Class) is forwarded to class driver. + // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE + TU_VERIFY(invoke_class_control(rhport, drvid, p_request)); } break; -- cgit v1.3.1 From b0270f499b7f0cc2f5589a274105cd4cac87f1a7 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 14 Apr 2020 10:22:37 -0400 Subject: stm32fsdev: dynamic allocation of PMA. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 147 ++++++++++++++++---------- 1 file changed, 94 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index e1f459b6c..14ffcbe40 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -63,10 +63,7 @@ * 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 fixed 64 bytes. - * - Smaller can be requested: - * - Must be a multiple of 8 bytes - * - All EP must have identical buffer size. + * - 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 @@ -76,7 +73,6 @@ * - 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. @@ -135,11 +131,7 @@ // 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 -# if (PMA_LENGTH == 512U) -# define MAX_EP_COUNT 3U -# else -# define MAX_EP_COUNT 7U -# endif +# 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 @@ -152,11 +144,6 @@ # define DCD_STM32_BTABLE_LENGTH (PMA_LENGTH - DCD_STM32_BTABLE_BASE) #endif -// Below is used by the static PMA allocator -#ifndef DCD_STM32_PMA_ALLOC_SIZE -# define DCD_STM32_PMA_ALLOC_SIZE 64U -#endif - /*************************************************** * Checks, structs, defines, function definitions, etc. */ @@ -168,21 +155,15 @@ TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_LENGTH))<=(PMA_LEN TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligned to 8 bytes"); -// With static allocation of 64 bytes per endpoint, ensure there is enough packet buffer space -// 8 bytes are required for control data for each EP. -TU_VERIFY_STATIC(((MAX_EP_COUNT*2u*DCD_STM32_PMA_ALLOC_SIZE + 8*MAX_EP_COUNT) <= DCD_STM32_BTABLE_LENGTH), "Packed buffer not long enough for count of endpoints"); - -TU_VERIFY_STATIC((DCD_STM32_PMA_ALLOC_SIZE % 8) == 0, "Packet buffer allocation must be a multiple of 8 bytes"); - -TU_VERIFY_STATIC(CFG_TUD_ENDPOINT0_SIZE <= DCD_STM32_PMA_ALLOC_SIZE,"EP0 size is more than PMA allocation size"); - // One of these for every EP IN & OUT, uses a bit of RAM.... 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]; @@ -196,14 +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 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 @@ -237,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 @@ -249,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(); @@ -386,6 +366,7 @@ static void dcd_handle_bus_reset(void) pcd_set_endpoint(USB,i,0u); } + dcd_pma_alloc_reset(); dcd_edpt_open (0, &ep0OUT_desc); dcd_edpt_open (0, &ep0IN_desc); @@ -609,28 +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 - * Currently statitically allocates 64 bytes for each EP. * - * stm32fsdev have 512 or 1024 bytes of packet RAM, and support 16 EP (8 in and 8 out), - * Static checks above have verified that there is enough packet memory space, so - * this should NEVER fail. + * 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); - (void)length; + 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 - TU_ASSERT(length <= DCD_STM32_PMA_ALLOC_SIZE); + // 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); - uint16_t addr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT; // Each EP needs 8 bytes to store control data - addr += ((2*epnum + dir) * DCD_STM32_PMA_ALLOC_SIZE); 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. @@ -640,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: @@ -669,21 +709,24 @@ 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) = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress, p_endpoint_desc->wMaxPacketSize.size); + *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) = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress, p_endpoint_desc->wMaxPacketSize.size); + *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); @@ -707,10 +750,6 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) uint32_t const epnum = tu_edpt_number(ep_addr); uint32_t const dir = tu_edpt_dir(ep_addr); -#ifndef NDEBUG - TU_ASSERT(epnum < MAX_EP_COUNT, /**/); -#endif - if(dir == TUSB_DIR_IN) { pcd_set_ep_tx_status(USB,epnum,USB_EP_TX_DIS); @@ -719,6 +758,8 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) { 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) -- cgit v1.3.1 From 0ddbda08cba7895d4710f787c230af074c25cb0f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 23:08:49 +0700 Subject: always response if GET_INTERFACE even if class driver does not support alt interface --- src/device/usbd.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 1df850165..cf16b28c8 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -573,7 +573,16 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // all requests to Interface (STD or Class) is forwarded to class driver. // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE - TU_VERIFY(invoke_class_control(rhport, drvid, p_request)); + if ( !invoke_class_control(rhport, drvid, p_request) ) + { + // For STD GET_INTERFACE even if class driver doesn't support alternate setting + // It is still mandatory to response with value of zero + TU_VERIFY( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && + TUSB_REQ_GET_INTERFACE == p_request->bRequest); + + uint8_t alternate = 0; + tud_control_xfer(rhport, p_request, &alternate, 1); + } } break; -- cgit v1.3.1 From 86ff5651ad94b6134aca0805b48d255da4786eef Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Apr 2020 23:10:52 +0700 Subject: correct usbnet control complete response don't return false with STD request get/setInterface() or targeted Data Interface (itfnum +1) --- src/class/net/net_device.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 575a15edd..8cb2e2e0b 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -224,14 +224,15 @@ 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 ( !_netd_itf.ecm_mode && (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(notify.rndis_buf, request->wLength); + if ( !_netd_itf.ecm_mode ) + { + rndis_class_set_handler(notify.rndis_buf, request->wLength); + } } return true; @@ -259,9 +260,14 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request case TUSB_REQ_SET_INTERFACE: { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + // Request to enable/disable network activities on ACM-ECM only TU_ASSERT(_netd_itf.ecm_mode); + // Only valid for Data Interface + TU_ASSERT(_netd_itf.itf_num+1 == req_itfnum); + _netd_itf.itf_data_alt = (uint8_t) request->wValue; if ( _netd_itf.itf_data_alt ) @@ -273,7 +279,8 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request 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 have opposite callback for application to disable network !! + // 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 -- cgit v1.3.1 From b9fca0bbb4a7706e7229962759130ee0ea2587b0 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Wed, 15 Apr 2020 14:16:48 -0500 Subject: nuc505: change dcd_set_config() behavior --- src/portable/nuvoton/nuc505/dcd_nuc505.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 3baed87c5..50057ac25 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) @@ -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; -- cgit v1.3.1 From 2eed58d0962849014ab3166d4a3f0d3677d32c01 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Apr 2020 11:13:54 +0700 Subject: per review --- src/class/net/net_device.c | 16 +++++++++++----- src/device/usbd.c | 4 ++-- 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 8cb2e2e0b..0f2ccbd44 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -255,20 +255,26 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request 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); + tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); + } break; case TUSB_REQ_SET_INTERFACE: { uint8_t const req_itfnum = (uint8_t) request->wIndex; + uint8_t const req_alt = (uint8_t) request->wValue; - // Request to enable/disable network activities on ACM-ECM only - TU_ASSERT(_netd_itf.ecm_mode); + // Only valid for Data Interface with Alternate is either 0 or 1 + TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2); - // Only valid for Data Interface - TU_ASSERT(_netd_itf.itf_num+1 == req_itfnum); + // ACM-ECM only: qequest to enable/disable network activities + TU_VERIFY(_netd_itf.ecm_mode); - _netd_itf.itf_data_alt = (uint8_t) request->wValue; + _netd_itf.itf_data_alt = req_alt; if ( _netd_itf.itf_data_alt ) { diff --git a/src/device/usbd.c b/src/device/usbd.c index cf16b28c8..29845ff36 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -575,8 +575,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE if ( !invoke_class_control(rhport, drvid, p_request) ) { - // For STD GET_INTERFACE even if class driver doesn't support alternate setting - // It is still mandatory to response with value of zero + // 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); -- cgit v1.3.1 From 969121df4f1025481cfe085397c8dede454f4537 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Apr 2020 15:52:45 +0700 Subject: added dcd disconnect/connect to lpc17/40 --- src/device/dcd.h | 6 +++--- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 14 +++++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index f4e6edb95..08b217fa9 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -106,10 +106,10 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num); // Wake up host void dcd_remote_wakeup(uint8_t rhport); -// Connect or disconnect D+/D- line pull-up resistor. -// Defined in dcd source if MCU has internal pull-up. -// Otherwise, may be defined in BSP. +// Connect by enabling internal pull-up resistor on D+/D- void dcd_connect(uint8_t rhport) TU_ATTR_WEAK; + +// Disconnect by disabling internal pull-up resistor on D+/D- void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; //--------------------------------------------------------------------+ diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 884260f31..b4a11f49c 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); } @@ -219,6 +217,16 @@ void dcd_remote_wakeup(uint8_t rhport) (void) rhport; } +void dcd_connect(uint8_t rhport) +{ + sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, SIE_DEV_STATUS_CONNECT_STATUS_MASK); +} + +void dcd_disconnect(uint8_t rhport) +{ + sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, 0); +} + //--------------------------------------------------------------------+ // CONTROL HELPER //--------------------------------------------------------------------+ -- cgit v1.3.1 From 418b69f2db1c07341cfca73bfb6373cc57ae3656 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Apr 2020 16:05:57 +0700 Subject: implement dcd disconnect/connect for lpc ip3511 --- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 2 ++ src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 14 +++++++++++++- src/portable/template/dcd_template.c | 12 ++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index b4a11f49c..dfdae1450 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -219,11 +219,13 @@ void dcd_remote_wakeup(uint8_t 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); } diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 9af8e6019..980fa118f 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 //--------------------------------------------------------------------+ 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 //--------------------------------------------------------------------+ -- cgit v1.3.1 From a00977574537b987250f7f16ee23ba9def42e051 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Apr 2020 16:56:16 +0700 Subject: dcd disconnect/connect for transdimension ip --- hw/bsp/mimxrt1015_evk/board.mk | 4 ++++ src/portable/nxp/transdimension/dcd_transdimension.c | 15 +++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/hw/bsp/mimxrt1015_evk/board.mk b/hw/bsp/mimxrt1015_evk/board.mk index abb6bc38b..7df60c2c6 100644 --- a/hw/bsp/mimxrt1015_evk/board.mk +++ b/hw/bsp/mimxrt1015_evk/board.mk @@ -50,3 +50,7 @@ JLINK_IF = swd # flash by copying bin file to DAP Mass Storage flash: $(BUILD)/$(BOARD)-firmware.bin cp $< /media/$(USER)/RT1015-EVK/ + +# flash using pyocd +#flash: $(BUILD)/$(BOARD)-firmware.hex +# pyocd flash -b MIMXRT1015-EVK $< diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 2872f1435..cea7c2b04 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 //--------------------------------------------------------------------+ -- cgit v1.3.1 From 4c74140b316d46cc62cd3d7031994c4f091e80e6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Apr 2020 20:20:20 +0700 Subject: stm32 sysnopsys disconnect/connect --- src/portable/sony/cxd56/dcd_cxd56.c | 12 ++++++++++++ src/portable/st/synopsys/dcd_synopsys.c | 21 +++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 320b7237e..57158838f 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); } +#if 0 // TODO implement for Spresense +void dcd_connect(uint8_t rhport) +{ + (void) rhport; +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; +} +#endif + //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index dc752b37a..38c284c5a 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 *------------------------------------------------------------------*/ -- cgit v1.3.1 From 63655ac9d790d55d7a002248dafe9df888606b18 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Apr 2020 20:43:26 +0700 Subject: cleanup for esp32 --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 126f3ea20..47c90fd13 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 *------------------------------------------------------------------*/ -- cgit v1.3.1 From 2994d100cd6198a4c90dce667f52fde07fe4a073 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Thu, 16 Apr 2020 09:57:56 -0400 Subject: Remove transfer queue filtering. May need to be revisited later. --- src/device/usbd.c | 47 ++--------------------------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 75c0a3720..55a9ccebc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1064,50 +1064,10 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) } /** - * Remove queued xfer complete messages from event queue, - * for a particular ep. + * usbd_edpt_close will disable an endpoint. * - * Must be called with interrupts enabled. - */ -static void usbd_abort_transfers(uint8_t rhport, uint8_t ep_addr) -{ - dcd_event_t ev_sentinal = - { - .event_id = DCD_EVENT_COUNT, ///< This is an invalid event ID. - }; - dcd_event_t event; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const ep_dir = tu_edpt_dir(ep_addr); - - dcd_int_disable(rhport); - // Queue sentinal element - TU_ASSERT(osal_queue_send(_usbd_q, &ev_sentinal, true), /**/); - - TU_ASSERT(osal_queue_receive(_usbd_q, &event), /**/); - - while(event.event_id != DCD_EVENT_COUNT) - { - if((event.rhport == rhport) && (event.event_id == DCD_EVENT_XFER_COMPLETE) - && (event.xfer_complete.ep_addr == ep_addr)) - { - _usbd_dev.ep_status[epnum][ep_dir].busy = false; - } - else - { - TU_ASSERT(osal_queue_send(_usbd_q, &event, true), /**/); - } - TU_ASSERT(osal_queue_receive(_usbd_q, &event), /**/); - } - - dcd_int_enable(rhport); -} - -/** - * usbd_edpt_close will disable an endpoint, and clear all pending transfers - * through the particular endpoint. + * In progress transfers on this EP may be delivered after this call. * - * It must be called from the usb task (e.g. from the control request - * handler while handling SET_ALTERNATE), with interrupts enabled. */ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { @@ -1116,9 +1076,6 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) dcd_edpt_close(rhport, ep_addr); - /* Now, in progress transfers have to be expunged */ - usbd_abort_transfers(rhport, ep_addr); - return; } -- cgit v1.3.1 From 18d936b414bd91a6337bbbddef54c09adcf6e49a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Apr 2020 21:04:28 +0700 Subject: msp430 disconnect/connect --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index edccec33f..680d63588 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,24 @@ void dcd_remote_wakeup(uint8_t rhport) (void) rhport; } +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + + USBKEYPID = USBKEY; + USBCNF |= PUR_EN; // Enable pullup. + USBKEYPID = 0; +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + + USBKEYPID = USBKEY; + USBCNF &= ~PUR_EN; // Disable pullup. + USBKEYPID = 0; +} + /*------------------------------------------------------------------*/ /* DCD Endpoint port *------------------------------------------------------------------*/ -- cgit v1.3.1 From 3aaad8cd730d01a65065d9eb8b694221724151c3 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Apr 2020 21:30:12 +0700 Subject: add int enable/disable for pullup --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 680d63588..1512f0de4 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -206,20 +206,24 @@ void dcd_remote_wakeup(uint8_t rhport) void dcd_connect(uint8_t rhport) { - (void) rhport; + dcd_int_disable(rhport); USBKEYPID = USBKEY; USBCNF |= PUR_EN; // Enable pullup. USBKEYPID = 0; + + dcd_int_enable(rhport); } void dcd_disconnect(uint8_t rhport) { - (void) rhport; + dcd_int_disable(rhport); USBKEYPID = USBKEY; USBCNF &= ~PUR_EN; // Disable pullup. USBKEYPID = 0; + + dcd_int_enable(rhport); } /*------------------------------------------------------------------*/ -- cgit v1.3.1 From 6377699d77b5b6dcadef4ce3a30ee613fef37729 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Apr 2020 22:30:33 +0700 Subject: implement dcd disconnect connect --- src/portable/valentyusb/eptri/dcd_eptri.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index 1054e71d6..1e7219a1f 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 //--------------------------------------------------------------------+ -- cgit v1.3.1 From 36d4efa077a34ac33d420a1e1d3d200ada04ff9a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Apr 2020 22:59:19 +0700 Subject: samg implement dcd connect/disconnect --- src/portable/microchip/samg/dcd_samg.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 93d9029d6..c122b9bee 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 //--------------------------------------------------------------------+ -- cgit v1.3.1 From 89f99426fc63a907c9fd55cc78d62d9bf88efb55 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Apr 2020 11:48:09 +0700 Subject: add code for disconnect/connect (not tested) --- hw/bsp/spresense/board.mk | 9 ++++++--- src/portable/sony/cxd56/dcd_cxd56.c | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/hw/bsp/spresense/board.mk b/hw/bsp/spresense/board.mk index c6b5ce12a..e3e3b6473 100644 --- a/hw/bsp/spresense/board.mk +++ b/hw/bsp/spresense/board.mk @@ -43,7 +43,10 @@ LDFLAGS += \ VENDOR = sony CHIP_FAMILY = cxd56 +$(BUILD)/$(BOARD)-firmware.spk: $(BUILD)/$(BOARD)-firmware.elf + @echo CREATE $@ + @$(SPRESENSE_SDK)/sdk/tools/linux/mkspk -c 2 $^ nuttx $@ + # flash -flash: - $(SPRESENSE_SDK)/sdk/tools/linux/mkspk -c 2 $(BUILD)/spresense-firmware.elf nuttx $(BUILD)/spresense-firmware.spk - $(SPRESENSE_SDK)/sdk/tools/flash.sh -c /dev/ttyUSB0 $(BUILD)/spresense-firmware.spk +flash: $(BUILD)/$(BOARD)-firmware.spk + @$(SPRESENSE_SDK)/sdk/tools/flash.sh -c /dev/ttyUSB0 $< diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 57158838f..ca6a8be20 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -205,11 +205,13 @@ void dcd_remote_wakeup(uint8_t rhport) void dcd_connect(uint8_t rhport) { (void) rhport; +// DEV_CONNECT(usbdev); } void dcd_disconnect(uint8_t rhport) { (void) rhport; +// DEV_DISCONNECT(usbdev); } #endif -- cgit v1.3.1 From 50be9d7c3ad08fdc8a79f38606111cf83c84efb9 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Apr 2020 12:27:53 +0700 Subject: mass rename tud/dcd_irq_handler to tud/dcd_init_handler --- changelog.md | 4 ++-- docs/porting.md | 2 +- examples/device/board_test/Makefile | 2 +- hw/bsp/adafruit_clue/adafruit_clue.c | 2 +- hw/bsp/arduino_nano33_ble/arduino_nano33_ble.c | 2 +- hw/bsp/circuitplayground_bluefruit/circuitplayground_bluefruit.c | 2 +- hw/bsp/circuitplayground_express/circuitplayground_express.c | 2 +- hw/bsp/ea4088qs/ea4088qs.c | 2 +- hw/bsp/ea4357/ea4357.c | 4 ++-- hw/bsp/feather_m0_express/feather_m0_express.c | 2 +- hw/bsp/feather_m4_express/feather_m4_express.c | 8 ++++---- hw/bsp/feather_nrf52840_express/feather_nrf52840_express.c | 2 +- hw/bsp/feather_nrf52840_sense/feather_nrf52840_sense.c | 2 +- hw/bsp/feather_stm32f405/feather_stm32f405.c | 2 +- hw/bsp/fomu/fomu.c | 2 +- hw/bsp/itsybitsy_m0/itsybitsy_m0.c | 2 +- hw/bsp/itsybitsy_m4/itsybitsy_m4.c | 8 ++++---- hw/bsp/lpcxpresso11u37/lpcxpresso11u37.c | 2 +- hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c | 2 +- hw/bsp/lpcxpresso1347/lpcxpresso1347.c | 2 +- hw/bsp/lpcxpresso1549/lpcxpresso1549.c | 2 +- hw/bsp/lpcxpresso1769/lpcxpresso1769.c | 2 +- hw/bsp/lpcxpresso51u68/lpcxpresso51u68.c | 2 +- hw/bsp/lpcxpresso54114/lpcxpresso54114.c | 2 +- hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c | 4 ++-- hw/bsp/mbed1768/mbed1768.c | 2 +- hw/bsp/mcb1800/mcb1800.c | 4 ++-- hw/bsp/metro_m0_express/metro_m0_express.c | 2 +- hw/bsp/metro_m4_express/metro_m4_express.c | 8 ++++---- hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c | 2 +- hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c | 2 +- hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c | 2 +- hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c | 4 ++-- hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c | 4 ++-- hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c | 4 ++-- hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c | 2 +- hw/bsp/ngx4330/ngx4330.c | 4 ++-- hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c | 2 +- hw/bsp/nutiny_nuc121s/nutiny_nuc121.c | 2 +- hw/bsp/nutiny_nuc125s/nutiny_nuc125.c | 2 +- hw/bsp/nutiny_nuc126v/nutiny_nuc126.c | 2 +- hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c | 2 +- hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c | 2 +- hw/bsp/pca10056/pca10056.c | 2 +- hw/bsp/pca10059/pca10059.c | 2 +- hw/bsp/pca10100/pca10100.c | 2 +- hw/bsp/pyboardv11/pyboardv11.c | 2 +- hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c | 2 +- hw/bsp/samg55xplained/samg55xplained.c | 2 +- hw/bsp/seeeduino_xiao/seeeduino_xiao.c | 2 +- hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c | 2 +- hw/bsp/stm32f072disco/stm32f072disco.c | 2 +- hw/bsp/stm32f103bluepill/stm32f103bluepill.c | 6 +++--- hw/bsp/stm32f207nucleo/stm32f207nucleo.c | 2 +- hw/bsp/stm32f303disco/stm32f303disco.c | 6 +++--- hw/bsp/stm32f401blackpill/stm32f401blackpill.c | 2 +- hw/bsp/stm32f407disco/stm32f407disco.c | 2 +- hw/bsp/stm32f411blackpill/stm32f411blackpill.c | 2 +- hw/bsp/stm32f411disco/stm32f411disco.c | 2 +- hw/bsp/stm32f412disco/stm32f412disco.c | 2 +- hw/bsp/stm32f767nucleo/stm32f767nucleo.c | 2 +- hw/bsp/stm32h743nucleo/stm32h743nucleo.c | 2 +- hw/bsp/stm32l0538disco/stm32l0538disco.c | 2 +- hw/bsp/stm32l476disco/stm32l476disco.c | 2 +- hw/bsp/teensy_40/teensy40.c | 4 ++-- src/device/dcd.h | 2 +- src/device/usbd.h | 2 +- src/portable/espressif/esp32s2/dcd_esp32s2.c | 4 ++-- src/portable/microchip/samd/dcd_samd.c | 2 +- src/portable/microchip/samg/dcd_samg.c | 2 +- src/portable/nordic/nrf5x/dcd_nrf5x.c | 2 +- src/portable/nuvoton/nuc120/dcd_nuc120.c | 2 +- src/portable/nuvoton/nuc121/dcd_nuc121.c | 2 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 2 +- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 2 +- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 2 +- src/portable/nxp/transdimension/dcd_transdimension.c | 2 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 2 +- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 2 +- src/portable/valentyusb/eptri/dcd_eptri.c | 2 +- 81 files changed, 104 insertions(+), 104 deletions(-) (limited to 'src') 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 83b08da27..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. 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/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/fomu.c b/hw/bsp/fomu/fomu.c index 404b72333..25e5e9613 100644 --- a/hw/bsp/fomu/fomu.c +++ b/hw/bsp/fomu/fomu.c @@ -63,7 +63,7 @@ void isr(void) #if CFG_TUSB_RHPORT0_MODE == OPT_MODE_DEVICE if (irqs & (1 << USB_INTERRUPT)) { - tud_irq_handler(0); + tud_int_handler(0); } #endif if (irqs & (1 << TIMER0_INTERRUPT)) { diff --git a/hw/bsp/itsybitsy_m0/itsybitsy_m0.c b/hw/bsp/itsybitsy_m0/itsybitsy_m0.c index 93661b899..652bc6b3d 100644 --- a/hw/bsp/itsybitsy_m0/itsybitsy_m0.c +++ b/hw/bsp/itsybitsy_m0/itsybitsy_m0.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/itsybitsy_m4/itsybitsy_m4.c b/hw/bsp/itsybitsy_m4/itsybitsy_m4.c index 3ae9565c9..0195a9fc4 100644 --- a/hw/bsp/itsybitsy_m4/itsybitsy_m4.c +++ b/hw/bsp/itsybitsy_m4/itsybitsy_m4.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/lpcxpresso11u37/lpcxpresso11u37.c b/hw/bsp/lpcxpresso11u37/lpcxpresso11u37.c index 6f2ae80e8..11f1797a2 100644 --- a/hw/bsp/lpcxpresso11u37/lpcxpresso11u37.c +++ b/hw/bsp/lpcxpresso11u37/lpcxpresso11u37.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USB_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //---------------------------------------------------------------- ----+ diff --git a/hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c b/hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c index 193df3bb1..e33a5c6e5 100644 --- a/hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c +++ b/hw/bsp/lpcxpresso11u68/lpcxpresso11u68.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USB_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/lpcxpresso1347/lpcxpresso1347.c b/hw/bsp/lpcxpresso1347/lpcxpresso1347.c index 14a0009e4..a9a67ae3a 100644 --- a/hw/bsp/lpcxpresso1347/lpcxpresso1347.c +++ b/hw/bsp/lpcxpresso1347/lpcxpresso1347.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USB_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/lpcxpresso1549/lpcxpresso1549.c b/hw/bsp/lpcxpresso1549/lpcxpresso1549.c index 2ae8d7506..a10cd38ec 100644 --- a/hw/bsp/lpcxpresso1549/lpcxpresso1549.c +++ b/hw/bsp/lpcxpresso1549/lpcxpresso1549.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USB_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c index 3b5c9dcab..cc6fd95ae 100644 --- a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c +++ b/hw/bsp/lpcxpresso1769/lpcxpresso1769.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/lpcxpresso51u68/lpcxpresso51u68.c b/hw/bsp/lpcxpresso51u68/lpcxpresso51u68.c index 2a314388d..6bade7743 100644 --- a/hw/bsp/lpcxpresso51u68/lpcxpresso51u68.c +++ b/hw/bsp/lpcxpresso51u68/lpcxpresso51u68.c @@ -35,7 +35,7 @@ //--------------------------------------------------------------------+ void USB0_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/lpcxpresso54114/lpcxpresso54114.c b/hw/bsp/lpcxpresso54114/lpcxpresso54114.c index 847accb67..3bccc4bd7 100644 --- a/hw/bsp/lpcxpresso54114/lpcxpresso54114.c +++ b/hw/bsp/lpcxpresso54114/lpcxpresso54114.c @@ -35,7 +35,7 @@ //--------------------------------------------------------------------+ void USB0_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c b/hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c index 31519dc8f..a17cffe9c 100644 --- a/hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c +++ b/hw/bsp/lpcxpresso55s69/lpcxpresso55s69.c @@ -35,12 +35,12 @@ //--------------------------------------------------------------------+ void USB0_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB1_IRQHandler(void) { - tud_irq_handler(1); + tud_int_handler(1); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/mbed1768/mbed1768.c b/hw/bsp/mbed1768/mbed1768.c index cda508803..5963ad8ec 100644 --- a/hw/bsp/mbed1768/mbed1768.c +++ b/hw/bsp/mbed1768/mbed1768.c @@ -145,7 +145,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/mcb1800/mcb1800.c b/hw/bsp/mcb1800/mcb1800.c index 43dc7bfbb..ae9f1b62f 100644 --- a/hw/bsp/mcb1800/mcb1800.c +++ b/hw/bsp/mcb1800/mcb1800.c @@ -37,7 +37,7 @@ void USB0_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } @@ -48,7 +48,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/metro_m0_express/metro_m0_express.c b/hw/bsp/metro_m0_express/metro_m0_express.c index 83b20793e..4eb157c8f 100644 --- a/hw/bsp/metro_m0_express/metro_m0_express.c +++ b/hw/bsp/metro_m0_express/metro_m0_express.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/metro_m4_express/metro_m4_express.c b/hw/bsp/metro_m4_express/metro_m4_express.c index 61b270de0..b489b79c4 100644 --- a/hw/bsp/metro_m4_express/metro_m4_express.c +++ b/hw/bsp/metro_m4_express/metro_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/mimxrt1010_evk/mimxrt1010_evk.c b/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c index d061c0e04..c682ace8d 100644 --- a/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c +++ b/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c @@ -125,7 +125,7 @@ void USB_OTG1_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/mimxrt1015_evk/mimxrt1015_evk.c b/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c index 874e4517e..214077a4a 100644 --- a/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c +++ b/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c @@ -125,7 +125,7 @@ void USB_OTG1_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/mimxrt1020_evk/mimxrt1020_evk.c b/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c index 17727c0ab..f32ec5401 100644 --- a/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c +++ b/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c @@ -124,7 +124,7 @@ void USB_OTG1_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/mimxrt1050_evkb/mimxrt1050_evkb.c b/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c index ed29be4d3..be0ae3ea8 100644 --- a/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c +++ b/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c @@ -128,7 +128,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } @@ -139,7 +139,7 @@ void USB_OTG2_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/mimxrt1060_evk/mimxrt1060_evk.c b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c index ed29be4d3..be0ae3ea8 100644 --- a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c +++ b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c @@ -128,7 +128,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } @@ -139,7 +139,7 @@ void USB_OTG2_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/mimxrt1064_evk/mimxrt1064_evk.c b/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c index ed29be4d3..be0ae3ea8 100644 --- a/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c +++ b/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c @@ -128,7 +128,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } @@ -139,7 +139,7 @@ void USB_OTG2_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/msp_exp430f5529lp/msp_exp430f5529lp.c b/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c index 621d21d55..e9336b634 100644 --- a/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c +++ b/hw/bsp/msp_exp430f5529lp/msp_exp430f5529lp.c @@ -33,7 +33,7 @@ //--------------------------------------------------------------------+ void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/ngx4330/ngx4330.c b/hw/bsp/ngx4330/ngx4330.c index a789a8819..5296ddcb3 100644 --- a/hw/bsp/ngx4330/ngx4330.c +++ b/hw/bsp/ngx4330/ngx4330.c @@ -229,7 +229,7 @@ void USB0_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } @@ -240,7 +240,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/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c b/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c index 99db842ac..870a290dd 100644 --- a/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c +++ b/hw/bsp/nrf52840_mdk_dongle/nrf52840_mdk_dongle.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/nutiny_nuc121s/nutiny_nuc121.c b/hw/bsp/nutiny_nuc121s/nutiny_nuc121.c index 115c88165..7117a3422 100644 --- a/hw/bsp/nutiny_nuc121s/nutiny_nuc121.c +++ b/hw/bsp/nutiny_nuc121s/nutiny_nuc121.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c b/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c index 115c88165..7117a3422 100644 --- a/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c +++ b/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c b/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c index 214873f8c..da62e7bd2 100644 --- a/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c +++ b/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c @@ -35,7 +35,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c b/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c index 906d44454..0d78116b8 100644 --- a/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c +++ b/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c b/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c index 9018e698d..49e66d2d0 100644 --- a/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c +++ b/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/pca10056/pca10056.c b/hw/bsp/pca10056/pca10056.c index ec34dbb9e..30df50124 100644 --- a/hw/bsp/pca10056/pca10056.c +++ b/hw/bsp/pca10056/pca10056.c @@ -41,7 +41,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/pca10059/pca10059.c b/hw/bsp/pca10059/pca10059.c index 72a85a9fa..2a2a45eb2 100644 --- a/hw/bsp/pca10059/pca10059.c +++ b/hw/bsp/pca10059/pca10059.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/pca10100/pca10100.c b/hw/bsp/pca10100/pca10100.c index ec34dbb9e..30df50124 100644 --- a/hw/bsp/pca10100/pca10100.c +++ b/hw/bsp/pca10100/pca10100.c @@ -41,7 +41,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/pyboardv11/pyboardv11.c b/hw/bsp/pyboardv11/pyboardv11.c index e6f45b339..5c910484d 100644 --- a/hw/bsp/pyboardv11/pyboardv11.c +++ b/hw/bsp/pyboardv11/pyboardv11.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c b/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c index 62e6fa045..97f3cbf05 100644 --- a/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c +++ b/hw/bsp/raytac_mdbt50q_rx/raytac_mdbt50q_rx.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USBD_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } /*------------------------------------------------------------------*/ diff --git a/hw/bsp/samg55xplained/samg55xplained.c b/hw/bsp/samg55xplained/samg55xplained.c index 4f894a2bc..c9bc0656e 100644 --- a/hw/bsp/samg55xplained/samg55xplained.c +++ b/hw/bsp/samg55xplained/samg55xplained.c @@ -100,7 +100,7 @@ void board_init(void) void UDP_Handler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } diff --git a/hw/bsp/seeeduino_xiao/seeeduino_xiao.c b/hw/bsp/seeeduino_xiao/seeeduino_xiao.c index d8dbd2b1c..0456228da 100644 --- a/hw/bsp/seeeduino_xiao/seeeduino_xiao.c +++ b/hw/bsp/seeeduino_xiao/seeeduino_xiao.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ void USB_Handler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c b/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c index 132da8aee..ded5a9c85 100644 --- a/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c +++ b/hw/bsp/stm32f070rbnucleo/stm32f070rbnucleo.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USB_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f072disco/stm32f072disco.c b/hw/bsp/stm32f072disco/stm32f072disco.c index 9a3a354ef..2815beef4 100644 --- a/hw/bsp/stm32f072disco/stm32f072disco.c +++ b/hw/bsp/stm32f072disco/stm32f072disco.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USB_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f103bluepill/stm32f103bluepill.c b/hw/bsp/stm32f103bluepill/stm32f103bluepill.c index dbb58032c..600f3aaef 100644 --- a/hw/bsp/stm32f103bluepill/stm32f103bluepill.c +++ b/hw/bsp/stm32f103bluepill/stm32f103bluepill.c @@ -32,17 +32,17 @@ //--------------------------------------------------------------------+ void USB_HP_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } void USB_LP_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } void USBWakeUp_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f207nucleo/stm32f207nucleo.c b/hw/bsp/stm32f207nucleo/stm32f207nucleo.c index 3d1765e8b..619c90d68 100644 --- a/hw/bsp/stm32f207nucleo/stm32f207nucleo.c +++ b/hw/bsp/stm32f207nucleo/stm32f207nucleo.c @@ -33,7 +33,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f303disco/stm32f303disco.c b/hw/bsp/stm32f303disco/stm32f303disco.c index 444472a79..1fe908bc3 100644 --- a/hw/bsp/stm32f303disco/stm32f303disco.c +++ b/hw/bsp/stm32f303disco/stm32f303disco.c @@ -38,7 +38,7 @@ // the highest possible transfer rate. void USB_HP_CAN_TX_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } // USB low-priority interrupt (Channel 20): Triggered by all USB events @@ -46,14 +46,14 @@ void USB_HP_CAN_TX_IRQHandler(void) // interrupt source before serving the interrupt. void USB_LP_CAN_RX0_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } // USB wakeup interrupt (Channel 42): Triggered by the wakeup event from the USB // Suspend mode. void USBWakeUp_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f401blackpill/stm32f401blackpill.c b/hw/bsp/stm32f401blackpill/stm32f401blackpill.c index 90507e178..f9daa364f 100644 --- a/hw/bsp/stm32f401blackpill/stm32f401blackpill.c +++ b/hw/bsp/stm32f401blackpill/stm32f401blackpill.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f407disco/stm32f407disco.c b/hw/bsp/stm32f407disco/stm32f407disco.c index d317ae7df..ce3b67da0 100644 --- a/hw/bsp/stm32f407disco/stm32f407disco.c +++ b/hw/bsp/stm32f407disco/stm32f407disco.c @@ -33,7 +33,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f411blackpill/stm32f411blackpill.c b/hw/bsp/stm32f411blackpill/stm32f411blackpill.c index 0d085b20e..af1cf70ed 100644 --- a/hw/bsp/stm32f411blackpill/stm32f411blackpill.c +++ b/hw/bsp/stm32f411blackpill/stm32f411blackpill.c @@ -33,7 +33,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f411disco/stm32f411disco.c b/hw/bsp/stm32f411disco/stm32f411disco.c index 3f95afb09..5d432fe23 100644 --- a/hw/bsp/stm32f411disco/stm32f411disco.c +++ b/hw/bsp/stm32f411disco/stm32f411disco.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f412disco/stm32f412disco.c b/hw/bsp/stm32f412disco/stm32f412disco.c index be0731fb6..669891d68 100644 --- a/hw/bsp/stm32f412disco/stm32f412disco.c +++ b/hw/bsp/stm32f412disco/stm32f412disco.c @@ -33,7 +33,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32f767nucleo/stm32f767nucleo.c b/hw/bsp/stm32f767nucleo/stm32f767nucleo.c index b9025a42c..8328c361a 100644 --- a/hw/bsp/stm32f767nucleo/stm32f767nucleo.c +++ b/hw/bsp/stm32f767nucleo/stm32f767nucleo.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32h743nucleo/stm32h743nucleo.c b/hw/bsp/stm32h743nucleo/stm32h743nucleo.c index 9a758988c..bb768eb40 100644 --- a/hw/bsp/stm32h743nucleo/stm32h743nucleo.c +++ b/hw/bsp/stm32h743nucleo/stm32h743nucleo.c @@ -34,7 +34,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32l0538disco/stm32l0538disco.c b/hw/bsp/stm32l0538disco/stm32l0538disco.c index 0bfb1f845..ab04e5c51 100644 --- a/hw/bsp/stm32l0538disco/stm32l0538disco.c +++ b/hw/bsp/stm32l0538disco/stm32l0538disco.c @@ -32,7 +32,7 @@ //--------------------------------------------------------------------+ void USB_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/stm32l476disco/stm32l476disco.c b/hw/bsp/stm32l476disco/stm32l476disco.c index 65c544137..2d4a4e3de 100644 --- a/hw/bsp/stm32l476disco/stm32l476disco.c +++ b/hw/bsp/stm32l476disco/stm32l476disco.c @@ -33,7 +33,7 @@ //--------------------------------------------------------------------+ void OTG_FS_IRQHandler(void) { - tud_irq_handler(0); + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/hw/bsp/teensy_40/teensy40.c b/hw/bsp/teensy_40/teensy40.c index 9e49ed19c..f45a98ef3 100644 --- a/hw/bsp/teensy_40/teensy40.c +++ b/hw/bsp/teensy_40/teensy40.c @@ -129,7 +129,7 @@ void USB_OTG1_IRQHandler(void) #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_irq_handler(0); + tud_int_handler(0); #endif } @@ -140,7 +140,7 @@ void USB_OTG2_IRQHandler(void) #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - tud_irq_handler(1); + tud_int_handler(1); #endif } diff --git a/src/device/dcd.h b/src/device/dcd.h index 6554be2c8..99a0e01ca 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -89,7 +89,7 @@ typedef struct TU_ATTR_ALIGNED(4) void dcd_init (uint8_t rhport); // Interrupt Handler -void dcd_irq_handler(uint8_t rhport) TU_ATTR_USED; +void dcd_int_handler(uint8_t rhport); // Enable device interrupt void dcd_int_enable (uint8_t rhport); diff --git a/src/device/usbd.h b/src/device/usbd.h index 3b409e70b..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); diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 47c90fd13..986df3b3b 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -638,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; @@ -726,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 c122b9bee..7703ee0dc 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -347,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..af6972961 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -435,7 +435,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; diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index dfdae1450..14f3dce3b 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -505,7 +505,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 980fa118f..c1f80185b 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -345,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 cea7c2b04..539629c3d 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -503,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/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 14ffcbe40..dbc1e6952 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -499,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; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 38c284c5a..0c9c2650d 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -669,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/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 1512f0de4..da75a7f3f 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -558,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 1e7219a1f..8dde874fc 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -626,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; -- cgit v1.3.1 From dddf30f53259e753b351c96580077552827482d6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Apr 2020 12:53:42 +0700 Subject: added disconnect for spresense --- src/portable/sony/cxd56/dcd_cxd56.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index ca6a8be20..7fd630384 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -201,19 +201,17 @@ void dcd_remote_wakeup(uint8_t rhport) DEV_WAKEUP(usbdev); } -#if 0 // TODO implement for Spresense void dcd_connect(uint8_t rhport) { (void) rhport; -// DEV_CONNECT(usbdev); + DEV_CONNECT(usbdev); } void dcd_disconnect(uint8_t rhport) { (void) rhport; -// DEV_DISCONNECT(usbdev); + DEV_DISCONNECT(usbdev); } -#endif //--------------------------------------------------------------------+ // Endpoint API -- cgit v1.3.1 From 6f9c256ad0e6b030468bd8a8fbfd41801b70a69a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Apr 2020 13:52:34 +0700 Subject: complete remove dcd_set_config(), fix unit test --- docs/porting.md | 4 ---- src/device/dcd.h | 3 --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 7 ------- src/portable/microchip/samd/dcd_samd.c | 7 ------- src/portable/microchip/samg/dcd_samg.c | 10 ---------- src/portable/nordic/nrf5x/dcd_nrf5x.c | 6 ------ src/portable/nuvoton/nuc120/dcd_nuc120.c | 6 ------ src/portable/nuvoton/nuc121/dcd_nuc121.c | 6 ------ src/portable/nuvoton/nuc505/dcd_nuc505.c | 6 ------ src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 6 ------ src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 6 ------ src/portable/nxp/transdimension/dcd_transdimension.c | 7 ------- src/portable/sony/cxd56/dcd_cxd56.c | 7 ------- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 8 -------- src/portable/st/synopsys/dcd_synopsys.c | 7 ------- src/portable/template/dcd_template.c | 7 ------- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 7 ------- src/portable/valentyusb/eptri/dcd_eptri.c | 8 -------- test/test/device/msc/test_msc_device.c | 2 -- 19 files changed, 120 deletions(-) (limited to 'src') diff --git a/docs/porting.md b/docs/porting.md index fabf24510..473768450 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -78,10 +78,6 @@ Called when the device is given a new bus address. If your peripheral automatically changes address during enumeration (like the nrf52) you may leave this empty and also no queue an event for the corresponding SETUP packet. -##### dcd_set_config - -Called when the device received SET_CONFIG request, you can leave this empty if your peripheral does not require any specific action. - ##### dcd_remote_wakeup Called to remote wake up host when suspended (e.g hid keyboard) diff --git a/src/device/dcd.h b/src/device/dcd.h index 99a0e01ca..68798c259 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -100,9 +100,6 @@ void dcd_int_disable(uint8_t rhport); // Receive Set Address request, mcu port must also include status IN response void dcd_set_address(uint8_t rhport, uint8_t dev_addr); -// Receive Set Configure request -void dcd_set_config (uint8_t rhport, uint8_t config_num); - // Wake up host void dcd_remote_wakeup(uint8_t rhport); diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 986df3b3b..16c0e7207 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -201,13 +201,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } -void dcd_set_config(uint8_t rhport, uint8_t config_num) -{ - (void)rhport; - (void)config_num; - // Nothing to do -} - void dcd_remote_wakeup(uint8_t rhport) { (void)rhport; diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index bd61df86a..a01bef38a 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -144,13 +144,6 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) USB->DEVICE.INTENSET.reg = USB_DEVICE_INTENSET_SUSPEND; } -void dcd_set_config (uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; - // Nothing to do -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 7703ee0dc..1824d549a 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -167,16 +167,6 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) // do it at dcd_edpt0_status_complete() } -// Receive Set Configure request -void dcd_set_config (uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; - - // Configured State -// UDP->UDP_GLB_STAT |= UDP_GLB_STAT_CONFG_Msk; -} - // Wake up host void dcd_remote_wakeup (uint8_t rhport) { diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 95240f9f0..12435ea23 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -216,12 +216,6 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) NRF_USBD->INTENSET = USBD_INTEN_USBEVENT_Msk; } -void dcd_set_config (uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 9195b8dbe..1a0007d8a 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -219,12 +219,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) assigned_address = dev_addr; } -void dcd_set_config(uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index edd1e14a7..af7fee8b0 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -225,12 +225,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) assigned_address = dev_addr; } -void dcd_set_config(uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index aceb6df09..02f0b35a6 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -298,12 +298,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) assigned_address = dev_addr; } -void dcd_set_config(uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 21a678c66..f7a59a808 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -208,12 +208,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) sie_write(SIE_CMDCODE_CONFIGURE_DEVICE, 1, 1); } -void dcd_set_config(uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index c1f80185b..3d1420c65 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -198,12 +198,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) DCD_REGS->DEVCMDSTAT |= dev_addr; } -void dcd_set_config(uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 539629c3d..fcedc1c0c 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -363,13 +363,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) dcd_reg->DEVICEADDR = (dev_addr << 25) | TU_BIT(24); } -void dcd_set_config(uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; - // nothing to do -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 7fd630384..bcf94dc21 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -187,13 +187,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) (void) dev_addr; } -// Receive Set Config request -void dcd_set_config(uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index dbc1e6952..c5666421b 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -317,14 +317,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) // do it at dcd_edpt0_status_complete() } -// Receive Set Config request -void dcd_set_config (uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; - // Nothing to do? Handled by stack. -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 0c9c2650d..3386abdac 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -234,13 +234,6 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } -void dcd_set_config (uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; - // Nothing to do -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index ba1383f31..812bb7866 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -78,13 +78,6 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) (void) dev_addr; } -// Receive Set Configure request -void dcd_set_config (uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; -} - // Wake up host void dcd_remote_wakeup (uint8_t rhport) { diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index da75a7f3f..8672050f0 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -192,13 +192,6 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } -void dcd_set_config (uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; - // Nothing to do -} - void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index 8dde874fc..d670dd38e 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -383,14 +383,6 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) usb_address_write(dev_addr); } -// Called when the device received SET_CONFIG request, you can leave this -// empty if your peripheral does not require any specific action. -void dcd_set_config(uint8_t rhport, uint8_t config_num) -{ - (void) rhport; - (void) config_num; -} - // Called to remote wake up host when suspended (e.g hid keyboard) void dcd_remote_wakeup(uint8_t rhport) { diff --git a/test/test/device/msc/test_msc_device.c b/test/test/device/msc/test_msc_device.c index 62a36d3e3..34bd90c7e 100644 --- a/test/test/device/msc/test_msc_device.c +++ b/test/test/device/msc/test_msc_device.c @@ -241,8 +241,6 @@ void test_msc(void) dcd_event_setup_received(rhport, (uint8_t*) &request_set_configuration, false); - dcd_set_config_Expect(rhport, 1); - // open endpoints dcd_edpt_open_ExpectAndReturn(rhport, (tusb_desc_endpoint_t const *) desc_ep, true); dcd_edpt_open_ExpectAndReturn(rhport, (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep), true); -- cgit v1.3.1 From 4571ce0d29398089cf6615515190a70ff9be2361 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Apr 2020 15:54:20 +0700 Subject: add a bit of document for cdc device API. also improve cdc write flush when complete. --- changelog.md | 4 ++++ src/class/cdc/cdc_device.c | 34 ++++++++++++++++++++++------------ src/class/cdc/cdc_device.h | 46 ++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 64 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/changelog.md b/changelog.md index 807b4dc3a..59af2ea74 100644 --- a/changelog.md +++ b/changelog.md @@ -14,6 +14,10 @@ - All default IRQ Handler is renamed to `dcd_int_handler()` +### Others + +- tud_cdc_n_write_flush() return number of bytes forced to transfer instead of bool + ## 0.6.0 - 2019.03.30 Added **CONTRIBUTORS.md** to give proper credit for contributors to the stack. Special thanks to [Nathan Conrad](https://github.com/pigrew), [Peter Lawrence](https://github.com/majbthrd) and [William D. Jones](https://github.com/cr1901) and others for spending their precious time to add lots of features and ports for this release. diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index f669cfa51..c03c714ce 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -157,10 +157,12 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) return ret; } -bool tud_cdc_n_write_flush (uint8_t itf) +uint32_t tud_cdc_n_write_flush (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in) ); // skip if previous transfer not complete + + // skip if previous transfer not complete yet + TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in), 0 ); uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, TU_ARRAY_SIZE(p_cdc->epin_buf)); if ( count ) @@ -169,7 +171,7 @@ bool tud_cdc_n_write_flush (uint8_t itf) TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count) ); } - return true; + return count; } uint32_t tud_cdc_n_write_available (uint8_t itf) @@ -376,16 +378,16 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ (void) rhport; (void) result; - uint8_t itf = 0; - cdcd_interface_t* p_cdc = _cdcd_itf; + uint8_t itf; + cdcd_interface_t* p_cdc; // Identify which interface to use - for ( ; ; itf++, p_cdc++) + for (itf = 0; itf < CFG_TUD_CDC; itf++) { - if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false; - + p_cdc = &_cdcd_itf[itf]; if ( ( ep_addr == p_cdc->ep_out ) || ( ep_addr == p_cdc->ep_in ) ) break; } + TU_ASSERT(itf < CFG_TUD_CDC); // Received new data if ( ep_addr == p_cdc->ep_out ) @@ -408,12 +410,20 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ _prep_out_transaction(itf); } - // Data sent to host, we could continue to fetch data tx fifo to send. - // But it will cause incorrect baudrate set in line coding. - // Though maybe the baudrate is not really important !!! + // Data sent to host, we continue to fetch from tx fifo to send. + // Note: This will cause incorrect baudrate set in line coding. + // Though maybe the baudrate is not really important !!! if ( ep_addr == p_cdc->ep_in ) { - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) && (0 == p_cdc->tx_ff.count) ) usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); + if ( 0 == tud_cdc_n_write_flush(itf) ) + { + // There is no data left, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) ) + { + usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); + } + } } // nothing to do with notif endpoint for now diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 969ec7f99..1db196c7b 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -48,28 +48,58 @@ * @{ */ //--------------------------------------------------------------------+ -// Application API (Multiple Interfaces) +// Application API (Multiple Ports) // CFG_TUD_CDC > 1 //--------------------------------------------------------------------+ + + +// Check if terminal is connected to this port bool tud_cdc_n_connected (uint8_t itf); + +// Get current line state. Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) uint8_t tud_cdc_n_get_line_state (uint8_t itf); + +// Get current line encoding: bit rate, stop bits parity etc .. void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding); + +// Set special character that will trigger tud_cdc_rx_wanted_cb() callback on receiving void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted); +// Get the number of bytes available for reading uint32_t tud_cdc_n_available (uint8_t itf); + +// Read received bytes uint32_t tud_cdc_n_read (uint8_t itf, void* buffer, uint32_t bufsize); + +// Read a byte, return -1 if there is none +static inline +int32_t tud_cdc_n_read_char (uint8_t itf); + +// Clear the received FIFO void tud_cdc_n_read_flush (uint8_t itf); + +// Get a byte from FIFO at the specified position without revmoing it bool tud_cdc_n_peek (uint8_t itf, int pos, uint8_t* u8); -static inline int32_t tud_cdc_n_read_char (uint8_t itf); +// Write bytes to TX FIFO, data may remain in the FIFO for a while uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); -bool tud_cdc_n_write_flush (uint8_t itf); + +// Write a byte +static inline +uint32_t tud_cdc_n_write_char (uint8_t itf, char ch); + +// Write a nul-terminated string +static inline +uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str); + +// Force sending data if possible, return number of forced bytes +uint32_t tud_cdc_n_write_flush (uint8_t itf); + +// Return number of characters available for writing uint32_t tud_cdc_n_write_available (uint8_t itf); -static inline uint32_t tud_cdc_n_write_char (uint8_t itf, char ch); -static inline uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str); //--------------------------------------------------------------------+ -// Application API (Interface0) +// Application API (Single Port) //--------------------------------------------------------------------+ static inline bool tud_cdc_connected (void); static inline uint8_t tud_cdc_get_line_state (void); @@ -85,7 +115,7 @@ static inline bool tud_cdc_peek (int pos, uint8_t* u8); static inline uint32_t tud_cdc_write_char (char ch); static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize); static inline uint32_t tud_cdc_write_str (char const* str); -static inline bool tud_cdc_write_flush (void); +static inline uint32_t tud_cdc_write_flush (void); static inline uint32_t tud_cdc_write_available (void); //--------------------------------------------------------------------+ @@ -183,7 +213,7 @@ static inline uint32_t tud_cdc_write_str (char const* str) return tud_cdc_n_write_str(0, str); } -static inline bool tud_cdc_write_flush (void) +static inline uint32_t tud_cdc_write_flush (void) { return tud_cdc_n_write_flush(0); } -- cgit v1.3.1 From 464b1e8e890866984c85505782540bd32e877581 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Apr 2020 15:57:24 +0700 Subject: correct return for write flush --- src/class/cdc/cdc_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index c03c714ce..3c7118f13 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -167,8 +167,8 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, TU_ARRAY_SIZE(p_cdc->epin_buf)); if ( count ) { - TU_VERIFY( tud_cdc_n_connected(itf) ); // fifo is empty if not connected - TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count) ); + TU_VERIFY( tud_cdc_n_connected(itf), 0 ); // fifo is empty if not connected + TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); } return count; -- cgit v1.3.1 From ce6a81e74d806844f3a705c137dd5c4febbf891a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Apr 2020 22:10:31 +0700 Subject: fix typo --- src/class/cdc/cdc_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 1db196c7b..69542a3b3 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -78,7 +78,7 @@ int32_t tud_cdc_n_read_char (uint8_t itf); // Clear the received FIFO void tud_cdc_n_read_flush (uint8_t itf); -// Get a byte from FIFO at the specified position without revmoing it +// Get a byte from FIFO at the specified position without removing it bool tud_cdc_n_peek (uint8_t itf, int pos, uint8_t* u8); // Write bytes to TX FIFO, data may remain in the FIFO for a while -- cgit v1.3.1 From fa71402e17fa973ea8c1112d4b36595e908bdf38 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 18 Apr 2020 22:59:56 +0700 Subject: implement disconnection detection for stm32 synopsys - disconnection is OTG INT session end bit - add USE_SOF to disable 1ms interrupt on mcu which isn't used now by the stack - add suspend detection --- src/portable/st/synopsys/dcd_synopsys.c | 50 ++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 3386abdac..4b7004cbe 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -75,6 +75,11 @@ /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ + +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#define USE_SOF 0 + #define DEVICE_BASE (USB_OTG_DeviceTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_DEVICE_BASE) #define OUT_EP_BASE (USB_OTG_OUTEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_OUT_ENDPOINT_BASE) #define IN_EP_BASE (USB_OTG_INEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_IN_ENDPOINT_BASE) @@ -187,15 +192,13 @@ void dcd_init (uint8_t rhport) // TODO: PHYSEL is read-only on some cores (STM32F407). Worth gating? USB_OTG_FS->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos) | USB_OTG_GUSBCFG_PHYSEL; - // Clear all used interrupts - USB_OTG_FS->GINTSTS |= USB_OTG_GINTSTS_OTGINT | USB_OTG_GINTSTS_MMIS | \ - USB_OTG_GINTSTS_USBRST | USB_OTG_GINTSTS_ENUMDNE | \ - USB_OTG_GINTSTS_ESUSP | USB_OTG_GINTSTS_USBSUSP | USB_OTG_GINTSTS_SOF; + // Clear all interrupts + USB_OTG_FS->GINTSTS |= USB_OTG_FS->GINTSTS; - // Required as part of core initialization. Disable OTGINT as we don't use - // it right now. TODO: How should mode mismatch be handled? It will cause + // Required as part of core initialization. + // TODO: How should mode mismatch be handled? It will cause // the core to stop working/require reset. - USB_OTG_FS->GINTMSK |= /* USB_OTG_GINTMSK_OTGINT | */ USB_OTG_GINTMSK_MMISM; + USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OTGINT | USB_OTG_GINTMSK_MMISM; USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; @@ -203,9 +206,8 @@ void dcd_init (uint8_t rhport) // (non zero-length packet), send STALL back and discard. Full speed. dev->DCFG |= USB_OTG_DCFG_NZLSOHSK | (3 << USB_OTG_DCFG_DSPD_Pos); - USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | \ - USB_OTG_GINTMSK_SOFM | USB_OTG_GINTMSK_RXFLVLM /* SB_OTG_GINTMSK_ESUSPM | \ - USB_OTG_GINTMSK_USBSUSPM */; + USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_USBSUSPM | + USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); // Enable USB transceiver. USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_PWRDWN; @@ -687,22 +689,50 @@ void dcd_int_handler(uint8_t rhport) { dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); } + if(int_status & USB_OTG_GINTSTS_USBSUSP) + { + USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_USBSUSP; + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + } + + if(int_status & USB_OTG_GINTSTS_OTGINT) + { + // OTG INT bit is read-only + uint32_t const otg_int = USB_OTG_FS->GOTGINT; + + if (otg_int & USB_OTG_GOTGINT_SEDET) + { + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + } + + USB_OTG_FS->GOTGINT = otg_int; + } + +#if USE_SOF if(int_status & USB_OTG_GINTSTS_SOF) { USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_SOF; dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } +#endif if(int_status & USB_OTG_GINTSTS_RXFLVL) { + // RXFLVL bit is read-only + + // Mask out RXFLVL while reading data from FIFO + USB_OTG_FS->GINTMSK &= ~USB_OTG_GINTMSK_RXFLVLM; read_rx_fifo(out_ep); + USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; } // OUT endpoint interrupt handling. if(int_status & USB_OTG_GINTSTS_OEPINT) { + // OEPINT is read-only handle_epout_ints(dev, out_ep); } // IN endpoint interrupt handling. if(int_status & USB_OTG_GINTSTS_IEPINT) { + // IEPINT bit read-only handle_epin_ints(dev, in_ep); } } -- cgit v1.3.1 From c3fc5f1595680846245dacbf1d51ee62228832e1 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 18 Apr 2020 23:42:51 +0700 Subject: session end interrupt doesn't trigger on esp32 saola board it is possibly due to the board design without vbus sense. Revisit later. --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 35 +++++++++++++++++----------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 16c0e7207..10c789da3 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -179,7 +179,8 @@ void dcd_init(uint8_t rhport) USB0.gintmsk = 0; //mask all USB0.gotgint = ~0U; //clear OTG ints USB0.gintsts = ~0U; //clear pending ints - USB0.gintmsk = USB_MODEMISMSK_M | + USB0.gintmsk = USB_OTGINTMSK_M | + USB_MODEMISMSK_M | #if USE_SOF USB_SOFMSK_M | #endif @@ -189,7 +190,7 @@ void dcd_init(uint8_t rhport) USB_USBRSTMSK_M | USB_ENUMDONEMSK_M | USB_RESETDETMSK_M | - USB_DISCONNINTMSK_M; + USB_DISCONNINTMSK_M; // host most only } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) @@ -638,12 +639,6 @@ static void _dcd_int_handler(void* arg) const uint32_t int_status = USB0.gintsts; //const uint32_t int_msk = USB0.gintmsk; - if (int_status & USB_DISCONNINT_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); - USB0.gintsts = USB_DISCONNINT_M; - dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); - } - if (int_status & USB_USBRST_M) { // start of reset ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); @@ -666,6 +661,21 @@ static void _dcd_int_handler(void* arg) dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); } + if (int_status & USB_OTGINT_M) + { + // OTG INT bit is read-only + ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); + + uint32_t const otg_int = USB0.gotgint; + + if (otg_int & USB_SESENDDET_M) + { + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + } + + USB0.gotgint = otg_int; + } + #if USE_SOF if (int_status & USB_SOF_M) { USB0.gintsts = USB_SOF_M; @@ -674,26 +684,25 @@ static void _dcd_int_handler(void* arg) #endif if (int_status & USB_RXFLVI_M) { + // RXFLVL bit is read-only ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); - USB0.gintsts = USB_RXFLVI_M; - // disable RXFLVI interrupt until we read data from FIFO + // Mask out RXFLVL while reading data from FIFO USB0.gintmsk &= ~USB_RXFLVIMSK_M; - read_rx_fifo(); - - // re-enable RXFLVI USB0.gintmsk |= USB_RXFLVIMSK_M; } // OUT endpoint interrupt handling. if (int_status & USB_OEPINT_M) { + // OEPINT is read-only ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); handle_epout_ints(); } // IN endpoint interrupt handling. if (int_status & USB_IEPINT_M) { + // IEPINT bit read-only ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); handle_epin_ints(); } -- cgit v1.3.1 From 1f442c0a9a19581fb03c8c3fa737e03495b9a2ea Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 18 Apr 2020 23:48:36 +0700 Subject: also add wakeup event --- src/portable/st/synopsys/dcd_synopsys.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 4b7004cbe..243ddd152 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -206,8 +206,9 @@ void dcd_init (uint8_t rhport) // (non zero-length packet), send STALL back and discard. Full speed. dev->DCFG |= USB_OTG_DCFG_NZLSOHSK | (3 << USB_OTG_DCFG_DSPD_Pos); - USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_USBSUSPM | - USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); + USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | + USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | + USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); // Enable USB transceiver. USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_PWRDWN; @@ -695,6 +696,12 @@ void dcd_int_handler(uint8_t rhport) { dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } + if(int_status & USB_OTG_GINTSTS_WKUINT) + { + USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_WKUINT; + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + if(int_status & USB_OTG_GINTSTS_OTGINT) { // OTG INT bit is read-only -- cgit v1.3.1 From a0598ef3699c1b502a499d76c26bd48d48355384 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sun, 19 Apr 2020 11:44:15 +0200 Subject: MIDI - Add flow control to incoming packet stream Larger SysEx transfers get corrupted by incoming packets. This changes the FIFOs not to overwrite their data. MIDI should not be a transport that drops packets. A potentially blocking device is easier to detect and handle than a device that silently corrupts the packet stream at random overflows, especially when SysEx messages are involved. --- src/class/midi/midi_device.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 56a27fbce..589d0123f 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -85,6 +85,18 @@ bool tud_midi_n_mounted (uint8_t itf) return midi->ep_in && midi->ep_out; } +static void _prep_out_transaction (midid_interface_t* p_midi) +{ + // skip if previous transfer not complete + if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_midi->ep_out) ) + return; + + // Prepare for incoming data but only allow what we can store in the ring buffer. + uint16_t max_read = tu_fifo_remaining(&p_midi->rx_ff); + if ( max_read >= CFG_TUD_MIDI_EPSIZE ) + usbd_edpt_xfer(TUD_OPT_RHPORT, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE); +} + //--------------------------------------------------------------------+ // READ API //--------------------------------------------------------------------+ @@ -138,11 +150,17 @@ void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id) { (void) jack_id; tu_fifo_clear(&_midid_itf[itf].rx_ff); + + if (tud_ready() && &_midid_itf[itf].ep_out != 0) + _prep_out_transaction(&_midid_itf[itf]); } bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]) { - return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4); + if (tud_ready() && &_midid_itf[itf].ep_out != 0) + _prep_out_transaction(&_midid_itf[itf]); + + return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4) == 4; } void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) { @@ -267,8 +285,8 @@ void midid_init(void) midid_interface_t* midi = &_midid_itf[i]; // config fifo - tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, true); - tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, true); + tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, false); + tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&midi->rx_ff, osal_mutex_create(&midi->rx_ff_mutex)); @@ -358,7 +376,7 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *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); + _prep_out_transaction(p_midi); return true; } @@ -381,6 +399,7 @@ bool midid_control_request(uint8_t rhport, tusb_control_request_t const * p_requ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + (void) rhport; (void) result; uint8_t itf = 0; @@ -399,7 +418,8 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 midi_rx_done_cb(p_midi, p_midi->epout_buf, xferred_bytes); // prepare for next - TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false ); + _prep_out_transaction(p_midi); + } else if ( ep_addr == p_midi->ep_in ) { maybe_transmit(p_midi, itf); } -- cgit v1.3.1 From e4570c35f757a6fcf7b4998ecd29663627051168 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 20 Apr 2020 00:27:35 +0700 Subject: add uart for ea4357 --- hw/bsp/ea4357/ea4357.c | 51 ++++++++++++++++++++---------------------------- src/common/tusb_common.h | 4 ++++ 2 files changed, 25 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/hw/bsp/ea4357/ea4357.c b/hw/bsp/ea4357/ea4357.c index 87f1e83cc..b7e7f7a5c 100644 --- a/hw/bsp/ea4357/ea4357.c +++ b/hw/bsp/ea4357/ea4357.c @@ -28,15 +28,14 @@ #include "../board.h" #include "pca9532.h" -#define BOARD_UART_PORT LPC_USART0 -#define BOARD_UART_PIN_PORT 0x0f -#define BOARD_UART_PIN_TX 10 // PF.10 : UART0_TXD -#define BOARD_UART_PIN_RX 11 // PF.11 : UART0_RXD +#define UART_DEV LPC_USART0 +#define UART_PORT 0x0f +#define UART_PIN_TX 10 // PF.10 : UART0_TXD +#define UART_PIN_RX 11 // PF.11 : UART0_RXD // P9_1 joystick down -#define BUTTON_PORT 4 -#define BUTTON_PIN 13 - +#define BUTTON_PORT 4 +#define BUTTON_PIN 13 //static const struct { // uint8_t mux_port; @@ -68,14 +67,6 @@ static const PINMUX_GRP_T pinmuxing[] = {0x9, 1, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLUP)}, // USB - - /* I2S */ - {0x3, 0, (SCU_PINIO_FAST | SCU_MODE_FUNC2)}, //I2S0_TX_CLK - {0xC, 12, (SCU_PINIO_FAST | SCU_MODE_FUNC6)}, //I2S0_TX_SDA - {0xC, 13, (SCU_PINIO_FAST | SCU_MODE_FUNC6)}, //I2S0_TX_WS - {0x6, 0, (SCU_PINIO_FAST | SCU_MODE_FUNC4)}, //I2S0_RX_SCK - {0x6, 1, (SCU_PINIO_FAST | SCU_MODE_FUNC3)}, //I2S0_RX_WS - {0x6, 2, (SCU_PINIO_FAST | SCU_MODE_FUNC3)}, //I2S0_RX_SDA }; /* Pin clock mux values, re-used structure, value in first index is meaningless */ @@ -127,19 +118,14 @@ void board_init(void) // Button Chip_GPIO_SetPinDIRInput(LPC_GPIO_PORT, BUTTON_PORT, BUTTON_PIN); -#if 0 //------------- UART -------------// - scu_pinmux(BOARD_UART_PIN_PORT, BOARD_UART_PIN_TX, MD_PDN, FUNC1); - scu_pinmux(BOARD_UART_PIN_PORT, BOARD_UART_PIN_RX, MD_PLN | MD_EZI | MD_ZI, FUNC1); + Chip_SCU_PinMuxSet(UART_PORT, UART_PIN_TX, (SCU_MODE_PULLDOWN | SCU_MODE_FUNC1)); + Chip_SCU_PinMuxSet(UART_PORT, UART_PIN_RX, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_FUNC1)); - UART_CFG_Type UARTConfigStruct; - UART_ConfigStructInit(&UARTConfigStruct); - UARTConfigStruct.Baud_rate = CFG_BOARD_UART_BAUDRATE; - UARTConfigStruct.Clock_Speed = 0; - - UART_Init(BOARD_UART_PORT, &UARTConfigStruct); - UART_TxCmd(BOARD_UART_PORT, ENABLE); // Enable UART Transmit -#endif + Chip_UART_Init(UART_DEV); + Chip_UART_SetBaud(UART_DEV, CFG_BOARD_UART_BAUDRATE); + Chip_UART_ConfigData(UART_DEV, UART_LCR_WLEN8 | UART_LCR_SBS_1BIT | UART_LCR_PARITY_DIS); + Chip_UART_TXEnable(UART_DEV); //------------- USB -------------// enum { @@ -278,16 +264,21 @@ uint32_t board_button_read(void) int board_uart_read(uint8_t* buf, int len) { - //return UART_ReceiveByte(BOARD_UART_PORT); + //return UART_ReceiveByte(BOARD_UART_DEV); (void) buf; (void) len; return 0; } int board_uart_write(void const * buf, int len) { - //UART_Send(BOARD_UART_PORT, &c, 1, BLOCKING); - (void) buf; (void) len; - return 0; + uint8_t const* buf8 = (uint8_t const*) buf; + for(int i=0; i 1 #define TU_LOG2 TU_LOG1 #define TU_LOG2_MEM TU_LOG1_MEM #define TU_LOG2_LOCATION() TU_LOG1_LOCATION() + #define TU_LOG2_INT TU_LOG1_INT + #define TU_LOG2_HEX TU_LOG1_HEX #endif -- cgit v1.3.1 From d57312602dd9aadc47ae8eae943f51b585e0a228 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 20 Apr 2020 16:09:17 +0700 Subject: add extra comma to HID_REPORT_ID this make the template with Report ID look less weird to the user --- examples/device/hid_composite/src/usb_descriptors.c | 4 ++-- src/class/hid/hid.h | 4 ++-- src/class/hid/hid_device.h | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index 6bde2ff7a..02cbc17f6 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -73,8 +73,8 @@ uint8_t const * tud_descriptor_device_cb(void) 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), ) + 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 diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 848274037..8803e4b66 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -413,8 +413,8 @@ enum { #define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, 1) #define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, n) -#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, n) +#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, 1), +#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, n), #define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, 1) #define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, n) diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index f5e29d8a2..efdde9569 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -93,17 +93,17 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); * HID Report Descriptor Template * * Convenient for declaring popular HID device (keyboard, mouse, consumer, - * gamepad etc...). Templates take "HID_REPORT_ID(n)," as input, leave + * gamepad etc...). Templates take "HID_REPORT_ID(n)" as input, leave * empty if multiple reports is not used * * - Only 1 report: no parameter * uint8_t const report_desc[] = { TUD_HID_REPORT_DESC_KEYBOARD() }; * - * - Multiple Reports: "HID_REPORT_ID(ID)," must be passed to template + * - Multiple Reports: "HID_REPORT_ID(ID)" must be passed to template * uint8_t const report_desc[] = * { - * TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(1), ) , - * TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(2), ) + * TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(1) ) , + * TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(2) ) * }; *--------------------------------------------------------------------*/ -- cgit v1.3.1 From bbcf9241bd3788c65c5fcbdabcc774f2f9cd8794 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 20 Apr 2020 23:46:17 +0700 Subject: add back MIDI multiple jack --- src/device/usbd.h | 66 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index fcb4e5c5f..713bee2b2 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -249,37 +249,61 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re //------------- MIDI -------------// -// Length of template descriptor (96 bytes) -#define TUD_MIDI_DESC_LEN (9 + 9 + 9 + 7 + 6 + 6 + 9 + 9 + 7 + 5 + 7 + 5) - -// MIDI simple descriptor -// - 1 Embedded Jack In connected to 1 External Jack Out -// - 1 Embedded Jack out connected to 1 External Jack In -#define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ +#define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) +#define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ /* Audio Control (AC) Interface */\ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V1, _stridx,\ /* AC Header */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum)+1),\ + 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ /* MIDI Streaming (MS) Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\ /* MS Header */\ - 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0025),\ + 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) + +#define TUD_MIDI_JACKID_IN_EMB(_cablenum) \ + (uint8_t)(((_cablenum) - 1) * 4 + 1) + +#define TUD_MIDI_JACKID_IN_EXT(_cablenum) \ + (uint8_t)(((_cablenum) - 1) * 4 + 2) + +#define TUD_MIDI_JACKID_OUT_EMB(_cablenum) \ + (uint8_t)(((_cablenum) - 1) * 4 + 3) + +#define TUD_MIDI_JACKID_OUT_EXT(_cablenum) \ + (uint8_t)(((_cablenum) - 1) * 4 + 4) + +#define TUD_MIDI_DESC_JACK_LEN (6 + 6 + 9 + 9) +#define TUD_MIDI_DESC_JACK(_cablenum) \ /* MS In Jack (Embedded) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, 1, 0,\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ /* MS In Jack (External) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, 2, 0,\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ /* MS Out Jack (Embedded), connected to In Jack External */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, 3, 1, 2, 1, 0,\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ /* MS Out Jack (External), connected to In Jack Embedded */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, 4, 1, 1, 1, 0,\ - /* Endpoint Out */\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 + +#define TUD_MIDI_DESC_EP_LEN(_numcables) (7 + 4 + (_numcables)) +#define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ + /* Endpoint */\ 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* MS Endpoint (connected to embedded jack in) */\ - 5, TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, 1, 1,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* MS Endpoint (connected to embedded jack out) */\ - 5, TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, 1, 3 + /* MS Endpoint (connected to embedded jack) */\ + (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables + +// Length of template descriptor (88 bytes) +#define TUD_MIDI_DESC_LEN (TUD_MIDI_DESC_HEAD_LEN + TUD_MIDI_DESC_JACK_LEN + TUD_MIDI_DESC_EP_LEN(1) * 2) + +// MIDI simple descriptor +// - 1 Embedded Jack In connected to 1 External Jack Out +// - 1 Embedded Jack out connected to 1 External Jack In +#define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ + TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ + TUD_MIDI_DESC_JACK(1),\ + TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ + TUD_MIDI_JACKID_IN_EMB(1),\ + TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ + TUD_MIDI_JACKID_OUT_EMB(1) + //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) -- cgit v1.3.1 From d1656c0b8d108d8f91748269e9196d1bbc711506 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Mon, 20 Apr 2020 16:00:21 -0400 Subject: tu_verify for getting descriptors --- src/device/usbd.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 26183c960..0a2169185 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -450,7 +450,7 @@ void tud_task (void) // Helper to invoke class driver control request handler static bool invoke_class_control(uint8_t rhport, uint8_t drvid, tusb_control_request_t const * request) { - TU_ASSERT(_usbd_driver[drvid].control_request); + TU_VERIFY(_usbd_driver[drvid].control_request); usbd_control_set_complete_callback(_usbd_driver[drvid].control_complete); TU_LOG2(" %s control request\r\n", _usbd_driver[drvid].name); @@ -463,7 +463,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { usbd_control_set_complete_callback(NULL); - TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); + TU_VERIFY(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) @@ -801,7 +801,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_CONFIGURATION: { tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index); - TU_ASSERT(desc_config); + TU_VERIFY(desc_config); uint16_t total_len; memcpy(&total_len, &desc_config->wTotalLength, 2); // possibly mis-aligned memory @@ -817,10 +817,11 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // The 0xEE index string is a Microsoft OS Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors return false; - }else + } + else { uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex); - TU_ASSERT(desc_str); + TU_VERIFY(desc_str); // first byte of descriptor is its size return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]); -- cgit v1.3.1 From 0ec69de77c22bd018f9e5e5d038cfb8275922351 Mon Sep 17 00:00:00 2001 From: Nathan Conrad Date: Tue, 21 Apr 2020 10:06:17 -0400 Subject: sof is optional, revert other changes but remove unneeded check. --- src/device/usbd.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 0a2169185..219dd23be 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -91,7 +91,7 @@ typedef struct bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - void (* sof ) (uint8_t rhport); + void (* sof ) (uint8_t rhport); /* optional */ } usbd_class_driver_t; static usbd_class_driver_t const _usbd_driver[] = @@ -450,8 +450,6 @@ void tud_task (void) // Helper to invoke class driver control request handler static bool invoke_class_control(uint8_t rhport, uint8_t drvid, tusb_control_request_t const * request) { - TU_VERIFY(_usbd_driver[drvid].control_request); - usbd_control_set_complete_callback(_usbd_driver[drvid].control_complete); TU_LOG2(" %s control request\r\n", _usbd_driver[drvid].name); return _usbd_driver[drvid].control_request(rhport, request); @@ -463,7 +461,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { usbd_control_set_complete_callback(NULL); - TU_VERIFY(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); + TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID); // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) @@ -801,7 +799,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_CONFIGURATION: { tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index); - TU_VERIFY(desc_config); + TU_ASSERT(desc_config); uint16_t total_len; memcpy(&total_len, &desc_config->wTotalLength, 2); // possibly mis-aligned memory @@ -821,7 +819,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const else { uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex); - TU_VERIFY(desc_str); + TU_ASSERT(desc_str); // first byte of descriptor is its size return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]); -- cgit v1.3.1 From 3b83813f017dfd08e19a7a3bc2dc575779b1eadd Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 22 Apr 2020 00:25:08 +0700 Subject: clean up --- .github/ISSUE_TEMPLATE/bug_report.md | 13 ++++++++----- .github/ISSUE_TEMPLATE/feature_request.md | 7 +++++-- .github/ISSUE_TEMPLATE/question.md | 2 +- README.md | 4 ---- src/class/midi/midi_device.c | 5 +++-- 5 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index c4d2757d2..5c70569d0 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,17 +7,20 @@ assignees: '' --- -**Set up (mandatory):** -Provide details of your setup help us to reproduce the issue as quick as possible +**Set up** +[Mandatory] Provide details of your setup help us to reproduce the issue as quick as possible - **PC OS** : Ubuntu 18.04 / Windows 10/ macOS 10.15 - **Board** : Feather nRF52840 Express - **Firmware**: examples/device/cdc_msc -**Bug Description** -Describe what the bug is. +**Describe the bug** +A clear and concise description of what the bug is. -**Reproduce** +**To reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. See error + +**Log & screenshots** +If applicable, add screenshots and TinyUSB's log to help explain your problem. To enable logging, add `LOG=2` to your make command if building with stock examples or set `CFG_TUSB_DEBUG=2` in your tusb_config.h. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index cb211eeb4..f34ff49ed 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -7,5 +7,8 @@ assignees: '' --- -**Feature Description** -Describe your feature +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index 3a9fd205c..d12c9785d 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -7,4 +7,4 @@ assignees: '' --- -**Question Description** +**Describe what the question is** diff --git a/README.md b/README.md index a8a533fd4..a7551155d 100644 --- a/README.md +++ b/README.md @@ -73,10 +73,6 @@ TinyUSB is completely thread-safe by pushing all ISR events into a central queue - **FreeRTOS** - **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its [own repo](https://github.com/hathach/mynewt-tinyusb-example) -## Compiler & IDE - -The stack is developed with GCC compiler and should be compilable with others. The `examples` folder provides Makefile and Segger Embedded Studio build support. [Here are example build instructions](examples/readme.md). - ## Getting Started [Here are the details for getting started](docs/getting_started.md) with the stack. diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 589d0123f..f8db63b73 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -88,13 +88,14 @@ bool tud_midi_n_mounted (uint8_t itf) static void _prep_out_transaction (midid_interface_t* p_midi) { // skip if previous transfer not complete - if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_midi->ep_out) ) - return; + if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_midi->ep_out) ) return; // Prepare for incoming data but only allow what we can store in the ring buffer. uint16_t max_read = tu_fifo_remaining(&p_midi->rx_ff); if ( max_read >= CFG_TUD_MIDI_EPSIZE ) + { usbd_edpt_xfer(TUD_OPT_RHPORT, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE); + } } //--------------------------------------------------------------------+ -- cgit v1.3.1 From 1fc7f54a8a05792d6e56d0ed14ded1c4a7b389bd Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 22 Apr 2020 19:18:03 +0700 Subject: added swo as logger tested with feather nrf52840 + jlink --- .../device/cdc_msc_freertos/src/FreeRTOSConfig.h | 71 +----------- .../hid_composite_freertos/src/FreeRTOSConfig.h | 71 +----------- examples/make.mk | 6 +- examples/readme.md | 14 ++- hw/bsp/board.c | 27 ++++- hw/bsp/board_mcu.h | 121 +++++++++++++++++++++ src/tusb_option.h | 6 +- 7 files changed, 172 insertions(+), 144 deletions(-) create mode 100644 hw/bsp/board_mcu.h (limited to 'src') diff --git a/examples/device/cdc_msc_freertos/src/FreeRTOSConfig.h b/examples/device/cdc_msc_freertos/src/FreeRTOSConfig.h index 0945baf1f..494452d43 100644 --- a/examples/device/cdc_msc_freertos/src/FreeRTOSConfig.h +++ b/examples/device/cdc_msc_freertos/src/FreeRTOSConfig.h @@ -42,78 +42,11 @@ * See http://www.freertos.org/a00110.html. *----------------------------------------------------------*/ -// for OPT_MCU_ -#include "tusb_option.h" - -#if CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC15XX || CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ - CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC40XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX - #include "chip.h" - -#elif CFG_TUSB_MCU == OPT_MCU_LPC51UXX || CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC55XX - #include "fsl_device_registers.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NRF5X - #include "nrf.h" - -#elif CFG_TUSB_MCU == OPT_MCU_SAMD21 || CFG_TUSB_MCU == OPT_MCU_SAMD51 - #include "sam.h" - -#elif CFG_TUSB_MCU == OPT_MCU_SAMG - #undef LITTLE_ENDIAN // hack to suppress "LITTLE_ENDIAN" redefined - #include "sam.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F0 - #include "stm32f0xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F1 - #include "stm32f1xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F2 - #include "stm32f2xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F3 - #include "stm32f3xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F4 - #include "stm32f4xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F7 - #include "stm32f7xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32H7 - #include "stm32h7xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L0 - #include "stm32l0xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L1 - #include "stm32l1xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 - #include "stm32l4xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX - #include "fsl_device_registers.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC120 - #include "NUC100Series.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC121 || CFG_TUSB_MCU == OPT_MCU_NUC126 - #include "NuMicro.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC505 - #include "NUC505Series.h" - -#else - #error "FreeRTOSConfig.h need to include low level mcu header for configuration" -#endif +// Include MCU header +#include "bsp/board_mcu.h" extern uint32_t SystemCoreClock; - /* Cortex M23/M33 port configuration. */ #define configENABLE_MPU 0 #define configENABLE_FPU 1 diff --git a/examples/device/hid_composite_freertos/src/FreeRTOSConfig.h b/examples/device/hid_composite_freertos/src/FreeRTOSConfig.h index 0945baf1f..494452d43 100644 --- a/examples/device/hid_composite_freertos/src/FreeRTOSConfig.h +++ b/examples/device/hid_composite_freertos/src/FreeRTOSConfig.h @@ -42,78 +42,11 @@ * See http://www.freertos.org/a00110.html. *----------------------------------------------------------*/ -// for OPT_MCU_ -#include "tusb_option.h" - -#if CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC15XX || CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ - CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC40XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX - #include "chip.h" - -#elif CFG_TUSB_MCU == OPT_MCU_LPC51UXX || CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC55XX - #include "fsl_device_registers.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NRF5X - #include "nrf.h" - -#elif CFG_TUSB_MCU == OPT_MCU_SAMD21 || CFG_TUSB_MCU == OPT_MCU_SAMD51 - #include "sam.h" - -#elif CFG_TUSB_MCU == OPT_MCU_SAMG - #undef LITTLE_ENDIAN // hack to suppress "LITTLE_ENDIAN" redefined - #include "sam.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F0 - #include "stm32f0xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F1 - #include "stm32f1xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F2 - #include "stm32f2xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F3 - #include "stm32f3xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F4 - #include "stm32f4xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F7 - #include "stm32f7xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32H7 - #include "stm32h7xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L0 - #include "stm32l0xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L1 - #include "stm32l1xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 - #include "stm32l4xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX - #include "fsl_device_registers.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC120 - #include "NUC100Series.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC121 || CFG_TUSB_MCU == OPT_MCU_NUC126 - #include "NuMicro.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC505 - #include "NUC505Series.h" - -#else - #error "FreeRTOSConfig.h need to include low level mcu header for configuration" -#endif +// Include MCU header +#include "bsp/board_mcu.h" extern uint32_t SystemCoreClock; - /* Cortex M23/M33 port configuration. */ #define configENABLE_MPU 0 #define configENABLE_FPU 1 diff --git a/examples/make.mk b/examples/make.mk index 78581f813..319ceece8 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -80,7 +80,7 @@ ifneq ($(LOG),) CFLAGS += -DCFG_TUSB_DEBUG=$(LOG) endif -# Logger: default is UART, can be set to RTT +# Logger: default is uart, can be set to rtt or swo ifeq ($(LOGGER),rtt) RTT_SRC = lib/SEGGER_RTT @@ -88,4 +88,8 @@ ifeq ($(LOGGER),rtt) INC += $(TOP)/$(RTT_SRC)/RTT SRC_C += $(RTT_SRC)/RTT/SEGGER_RTT_printf.c SRC_C += $(RTT_SRC)/RTT/SEGGER_RTT.c + +else ifeq ($(LOGGER),swo) + CFLAGS += -DLOGGER_SWO + endif diff --git a/examples/readme.md b/examples/readme.md index 092787221..ae7b0a111 100644 --- a/examples/readme.md +++ b/examples/readme.md @@ -44,13 +44,23 @@ $ make LOG=2 BOARD=feather_nrf52840_express all ### Logger -By default log message is printed via on-board UART which is slow and take lots of CPU time comparing to USB speed. If your board support on-board/external JLink debugger, it would be more efficient to use it with [RTT protocol](https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/) for logging. To do that add option `LOGGER=rtt` to build command e.g +By default log message is printed via on-board UART which is slow and take lots of CPU time comparing to USB speed. If your board support on-board/external debugger, it would be more efficient to use it for logging. There are 2 protocols: + +- `LOGGER=rtt`: use [Segger RTT protocol](https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/) + - Cons: requires jlink as the debugger. + - Pros: work with most if not all MCUs + - Software viewer is JLink RTT Viewer/Client/Logger which is bundled with JLink driver package. +- `LOGGER=swo`: Use dedicated SWO pin of ARM Cortex SWD debug header. + - Cons: only work with ARM Cortex MCUs minus M0 + - Pros: even faster than RTT, and should be compatible with hardware and software debugger that support SWO. + - Software viewer is JLink SWO Viewer which is also bundled with JLink driver package. ``` $ make LOG=2 LOGGER=rtt BOARD=feather_nrf52840_express all +$ make LOG=2 LOGGER=swo BOARD=feather_nrf52840_express all ``` -The log can be retrieved by JLink RTT Viewer/Client/Logger software which is bundled with their JLink driver. +The log can be retrieved by ## Flash diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 55236668f..56f407326 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -37,7 +37,8 @@ // newlib read()/write() retarget //--------------------------------------------------------------------+ -#ifdef LOGGER_RTT +#if defined(LOGGER_RTT) +// Logging with RTT #include "SEGGER_RTT.h" @@ -54,9 +55,31 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) return SEGGER_RTT_Read(0, buf, count); } +#elif defined(LOGGER_SWO) +// Logging with SWO for ARM Cortex + +#include "board_mcu.h" + +TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) +{ + (void) fhdl; + uint8_t const* buf8 = (uint8_t const*) buf; + for(size_t i=0; i Date: Wed, 22 Apr 2020 17:39:53 +0200 Subject: Added support for STM32F1 Connectivity Line MCU STM32F105 and STM32F107 are using the Synopsys IP --- src/portable/st/synopsys/dcd_synopsys.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 243ddd152..66ef44cf3 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -27,6 +27,11 @@ #include "tusb_option.h" +#if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ + defined (STM32F107xB) || defined (STM32F107xC) +#define STM32F1_SYNOPSYS +#endif + #if defined (STM32L475xx) || defined (STM32L476xx) || \ defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \ defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \ @@ -35,7 +40,8 @@ #endif #if TUSB_OPT_DEVICE_ENABLED && \ - ( CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ + ( (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_SYNOPSYS)) || \ + CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ @@ -45,7 +51,11 @@ // TODO Support OTG_HS // EP_MAX : Max number of bi-directional endpoints including EP0 // EP_FIFO_SIZE : Size of dedicated USB SRAM -#if CFG_TUSB_MCU == OPT_MCU_STM32F2 +#if CFG_TUSB_MCU == OPT_MCU_STM32F1 + #include "stm32f1xx.h" + #define EP_MAX 4 + #define EP_FIFO_SIZE 1280 +#elif CFG_TUSB_MCU == OPT_MCU_STM32F2 #include "stm32f2xx.h" #define EP_MAX USB_OTG_FS_MAX_IN_ENDPOINTS #define EP_FIFO_SIZE USB_OTG_FS_TOTAL_FIFO_SIZE -- cgit v1.3.1 From 10e035241f0ea4bf8604fab2556fd65be16137b9 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 22 Apr 2020 23:04:21 +0700 Subject: house keeping --- examples/readme.md | 4 ++-- src/class/msc/msc_device.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/examples/readme.md b/examples/readme.md index 8d3d2e415..1c85214e9 100644 --- a/examples/readme.md +++ b/examples/readme.md @@ -52,8 +52,8 @@ By default log message is printed via on-board UART which is slow and take lots - Software viewer is JLink RTT Viewer/Client/Logger which is bundled with JLink driver package. - `LOGGER=swo`: Use dedicated SWO pin of ARM Cortex SWD debug header. - Cons: only work with ARM Cortex MCUs minus M0 - - Pros: even faster than RTT, and should be compatible with hardware and software debugger that support SWO. - - Software viewer is JLink SWO Viewer which is also bundled with JLink driver package. + - Pros: should be compatible with more debugger that support SWO. + - Software viewer should be provided along with your debugger driver. ``` $ make LOG=2 LOGGER=rtt BOARD=feather_nrf52840_express all diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 68f5587fd..70ba956aa 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -605,6 +605,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t else { // Invoke complete callback if defined + // Note: There is racing issue with samd51 + qspi flash testing with arduino + // if complete_cb() is invoked after queuing the status. switch(p_cbw->command[0]) { case SCSI_CMD_READ_10: -- cgit v1.3.1 From c59fa774274b13790a3ae0fc19d9651eeba560ab Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 23 Apr 2020 23:25:20 +0700 Subject: Revert "Merge pull request #359 from versioduo/midi-flow-control" This reverts commit 1d33aa9b6f7940f9eac07ce684515856940175da, reversing changes made to 718db7e5369df57b0f49a563737e6e0446fd4c4d. --- src/class/midi/midi_device.c | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index f8db63b73..56a27fbce 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -85,19 +85,6 @@ bool tud_midi_n_mounted (uint8_t itf) return midi->ep_in && midi->ep_out; } -static void _prep_out_transaction (midid_interface_t* p_midi) -{ - // skip if previous transfer not complete - if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_midi->ep_out) ) return; - - // Prepare for incoming data but only allow what we can store in the ring buffer. - uint16_t max_read = tu_fifo_remaining(&p_midi->rx_ff); - if ( max_read >= CFG_TUD_MIDI_EPSIZE ) - { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE); - } -} - //--------------------------------------------------------------------+ // READ API //--------------------------------------------------------------------+ @@ -151,17 +138,11 @@ void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id) { (void) jack_id; tu_fifo_clear(&_midid_itf[itf].rx_ff); - - if (tud_ready() && &_midid_itf[itf].ep_out != 0) - _prep_out_transaction(&_midid_itf[itf]); } bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]) { - if (tud_ready() && &_midid_itf[itf].ep_out != 0) - _prep_out_transaction(&_midid_itf[itf]); - - return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4) == 4; + return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4); } void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) { @@ -286,8 +267,8 @@ void midid_init(void) midid_interface_t* midi = &_midid_itf[i]; // config fifo - tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, false); - tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); + tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, true); + tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&midi->rx_ff, osal_mutex_create(&midi->rx_ff_mutex)); @@ -377,7 +358,7 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_length = drv_len; // Prepare for incoming data - _prep_out_transaction(p_midi); + TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false); return true; } @@ -400,7 +381,6 @@ bool midid_control_request(uint8_t rhport, tusb_control_request_t const * p_requ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - (void) rhport; (void) result; uint8_t itf = 0; @@ -419,8 +399,7 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 midi_rx_done_cb(p_midi, p_midi->epout_buf, xferred_bytes); // prepare for next - _prep_out_transaction(p_midi); - + TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false ); } else if ( ep_addr == p_midi->ep_in ) { maybe_transmit(p_midi, itf); } -- cgit v1.3.1 From b949ae596f72213788a7a762d2a8af696f64b3d0 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 24 Apr 2020 16:40:48 +0200 Subject: synopsys: Reduce interrupt time for IN ZLP For IN endpoints output FIFO is filled in interrupt, therefor before endpoint is enabled, DIEPTSIZ is set with correct size of packet. Then endpoint is enabled and FIFO empty interrupt is enabled. This works fine except for the ZLP. Enabling FIFO empty interrupt results in interrupt handler being called all the time because there is nothing to put in the FIFO. Eventually it ends when IN token is received and empty packed is transmitted out. This change does not enable FIFO empty interrupt for ZLP reducing CPU load. --- src/portable/st/synopsys/dcd_synopsys.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 66ef44cf3..9c1672220 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -372,7 +372,10 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t in_ep[epnum].DIEPTSIZ = (num_packets << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | \ ((total_bytes & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) << USB_OTG_DIEPTSIZ_XFRSIZ_Pos); in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; - dev->DIEPEMPMSK |= (1 << epnum); + // Enable fifo empty interrupt only if there are something to put in the fifo. + if(total_bytes != 0) { + dev->DIEPEMPMSK |= (1 << epnum); + } } else { // Each complete packet for OUT xfers triggers XFRC. out_ep[epnum].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | \ -- cgit v1.3.1 From 017c95037f3173455fa09efae6093d56fd3f3d1a Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 26 Apr 2020 14:51:44 +0700 Subject: add usbd edpt open - RTT mode is blocking to prevent log lost - Improve logging message --- examples/make.mk | 2 +- src/class/cdc/cdc_device.c | 2 +- src/class/midi/midi_device.c | 2 +- src/class/net/net_device.c | 2 +- src/class/usbtmc/usbtmc_device.c | 2 +- src/common/tusb_common.h | 12 ++++++++++-- src/common/tusb_verify.h | 6 +++--- src/device/usbd.c | 38 ++++++++++++++++++++++++++++++-------- src/device/usbd_control.c | 6 +++--- src/device/usbd_pvt.h | 5 ++++- src/tusb.c | 8 +++++--- test/test/support/tusb_config.h | 2 ++ 12 files changed, 62 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/examples/make.mk b/examples/make.mk index 319ceece8..449dc899d 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -84,7 +84,7 @@ endif ifeq ($(LOGGER),rtt) RTT_SRC = lib/SEGGER_RTT - CFLAGS += -DLOGGER_RTT + CFLAGS += -DLOGGER_RTT -DSEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL INC += $(TOP)/$(RTT_SRC)/RTT SRC_C += $(RTT_SRC)/RTT/SEGGER_RTT_printf.c SRC_C += $(RTT_SRC)/RTT/SEGGER_RTT.c diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 3c7118f13..2d8f986ae 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -260,7 +260,7 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { // notification endpoint if any - TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 56a27fbce..7bc8cef84 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -339,7 +339,7 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t { if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { - TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { p_midi->ep_in = ep_addr; diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 0f2ccbd44..ad1d66fca 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -167,7 +167,7 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t // notification endpoint (if any) if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { - TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index abe26ced3..b14135146 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -309,7 +309,7 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin default: TU_ASSERT(false); } - TU_VERIFY( dcd_edpt_open(rhport, ep_desc)); + TU_VERIFY( usbd_edpt_open(rhport, ep_desc)); found_endpoints++; } (*p_length) = (uint8_t)((*p_length) + p_desc[DESC_OFFSET_LEN]); diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 2d80f8210..fcb22cde1 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -219,17 +219,25 @@ void tu_print_mem(void const *buf, uint16_t count, uint8_t indent); #define tu_printf printf #endif +static inline +void tu_print_var(uint8_t const* buf, uint32_t bufsize) +{ + for(uint32_t i=0; i 1 #define TU_LOG2 TU_LOG1 #define TU_LOG2_MEM TU_LOG1_MEM + #define TU_LOG2_VAR TU_LOG1_VAR #define TU_LOG2_LOCATION() TU_LOG1_LOCATION() #define TU_LOG2_INT TU_LOG1_INT #define TU_LOG2_HEX TU_LOG1_HEX diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index fee291df6..406f5e6ee 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -90,13 +90,13 @@ volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ \ } while(0) -#else -#if defined(__riscv) + +#elif defined(__riscv) #define TU_BREAKPOINT() do { __asm("ebreak\n"); } while(0) + #else #define TU_BREAKPOINT() do {} while (0) #endif -#endif /*------------------------------------------------------------------*/ /* Macro Generator diff --git a/src/device/usbd.c b/src/device/usbd.c index 219dd23be..f0b7fcefc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -356,7 +356,8 @@ void tud_task (void) if ( !osal_queue_receive(_usbd_q, &event) ) return; - TU_LOG2("USBD: event %s\r\n", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); + TU_LOG2("USBD: %s", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); + TU_LOG2("%s", (event.event_id != DCD_EVENT_XFER_COMPLETE && event.event_id != DCD_EVENT_SETUP_RECEIVED) ? "\r\n" : " "); switch ( event.event_id ) { @@ -372,7 +373,8 @@ void tud_task (void) break; case DCD_EVENT_SETUP_RECEIVED: - TU_LOG2_MEM(&event.setup_received, 8, 2); + TU_LOG2_VAR(&event.setup_received); + TU_LOG2("\r\n"); // Mark as connected after receiving 1st setup packet. // But it is easier to set it every time instead of wasting time to check then set @@ -395,7 +397,7 @@ void tud_task (void) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Endpoint: 0x%02X, Bytes: %u\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); _usbd_dev.ep_status[epnum][ep_dir].busy = false; @@ -472,10 +474,11 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const return tud_vendor_control_request_cb(rhport, p_request); } -#if CFG_TUSB_DEBUG > 1 +#if CFG_TUSB_DEBUG >= 2 if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME) { - TU_LOG2(" %s\r\n", _tusb_std_request_str[p_request->bRequest]); + TU_LOG2(" %s", _tusb_std_request_str[p_request->bRequest]); + if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG2("\r\n"); } #endif @@ -702,7 +705,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // 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); + TU_LOG2(" %s opened\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 @@ -767,6 +770,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const { case TUSB_DESC_DEVICE: { + TU_LOG2(" Device\r\n"); + uint16_t len = sizeof(tusb_desc_device_t); // Only send up to EP0 Packet Size if not addressed @@ -785,6 +790,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_BOS: { + TU_LOG2(" BOS\r\n"); + // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) if (!tud_descriptor_bos_cb) return false; @@ -798,6 +805,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_CONFIGURATION: { + TU_LOG2(" Configuration[%u]\r\n", desc_index); + tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index); TU_ASSERT(desc_config); @@ -809,6 +818,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const break; case TUSB_DESC_STRING: + TU_LOG2(" String[%u]\r\n", desc_index); + // String Descriptor always uses the desc set from user if ( desc_index == 0xEE ) { @@ -827,6 +838,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const break; case TUSB_DESC_DEVICE_QUALIFIER: + TU_LOG2(" Device Qualifier\r\n"); + // TODO If not highspeed capable stall this request otherwise // return the descriptor that could work in highspeed return false; @@ -920,7 +933,7 @@ bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && xfer_type == desc_ep->bmAttributes.xfer); - TU_ASSERT(dcd_edpt_open(rhport, desc_ep)); + TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) { @@ -955,15 +968,24 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) // USBD Endpoint API //--------------------------------------------------------------------+ +bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) +{ + TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); + + return dcd_edpt_open(rhport, desc_ep); +} + bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + TU_VERIFY( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ); _usbd_dev.ep_status[epnum][dir].busy = true; - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", ep_addr, total_bytes); + TU_LOG2("OK\r\n"); return true; } diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index c61606f18..b0ae85e3b 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -63,7 +63,7 @@ static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t con // Opposite to endpoint in Data Phase uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", ep_addr, 0); + TU_LOG2(" Queue EP %02X with zlp Status\r\n", ep_addr); // status direction is reversed to one in the setup packet // Note: Status must always be DATA1 @@ -96,7 +96,7 @@ static bool _data_stage_xact(uint8_t rhport) if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len); } - TU_LOG2(" XACT Control: 0x%02X, Bytes: %d\r\n", ep_addr, xact_len); + TU_LOG2(" Queue EP %02X with %u bytes\r\n", ep_addr, xact_len); return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); } @@ -118,7 +118,7 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo TU_ASSERT(buffer); } - TU_LOG2(" XFER Endpoint: 0x%02X, Bytes: %d\r\n", request->bmRequestType_bit.direction ? EDPT_CTRL_IN : EDPT_CTRL_OUT, _ctrl_xfer.data_len); +// TU_LOG2(" Control total data length is %u bytes\r\n", _ctrl_xfer.data_len); // Data stage TU_ASSERT( _data_stage_xact(rhport) ); diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 26b9700e8..48188ec99 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -37,7 +37,10 @@ // USBD Endpoint API //--------------------------------------------------------------------+ -//bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +// Open an endpoint +bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); + +// Close an endpoint void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer diff --git a/src/tusb.c b/src/tusb.c index 8f234455f..1bc134dba 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -78,9 +78,11 @@ static void dump_str_line(uint8_t const* buf, uint16_t count) } } -// size : item size in bytes -// count : number of item -// print offet or not (handfy for dumping large memory) +/* Print out memory contents + * - size : item size in bytes + * - count : number of item + * - indent: prefix spaces on every line + */ void tu_print_mem(void const *buf, uint16_t count, uint8_t indent) { uint8_t const size = 1; // fixed 1 byte for now diff --git a/test/test/support/tusb_config.h b/test/test/support/tusb_config.h index 5e7b70e0d..5258513ec 100644 --- a/test/test/support/tusb_config.h +++ b/test/test/support/tusb_config.h @@ -52,7 +52,9 @@ #define CFG_TUSB_OS OPT_OS_NONE // CFG_TUSB_DEBUG is defined by compiler in DEBUG build +#ifndef CFG_TUSB_DEBUG #define CFG_TUSB_DEBUG 0 +#endif /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. * Tinyusb use follows macros to declare transferring memory so that they can be put -- cgit v1.3.1 From 9c8517a8d2603a0ce3a16c8cc144749d2ba9fece Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 26 Apr 2020 14:58:23 +0700 Subject: fix missing debug log macros --- src/common/tusb_common.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index fcb22cde1..052caef21 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -271,11 +271,17 @@ static inline char const* lookup_find(lookup_table_t const* p_table, uint32_t ke #ifndef TU_LOG1 #define TU_LOG1(...) #define TU_LOG1_MEM(...) + #define TU_LOG1_VAR(...) + #define TU_LOG1_INT(...) + #define TU_LOG1_HEX(...) #endif #ifndef TU_LOG2 #define TU_LOG2(...) #define TU_LOG2_MEM(...) + #define TU_LOG2_VAR(...) + #define TU_LOG2_INT(...) + #define TU_LOG2_HEX(...) #endif #ifdef __cplusplus -- cgit v1.3.1 From a1c599f4b6a05aefb948aaacf9a0984f577252bb Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 26 Apr 2020 22:02:41 +0700 Subject: clean up log message --- src/device/usbd.c | 31 ++++++++++++++++++++++--------- src/device/usbd_control.c | 11 ++++++++--- 2 files changed, 30 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index f0b7fcefc..1f660f0f2 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -232,15 +232,15 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, #if CFG_TUSB_DEBUG >= 2 static char const* const _usbd_event_str[DCD_EVENT_COUNT] = { - "INVALID" , - "BUS_RESET" , - "UNPLUGGED" , + "Invalid" , + "Bus Reset" , + "Unplugged" , "SOF" , - "SUSPEND" , - "RESUME" , - "SETUP_RECEIVED" , - "XFER_COMPLETE" , - "FUNC_CALL" + "Suspend" , + "Resume" , + "Setup Received" , + "Xfer Complete" , + "Func Call" }; static char const* const _tusb_std_request_str[] = @@ -260,6 +260,19 @@ static char const* const _tusb_std_request_str[] = "Synch Frame" }; +// for usbd_control to print the name of control complete driver +void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const * )) +{ + for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) + { + if (_usbd_driver[i].control_complete == control_complete ) + { + TU_LOG2(" %s control complete\r\n", _usbd_driver[i].name); + return; + } + } +} + #endif //--------------------------------------------------------------------+ @@ -356,7 +369,7 @@ void tud_task (void) if ( !osal_queue_receive(_usbd_q, &event) ) return; - TU_LOG2("USBD: %s", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); + TU_LOG2("USBD %s", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); TU_LOG2("%s", (event.event_id != DCD_EVENT_XFER_COMPLETE && event.event_id != DCD_EVENT_SETUP_RECEIVED) ? "\r\n" : " "); switch ( event.event_id ) diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index b0ae85e3b..2778a0d77 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -58,6 +58,7 @@ static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; // Application API //--------------------------------------------------------------------+ +// Queue ZLP status transaction static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const * request) { // Opposite to endpoint in Data Phase @@ -81,7 +82,7 @@ bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) return _status_stage_xact(rhport, request); } -// Transfer an transaction in Data Stage +// Queue an transaction in Data Stage // Each transaction has up to Endpoint0's max packet size. // This function can also transfer an zero-length packet static bool _data_stage_xact(uint8_t rhport) @@ -102,7 +103,6 @@ static bool _data_stage_xact(uint8_t rhport) } // Transmit data to/from the control endpoint. -// // If the request's wLength is zero, a status packet is sent instead. bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len) { @@ -182,7 +182,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result // Data Stage is complete when all request's length are transferred or // a short packet is sent including zero-length packet. - if ( (_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || xferred_bytes < CFG_TUD_ENDPOINT0_SIZE ) + if ( (_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || (xferred_bytes < CFG_TUD_ENDPOINT0_SIZE) ) { // DATA stage is complete bool is_ok = true; @@ -191,6 +191,11 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result // callback can still stall control in status phase e.g out data does not make sense if ( _ctrl_xfer.complete_cb ) { + #if CFG_TUSB_DEBUG >= 2 + extern void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const *)); + usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); + #endif + is_ok = _ctrl_xfer.complete_cb(rhport, &_ctrl_xfer.request); } -- cgit v1.3.1 From 83353dd93f2c24b87b9d22e3543e91420d758513 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 26 Apr 2020 22:03:05 +0700 Subject: add TODO for usbnet clean up --- src/class/net/net_device.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index ad1d66fca..e3faa0187 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -89,7 +89,8 @@ static const struct ecm_notify_struct ecm_notify_csc = .uplink = 9728000, }; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static union +// TODO remove CFG_TUSB_MEM_SECTION, control internal buffer is already in this special section +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static union { uint8_t rndis_buf[120]; struct ecm_notify_struct ecm_buf; @@ -98,6 +99,7 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static union //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ +// TODO remove CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_SECTION static netd_interface_t _netd_itf; static bool can_xmit; -- cgit v1.3.1 From 8d18d6077bb1100e0f5ac5b3a11b807751d93149 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 26 Apr 2020 22:14:59 +0700 Subject: turn off TX FIFO Empty for EPIN if all bytes are written fix dcd synopsys issue with usbnet #289 --- src/portable/st/synopsys/dcd_synopsys.c | 60 ++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 9c1672220..a86d07578 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -291,9 +291,10 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) if(dir == TUSB_DIR_OUT) { - out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | \ - desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos | \ - desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos; + out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | + (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) | + (desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos); + dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum)); } else @@ -321,11 +322,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // - Offset: GRXFSIZ + 16 + Size*(epnum-1) // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". - in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | \ - epnum << USB_OTG_DIEPCTL_TXFNUM_Pos | \ - desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos | \ - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | \ - desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos; + in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | + (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) | + (desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos) | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | + (desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos); + dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); // Both TXFD and TXSA are in unit of 32-bit words. @@ -352,9 +354,9 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t uint8_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = buffer; - xfer->total_len = total_bytes; - xfer->queued_len = 0; + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->queued_len = 0; xfer->short_packet = false; uint16_t num_packets = (total_bytes / xfer->max_size); @@ -365,21 +367,23 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t num_packets++; } - // IN and OUT endpoint xfers are interrupt-driven, we just schedule them - // here. + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them here. if(dir == TUSB_DIR_IN) { // A full IN transfer (multiple packets, possibly) triggers XFRC. - in_ep[epnum].DIEPTSIZ = (num_packets << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | \ - ((total_bytes & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) << USB_OTG_DIEPTSIZ_XFRSIZ_Pos); + in_ep[epnum].DIEPTSIZ = (num_packets << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | + ((total_bytes & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) << USB_OTG_DIEPTSIZ_XFRSIZ_Pos); + in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; + // Enable fifo empty interrupt only if there are something to put in the fifo. if(total_bytes != 0) { dev->DIEPEMPMSK |= (1 << epnum); } } else { // Each complete packet for OUT xfers triggers XFRC. - out_ep[epnum].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | \ - ((xfer->max_size & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) << USB_OTG_DOEPTSIZ_XFRSIZ_Pos); + out_ep[epnum].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | + ((xfer->max_size & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) << USB_OTG_DOEPTSIZ_XFRSIZ_Pos); + out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; } @@ -535,6 +539,7 @@ static void receive_packet(xfer_ctl_t * xfer, /* USB_OTG_OUTEndpointTypeDef * ou xfer->short_packet = (xfer_size < xfer->max_size); } +// Write a data packet to EPIN FIFO static void transmit_packet(xfer_ctl_t * xfer, USB_OTG_INEndpointTypeDef * in_ep, uint8_t fifo_num) { usb_fifo_t tx_fifo = FIFO_BASE(fifo_num); @@ -658,21 +663,30 @@ static void handle_epout_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTy static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointTypeDef * in_ep) { // DAINT for a given EP clears when DIEPINTx is cleared. // IEPINT will be cleared when DAINT's out bits are cleared. - for(uint8_t n = 0; n < EP_MAX; n++) { - xfer_ctl_t * xfer = XFER_CTL_BASE(n, TUSB_DIR_IN); + for ( uint8_t n = 0; n < EP_MAX; n++ ) + { + xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_IN); - if(dev->DAINT & (1 << (USB_OTG_DAINT_IEPINT_Pos + n))) { + if ( dev->DAINT & (1 << (USB_OTG_DAINT_IEPINT_Pos + n)) ) + { // IN XFER complete (entire xfer). - if(in_ep[n].DIEPINT & USB_OTG_DIEPINT_XFRC) { + if ( in_ep[n].DIEPINT & USB_OTG_DIEPINT_XFRC ) + { in_ep[n].DIEPINT = USB_OTG_DIEPINT_XFRC; - dev->DIEPEMPMSK &= ~(1 << n); // Turn off TXFE b/c xfer inactive. dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); } // XFER FIFO empty - if(in_ep[n].DIEPINT & USB_OTG_DIEPINT_TXFE) { + if ( in_ep[n].DIEPINT & USB_OTG_DIEPINT_TXFE ) + { in_ep[n].DIEPINT = USB_OTG_DIEPINT_TXFE; transmit_packet(xfer, &in_ep[n], n); + + // Turn off TXFE if all bytes are written. + if (xfer->queued_len == xfer->total_len) + { + dev->DIEPEMPMSK &= ~(1 << n); + } } } } -- cgit v1.3.1 From 00fcf829a12c2f075f696c78a64640b8b8e44b6b Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 26 Apr 2020 22:41:04 +0700 Subject: sync synopsis fix for esp32s2 --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 36 ++++++++++++++++++---------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 10c789da3..d49b69a10 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -244,8 +244,8 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) if (dir == TUSB_DIR_OUT) { out_ep[epnum].doepctl |= USB_USBACTEP0_M | - desc_edpt->bmAttributes.xfer << USB_EPTYPE0_S | - desc_edpt->wMaxPacketSize.size << USB_MPS0_S; + desc_edpt->bmAttributes.xfer << USB_EPTYPE0_S | + desc_edpt->wMaxPacketSize.size << USB_MPS0_S; USB0.daintmsk |= (1 << (16 + epnum)); } else { // "USB Data FIFOs" section in reference manual @@ -272,10 +272,11 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". in_ep[epnum].diepctl |= USB_D_USBACTEP1_M | - epnum << USB_D_TXFNUM1_S | - desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | - desc_edpt->wMaxPacketSize.size << 0; + epnum << USB_D_TXFNUM1_S | + desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | + desc_edpt->wMaxPacketSize.size << 0; + USB0.daintmsk |= (1 << (0 + epnum)); // Both TXFD and TXSA are in unit of 32-bit words. @@ -295,12 +296,12 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to (void)rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = buffer; - xfer->total_len = total_bytes; - xfer->queued_len = 0; + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->queued_len = 0; xfer->short_packet = false; uint16_t num_packets = (total_bytes / xfer->max_size); @@ -321,7 +322,11 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to // A full IN transfer (multiple packets, possibly) triggers XFRC. USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK - USB0.dtknqr4_fifoemptymsk |= (1 << epnum); + + // Enable fifo empty interrupt only if there are something to put in the fifo. + if(total_bytes != 0) { + USB0.dtknqr4_fifoemptymsk |= (1 << epnum); + } } else { // Each complete packet for OUT xfers triggers XFRC. USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); @@ -617,7 +622,6 @@ static void handle_epin_ints(void) if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER complete!"); USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M; - USB0.dtknqr4_fifoemptymsk &= ~(1 << n); // Turn off TXFE b/c xfer inactive. dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); } @@ -626,6 +630,12 @@ static void handle_epin_ints(void) ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER FIFO empty!"); USB0.in_ep_reg[n].diepint = USB_D_TXFEMP0_M; transmit_packet(xfer, &USB0.in_ep_reg[n], n); + + // Turn off TXFE if all bytes are written. + if (xfer->queued_len == xfer->total_len) + { + USB0.dtknqr4_fifoemptymsk &= ~(1 << n); + } } } } -- cgit v1.3.1 From d0487088ac094eaaff54c04241d8018ffc729b36 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 26 Apr 2020 23:04:17 +0700 Subject: revert a change to net driver --- src/class/net/net_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index e3faa0187..fedd4db99 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -90,7 +90,7 @@ static const struct ecm_notify_struct ecm_notify_csc = }; // TODO remove CFG_TUSB_MEM_SECTION, control internal buffer is already in this special section -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static union +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static union { uint8_t rndis_buf[120]; struct ecm_notify_struct ecm_buf; -- cgit v1.3.1 From e785b091184b5e741d9c2ade0b54bca651834bd1 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 27 Apr 2020 12:06:14 +0700 Subject: TXFE is read only bit --- src/portable/st/synopsys/dcd_synopsys.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index a86d07578..b479930ed 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -679,7 +679,8 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType // XFER FIFO empty if ( in_ep[n].DIEPINT & USB_OTG_DIEPINT_TXFE ) { - in_ep[n].DIEPINT = USB_OTG_DIEPINT_TXFE; + // DIEPINT's TXFE bit is read-only -> no need to clear + transmit_packet(xfer, &in_ep[n], n); // Turn off TXFE if all bytes are written. -- cgit v1.3.1 From 958b5510cb9ac913b30772ec248e0ffcd3827890 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 27 Apr 2020 13:17:47 +0700 Subject: added comment for hw clearing TXFE --- src/portable/st/synopsys/dcd_synopsys.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index b479930ed..4e0d6f8c4 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -679,7 +679,10 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType // XFER FIFO empty if ( in_ep[n].DIEPINT & USB_OTG_DIEPINT_TXFE ) { - // DIEPINT's TXFE bit is read-only -> no need to clear + // DIEPINT's TXFE bit is read-only, software cannot clear it. + // It will only be cleared by hardware when written bytes is more than + // - 64 bytes or + // - Half of TX FIFO size (configured by DIEPTXF) transmit_packet(xfer, &in_ep[n], n); -- cgit v1.3.1 From 63cefb761535bf9f9f86a261c4a7ba07710c6c1d Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 27 Apr 2020 16:42:35 +0200 Subject: Fix endpoint busy flag race condition Busy flag was set to true after call to dcd_edpt_xfer(). In some cased it was possible that transfer finished before function ended. In this case busy flag could be set to false before it was set to true. Then setting it to true after dcd_edpt_xfer() made edpoint busy forever. This change marks endpoint as busy before transfer is started to avoid race condition. --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index f0b7fcefc..2042d35b7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -982,8 +982,8 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); - TU_VERIFY( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ); _usbd_dev.ep_status[epnum][dir].busy = true; + TU_VERIFY_HDLR( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes), _usbd_dev.ep_status[epnum][dir].busy = false); TU_LOG2("OK\r\n"); -- cgit v1.3.1 From fcdb22b2f9db6f4e08ce05a1b2b7a1c9cc06a4ab Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 28 Apr 2020 10:53:43 +0700 Subject: fix typo --- src/device/usbd_control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 2778a0d77..353a66ad1 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -82,7 +82,7 @@ bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request) return _status_stage_xact(rhport, request); } -// Queue an transaction in Data Stage +// Queue a transaction in Data Stage // Each transaction has up to Endpoint0's max packet size. // This function can also transfer an zero-length packet static bool _data_stage_xact(uint8_t rhport) -- cgit v1.3.1 From c14c0cfc9fec9101b63df682c5fa5ac0576de0f8 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 29 Apr 2020 10:49:58 +0700 Subject: support class drivers implemented by application --- src/device/usbd.c | 114 ++++++++++++++++++++++++++++---------------------- src/device/usbd_pvt.h | 23 ++++++++++ 2 files changed, 87 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 1f660f0f2..432786140 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -79,21 +79,7 @@ enum { DRVID_INVALID = 0xFFu }; #define DRIVER_NAME(_name) #endif -typedef struct -{ - #if CFG_TUSB_DEBUG >= 2 - char const* name; - #endif - - void (* init ) (void); - void (* reset ) (uint8_t rhport); - bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); - bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); - bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); - bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - void (* sof ) (uint8_t rhport); /* optional */ -} usbd_class_driver_t; - +// Built-in class drivers static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_CDC @@ -203,6 +189,29 @@ static usbd_class_driver_t const _usbd_driver[] = enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; +// Additional class drivers implemented by application +static usbd_class_driver_t const * _app_driver = NULL; +static uint8_t _app_driver_count = 0; + +// virtually joins built-in and application drivers together +// All drivers = built-in + application +static inline usbd_class_driver_t const * get_driver(uint8_t drvid) +{ + // Built-in drivers + if (drvid < USBD_CLASS_DRIVER_COUNT) return &_usbd_driver[drvid]; + + // App drivers + if ( usbd_app_driver_get_cb ) + { + drvid -= USBD_CLASS_DRIVER_COUNT; + if ( drvid < _app_driver_count ) return &_app_driver[drvid]; + } + + return NULL; +} + +#define TOTAL_DRIVER_COUNT (USBD_CLASS_DRIVER_COUNT+_app_driver_count) + //--------------------------------------------------------------------+ // DCD Event //--------------------------------------------------------------------+ @@ -263,11 +272,12 @@ static char const* const _tusb_std_request_str[] = // for usbd_control to print the name of control complete driver void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const * )) { - for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { - if (_usbd_driver[i].control_complete == control_complete ) + usbd_class_driver_t const * driver = get_driver(i); + if ( driver->control_complete == control_complete ) { - TU_LOG2(" %s control complete\r\n", _usbd_driver[i].name); + TU_LOG2(" %s control complete\r\n", driver->name); return; } } @@ -309,11 +319,18 @@ bool tud_init (void) _usbd_q = osal_queue_create(&_usbd_qdef); TU_ASSERT(_usbd_q != NULL); + // Get application driver if available + if ( usbd_app_driver_get_cb ) + { + _app_driver = usbd_app_driver_get_cb(&_app_driver_count); + } + // Init class drivers - for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { - TU_LOG2("%s init\r\n", _usbd_driver[i].name); - _usbd_driver[i].init(); + usbd_class_driver_t const * driver = get_driver(i); + TU_LOG2("%s init\r\n", driver->name); + driver->init(); } // Init device controller driver @@ -333,9 +350,9 @@ static void usbd_reset(uint8_t rhport) usbd_control_reset(); - for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) + for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) { - if ( _usbd_driver[i].reset ) _usbd_driver[i].reset( rhport ); + get_driver(i)->reset(rhport); } } @@ -420,11 +437,11 @@ void tud_task (void) } else { - uint8_t const drv_id = _usbd_dev.ep2drv[epnum][ep_dir]; - TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,); + usbd_class_driver_t const * driver = get_driver( _usbd_dev.ep2drv[epnum][ep_dir] ); + TU_ASSERT(driver, ); - 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); + TU_LOG2(" %s xfer callback\r\n", driver->name); + driver->xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); } } break; @@ -438,12 +455,10 @@ void tud_task (void) break; case DCD_EVENT_SOF: - for ( uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++ ) + for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ ) { - if ( _usbd_driver[i].sof ) - { - _usbd_driver[i].sof(event.rhport); - } + usbd_class_driver_t const * driver = get_driver(i); + if ( driver->sof ) driver->sof(event.rhport); } break; @@ -463,11 +478,11 @@ void tud_task (void) //--------------------------------------------------------------------+ // Helper to invoke class driver control request handler -static bool invoke_class_control(uint8_t rhport, uint8_t drvid, tusb_control_request_t const * request) +static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request) { - usbd_control_set_complete_callback(_usbd_driver[drvid].control_complete); - TU_LOG2(" %s control request\r\n", _usbd_driver[drvid].name); - return _usbd_driver[drvid].control_request(rhport, request); + usbd_control_set_complete_callback(driver->control_complete); + TU_LOG2(" %s control request\r\n", driver->name); + return driver->control_request(rhport, request); } // This handles the actual request and its response. @@ -580,12 +595,12 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const uint8_t const itf = tu_u16_low(p_request->wIndex); TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); - uint8_t const drvid = _usbd_dev.itf2drv[itf]; - TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT); + usbd_class_driver_t const * driver = get_driver(_usbd_dev.itf2drv[itf]); + TU_VERIFY(driver); // 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) ) + if ( !invoke_class_control(rhport, driver, p_request) ) { // For GET_INTERFACE, it is mandatory to respond even if the class // driver doesn't use alternate settings. @@ -607,8 +622,6 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) ); - uint8_t const drvid = _usbd_dev.ep2drv[ep_num][ep_dir]; - bool ret = false; // Handle STD request to endpoint @@ -647,16 +660,17 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const } } - if (drvid < 0xFF) { - TU_ASSERT(drvid < USBD_CLASS_DRIVER_COUNT); - + usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]); + + if (driver) + { // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request // We will forward all request targeted endpoint to class drivers after // - For class-type requests: driver is fully responsible to reply to host // - For std-type requests : driver init/re-init internal variable/buffer only, and // must not call tud_control_status(), driver's return value will have no effect. // EP state has already affected (stalled/cleared) - if ( invoke_class_control(rhport, drvid, p_request) ) ret = true; + if ( invoke_class_control(rhport, driver, p_request) ) ret = true; } if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ) @@ -708,17 +722,17 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) uint8_t drv_id; uint16_t drv_len; - for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) + for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { - usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; + usbd_class_driver_t const *driver = get_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_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber]); - TU_LOG2(" %s opened\r\n", _usbd_driver[drv_id].name); + TU_LOG2(" %s opened\r\n", driver->name); _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; // If IAD exist, assign all interfaces to the same driver @@ -741,7 +755,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } // Assert if cannot find supported driver - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); + TU_ASSERT( drv_id < TOTAL_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 48188ec99..d6eb289c1 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -33,6 +33,29 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Class Drivers +//--------------------------------------------------------------------+ + +typedef struct +{ +#if CFG_TUSB_DEBUG >= 2 + char const* name; +#endif + + void (* init ) (void); + void (* reset ) (uint8_t rhport); + bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); + bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + void (* sof ) (uint8_t rhport); /* optional */ +} usbd_class_driver_t; + +// Invoked when initializing device stack to get additional class drivers. +// Can optionally implemented by application to extend/overwrite class driver support. +usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; + //--------------------------------------------------------------------+ // USBD Endpoint API //--------------------------------------------------------------------+ -- cgit v1.3.1 From 6f4b6a1d03efa2a1f878e90d523746395be622c6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 29 Apr 2020 11:31:27 +0700 Subject: remove the use of TU_VERIFY_HDLR --- src/device/usbd.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 62133bdb8..06e724cb3 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -995,12 +995,21 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return + // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - TU_VERIFY_HDLR( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes), _usbd_dev.ep_status[epnum][dir].busy = false); - TU_LOG2("OK\r\n"); - - return true; + if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + _usbd_dev.ep_status[epnum][dir].busy = false; + TU_LOG2("failed\r\n"); + TU_BREAKPOINT(); + return false; + } } bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) -- cgit v1.3.1 From 3e6feb7f6d59ff500395471561e24b449356e2f1 Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Wed, 29 Apr 2020 11:32:22 +0200 Subject: Redesign of Synopsys device transmission Changes: - checking if tx buffer empty interrupt is masked - process more than one packet in isr - mask tx buffer empty just after all bytes were written - use of transmit_fifo_packet instead of transmit_packet --- src/portable/st/synopsys/dcd_synopsys.c | 90 ++++++++++++++++----------------- 1 file changed, 45 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 4e0d6f8c4..39079c9d2 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -195,7 +195,7 @@ void dcd_init (uint8_t rhport) // Programming model begins in the last section of the chapter on the USB // peripheral in each Reference Manual. - USB_OTG_FS->GAHBCFG |= USB_OTG_GAHBCFG_TXFELVL | USB_OTG_GAHBCFG_GINT; + USB_OTG_FS->GAHBCFG |= USB_OTG_GAHBCFG_GINT; // No HNP/SRP (no OTG support), program timeout later, turnaround // programmed for 32+ MHz. @@ -374,7 +374,6 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t ((total_bytes & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) << USB_OTG_DIEPTSIZ_XFRSIZ_Pos); in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; - // Enable fifo empty interrupt only if there are something to put in the fifo. if(total_bytes != 0) { dev->DIEPEMPMSK |= (1 << epnum); @@ -539,46 +538,27 @@ static void receive_packet(xfer_ctl_t * xfer, /* USB_OTG_OUTEndpointTypeDef * ou xfer->short_packet = (xfer_size < xfer->max_size); } -// Write a data packet to EPIN FIFO -static void transmit_packet(xfer_ctl_t * xfer, USB_OTG_INEndpointTypeDef * in_ep, uint8_t fifo_num) { - usb_fifo_t tx_fifo = FIFO_BASE(fifo_num); - - uint16_t remaining = (in_ep->DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos; - xfer->queued_len = xfer->total_len - remaining; - - uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; - uint8_t to_xfer_rem = to_xfer_size % 4; - uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; - - // Buffer might not be aligned to 32b, so we need to force alignment - // by copying to a temp var. - uint8_t * base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to send off. - if(to_xfer_size >= 4) { - for(uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { - uint32_t tmp = base[i] | (base[i + 1] << 8) | \ - (base[i + 2] << 16) | (base[i + 3] << 24); - (* tx_fifo) = tmp; - } - } - - // Do not read beyond end of buffer if not divisible by 4. - if(to_xfer_rem != 0) { - uint32_t tmp = 0; - uint8_t * last_32b_bound = base + to_xfer_size_aligned; - - tmp |= last_32b_bound[0]; - if(to_xfer_rem > 1) { - tmp |= (last_32b_bound[1] << 8); - } - if(to_xfer_rem > 2) { - tmp |= (last_32b_bound[2] << 16); - } - - (* tx_fifo) = tmp; - } +// Write a single data packet to EPIN FIFO +static void transmit_fifo_packet(uint8_t fifo_num, uint8_t * src, uint16_t len){ + usb_fifo_t tx_fifo = FIFO_BASE(fifo_num); + + // Pushing full available 32 bit words to fifo + uint16_t full_words = len >> 2; + for(uint16_t i = 0; i < full_words; i++){ + *tx_fifo = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0]; + src += 4; + } + + // Write the remaining 1-3 bytes into fifo + uint32_t tmp_word = 0; + switch(len & 0x0003){ + case 3: tmp_word |= src[2] << 16; + case 2: tmp_word |= src[1] << 8; + case 1: tmp_word |= src[0]; + *tx_fifo = tmp_word; + break; + default: break; + } } static void read_rx_fifo(USB_OTG_OUTEndpointTypeDef * out_ep) { @@ -677,17 +657,37 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType } // XFER FIFO empty - if ( in_ep[n].DIEPINT & USB_OTG_DIEPINT_TXFE ) + if ( (in_ep[n].DIEPINT & USB_OTG_DIEPINT_TXFE) && (dev->DIEPEMPMSK & (1 << n)) ) { // DIEPINT's TXFE bit is read-only, software cannot clear it. // It will only be cleared by hardware when written bytes is more than // - 64 bytes or // - Half of TX FIFO size (configured by DIEPTXF) - transmit_packet(xfer, &in_ep[n], n); + // Packets to be processed + uint16_t tx_packet_amount = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_PKTCNT_Msk) >> USB_OTG_DIEPTSIZ_PKTCNT_Pos; + + // Process every single packet (only whole packets can be written to fifo) + for(uint16_t i = 0; i < tx_packet_amount; i++){ + // amount of bytes EP still needs to transfer + uint16_t tx_remaining = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos; + // Packet can not be larger than ep max size + uint16_t packet_size = (tx_remaining > xfer->max_size) ? xfer->max_size : tx_remaining; + + // It's only possible to write full packets into FIFO. Therefore DTXFSTS register of current + // EP has to be checked if the buffer can take another WHOLE packet + if(packet_size > ((in_ep[n].DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV_Msk) << 2)){ + break; + } + + xfer->queued_len = xfer->total_len - tx_remaining; + + // Push packet to Tx-FIFO + transmit_fifo_packet(n, (xfer->buffer + xfer->queued_len), packet_size); + } // Turn off TXFE if all bytes are written. - if (xfer->queued_len == xfer->total_len) + if (((in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos) == 0) { dev->DIEPEMPMSK &= ~(1 << n); } -- cgit v1.3.1 From 59ff208c65f1314cdd9691979c849e80920581c1 Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Wed, 29 Apr 2020 12:37:29 +0200 Subject: Changed switch into if statements --- src/portable/st/synopsys/dcd_synopsys.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 39079c9d2..6686c1704 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -550,14 +550,17 @@ static void transmit_fifo_packet(uint8_t fifo_num, uint8_t * src, uint16_t len){ } // Write the remaining 1-3 bytes into fifo - uint32_t tmp_word = 0; - switch(len & 0x0003){ - case 3: tmp_word |= src[2] << 16; - case 2: tmp_word |= src[1] << 8; - case 1: tmp_word |= src[0]; - *tx_fifo = tmp_word; - break; - default: break; + uint8_t bytes_rem = len & 0x03; + if(bytes_rem){ + uint32_t tmp_word = 0; + tmp_word |= src[0]; + if(bytes_rem > 1){ + tmp_word |= src[1] << 8; + } + if(bytes_rem > 2){ + tmp_word |= src[2] << 16; + } + *tx_fifo = tmp_word; } } -- cgit v1.3.1 From a74a823b0a140667a4e4e80fa2678870faba2bd0 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 30 Apr 2020 00:29:47 +0700 Subject: fix dcd samd race condition with setup packet setup packet can complete together with previous status (in & out). Always make sure to prepare valid buffer for holding setup packet when queuing control status. --- src/portable/microchip/samd/dcd_samd.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index a01bef38a..a859b72b9 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -37,14 +37,11 @@ static TU_ATTR_ALIGNED(4) UsbDeviceDescBank sram_registers[8][2]; static TU_ATTR_ALIGNED(4) uint8_t _setup_packet[8]; - // ready for receiving SETUP packet static inline void prepare_setup(void) { // Only make sure the EP0 OUT buffer is ready sram_registers[0][0].ADDR.reg = (uint32_t) _setup_packet; - sram_registers[0][0].PCKSIZE.bit.MULTI_PACKET_SIZE = sizeof(_setup_packet); - sram_registers[0][0].PCKSIZE.bit.BYTE_COUNT = 0; } // Setup the control endpoint 0. @@ -64,7 +61,6 @@ static void bus_reset(void) prepare_setup(); } - /*------------------------------------------------------------------*/ /* Controller API *------------------------------------------------------------------*/ @@ -183,7 +179,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re } // Just finished status stage, prepare for next setup packet - // Note: we may already prepare setup when the last EP0 OUT complete. + // Note: we may already prepare setup when queueing the control status. // but it has no harm to do it again here prepare_setup(); } @@ -235,6 +231,14 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum]; bank->ADDR.reg = (uint32_t) buffer; + + // A SETUP token can occur immediately after an ZLP Status. + // So make sure we have a valid buffer for setup packet. + // Status = ZLP EP0 with direction opposite to one in the dir bit of current setup + if ( (epnum == 0) && (buffer == NULL) && (total_bytes == 0) && (dir != tu_edpt_dir(_setup_packet[0])) ) { + prepare_setup(); + } + if ( dir == TUSB_DIR_OUT ) { bank->PCKSIZE.bit.MULTI_PACKET_SIZE = total_bytes; @@ -297,7 +301,7 @@ void maybe_transfer_complete(void) { // Handle IN completions if ((epintflag & USB_DEVICE_EPINTFLAG_TRCPT1) != 0) { UsbDeviceDescBank* bank = &sram_registers[epnum][TUSB_DIR_IN]; - uint16_t total_transfer_size = bank->PCKSIZE.bit.BYTE_COUNT; + uint16_t const total_transfer_size = bank->PCKSIZE.bit.BYTE_COUNT; dcd_event_xfer_complete(0, epnum | TUSB_DIR_IN_MASK, total_transfer_size, XFER_RESULT_SUCCESS, true); @@ -306,15 +310,8 @@ void maybe_transfer_complete(void) { // Handle OUT completions if ((epintflag & USB_DEVICE_EPINTFLAG_TRCPT0) != 0) { - UsbDeviceDescBank* bank = &sram_registers[epnum][TUSB_DIR_OUT]; - uint16_t total_transfer_size = bank->PCKSIZE.bit.BYTE_COUNT; - - // A SETUP token can occur immediately after an OUT packet - // so make sure we have a valid buffer for the control endpoint. - if (epnum == 0) { - prepare_setup(); - } + uint16_t const total_transfer_size = bank->PCKSIZE.bit.BYTE_COUNT; dcd_event_xfer_complete(0, epnum, total_transfer_size, XFER_RESULT_SUCCESS, true); @@ -381,7 +378,10 @@ void dcd_int_handler (uint8_t rhport) // This copies the data elsewhere so we can reuse the buffer. dcd_event_setup_received(0, _setup_packet, true); - USB->DEVICE.DeviceEndpoint[0].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP; + // Although Setup packet only set RXSTP bit, + // TRCPT0 bit could already be set by previous ZLP OUT Status (not handled until now). + // Since control status complete event is optional, we can just clear TRCPT0 and skip the status event + USB->DEVICE.DeviceEndpoint[0].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP | USB_DEVICE_EPINTFLAG_TRCPT0; } // Handle complete transfer -- cgit v1.3.1 From 2a479175aedc6a1e15c5022a39acef58fa77b904 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 2 May 2020 14:51:21 +0700 Subject: remove toggle walkaround, fix control stall race condition --- src/portable/microchip/samg/dcd_samg.c | 158 ++++++++++++++++++++------------- 1 file changed, 96 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 1824d549a..50abe349e 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -51,12 +51,6 @@ typedef struct // Endpoint 0-5, each can only be either OUT or In xfer_desc_t _dcd_xfer[EP_COUNT]; -// Indicate that DATA Toggle for Control Status is incorrect, which must always be DATA1 by USB Specs. -// However SAMG DToggle is read-only, therefore we must duplicate the status phase ( D0 then D1 ) -// as walk-around to resolve this. The D0 status packet is likely to be discarded by USB Host safely. -// Note: Only needed for IN Status e.g CDC_SET_LINE_CODING, since out data is sent by host -volatile bool _walkaround_incorrect_dtoggle_control_status; - void xfer_epsize_set(xfer_desc_t* xfer, uint16_t epsize) { xfer->epsize = epsize; @@ -110,6 +104,49 @@ static void xact_ep_read(uint8_t epnum, uint8_t* buffer, uint16_t xact_len) } } + +//! Bitmap for all status bits in CSR that are not affected by a value 1. +#define UDP_REG_NO_EFFECT_1_ALL (UDP_CSR_RX_DATA_BK0 | UDP_CSR_RX_DATA_BK1 | UDP_CSR_STALLSENT | UDP_CSR_RXSETUP | UDP_CSR_TXCOMP) + +/*! Sets specified bit(s) in the UDP_CSR. +* \param ep +Endpoint number. +* \param bits Bitmap to set to 1. +*/ +#define csr_set(ep, bits) \ + do { \ + volatile uint32_t reg; \ + volatile uint32_t nop_count; \ + reg = UDP->UDP_CSR[ep]; \ + reg |= UDP_REG_NO_EFFECT_1_ALL; \ + reg |= (bits); \ + UDP->UDP_CSR[ep] = reg; \ + for (nop_count = 0; nop_count < 20; nop_count ++) {\ + __NOP(); \ + } \ + } while (0) + + +/*! Clears specified bit(s) in the UDP_CSR. +* \param ep +Endpoint number. +* \param bits Bitmap to set to 0. +*/ +#define csr_clear(ep, bits) \ + do { \ + volatile uint32_t reg; \ + volatile uint32_t nop_count; \ + reg = UDP->UDP_CSR[ep]; \ + reg |= UDP_REG_NO_EFFECT_1_ALL; \ + reg &= ~(bits); \ + UDP->UDP_CSR[ep] = reg; \ + for (nop_count = 0; nop_count < 20; nop_count ++) {\ + __NOP(); \ + } \ + } while (0) + +#define udp_clear_csr csr_clear +#define udp_set_csr csr_set /*------------------------------------------------------------------*/ /* Device API *------------------------------------------------------------------*/ @@ -117,7 +154,6 @@ static void xact_ep_read(uint8_t epnum, uint8_t* buffer, uint16_t xact_len) // Set up endpoint 0, clear all other endpoints static void bus_reset(void) { - _walkaround_incorrect_dtoggle_control_status = false; tu_memclr(_dcd_xfer, sizeof(_dcd_xfer)); xfer_epsize_set(&_dcd_xfer[0], CFG_TUD_ENDPOINT0_SIZE); @@ -189,7 +225,6 @@ void dcd_disconnect(uint8_t rhport) UDP->UDP_TXVC = UDP_TXVC_TXVDIS_Msk; } - //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ @@ -240,7 +275,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) xfer_epsize_set(&_dcd_xfer[epnum], ep_desc->wMaxPacketSize.size); - // Configure type and eanble EP + // Configure type and enable EP UDP->UDP_CSR[epnum] = UDP_CSR_EPEDS_Msk | UDP_CSR_EPTYPE(ep_desc->bmAttributes.xfer + 4*dir); // Enable EP Interrupt for IN @@ -260,49 +295,30 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_desc_t* xfer = &_dcd_xfer[epnum]; xfer_begin(xfer, buffer, total_bytes); - if (dir == TUSB_DIR_OUT) + // Control Status Stage if EP0 with len = 0 and direction is opposite of current Data Stage + if ( (epnum == 0) && /*(total_bytes == 0) &&*/ (dir != ((UDP->UDP_CSR[epnum] & UDP_CSR_DIR_Msk) >> UDP_CSR_DIR_Pos)) ) { - // Clear EP0 direction bit - if (epnum == 0) UDP->UDP_CSR[epnum] &= ~UDP_CSR_DIR_Msk; + TU_LOG2_INT(dir); + if ( dir ) + { + csr_set(0, UDP_CSR_DIR_Msk); + }else + { + csr_clear(0, UDP_CSR_DIR_Msk); + } + } + if (dir == TUSB_DIR_OUT) + { // Enable interrupt when starting OUT transfer if (epnum != 0) UDP->UDP_IER |= (1 << epnum); } else { - if (epnum == 0) - { - // Previous EP0 direction is OUT --> This transfer is ZLP control status. - if ( !(UDP->UDP_CSR[epnum] & UDP_CSR_DIR_Msk) ) - { - // Set EP0 dir bit - UDP->UDP_CSR[epnum] |= UDP_CSR_DIR_Msk; - - // DATA Toggle is 0, USB Specs requires Status Stage must be DATA1 - // Since SAMG DToggle is read-only, we mark this and implement the walk-around - if ( !(UDP->UDP_CSR[epnum] & UDP_CSR_DTGLE_Msk) ) - { - TU_LOG2("Incorrect DATA TOGGLE, Control Status must be DATA1\n"); - - // DTGLE is read-only on SAMG, this statement has no effect - UDP->UDP_CSR[epnum] |= UDP_CSR_DTGLE_Msk; - - // WALKROUND: duplicate IN transfer to send DATA1 status packet - // set flag for irq to skip reporting first incorrect packet - _walkaround_incorrect_dtoggle_control_status = true; - - UDP->UDP_CSR[epnum] |= UDP_CSR_TXPKTRDY_Msk; - while ( UDP->UDP_CSR[epnum] & UDP_CSR_TXPKTRDY_Msk ) {} - - _walkaround_incorrect_dtoggle_control_status = false; - } - } - } - xact_ep_write(epnum, xfer->buffer, xfer_packet_len(xfer)); // TX ready for transfer - UDP->UDP_CSR[epnum] |= UDP_CSR_TXPKTRDY_Msk; + csr_set(epnum, UDP_CSR_TXPKTRDY_Msk); } return true; @@ -313,10 +329,14 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; + // For EP0 USBD will stall both EP0 Out and In with 0x00 and 0x80 + // only handle one by skipping 0x80 + if ( ep_addr == tu_edpt_addr(0, TUSB_DIR_IN_MASK) ) return; + uint8_t const epnum = tu_edpt_number(ep_addr); // Set force stall bit - UDP->UDP_CSR[epnum] |= UDP_CSR_FORCESTALL_Msk; + csr_set(epnum, UDP_CSR_FORCESTALL_Msk); } // clear stall, data toggle is also reset to DATA0 @@ -327,11 +347,11 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) uint8_t const epnum = tu_edpt_number(ep_addr); // clear stall - UDP->UDP_CSR[epnum] &= ~UDP_CSR_FORCESTALL_Msk; + csr_clear(epnum, UDP_CSR_FORCESTALL_Msk); // must also reset EP to clear data toggle - UDP->UDP_RST_EP = tu_bit_set(UDP->UDP_RST_EP, epnum); - UDP->UDP_RST_EP = tu_bit_clear(UDP->UDP_RST_EP, epnum); + UDP->UDP_RST_EP |= (1 << epnum); + UDP->UDP_RST_EP &= ~(1 << epnum); } //--------------------------------------------------------------------+ @@ -368,8 +388,10 @@ void dcd_int_handler(uint8_t rhport) if ( intr_status & TU_BIT(0) ) { + uint32_t csr0 = UDP->UDP_CSR[0]; + // setup packet - if (UDP->UDP_CSR[0] & UDP_CSR_RXSETUP) + if (csr0 & UDP_CSR_RXSETUP) { // get setup from FIFO uint8_t setup[8]; @@ -381,19 +403,31 @@ void dcd_int_handler(uint8_t rhport) // notify usbd dcd_event_setup_received(rhport, setup, true); + // Reset FIFO +// UDP->UDP_RST_EP |= (1 << 0); +// UDP->UDP_RST_EP &= ~(1 << 0); + + csr0 &= ~(UDP_CSR_TXPKTRDY_Msk | UDP_CSR_TXCOMP_Msk | UDP_CSR_RX_DATA_BK0 | UDP_CSR_RX_DATA_BK1); + // Set EP direction bit according to DATA stage - if (setup[0] & 0x80) + // must be set before RXSETUP is clear per specs + if ( tu_edpt_dir(setup[0]) ) { - UDP->UDP_CSR[0] |= UDP_CSR_DIR_Msk; - }else + //csr_set(0, UDP_CSR_DIR_Msk); + csr0 |= UDP_CSR_DIR_Msk; + } + else { - UDP->UDP_CSR[0] &= ~UDP_CSR_DIR_Msk; + //csr_clear(0, UDP_CSR_DIR_Msk); + csr0 &= ~UDP_CSR_DIR_Msk; } // Clear Setup bit & stall bit if needed - UDP->UDP_CSR[0] &= ~(UDP_CSR_RXSETUP_Msk | UDP_CSR_FORCESTALL_Msk); + //csr_clear(0, UDP_CSR_RXSETUP_Msk | UDP_CSR_FORCESTALL_Msk); + csr0 &= ~(UDP_CSR_RXSETUP_Msk | UDP_CSR_STALLSENT_Msk | UDP_CSR_FORCESTALL_Msk); - return; + UDP->UDP_CSR[0] = csr0; + for (uint32_t nop_count = 0; nop_count < 20; nop_count ++) __NOP(); } } @@ -416,21 +450,19 @@ void dcd_int_handler(uint8_t rhport) xact_ep_write(epnum, xfer->buffer, xact_len); // TX ready for transfer + //csr_set(epnum, UDP_CSR_TXPKTRDY_Msk); UDP->UDP_CSR[epnum] |= UDP_CSR_TXPKTRDY_Msk; }else { - // WALKAROUND: Skip reporting this incorrect DATA Toggle status IN transfer - if ( !(_walkaround_incorrect_dtoggle_control_status && (epnum == 0) && (xfer->actual_len == 0)) ) - { - // xfer is complete - dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true); - - // Required since control OUT can happen right after before stack handle this event - xfer_end(xfer); - } + // xfer is complete + dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true); + + // Required since control OUT can happen right after before stack handle this event + xfer_end(xfer); } // Clear TX Complete bit + //csr_clear(epnum, UDP_CSR_TXCOMP_Msk); UDP->UDP_CSR[epnum] &= ~UDP_CSR_TXCOMP_Msk; } @@ -456,12 +488,14 @@ void dcd_int_handler(uint8_t rhport) } // Clear DATA Bank0/1 bit + //csr_clear(epnum, banks_complete); UDP->UDP_CSR[epnum] &= ~banks_complete; } // Stall sent to host if (UDP->UDP_CSR[epnum] & UDP_CSR_STALLSENT_Msk) { + //csr_clear(epnum, UDP_CSR_STALLSENT_Msk); UDP->UDP_CSR[epnum] &= ~UDP_CSR_STALLSENT_Msk; } } -- cgit v1.3.1 From ac3c645dc114cfdbff4a232fecf35eb523d9b24f Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 2 May 2020 16:09:28 +0700 Subject: fix EP0 data toggle issue --- src/portable/microchip/samg/dcd_samg.c | 51 +++++++--------------------------- 1 file changed, 10 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 50abe349e..36f9b4832 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -295,19 +295,6 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_desc_t* xfer = &_dcd_xfer[epnum]; xfer_begin(xfer, buffer, total_bytes); - // Control Status Stage if EP0 with len = 0 and direction is opposite of current Data Stage - if ( (epnum == 0) && /*(total_bytes == 0) &&*/ (dir != ((UDP->UDP_CSR[epnum] & UDP_CSR_DIR_Msk) >> UDP_CSR_DIR_Pos)) ) - { - TU_LOG2_INT(dir); - if ( dir ) - { - csr_set(0, UDP_CSR_DIR_Msk); - }else - { - csr_clear(0, UDP_CSR_DIR_Msk); - } - } - if (dir == TUSB_DIR_OUT) { // Enable interrupt when starting OUT transfer @@ -388,10 +375,8 @@ void dcd_int_handler(uint8_t rhport) if ( intr_status & TU_BIT(0) ) { - uint32_t csr0 = UDP->UDP_CSR[0]; - // setup packet - if (csr0 & UDP_CSR_RXSETUP) + if ( UDP->UDP_CSR[0] & UDP_CSR_RXSETUP ) { // get setup from FIFO uint8_t setup[8]; @@ -403,31 +388,19 @@ void dcd_int_handler(uint8_t rhport) // notify usbd dcd_event_setup_received(rhport, setup, true); - // Reset FIFO -// UDP->UDP_RST_EP |= (1 << 0); -// UDP->UDP_RST_EP &= ~(1 << 0); - - csr0 &= ~(UDP_CSR_TXPKTRDY_Msk | UDP_CSR_TXCOMP_Msk | UDP_CSR_RX_DATA_BK0 | UDP_CSR_RX_DATA_BK1); - // Set EP direction bit according to DATA stage - // must be set before RXSETUP is clear per specs + // MUST only be set before RXSETUP is clear per specs if ( tu_edpt_dir(setup[0]) ) { - //csr_set(0, UDP_CSR_DIR_Msk); - csr0 |= UDP_CSR_DIR_Msk; + csr_set(0, UDP_CSR_DIR_Msk); } else { - //csr_clear(0, UDP_CSR_DIR_Msk); - csr0 &= ~UDP_CSR_DIR_Msk; + csr_clear(0, UDP_CSR_DIR_Msk); } - // Clear Setup bit & stall bit if needed - //csr_clear(0, UDP_CSR_RXSETUP_Msk | UDP_CSR_FORCESTALL_Msk); - csr0 &= ~(UDP_CSR_RXSETUP_Msk | UDP_CSR_STALLSENT_Msk | UDP_CSR_FORCESTALL_Msk); - - UDP->UDP_CSR[0] = csr0; - for (uint32_t nop_count = 0; nop_count < 20; nop_count ++) __NOP(); + // Clear Setup, stall and other on-going transfer bits + csr_clear(0, UDP_CSR_RXSETUP_Msk | UDP_CSR_TXPKTRDY_Msk | UDP_CSR_TXCOMP_Msk | UDP_CSR_RX_DATA_BK0 | UDP_CSR_RX_DATA_BK1 | UDP_CSR_STALLSENT_Msk | UDP_CSR_FORCESTALL_Msk); } } @@ -450,8 +423,7 @@ void dcd_int_handler(uint8_t rhport) xact_ep_write(epnum, xfer->buffer, xact_len); // TX ready for transfer - //csr_set(epnum, UDP_CSR_TXPKTRDY_Msk); - UDP->UDP_CSR[epnum] |= UDP_CSR_TXPKTRDY_Msk; + csr_set(epnum, UDP_CSR_TXPKTRDY_Msk); }else { // xfer is complete @@ -462,8 +434,7 @@ void dcd_int_handler(uint8_t rhport) } // Clear TX Complete bit - //csr_clear(epnum, UDP_CSR_TXCOMP_Msk); - UDP->UDP_CSR[epnum] &= ~UDP_CSR_TXCOMP_Msk; + csr_clear(epnum, UDP_CSR_TXCOMP_Msk); } //------------- Endpoint OUT -------------// @@ -488,15 +459,13 @@ void dcd_int_handler(uint8_t rhport) } // Clear DATA Bank0/1 bit - //csr_clear(epnum, banks_complete); - UDP->UDP_CSR[epnum] &= ~banks_complete; + csr_clear(epnum, banks_complete); } // Stall sent to host if (UDP->UDP_CSR[epnum] & UDP_CSR_STALLSENT_Msk) { - //csr_clear(epnum, UDP_CSR_STALLSENT_Msk); - UDP->UDP_CSR[epnum] &= ~UDP_CSR_STALLSENT_Msk; + csr_clear(epnum, UDP_CSR_STALLSENT_Msk); } } } -- cgit v1.3.1 From 3ad0cd041b7a741b29fd1463c852f907a5ade80a Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 2 May 2020 16:21:38 +0700 Subject: clean up --- src/portable/microchip/samg/dcd_samg.c | 63 ++++++++++++---------------------- 1 file changed, 22 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 36f9b4832..296973247 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -106,47 +106,28 @@ static void xact_ep_read(uint8_t epnum, uint8_t* buffer, uint16_t xact_len) //! Bitmap for all status bits in CSR that are not affected by a value 1. -#define UDP_REG_NO_EFFECT_1_ALL (UDP_CSR_RX_DATA_BK0 | UDP_CSR_RX_DATA_BK1 | UDP_CSR_STALLSENT | UDP_CSR_RXSETUP | UDP_CSR_TXCOMP) - -/*! Sets specified bit(s) in the UDP_CSR. -* \param ep -Endpoint number. -* \param bits Bitmap to set to 1. -*/ -#define csr_set(ep, bits) \ - do { \ - volatile uint32_t reg; \ - volatile uint32_t nop_count; \ - reg = UDP->UDP_CSR[ep]; \ - reg |= UDP_REG_NO_EFFECT_1_ALL; \ - reg |= (bits); \ - UDP->UDP_CSR[ep] = reg; \ - for (nop_count = 0; nop_count < 20; nop_count ++) {\ - __NOP(); \ - } \ - } while (0) - - -/*! Clears specified bit(s) in the UDP_CSR. -* \param ep -Endpoint number. -* \param bits Bitmap to set to 0. -*/ -#define csr_clear(ep, bits) \ - do { \ - volatile uint32_t reg; \ - volatile uint32_t nop_count; \ - reg = UDP->UDP_CSR[ep]; \ - reg |= UDP_REG_NO_EFFECT_1_ALL; \ - reg &= ~(bits); \ - UDP->UDP_CSR[ep] = reg; \ - for (nop_count = 0; nop_count < 20; nop_count ++) {\ - __NOP(); \ - } \ - } while (0) - -#define udp_clear_csr csr_clear -#define udp_set_csr csr_set +#define CSR_NO_EFFECT_1_ALL (UDP_CSR_RX_DATA_BK0 | UDP_CSR_RX_DATA_BK1 | UDP_CSR_STALLSENT | UDP_CSR_RXSETUP | UDP_CSR_TXCOMP) + +// Per Specs: CSR need synchronization each write +static inline void csr_set(uint8_t epnum, uint32_t mask) +{ + uint32_t const csr = UDP->UDP_CSR[epnum] | CSR_NO_EFFECT_1_ALL | mask; + UDP->UDP_CSR[epnum] = csr; + + volatile uint32_t nop_count; + for (nop_count = 0; nop_count < 20; nop_count ++) __NOP(); +} + +// Per Specs: CSR need synchronization each write +static inline void csr_clear(uint8_t epnum, uint32_t mask) +{ + uint32_t const csr = (UDP->UDP_CSR[epnum] | CSR_NO_EFFECT_1_ALL) & ~mask; + UDP->UDP_CSR[epnum] = csr; + + volatile uint32_t nop_count; + for (nop_count = 0; nop_count < 20; nop_count ++) __NOP(); +} + /*------------------------------------------------------------------*/ /* Device API *------------------------------------------------------------------*/ -- cgit v1.3.1 From 0e30afa6913a675a6034de6965788b9e64f42fb7 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 2 May 2020 18:24:23 +0700 Subject: abstract all UDP_CSR --- src/portable/microchip/samg/dcd_samg.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 296973247..4a8ed53f3 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -109,9 +109,9 @@ static void xact_ep_read(uint8_t epnum, uint8_t* buffer, uint16_t xact_len) #define CSR_NO_EFFECT_1_ALL (UDP_CSR_RX_DATA_BK0 | UDP_CSR_RX_DATA_BK1 | UDP_CSR_STALLSENT | UDP_CSR_RXSETUP | UDP_CSR_TXCOMP) // Per Specs: CSR need synchronization each write -static inline void csr_set(uint8_t epnum, uint32_t mask) +static inline void csr_write(uint8_t epnum, uint32_t value) { - uint32_t const csr = UDP->UDP_CSR[epnum] | CSR_NO_EFFECT_1_ALL | mask; + uint32_t const csr = value; UDP->UDP_CSR[epnum] = csr; volatile uint32_t nop_count; @@ -119,13 +119,15 @@ static inline void csr_set(uint8_t epnum, uint32_t mask) } // Per Specs: CSR need synchronization each write -static inline void csr_clear(uint8_t epnum, uint32_t mask) +static inline void csr_set(uint8_t epnum, uint32_t mask) { - uint32_t const csr = (UDP->UDP_CSR[epnum] | CSR_NO_EFFECT_1_ALL) & ~mask; - UDP->UDP_CSR[epnum] = csr; + csr_write(epnum, UDP->UDP_CSR[epnum] | CSR_NO_EFFECT_1_ALL | mask); +} - volatile uint32_t nop_count; - for (nop_count = 0; nop_count < 20; nop_count ++) __NOP(); +// Per Specs: CSR need synchronization each write +static inline void csr_clear(uint8_t epnum, uint32_t mask) +{ + csr_write(epnum, (UDP->UDP_CSR[epnum] | CSR_NO_EFFECT_1_ALL) & ~mask); } /*------------------------------------------------------------------*/ @@ -140,7 +142,7 @@ static void bus_reset(void) xfer_epsize_set(&_dcd_xfer[0], CFG_TUD_ENDPOINT0_SIZE); // Enable EP0 control - UDP->UDP_CSR[0] = UDP_CSR_EPEDS_Msk; + csr_write(0, UDP_CSR_EPEDS_Msk); // Enable interrupt : EP0, Suspend, Resume, Wakeup UDP->UDP_IER = UDP_IER_EP0INT_Msk | UDP_IER_RXSUSP_Msk | UDP_IER_RXRSM_Msk | UDP_IER_WAKEUP_Msk; @@ -257,7 +259,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) xfer_epsize_set(&_dcd_xfer[epnum], ep_desc->wMaxPacketSize.size); // Configure type and enable EP - UDP->UDP_CSR[epnum] = UDP_CSR_EPEDS_Msk | UDP_CSR_EPTYPE(ep_desc->bmAttributes.xfer + 4*dir); + csr_write(epnum, UDP_CSR_EPEDS_Msk | UDP_CSR_EPTYPE(ep_desc->bmAttributes.xfer + 4*dir)); // Enable EP Interrupt for IN if (dir == TUSB_DIR_IN) UDP->UDP_IER |= (1 << epnum); -- cgit v1.3.1 From 4a3a44834048006b05d82d32e1f69be856554d4d Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 4 May 2020 00:29:52 +0700 Subject: clean up things, add makefile for host example --- examples/host/cdc_msc_hid/Makefile | 22 +++++++ .../host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject | 21 +++--- .../host/cdc_msc_hid/ses/lpc43xx/lpc43xx.emProject | 19 ++++-- examples/host/cdc_msc_hid/src/main.c | 2 +- examples/host/cdc_msc_hid/src/tusb_config.h | 15 +---- hw/bsp/ea4357/ea4357.c | 15 +++-- hw/bsp/mcb1800/mcb1800.c | 77 +++++++++++----------- src/class/cdc/cdc_host.c | 1 - src/host/ehci/ehci.c | 6 +- test/test/support/tusb_config.h | 10 +-- 10 files changed, 107 insertions(+), 81 deletions(-) create mode 100644 examples/host/cdc_msc_hid/Makefile (limited to 'src') diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile new file mode 100644 index 000000000..20cd7ba69 --- /dev/null +++ b/examples/host/cdc_msc_hid/Makefile @@ -0,0 +1,22 @@ +include ../../../tools/top.mk +include ../../make.mk + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + + +# TinyUSB Host Stack source +SRC_C += \ + src/host/usbh.c \ + src/host/hub.c \ + src/host/ehci/ehci.c \ + src/class/cdc/cdc_host.c \ + src/host/ehci/ehci.c \ + src/portable/nxp/lpc18_43/hcd_lpc18_43.c + +include ../../rules.mk diff --git a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject index 2dd7de552..2b68bfa23 100644 --- a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject +++ b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject @@ -17,8 +17,8 @@ arm_target_debug_interface_type="ADIv5" arm_target_device_name="LPC1857" arm_target_interface_type="SWD" - c_preprocessor_definitions="LPC18xx;__LPC1800_FAMILY;__LPC185x_SUBFAMILY;ARM_MATH_CM3;FLASH_PLACEMENT=1;CORE_M3;BOARD_MCB1800;CFG_TUSB_MCU=OPT_MCU_LPC18XX;CFG_TUSB_MEM_SECTION= __attribute__((section(".bss2")))" - c_user_include_directories="../../src;$(rootDir)/hw;$(rootDir)/src;$(lpcDir)//inc;$(lpcDir)//inc/config_18xx" + c_preprocessor_definitions="LPC18xx;__LPC1800_FAMILY;__LPC185x_SUBFAMILY;ARM_MATH_CM3;FLASH_PLACEMENT=1;CORE_M3;BOARD_MCB1800;CFG_TUSB_MCU=OPT_MCU_LPC18XX;CFG_TUSB_MEM_SECTION= __attribute__((section(".bss2")));CFG_TUSB_DEBUG=2" + c_user_include_directories="../../src;$(rootDir)/hw;$(rootDir)/src;$(lpcDir)//inc;$(lpcDir)//inc/config_18xx;$(rootDir)/lib/SEGGER_RTT/RTT" debug_register_definition_file="$(ProjectDir)/LPC18xx_Registers.xml" debug_target_connection="J-Link" gcc_entry_point="Reset_Handler" @@ -101,12 +101,6 @@ - + + + + + + + + + + + - + + + + + + + + + + + diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 0fbbd4534..6f5df1250 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -193,7 +193,7 @@ void print_greeting(void) printf("- issue at https://github.com/hathach/tinyusb\n"); printf("--------------------------------------------------------------------\n\n"); - printf("This Host demo is configured to support:"); + printf("This Host demo is configured to support:\r\n"); printf(" - RTOS = %s\n", rtos_name[CFG_TUSB_OS]); // if (CFG_TUH_CDC ) puts(" - Communication Device Class"); // if (CFG_TUH_MSC ) puts(" - Mass Storage"); diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index aa259dafd..235402180 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -75,23 +75,10 @@ #define CFG_TUH_HID_MOUSE 0 #define CFG_TUSB_HOST_HID_GENERIC 0 // (not yet supported) #define CFG_TUH_MSC 0 +#define CFG_TUH_VENDOR 0 #define CFG_TUSB_HOST_DEVICE_MAX (CFG_TUH_HUB ? 5 : 1) // normal hub has 4 ports -//------------- CLASS -------------// -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_HID 0 -#define CFG_TUD_VENDOR 0 - -// CDC FIFO size of TX and RX -#define CFG_TUD_CDC_RX_BUFSIZE 64 -#define CFG_TUD_CDC_TX_BUFSIZE 64 - -// MSC Buffer size of Device Mass storage -#define CFG_TUD_MSC_BUFSIZE 512 - - #ifdef __cplusplus } #endif diff --git a/hw/bsp/ea4357/ea4357.c b/hw/bsp/ea4357/ea4357.c index 30d899f69..193e19831 100644 --- a/hw/bsp/ea4357/ea4357.c +++ b/hw/bsp/ea4357/ea4357.c @@ -63,7 +63,7 @@ const uint32_t ExtRateIn = 0; static const PINMUX_GRP_T pinmuxing[] = { - // Button + // Button ( Joystick down ) {0x9, 1, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLUP)}, // UART @@ -139,21 +139,26 @@ void board_init(void) USBMODE_VBUS_HIGH = 1 }; - /* USB0 - * For USB0 Device operation: - * - insert jumpers in position 1-2 in JP17/JP18/JP19. + /* From EA4357 user manual + * + * USB0 Device operation: + * - Insert jumpers in position 1-2 in JP17/JP18/JP19. * - GPIO28 controls USB connect functionality * - LED32 lights when the USB Device is connected. SJ4 has pads 1-2 shorted by default. * - LED33 is controlled by GPIO27 and signals USB-up state. GPIO54 is used for VBUS * sensing. * - * For USB0 Host operation: + * USB0 Host operation: * - insert jumpers in position 2-3 in JP17/JP18/JP19. * - USB Host power is controlled via distribution switch U20 (found in schematic page 11). * - Signal GPIO26 is active low and enables +5V on VBUS2. * - LED35 light whenever +5V is present on VBUS2. * - GPIO55 is connected to status feedback from the distribution switch. * - GPIO54 is used for VBUS sensing. 15Kohm pull-down resistors are always active + * + * Note: + * - Insert jumpers in position 2-3 in JP17/JP18/JP19 + * - Insert jumpers in JP31 (OTG) */ #if CFG_TUSB_RHPORT0_MODE Chip_USB0_Init(); diff --git a/hw/bsp/mcb1800/mcb1800.c b/hw/bsp/mcb1800/mcb1800.c index 075210c85..fdbe389a3 100644 --- a/hw/bsp/mcb1800/mcb1800.c +++ b/hw/bsp/mcb1800/mcb1800.c @@ -76,30 +76,27 @@ const uint32_t ExtRateIn = 0; static const PINMUX_GRP_T pinmuxing[] = { - // LEDs - {0xD, 10, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4)}, - {0xD, 11, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN)}, - {0xD, 12, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN)}, - {0xD, 13, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN)}, - {0xD, 14, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN)}, - {0x9, 0, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN)}, - {0x9, 1, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN)}, - {0x9, 2, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN)}, - - // Button - {0x4, 0, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLUP)}, - - // UART - {UART_PORT, UART_PIN_TX, SCU_MODE_PULLDOWN | SCU_MODE_FUNC2 }, - {UART_PORT, UART_PIN_RX, SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_FUNC2 }, - - /* I2S */ - {0x3, 0, (SCU_PINIO_FAST | SCU_MODE_FUNC2)}, - {0x6, 0, (SCU_PINIO_FAST | SCU_MODE_FUNC4)}, - {0x7, 2, (SCU_PINIO_FAST | SCU_MODE_FUNC2)}, - {0x6, 2, (SCU_PINIO_FAST | SCU_MODE_FUNC3)}, - {0x7, 1, (SCU_PINIO_FAST | SCU_MODE_FUNC2)}, - {0x6, 1, (SCU_PINIO_FAST | SCU_MODE_FUNC3)}, + // LEDs + { 0xD, 10, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4) }, + { 0xD, 11, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN) }, + { 0xD, 12, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN) }, + { 0xD, 13, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN) }, + { 0xD, 14, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN) }, + { 0x9, 0, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN) }, + { 0x9, 1, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN) }, + { 0x9, 2, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN) }, + + // Button + { 0x4, 0, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLUP) }, + + // UART + { UART_PORT, UART_PIN_TX, SCU_MODE_PULLDOWN | SCU_MODE_FUNC2 }, + { UART_PORT, UART_PIN_RX, SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_FUNC2 }, + + // USB + { 0x9, 5, SCU_MODE_PULLUP | SCU_MODE_INBUFF_EN | SCU_MODE_FUNC2 }, // P9_5 USB1_VBUS_EN, USB1 VBus function + { 0x2, 5, SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_FUNC2 }, // P2_5 USB1_VBUS, MUST CONFIGURE THIS SIGNAL FOR USB1 NORMAL OPERATION */ + { 0x6, 3, SCU_MODE_PULLUP | SCU_MODE_INBUFF_EN | SCU_MODE_FUNC1 } // P6_3 USB0_PWR_EN, USB0 VBus function }; /* Pin clock mux values, re-used structure, value in first index is meaningless */ @@ -147,10 +144,10 @@ void board_init(void) Chip_GPIO_SetPinDIRInput(LPC_GPIO_PORT, BUTTON_PORT, BUTTON_PIN); //------------- UART -------------// - Chip_UART_Init(UART_DEV); - Chip_UART_SetBaud(UART_DEV, CFG_BOARD_UART_BAUDRATE); - Chip_UART_ConfigData(UART_DEV, UART_LCR_WLEN8 | UART_LCR_SBS_1BIT | UART_LCR_PARITY_DIS); - Chip_UART_TXEnable(UART_DEV); + Chip_UART_Init(UART_DEV); + Chip_UART_SetBaud(UART_DEV, CFG_BOARD_UART_BAUDRATE); + Chip_UART_ConfigData(UART_DEV, UART_LCR_WLEN8 | UART_LCR_SBS_1BIT | UART_LCR_PARITY_DIS); + Chip_UART_TXEnable(UART_DEV); //------------- USB -------------// enum { @@ -167,17 +164,19 @@ void board_init(void) #if CFG_TUSB_RHPORT0_MODE Chip_USB0_Init(); -// // Reset controller -// LPC_USB0->USBCMD_D |= 0x02; -// while( LPC_USB0->USBCMD_D & 0x02 ) {} -// -// // Set mode -// #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST -// LPC_USB0->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5); -// #else // TODO OTG -// LPC_USB0->USBMODE_D = USBMODE_DEVICE; -// LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/; -// #endif + // Host/Device mode can only be set right after controller reset + LPC_USB0->USBCMD_D |= 0x02; + while( LPC_USB0->USBCMD_D & 0x02 ) {} + + // Set mode + #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST + LPC_USB0->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5); + + LPC_USB0->PORTSC1_D |= (1<<24); // FIXME force full speed for debugging + #else // TODO OTG + LPC_USB0->USBMODE_D = USBMODE_DEVICE; + LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/; + #endif #endif // USB1 diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 5e45e8f6b..6b36ea94d 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -86,7 +86,6 @@ 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_NONE <= cdch_data[dev_addr-1].itf_protocol) && (cdch_data[dev_addr-1].itf_protocol <= CDC_COMM_PROTOCOL_ATCOMMAND_CDMA); } diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 9ddffaf2c..bbad072bf 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -358,7 +358,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const if ( dev_addr == 0 ) return true; // Insert to list - ehci_link_t * list_head; + ehci_link_t * list_head = NULL; switch (ep_desc->bmAttributes.xfer) { @@ -378,8 +378,10 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const default: break; } + TU_ASSERT(list_head); + // TODO might need to disable async/period list - list_insert( list_head, (ehci_link_t*) p_qhd, EHCI_QTYPE_QHD); + list_insert(list_head, (ehci_link_t*) p_qhd, EHCI_QTYPE_QHD); return true; } diff --git a/test/test/support/tusb_config.h b/test/test/support/tusb_config.h index 5258513ec..578c4126f 100644 --- a/test/test/support/tusb_config.h +++ b/test/test/support/tusb_config.h @@ -43,10 +43,12 @@ #define CFG_TUSB_MCU OPT_MCU_NRF5X #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) -#else -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE +#ifndef CFG_TUSB_RHPORT0_MODE + #if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) + #else + #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + #endif #endif #define CFG_TUSB_OS OPT_OS_NONE -- cgit v1.3.1 From fd69cc3dcc453b2a14d9e4f71f6acc6627e826d2 Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Mon, 4 May 2020 07:59:13 +0200 Subject: clean up renaming function and variables changing indent size --- src/portable/st/synopsys/dcd_synopsys.c | 80 ++++++++++++++++----------------- 1 file changed, 40 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 6686c1704..717a59db6 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -539,29 +539,29 @@ static void receive_packet(xfer_ctl_t * xfer, /* USB_OTG_OUTEndpointTypeDef * ou } // Write a single data packet to EPIN FIFO -static void transmit_fifo_packet(uint8_t fifo_num, uint8_t * src, uint16_t len){ - usb_fifo_t tx_fifo = FIFO_BASE(fifo_num); - - // Pushing full available 32 bit words to fifo - uint16_t full_words = len >> 2; - for(uint16_t i = 0; i < full_words; i++){ - *tx_fifo = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0]; - src += 4; - } - - // Write the remaining 1-3 bytes into fifo - uint8_t bytes_rem = len & 0x03; - if(bytes_rem){ - uint32_t tmp_word = 0; - tmp_word |= src[0]; - if(bytes_rem > 1){ - tmp_word |= src[1] << 8; - } - if(bytes_rem > 2){ - tmp_word |= src[2] << 16; - } - *tx_fifo = tmp_word; - } +static void write_fifo_packet(uint8_t fifo_num, uint8_t * src, uint16_t len){ + usb_fifo_t tx_fifo = FIFO_BASE(fifo_num); + + // Pushing full available 32 bit words to fifo + uint16_t full_words = len >> 2; + for(uint16_t i = 0; i < full_words; i++){ + *tx_fifo = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0]; + src += 4; + } + + // Write the remaining 1-3 bytes into fifo + uint8_t bytes_rem = len & 0x03; + if(bytes_rem){ + uint32_t tmp_word = 0; + tmp_word |= src[0]; + if(bytes_rem > 1){ + tmp_word |= src[1] << 8; + } + if(bytes_rem > 2){ + tmp_word |= src[2] << 16; + } + *tx_fifo = tmp_word; + } } static void read_rx_fifo(USB_OTG_OUTEndpointTypeDef * out_ep) { @@ -652,6 +652,7 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType if ( dev->DAINT & (1 << (USB_OTG_DAINT_IEPINT_Pos + n)) ) { + // IN XFER complete (entire xfer). if ( in_ep[n].DIEPINT & USB_OTG_DIEPINT_XFRC ) { @@ -667,27 +668,26 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType // - 64 bytes or // - Half of TX FIFO size (configured by DIEPTXF) - // Packets to be processed - uint16_t tx_packet_amount = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_PKTCNT_Msk) >> USB_OTG_DIEPTSIZ_PKTCNT_Pos; + uint16_t remaining_packets = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_PKTCNT_Msk) >> USB_OTG_DIEPTSIZ_PKTCNT_Pos; - // Process every single packet (only whole packets can be written to fifo) - for(uint16_t i = 0; i < tx_packet_amount; i++){ - // amount of bytes EP still needs to transfer - uint16_t tx_remaining = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos; - // Packet can not be larger than ep max size - uint16_t packet_size = (tx_remaining > xfer->max_size) ? xfer->max_size : tx_remaining; + // Process every single packet (only whole packets can be written to fifo) + for(uint16_t i = 0; i < remaining_packets; i++){ + uint16_t remaining_bytes = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos; + // Packet can not be larger than ep max size + uint16_t packet_size = tu_min16(remaining_bytes, xfer->max_size); - // It's only possible to write full packets into FIFO. Therefore DTXFSTS register of current - // EP has to be checked if the buffer can take another WHOLE packet - if(packet_size > ((in_ep[n].DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV_Msk) << 2)){ - break; - } + // It's only possible to write full packets into FIFO. Therefore DTXFSTS register of current + // EP has to be checked if the buffer can take another WHOLE packet + if(packet_size > ((in_ep[n].DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV_Msk) << 2)){ + break; + } - xfer->queued_len = xfer->total_len - tx_remaining; + // TODO: queued_len can be removed later + xfer->queued_len = xfer->total_len - remaining_bytes; - // Push packet to Tx-FIFO - transmit_fifo_packet(n, (xfer->buffer + xfer->queued_len), packet_size); - } + // Push packet to Tx-FIFO + write_fifo_packet(n, (xfer->buffer + xfer->queued_len), packet_size); + } // Turn off TXFE if all bytes are written. if (((in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos) == 0) -- cgit v1.3.1 From 905a80d1b2de5e8ad67b3687ffd0543d90ac904e Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 4 May 2020 14:11:58 +0700 Subject: temporarily remove osal_task_delay() from osal - add hcd_uframe_number() API, update EHCI to return uframe number - get host running on ea4357 --- examples/host/cdc_msc_hid/src/tusb_config.h | 2 +- hw/bsp/ea4357/board.mk | 4 ++-- hw/bsp/ea4357/ea4357.c | 26 +++++++++++++------------- hw/bsp/mcb1800/mcb1800.c | 25 +++++++++++++------------ src/host/ehci/ehci.c | 13 ++++++++++++- src/host/ehci/ehci.h | 6 ++++-- src/host/hcd.h | 9 +++++++++ src/host/usbh.c | 9 +++++++++ src/osal/osal.h | 2 +- src/osal/osal_none.h | 16 ++++++++-------- 10 files changed, 72 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 235402180..a929e36d8 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -69,7 +69,7 @@ // CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUH_HUB 1 +#define CFG_TUH_HUB 0 #define CFG_TUH_CDC 1 #define CFG_TUH_HID_KEYBOARD 0 #define CFG_TUH_HID_MOUSE 0 diff --git a/hw/bsp/ea4357/board.mk b/hw/bsp/ea4357/board.mk index dc002215b..dd987f476 100644 --- a/hw/bsp/ea4357/board.mk +++ b/hw/bsp/ea4357/board.mk @@ -6,9 +6,9 @@ CFLAGS += \ -mfloat-abi=hard \ -mfpu=fpv4-sp-d16 \ -nostdlib \ + -D__USE_LPCOPEN \ -DCORE_M4 \ - -DCFG_TUSB_MCU=OPT_MCU_LPC43XX \ - -D__USE_LPCOPEN + -DCFG_TUSB_MCU=OPT_MCU_LPC43XX # mcu driver cause following warnings CFLAGS += -Wno-error=unused-parameter -Wno-error=strict-prototypes diff --git a/hw/bsp/ea4357/ea4357.c b/hw/bsp/ea4357/ea4357.c index 193e19831..daa3a6bd0 100644 --- a/hw/bsp/ea4357/ea4357.c +++ b/hw/bsp/ea4357/ea4357.c @@ -163,19 +163,19 @@ void board_init(void) #if CFG_TUSB_RHPORT0_MODE Chip_USB0_Init(); -// // Reset controller -// LPC_USB0->USBCMD_D |= 0x02; -// while( LPC_USB0->USBCMD_D & 0x02 ) {} -// -// // Set mode -// #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST -// LPC_USB0->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5); -// -// LPC_USB0->PORTSC1_D |= (1<<24); // FIXME force full speed for debugging -// #else // TODO OTG -// LPC_USB0->USBMODE_D = USBMODE_DEVICE; -// LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/; -// #endif + // Reset controller + LPC_USB0->USBCMD_D |= 0x02; + while( LPC_USB0->USBCMD_D & 0x02 ) {} + + // Set mode + #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST + LPC_USB0->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5); + + LPC_USB0->PORTSC1_D |= (1<<24); // FIXME force full speed for debugging + #else // TODO OTG + LPC_USB0->USBMODE_D = USBMODE_DEVICE; + LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/; + #endif #endif /* USB1 diff --git a/hw/bsp/mcb1800/mcb1800.c b/hw/bsp/mcb1800/mcb1800.c index fdbe389a3..bfeb126fc 100644 --- a/hw/bsp/mcb1800/mcb1800.c +++ b/hw/bsp/mcb1800/mcb1800.c @@ -82,9 +82,9 @@ static const PINMUX_GRP_T pinmuxing[] = { 0xD, 12, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN) }, { 0xD, 13, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN) }, { 0xD, 14, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC4 | SCU_MODE_PULLDOWN) }, - { 0x9, 0, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN) }, - { 0x9, 1, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN) }, - { 0x9, 2, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN) }, + { 0x9, 0, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN) }, + { 0x9, 1, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN) }, + { 0x9, 2, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLDOWN) }, // Button { 0x4, 0, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLUP) }, @@ -93,19 +93,20 @@ static const PINMUX_GRP_T pinmuxing[] = { UART_PORT, UART_PIN_TX, SCU_MODE_PULLDOWN | SCU_MODE_FUNC2 }, { UART_PORT, UART_PIN_RX, SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_FUNC2 }, - // USB - { 0x9, 5, SCU_MODE_PULLUP | SCU_MODE_INBUFF_EN | SCU_MODE_FUNC2 }, // P9_5 USB1_VBUS_EN, USB1 VBus function - { 0x2, 5, SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_FUNC2 }, // P2_5 USB1_VBUS, MUST CONFIGURE THIS SIGNAL FOR USB1 NORMAL OPERATION */ - { 0x6, 3, SCU_MODE_PULLUP | SCU_MODE_INBUFF_EN | SCU_MODE_FUNC1 } // P6_3 USB0_PWR_EN, USB0 VBus function + // USB0 + { 0x6, 3, SCU_MODE_PULLUP | SCU_MODE_INBUFF_EN | SCU_MODE_FUNC1 }, // P6_3 USB0_PWR_EN, USB0 VBus function + + { 0x9, 5, SCU_MODE_PULLUP | SCU_MODE_INBUFF_EN | SCU_MODE_FUNC2 }, // P9_5 USB1_VBUS_EN, USB1 VBus function + { 0x2, 5, SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_FUNC2 }, // P2_5 USB1_VBUS, MUST CONFIGURE THIS SIGNAL FOR USB1 NORMAL OPERATION }; /* Pin clock mux values, re-used structure, value in first index is meaningless */ static const PINMUX_GRP_T pinclockmuxing[] = { - {0, 0, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_HIGHSPEEDSLEW_EN | SCU_MODE_FUNC0)}, - {0, 1, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_HIGHSPEEDSLEW_EN | SCU_MODE_FUNC0)}, - {0, 2, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_HIGHSPEEDSLEW_EN | SCU_MODE_FUNC0)}, - {0, 3, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_HIGHSPEEDSLEW_EN | SCU_MODE_FUNC0)}, + { 0, 0, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_HIGHSPEEDSLEW_EN | SCU_MODE_FUNC0)}, + { 0, 1, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_HIGHSPEEDSLEW_EN | SCU_MODE_FUNC0)}, + { 0, 2, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_HIGHSPEEDSLEW_EN | SCU_MODE_FUNC0)}, + { 0, 3, (SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_HIGHSPEEDSLEW_EN | SCU_MODE_FUNC0)}, }; // Invoked by startup code @@ -172,7 +173,7 @@ void board_init(void) #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST LPC_USB0->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5); - LPC_USB0->PORTSC1_D |= (1<<24); // FIXME force full speed for debugging +// LPC_USB0->PORTSC1_D |= (1<<24); // FIXME force full speed for debugging #else // TODO OTG LPC_USB0->USBMODE_D = USBMODE_DEVICE; LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/; diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index bbad072bf..048affb1e 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -108,6 +108,12 @@ bool hcd_init(void) return ehci_init(TUH_OPT_RHPORT); } +uint32_t hcd_uframe_number(uint8_t rhport) +{ + (void) rhport; + return ehci_data.uframe_number + ehci_data.regs->frame_index; +} + void hcd_port_reset(uint8_t rhport) { (void) rhport; @@ -192,7 +198,7 @@ static bool ehci_init(uint8_t rhport) regs->status = EHCI_INT_MASK_ALL; // 2. clear all status regs->inten = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE | EHCI_INT_MASK_ASYNC_ADVANCE | - EHCI_INT_MASK_NXP_PERIODIC | EHCI_INT_MASK_NXP_ASYNC ; + EHCI_INT_MASK_NXP_PERIODIC | EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_FRAMELIST_ROLLOVER; //------------- Asynchronous List -------------// ehci_qhd_t * const async_head = qhd_async_head(rhport); @@ -636,6 +642,11 @@ void hcd_isr(uint8_t rhport) if (int_status == 0) return; + if (int_status & EHCI_INT_MASK_FRAMELIST_ROLLOVER) + { + ehci_data.uframe_number += (EHCI_FRAMELIST_SIZE << 3); + } + if (int_status & EHCI_INT_MASK_PORT_CHANGE) { uint32_t port_status = regs->portsc & EHCI_PORTSC_MASK_ALL; diff --git a/src/host/ehci/ehci.h b/src/host/ehci/ehci.h index ce2f56771..f11c4536a 100644 --- a/src/host/ehci/ehci.h +++ b/src/host/ehci/ehci.h @@ -54,8 +54,8 @@ //--------------------------------------------------------------------+ // EHCI CONFIGURATION & CONSTANTS //--------------------------------------------------------------------+ -#define EHCI_CFG_FRAMELIST_SIZE_BITS 7 /// Framelist Size (NXP specific) (0:1024) - (1:512) - (2:256) - (3:128) - (4:64) - (5:32) - (6:16) - (7:8) -#define EHCI_FRAMELIST_SIZE (1024 >> EHCI_CFG_FRAMELIST_SIZE_BITS) +#define EHCI_CFG_FRAMELIST_SIZE_BITS 7 /// Framelist Size (NXP specific) (0:1024) - (1:512) - (2:256) - (3:128) - (4:64) - (5:32) - (6:16) - (7:8) +#define EHCI_FRAMELIST_SIZE (1024 >> EHCI_CFG_FRAMELIST_SIZE_BITS) // TODO merge OHCI with EHCI enum { @@ -445,6 +445,8 @@ typedef struct ehci_qtd_t qtd_pool[HCD_MAX_XFER] TU_ATTR_ALIGNED(32); ehci_registers_t* regs; + + volatile uint32_t uframe_number; }ehci_data_t; #ifdef __cplusplus diff --git a/src/host/hcd.h b/src/host/hcd.h index a39e7fe16..d9307ca09 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -91,6 +91,15 @@ void hcd_isr(uint8_t hostid); void hcd_int_enable (uint8_t rhport); void hcd_int_disable(uint8_t rhport); +// Get micro frame number (125 us) +uint32_t hcd_uframe_number(uint8_t rhport); + +// Get frame number (1ms) +static inline uint32_t hcd_frame_number(uint8_t rhport) +{ + return hcd_uframe_number(rhport) >> 3; +} + // PORT API /// return the current connect status of roothub port bool hcd_port_connect_status(uint8_t hostid); diff --git a/src/host/usbh.c b/src/host/usbh.c index f1b88259c..7171f6bab 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -127,6 +127,15 @@ tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr) return (tusb_device_state_t) _usbh_devices[dev_addr].state; } + +static inline void osal_task_delay(uint32_t msec) +{ + (void) msec; + + uint32_t start = hcd_frame_number(TUH_OPT_RHPORT); + while ( ( hcd_frame_number(TUH_OPT_RHPORT) - start ) < msec ) {} +} + //--------------------------------------------------------------------+ // CLASS-USBD API (don't require to verify parameters) //--------------------------------------------------------------------+ diff --git a/src/osal/osal.h b/src/osal/osal.h index 0421b3294..02dcf5367 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -62,7 +62,7 @@ typedef void (*osal_task_func_t)( void * ); //--------------------------------------------------------------------+ // OSAL Porting API //--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec); +//static inline void osal_task_delay(uint32_t msec); //------------- Semaphore -------------// static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef); diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index b27e628a9..e7ce18079 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -34,14 +34,14 @@ //--------------------------------------------------------------------+ // TASK API //--------------------------------------------------------------------+ -static inline void osal_task_delay(uint32_t msec) -{ - (void) msec; - // TODO only used by Host stack, will implement using SOF - -// uint32_t start = tusb_hal_millis(); -// while ( ( tusb_hal_millis() - start ) < msec ) {} -} +//static inline void osal_task_delay(uint32_t msec) +//{ +// (void) msec; +// // TODO only used by Host stack, will implement using SOF +// +//// uint32_t start = tusb_hal_millis(); +//// while ( ( tusb_hal_millis() - start ) < msec ) {} +//} //--------------------------------------------------------------------+ // Binary Semaphore API -- cgit v1.3.1 From 58b99e59d44197c32cf68e730f67563f28382d2e Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 5 May 2020 23:07:56 +0700 Subject: detect if SD is actually present on the flash using SD magic even with SOFTDEVICE_PRESENT defined, SD may not be present on actual flash. --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 12435ea23..d788547b8 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -32,13 +32,6 @@ #include "nrf_clock.h" #include "nrf_power.h" #include "nrfx_usbd_errata.h" - -#ifdef SOFTDEVICE_PRESENT -// For enable/disable hfclk with SoftDevice -#include "nrf_sdm.h" -#include "nrf_soc.h" -#endif - #include "device/dcd.h" // TODO remove later @@ -564,9 +557,26 @@ void dcd_int_handler(uint8_t rhport) // HFCLK helper //--------------------------------------------------------------------+ #ifdef SOFTDEVICE_PRESENT -// check if SD is present and enabled -static bool is_sd_enabled(void) + +// For enable/disable hfclk with SoftDevice +#include "nrf_mbr.h" +#include "nrf_sdm.h" +#include "nrf_soc.h" + +#ifndef SD_MAGIC_NUMBER + #define SD_MAGIC_NUMBER 0x51B1E5DB +#endif + +static inline bool is_sd_existed(void) { + return *((uint32_t*)(SOFTDEVICE_INFO_STRUCT_ADDRESS+4)) == SD_MAGIC_NUMBER; +} + +// check if SD is existed and enabled +static inline bool is_sd_enabled(void) +{ + if ( !is_sd_existed() ) return false; + uint8_t sd_en = false; (void) sd_softdevice_is_enabled(&sd_en); return sd_en; -- cgit v1.3.1 From 63bd8d2e44225341caae6dafb2affb1fe711a9b4 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Thu, 7 May 2020 19:00:41 +0800 Subject: device: fix build warning when CFG_TUSB_DEBUG >= 2 The function is defined inside of a function body which generates a warning. Circuit Python treats these warnings as errors, and so refuses to build with debugging enabled: ../../lib/tinyusb/src/device/usbd_control.c: In function 'usbd_control_xfer_cb': ../../lib/tinyusb/src/device/usbd_control.c:195:19: error: nested extern declaration of 'usbd_driver_print_control_complete_name' [-Werror=nested-externs] 195 | extern void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const *)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors make: *** [../../py/mkrules.mk:55: build-simmel/lib/tinyusb/src/device/usbd_control.o] Error 1 Move the declaration to the top of the function to silence this warning. Signed-off-by: Sean Cross --- src/device/usbd_control.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 353a66ad1..db0eb70a7 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -32,6 +32,10 @@ #include "device/usbd_pvt.h" #include "dcd.h" +#if CFG_TUSB_DEBUG >= 2 +extern void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const *)); +#endif + enum { EDPT_CTRL_OUT = 0x00, @@ -192,7 +196,6 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result if ( _ctrl_xfer.complete_cb ) { #if CFG_TUSB_DEBUG >= 2 - extern void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const *)); usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); #endif -- cgit v1.3.1 From eeb076454b8e9b91654f0de3ce565e4f1c1967af Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 May 2020 12:56:32 +0700 Subject: add CFG_TUSB_DEBUG_PRINTF() for log retargeting --- src/common/tusb_common.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 052caef21..2389bfcd4 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -215,8 +215,11 @@ static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value void tu_print_mem(void const *buf, uint16_t count, uint8_t indent); -#ifndef tu_printf - #define tu_printf printf +#ifdef CFG_TUSB_DEBUG_PRINTF + extern int CFG_TUSB_DEBUG_PRINTF(const char *format, ...); + #define tu_printf CFG_TUSB_DEBUG_PRINTF +#else + #define tu_printf printf #endif static inline -- cgit v1.3.1 From f02ad1d0dcbbad57ccb8308d09843b8f688bcceb Mon Sep 17 00:00:00 2001 From: Mengsk Date: Fri, 8 May 2020 13:29:33 +0200 Subject: Add IAR compiler attribute and endian support. --- src/common/tusb_compiler.h | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index e403c749b..6f6aa3c39 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -99,7 +99,26 @@ #define TU_BSWAP16(u16) (__builtin_bswap16(u16)) #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) -#else +#elif defined(__ICCARM__) + #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) + #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) + #define TU_ATTR_PACKED __attribute__ ((packed)) + #define TU_ATTR_PREPACKED + #define TU_ATTR_WEAK __attribute__ ((weak)) + #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used + #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused + #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used + + // Endian conversion use well-known host to network (big endian) naming + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #define TU_BYTE_ORDER TU_LITTLE_ENDIAN + #else + #define TU_BYTE_ORDER TU_BIG_ENDIAN + #endif + + #define TU_BSWAP16(u16) (__iar_builtin_REV16(u16)) + #define TU_BSWAP32(u32) (__iar_builtin_REV(u32)) +#else #error "Compiler attribute porting is required" #endif -- cgit v1.3.1 From 3401e0f6ff419888282e8ce75768bd47b630b674 Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Fri, 8 May 2020 18:10:48 +0200 Subject: Synopsys OUT EP improvements: - Use register based XFRSIZ to determine transfer complete (xfer->queued_len and xfer->short_packet were deleted) - Pop out as many RxFIFO data entries as available within a IRQ call - less application interruption due to XFRC calls --- src/portable/st/synopsys/dcd_synopsys.c | 126 ++++++++++---------------------- 1 file changed, 40 insertions(+), 86 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 717a59db6..149919d54 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -101,9 +101,7 @@ static uint8_t _setup_offs; // We store up to 3 setup packets. typedef struct { uint8_t * buffer; uint16_t total_len; - uint16_t queued_len; uint16_t max_size; - bool short_packet; } xfer_ctl_t; typedef volatile uint32_t * usb_fifo_t; @@ -356,8 +354,6 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->buffer = buffer; xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->short_packet = false; uint16_t num_packets = (total_bytes / xfer->max_size); uint8_t short_packet_size = total_bytes % xfer->max_size; @@ -379,9 +375,10 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t dev->DIEPEMPMSK |= (1 << epnum); } } else { - // Each complete packet for OUT xfers triggers XFRC. - out_ep[epnum].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | - ((xfer->max_size & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) << USB_OTG_DOEPTSIZ_XFRSIZ_Pos); + // A full OUT transfer (multiple packets, possibly) triggers XFRC. + out_ep[epnum].DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT_Msk | USB_OTG_DOEPTSIZ_XFRSIZ); + out_ep[epnum].DOEPTSIZ |= (num_packets << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | + ((total_bytes << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) & USB_OTG_DOEPTSIZ_XFRSIZ_Msk); out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; } @@ -477,65 +474,33 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) /*------------------------------------------------------------------*/ -// TODO: Split into "receive on endpoint 0" and "receive generic"; endpoint 0's -// DOEPTSIZ register is smaller than the others, and so is insufficient for -// determining how much of an OUT transfer is actually remaining. -static void receive_packet(xfer_ctl_t * xfer, /* USB_OTG_OUTEndpointTypeDef * out_ep, */ uint16_t xfer_size) { +// Read a single data packet from receive FIFO +static void read_fifo_packet(uint8_t * dst, uint16_t len){ usb_fifo_t rx_fifo = FIFO_BASE(0); - // See above TODO - // uint16_t remaining = (out_ep->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DOEPTSIZ_XFRSIZ_Pos; - // xfer->queued_len = xfer->total_len - remaining; - - uint16_t remaining = xfer->total_len - xfer->queued_len; - uint16_t to_recv_size; - - if(remaining <= xfer->max_size) { - // Avoid buffer overflow. - to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; - } else { - // Room for full packet, choose recv_size based on what the microcontroller - // claims. - to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; - } - - uint8_t to_recv_rem = to_recv_size % 4; - uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; - - // Do not assume xfer buffer is aligned. - uint8_t * base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to collect. - if(to_recv_size >= 4) { - for(uint16_t i = 0; i < to_recv_size_aligned; i += 4) { - uint32_t tmp = (* rx_fifo); - base[i] = tmp & 0x000000FF; - base[i + 1] = (tmp & 0x0000FF00) >> 8; - base[i + 2] = (tmp & 0x00FF0000) >> 16; - base[i + 3] = (tmp & 0xFF000000) >> 24; - } + // Reading full available 32 bit words from fifo + uint16_t full_words = len >> 2; + for(uint16_t i = 0; i < full_words; i++) { + uint32_t tmp = *rx_fifo; + dst[0] = tmp & 0x000000FF; + dst[1] = (tmp & 0x0000FF00) >> 8; + dst[2] = (tmp & 0x00FF0000) >> 16; + dst[3] = (tmp & 0xFF000000) >> 24; + dst += 4; } - // Do not read invalid bytes from RX FIFO. - if(to_recv_rem != 0) { - uint32_t tmp = (* rx_fifo); - uint8_t * last_32b_bound = base + to_recv_size_aligned; - - last_32b_bound[0] = tmp & 0x000000FF; - if(to_recv_rem > 1) { - last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; + // Read the remaining 1-3 bytes from fifo + uint8_t bytes_rem = len & 0x03; + if(bytes_rem != 0) { + uint32_t tmp = *rx_fifo; + dst[0] = tmp & 0x000000FF; + if(bytes_rem > 1) { + dst[1] = (tmp & 0x0000FF00) >> 8; } - if(to_recv_rem > 2) { - last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; + if(bytes_rem > 2) { + dst[2] = (tmp & 0x00FF0000) >> 16; } } - - xfer->queued_len += xfer_size; - - // Per USB spec, a short OUT packet (including length 0) is always - // indicative of the end of a transfer (at least for ctl, bulk, int). - xfer->short_packet = (xfer_size < xfer->max_size); } // Write a single data packet to EPIN FIFO @@ -564,11 +529,10 @@ static void write_fifo_packet(uint8_t fifo_num, uint8_t * src, uint16_t len){ } } -static void read_rx_fifo(USB_OTG_OUTEndpointTypeDef * out_ep) { +static void handle_rxflvl_ints(USB_OTG_OUTEndpointTypeDef * out_ep) { usb_fifo_t rx_fifo = FIFO_BASE(0); - // Pop control word off FIFO (completed xfers will have 2 control words, - // we only pop one ctl word each interrupt). + // Pop control word off FIFO uint32_t ctl_word = USB_OTG_FS->GRXSTSP; uint8_t pktsts = (ctl_word & USB_OTG_GRXSTSP_PKTSTS_Msk) >> USB_OTG_GRXSTSP_PKTSTS_Pos; uint8_t epnum = (ctl_word & USB_OTG_GRXSTSP_EPNUM_Msk) >> USB_OTG_GRXSTSP_EPNUM_Pos; @@ -580,7 +544,13 @@ static void read_rx_fifo(USB_OTG_OUTEndpointTypeDef * out_ep) { case 0x02: // Out packet recvd { xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - receive_packet(xfer, bcnt); + + // Use BCNT to calculate correct bytes before data entry popped out from RxFIFO + uint16_t remaining_bytes = ((out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) \ + >> USB_OTG_DOEPTSIZ_XFRSIZ_Pos) + bcnt; + + // Read packet off RxFIFO + read_fifo_packet((xfer->buffer + xfer->total_len - remaining_bytes), bcnt); } break; case 0x03: // Out packet done (Interrupt) @@ -619,25 +589,10 @@ static void handle_epout_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTy _setup_offs = 0; } - // OUT XFER complete (single packet). + // OUT XFER complete if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_XFRC) { out_ep[n].DOEPINT = USB_OTG_DOEPINT_XFRC; - - // TODO: Because of endpoint 0's constrained size, we handle XFRC - // on a packet-basis. The core can internally handle multiple OUT - // packets; it would be more efficient to only trigger XFRC on a - // completed transfer for non-0 endpoints. - - // Transfer complete if short packet or total len is transferred - if(xfer->short_packet || (xfer->queued_len == xfer->total_len)) { - xfer->short_packet = false; - dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); - } else { - // Schedule another packet to be received. - out_ep[n].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | \ - ((xfer->max_size & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) << USB_OTG_DOEPTSIZ_XFRSIZ_Pos); - out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; - } + dcd_event_xfer_complete(0, n, xfer->total_len, XFER_RESULT_SUCCESS, true); } } } @@ -682,11 +637,8 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType break; } - // TODO: queued_len can be removed later - xfer->queued_len = xfer->total_len - remaining_bytes; - // Push packet to Tx-FIFO - write_fifo_packet(n, (xfer->buffer + xfer->queued_len), packet_size); + write_fifo_packet(n, (xfer->buffer + xfer->total_len - remaining_bytes), packet_size); } // Turn off TXFE if all bytes are written. @@ -756,12 +708,14 @@ void dcd_int_handler(uint8_t rhport) { } #endif - if(int_status & USB_OTG_GINTSTS_RXFLVL) { + // Use while loop to handle more than one fifo data entry + // within a single interrupt call + while(USB_OTG_FS->GINTSTS & USB_OTG_GINTSTS_RXFLVL) { // RXFLVL bit is read-only // Mask out RXFLVL while reading data from FIFO USB_OTG_FS->GINTMSK &= ~USB_OTG_GINTMSK_RXFLVLM; - read_rx_fifo(out_ep); + handle_rxflvl_ints(out_ep); USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; } -- cgit v1.3.1 From 46875a3912cd1fddeef7e6c67744d5bf7cce2155 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Tue, 12 May 2020 18:50:26 +0200 Subject: Optimize FIFO for byte transfer. Signed-off-by: Mengsk --- src/common/tusb_fifo.c | 80 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 01e990311..3ed610021 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -103,9 +103,9 @@ static void _tu_ff_push(tu_fifo_t* f, void const * data) /******************************************************************************/ /*! - @brief Read one byte out of the RX buffer. + @brief Read one element out of the RX buffer. - This function will return the byte located at the array index of the + This function will return the element located at the array index of the read pointer, and then increment the read pointer index. If the read pointer exceeds the maximum buffer size, it will roll over to zero. @@ -132,8 +132,8 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) /******************************************************************************/ /*! - @brief This function will read n elements into the array index specified by - the write pointer and increment the write index. If the write index + @brief This function will read n elements from the array index specified by + the read pointer and increment the read index. If the read index exceeds the max buffer size, then it will roll over to zero. @param[in] f @@ -148,32 +148,39 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) /******************************************************************************/ uint16_t tu_fifo_read_n (tu_fifo_t* f, void * buffer, uint16_t count) { - if( tu_fifo_empty(f) ) return 0; + if(tu_fifo_empty(f)) return 0; tu_fifo_lock(f); /* Limit up to fifo's count */ - if ( count > f->count ) count = f->count; - - uint8_t* buf8 = (uint8_t*) buffer; - uint16_t len = 0; + if(count > f->count) + count = f->count; - while (len < count) + if(count + f->rd_idx <= f->depth) { - _tu_ff_pull(f, buf8); - - len++; - buf8 += f->item_size; + memcpy(buffer, f->buffer + f->rd_idx * f->item_size, count * f->item_size); } + else + { + uint16_t part1 = (f->depth - f->rd_idx) * f->item_size; + memcpy(buffer, f->buffer + f->rd_idx * f->item_size, part1); + memcpy((uint8_t*)buffer + part1, f->buffer, count * f->item_size - part1); + } + + f->rd_idx += count; + if (f->rd_idx >= f->depth) + f->rd_idx -= f->depth; + + f->count -= count; tu_fifo_unlock(f); - return len; + return count; } /******************************************************************************/ /*! - @brief Reads one item without removing it from the FIFO + @brief Read one item without removing it from the FIFO @param[in] f Pointer to the FIFO buffer to manipulate @@ -249,23 +256,42 @@ uint16_t tu_fifo_write_n (tu_fifo_t* f, const void * data, uint16_t count) tu_fifo_lock(f); - // Not overwritable limit up to full - if (!f->overwritable) count = tu_min16(count, tu_fifo_remaining(f)); - uint8_t const* buf8 = (uint8_t const*) data; - uint16_t len = 0; - - while (len < count) + // Not overwritable limit up to full + if (!f->overwritable) { - _tu_ff_push(f, buf8); - - len++; - buf8 += f->item_size; + count = tu_min16(count, tu_fifo_remaining(f)); + } + // Only copy last part + else if (count > f->depth) + { + buf8 = buf8 + (count - f->depth) * f->item_size; + count = f->depth; + f->wr_idx = 0; + f->rd_idx = 0; + f->count = 0; } + if (count + f->wr_idx <= f->depth ) + { + memcpy(f->buffer + f->wr_idx * f->item_size, buf8, count * f->item_size); + } + else + { + uint16_t part1 = (f->depth - f->wr_idx) * f->item_size; + memcpy(f->buffer + f->wr_idx * f->item_size, buf8, part1); + memcpy(f->buffer, buf8 + part1, count * f->item_size - part1); + } + + f->wr_idx += count; + if (f->wr_idx >= f->depth) + f->wr_idx -= f->depth; + + f->count += count; + tu_fifo_unlock(f); - return len; + return count; } /******************************************************************************/ -- cgit v1.3.1 From b0d49e55de8a9359f76750b6f8cc6517d10a913e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 14 May 2020 14:24:55 +0700 Subject: refactor copy to and from fifo --- src/common/tusb_fifo.c | 85 +++++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 3ed610021..6ab158cca 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -71,33 +71,38 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si return true; } +static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) +{ + return (idx < depth) ? idx : (idx-depth); +} + // retrieve data from fifo -static void _tu_ff_pull(tu_fifo_t* f, void * buffer) +static inline void _ff_pull(tu_fifo_t* f, void * buffer, uint16_t n) { memcpy(buffer, f->buffer + (f->rd_idx * f->item_size), - f->item_size); + f->item_size*n); - f->rd_idx = (f->rd_idx + 1) % f->depth; - f->count--; + f->rd_idx = _ff_mod(f->rd_idx + n, f->depth); + f->count -= n; } // send data to fifo -static void _tu_ff_push(tu_fifo_t* f, void const * data) +static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t n) { - memcpy( f->buffer + (f->wr_idx * f->item_size), - data, - f->item_size); + memcpy(f->buffer + (f->wr_idx * f->item_size), + data, + f->item_size*n); - f->wr_idx = (f->wr_idx + 1) % f->depth; + f->wr_idx = _ff_mod(f->wr_idx + n, f->depth); if (tu_fifo_full(f)) { - f->rd_idx = f->wr_idx; // keep the full state (rd == wr && len = size) + f->rd_idx = f->wr_idx; // keep the full state (rd == wr && count = depth) } else { - f->count++; + f->count += n; } } @@ -123,7 +128,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) tu_fifo_lock(f); - _tu_ff_pull(f, buffer); + _ff_pull(f, buffer, 1); tu_fifo_unlock(f); @@ -152,26 +157,24 @@ uint16_t tu_fifo_read_n (tu_fifo_t* f, void * buffer, uint16_t count) tu_fifo_lock(f); - /* Limit up to fifo's count */ - if(count > f->count) - count = f->count; + // Limit up to fifo's count + if(count > f->count) count = f->count; if(count + f->rd_idx <= f->depth) { - memcpy(buffer, f->buffer + f->rd_idx * f->item_size, count * f->item_size); + _ff_pull(f, buffer, count); } else { - uint16_t part1 = (f->depth - f->rd_idx) * f->item_size; - memcpy(buffer, f->buffer + f->rd_idx * f->item_size, part1); - memcpy((uint8_t*)buffer + part1, f->buffer, count * f->item_size - part1); + uint16_t const part1 = f->depth - f->rd_idx; + + // Part 1: from rd_idx to end + _ff_pull(f, buffer, part1); + buffer = ((uint8_t*) buffer) + part1*f->item_size; + + // Part 2: start to remaining + _ff_pull(f, buffer, count-part1); } - - f->rd_idx += count; - if (f->rd_idx >= f->depth) - f->rd_idx -= f->depth; - - f->count -= count; tu_fifo_unlock(f); @@ -196,12 +199,16 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer) { if ( pos >= f->count ) return false; + tu_fifo_lock(f); + // rd_idx is pos=0 - uint16_t index = (f->rd_idx + pos) % f->depth; + uint16_t index = _ff_mod(f->rd_idx + pos, f->depth); memcpy(p_buffer, f->buffer + (index * f->item_size), f->item_size); + tu_fifo_unlock(f); + return true; } @@ -228,7 +235,7 @@ bool tu_fifo_write (tu_fifo_t* f, const void * data) tu_fifo_lock(f); - _tu_ff_push(f, data); + _ff_push(f, data, 1); tu_fifo_unlock(f); @@ -257,14 +264,15 @@ uint16_t tu_fifo_write_n (tu_fifo_t* f, const void * data, uint16_t count) tu_fifo_lock(f); uint8_t const* buf8 = (uint8_t const*) data; - // Not overwritable limit up to full + if (!f->overwritable) { + // Not overwritable limit up to full count = tu_min16(count, tu_fifo_remaining(f)); } - // Only copy last part else if (count > f->depth) { + // Only copy last part buf8 = buf8 + (count - f->depth) * f->item_size; count = f->depth; f->wr_idx = 0; @@ -274,21 +282,20 @@ uint16_t tu_fifo_write_n (tu_fifo_t* f, const void * data, uint16_t count) if (count + f->wr_idx <= f->depth ) { - memcpy(f->buffer + f->wr_idx * f->item_size, buf8, count * f->item_size); + _ff_push(f, buf8, count); } else { - uint16_t part1 = (f->depth - f->wr_idx) * f->item_size; - memcpy(f->buffer + f->wr_idx * f->item_size, buf8, part1); - memcpy(f->buffer, buf8 + part1, count * f->item_size - part1); + uint16_t const part1 = f->depth - f->wr_idx; + + // Part 1: from wr_idx to end + _ff_push(f, buf8, part1); + buf8 += part1*f->item_size; + + // Part 2: start to remaining + _ff_push(f, buf8, count-part1); } - f->wr_idx += count; - if (f->wr_idx >= f->depth) - f->wr_idx -= f->depth; - - f->count += count; - tu_fifo_unlock(f); return count; -- cgit v1.3.1 From 28696de39011f01ba34e49c2a53efa8e6f43c8ea Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Fri, 15 May 2020 18:21:44 +0200 Subject: Interrupt time improvements --- src/portable/st/synopsys/dcd_synopsys.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 149919d54..73e6ca827 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -708,14 +708,19 @@ void dcd_int_handler(uint8_t rhport) { } #endif - // Use while loop to handle more than one fifo data entry - // within a single interrupt call - while(USB_OTG_FS->GINTSTS & USB_OTG_GINTSTS_RXFLVL) { + // RxFIFO non-empty interrupt handling. + if(int_status & USB_OTG_GINTSTS_RXFLVL) { // RXFLVL bit is read-only // Mask out RXFLVL while reading data from FIFO USB_OTG_FS->GINTMSK &= ~USB_OTG_GINTMSK_RXFLVLM; - handle_rxflvl_ints(out_ep); + + // Loop until all available packets were handled + do { + handle_rxflvl_ints(out_ep); + int_status = USB_OTG_FS->GINTSTS; + } while(int_status & USB_OTG_GINTSTS_RXFLVL); + USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; } -- cgit v1.3.1 From 42edbc000665e555bc5f44046d2ed72f4597de5a Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Fri, 15 May 2020 22:26:14 +0200 Subject: Allow EP0 to use xfer sizes larger than one packet --- src/portable/st/synopsys/dcd_synopsys.c | 50 +++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 73e6ca827..06f41ceec 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -109,6 +109,9 @@ typedef volatile uint32_t * usb_fifo_t; xfer_ctl_t xfer_status[EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] +// EP0 transfers are limited to 1 packet - larger sizes has to be split +static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type + // Setup the control endpoint 0. static void bus_reset(void) { @@ -356,13 +359,26 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->total_len = total_bytes; uint16_t num_packets = (total_bytes / xfer->max_size); - uint8_t short_packet_size = total_bytes % xfer->max_size; + uint8_t const short_packet_size = total_bytes % xfer->max_size; // Zero-size packet is special case. if(short_packet_size > 0 || (total_bytes == 0)) { num_packets++; } + // EP0 can only handle one packet + if(epnum == 0) { + num_packets = 1; + if(total_bytes > xfer->max_size) { + ep0_pending[dir] = total_bytes - xfer->max_size; + total_bytes = xfer->max_size; + // Decrement pointer to make EP0 buffers compatible with existing routines. + xfer->buffer -= ep0_pending[dir]; + } else { + ep0_pending[dir] = 0; + } + } + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them here. if(dir == TUSB_DIR_IN) { // A full IN transfer (multiple packets, possibly) triggers XFRC. @@ -549,6 +565,9 @@ static void handle_rxflvl_ints(USB_OTG_OUTEndpointTypeDef * out_ep) { uint16_t remaining_bytes = ((out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) \ >> USB_OTG_DOEPTSIZ_XFRSIZ_Pos) + bcnt; + // Adjust remaining bytes in case of multi packet EP0 transfer + if(epnum == 0) remaining_bytes += ep0_pending[TUSB_DIR_OUT]; + // Read packet off RxFIFO read_fifo_packet((xfer->buffer + xfer->total_len - remaining_bytes), bcnt); } @@ -592,7 +611,18 @@ static void handle_epout_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTy // OUT XFER complete if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_XFRC) { out_ep[n].DOEPINT = USB_OTG_DOEPINT_XFRC; - dcd_event_xfer_complete(0, n, xfer->total_len, XFER_RESULT_SUCCESS, true); + + // EP0 can only handle one packet + if((n == 0) && ep0_pending[TUSB_DIR_OUT]){ + uint16_t const total_bytes = tu_min16(ep0_pending[TUSB_DIR_OUT], xfer->max_size); + ep0_pending[TUSB_DIR_OUT] -= total_bytes; + // Schedule another packet to be received. + out_ep[0].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | + ((total_bytes << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) & USB_OTG_DOEPTSIZ_XFRSIZ_Msk); + out_ep[0].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + } else { + dcd_event_xfer_complete(0, n, xfer->total_len, XFER_RESULT_SUCCESS, true); + } } } } @@ -612,7 +642,18 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType if ( in_ep[n].DIEPINT & USB_OTG_DIEPINT_XFRC ) { in_ep[n].DIEPINT = USB_OTG_DIEPINT_XFRC; - dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + + // EP0 can only handle one packet + if((n == 0) && ep0_pending[TUSB_DIR_IN]){ + uint16_t const total_bytes = tu_min16(ep0_pending[TUSB_DIR_IN], xfer->max_size); + ep0_pending[TUSB_DIR_IN] -= total_bytes; + // Schedule another packet to be received. + in_ep[0].DIEPTSIZ |= (1 << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | + ((total_bytes << USB_OTG_DIEPTSIZ_XFRSIZ_Pos) & USB_OTG_DIEPTSIZ_XFRSIZ_Msk); + in_ep[0].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; + } else { + dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + } } // XFER FIFO empty @@ -637,6 +678,9 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType break; } + // Adjust remaining bytes in case of multi packet EP0 transfer + if(n == 0) remaining_bytes += ep0_pending[TUSB_DIR_IN]; + // Push packet to Tx-FIFO write_fifo_packet(n, (xfer->buffer + xfer->total_len - remaining_bytes), packet_size); } -- cgit v1.3.1 From 1a8ce043ed937012454e5b79396455f9c5568a68 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 17 May 2020 14:24:15 +0700 Subject: enable -Wcast-align suppress vendor sdk driver at board.mk --- examples/make.mk | 8 +++----- hw/bsp/adafruit_clue/board.mk | 4 ++-- hw/bsp/arduino_nano33_ble/board.mk | 4 ++-- hw/bsp/circuitplayground_bluefruit/board.mk | 4 ++-- hw/bsp/feather_nrf52840_express/board.mk | 4 ++-- hw/bsp/feather_nrf52840_sense/board.mk | 4 ++-- hw/bsp/feather_stm32f405/board.mk | 3 +++ hw/bsp/nrf52840_mdk_dongle/board.mk | 4 ++-- hw/bsp/nutiny_sdk_nuc505/board.mk | 5 +++-- hw/bsp/pca10056/board.mk | 4 ++-- hw/bsp/pca10059/board.mk | 4 ++-- hw/bsp/pca10100/board.mk | 4 ++-- hw/bsp/raytac_mdbt50q_rx/board.mk | 4 ++-- hw/bsp/stm32f070rbnucleo/board.mk | 4 ++-- hw/bsp/stm32f072disco/board.mk | 4 ++-- hw/bsp/stm32f407disco/board.mk | 3 +++ hw/bsp/stm32f411disco/board.mk | 3 +++ hw/bsp/stm32f412disco/board.mk | 4 ++-- hw/bsp/stm32f746nucleo/board.mk | 4 ++-- hw/bsp/stm32f767nucleo/board.mk | 4 ++-- hw/bsp/stm32h743nucleo/board.mk | 1 - src/common/tusb_common.h | 2 +- src/portable/nxp/transdimension/dcd_transdimension.c | 6 ++++-- 23 files changed, 50 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/examples/make.mk b/examples/make.mk index 449dc899d..2ea50753b 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -63,11 +63,9 @@ CFLAGS += \ -Wwrite-strings \ -Wsign-compare \ -Wmissing-format-attribute \ - -Wunreachable-code - -# This causes lots of warning with nrf5x build due to nrfx code -# CFLAGS += -Wcast-align - + -Wunreachable-code \ + -Wcast-align + # Debugging/Optimization ifeq ($(DEBUG), 1) CFLAGS += -Og -ggdb diff --git a/hw/bsp/adafruit_clue/board.mk b/hw/bsp/adafruit_clue/board.mk index be8c5bf56..5290455cc 100644 --- a/hw/bsp/adafruit_clue/board.mk +++ b/hw/bsp/adafruit_clue/board.mk @@ -9,8 +9,8 @@ CFLAGS += \ -DNRF52840_XXAA \ -DCONFIG_GPIO_AS_PINRESET -# nrfx issue undef _ARMCC_VERSION usage https://github.com/NordicSemiconductor/nrfx/issues/49 -CFLAGS += -Wno-error=undef -Wno-error=unused-parameter +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=undef -Wno-error=unused-parameter -Wno-error=cast-align # due to tusb_hal_nrf_power_event GCCVERSION = $(firstword $(subst ., ,$(shell arm-none-eabi-gcc -dumpversion))) diff --git a/hw/bsp/arduino_nano33_ble/board.mk b/hw/bsp/arduino_nano33_ble/board.mk index d217d37c0..0a25d0b19 100644 --- a/hw/bsp/arduino_nano33_ble/board.mk +++ b/hw/bsp/arduino_nano33_ble/board.mk @@ -9,8 +9,8 @@ CFLAGS += \ -DNRF52840_XXAA \ -DCONFIG_GPIO_AS_PINRESET -# nrfx issue undef _ARMCC_VERSION usage https://github.com/NordicSemiconductor/nrfx/issues/49 -CFLAGS += -Wno-error=undef -Wno-error=unused-parameter +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=undef -Wno-error=unused-parameter -Wno-error=cast-align # due to tusb_hal_nrf_power_event GCCVERSION = $(firstword $(subst ., ,$(shell arm-none-eabi-gcc -dumpversion))) diff --git a/hw/bsp/circuitplayground_bluefruit/board.mk b/hw/bsp/circuitplayground_bluefruit/board.mk index be8c5bf56..5290455cc 100644 --- a/hw/bsp/circuitplayground_bluefruit/board.mk +++ b/hw/bsp/circuitplayground_bluefruit/board.mk @@ -9,8 +9,8 @@ CFLAGS += \ -DNRF52840_XXAA \ -DCONFIG_GPIO_AS_PINRESET -# nrfx issue undef _ARMCC_VERSION usage https://github.com/NordicSemiconductor/nrfx/issues/49 -CFLAGS += -Wno-error=undef -Wno-error=unused-parameter +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=undef -Wno-error=unused-parameter -Wno-error=cast-align # due to tusb_hal_nrf_power_event GCCVERSION = $(firstword $(subst ., ,$(shell arm-none-eabi-gcc -dumpversion))) diff --git a/hw/bsp/feather_nrf52840_express/board.mk b/hw/bsp/feather_nrf52840_express/board.mk index 9f38d6796..7b2625cd4 100644 --- a/hw/bsp/feather_nrf52840_express/board.mk +++ b/hw/bsp/feather_nrf52840_express/board.mk @@ -9,8 +9,8 @@ CFLAGS += \ -DNRF52840_XXAA \ -DCONFIG_GPIO_AS_PINRESET -# nrfx issue undef _ARMCC_VERSION usage https://github.com/NordicSemiconductor/nrfx/issues/49 -CFLAGS += -Wno-error=undef -Wno-error=unused-parameter +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=undef -Wno-error=unused-parameter -Wno-error=cast-align # due to tusb_hal_nrf_power_event GCCVERSION = $(firstword $(subst ., ,$(shell arm-none-eabi-gcc -dumpversion))) diff --git a/hw/bsp/feather_nrf52840_sense/board.mk b/hw/bsp/feather_nrf52840_sense/board.mk index be8c5bf56..5290455cc 100644 --- a/hw/bsp/feather_nrf52840_sense/board.mk +++ b/hw/bsp/feather_nrf52840_sense/board.mk @@ -9,8 +9,8 @@ CFLAGS += \ -DNRF52840_XXAA \ -DCONFIG_GPIO_AS_PINRESET -# nrfx issue undef _ARMCC_VERSION usage https://github.com/NordicSemiconductor/nrfx/issues/49 -CFLAGS += -Wno-error=undef -Wno-error=unused-parameter +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=undef -Wno-error=unused-parameter -Wno-error=cast-align # due to tusb_hal_nrf_power_event GCCVERSION = $(firstword $(subst ., ,$(shell arm-none-eabi-gcc -dumpversion))) diff --git a/hw/bsp/feather_stm32f405/board.mk b/hw/bsp/feather_stm32f405/board.mk index 2d1f8bb8d..8233c6608 100644 --- a/hw/bsp/feather_stm32f405/board.mk +++ b/hw/bsp/feather_stm32f405/board.mk @@ -9,6 +9,9 @@ CFLAGS += \ -DSTM32F405xx \ -DCFG_TUSB_MCU=OPT_MCU_STM32F4 +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=cast-align + ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F4xx_HAL_Driver ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F4xx diff --git a/hw/bsp/nrf52840_mdk_dongle/board.mk b/hw/bsp/nrf52840_mdk_dongle/board.mk index 0ab5ff2e1..9ba04ba1f 100644 --- a/hw/bsp/nrf52840_mdk_dongle/board.mk +++ b/hw/bsp/nrf52840_mdk_dongle/board.mk @@ -8,8 +8,8 @@ CFLAGS += \ -DNRF52840_XXAA \ -DCFG_TUSB_MCU=OPT_MCU_NRF5X -# nrfx issue undef _ARMCC_VERSION usage https://github.com/NordicSemiconductor/nrfx/issues/49 -CFLAGS += -Wno-error=undef -Wno-error=unused-parameter +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=undef -Wno-error=unused-parameter -Wno-error=cast-align # due to tusb_hal_nrf_power_event GCCVERSION = $(firstword $(subst ., ,$(shell arm-none-eabi-gcc -dumpversion))) diff --git a/hw/bsp/nutiny_sdk_nuc505/board.mk b/hw/bsp/nutiny_sdk_nuc505/board.mk index 39df77d2c..874d4ae42 100644 --- a/hw/bsp/nutiny_sdk_nuc505/board.mk +++ b/hw/bsp/nutiny_sdk_nuc505/board.mk @@ -7,6 +7,9 @@ CFLAGS += \ -mfpu=fpv4-sp-d16 \ -DCFG_TUSB_MCU=OPT_MCU_NUC505 +# TODO this cast-align is caused by dcd_nuc505 should be fixed +CFLAGS += -Wno-error=cast-align + # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/nuc505_flashtoram.ld @@ -19,13 +22,11 @@ SRC_C += \ hw/mcu/nuvoton/nuc505/StdDriver/src/i2s.c \ hw/mcu/nuvoton/nuc505/StdDriver/src/pwm.c \ hw/mcu/nuvoton/nuc505/StdDriver/src/rtc.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/sd.c \ hw/mcu/nuvoton/nuc505/StdDriver/src/spi.c \ hw/mcu/nuvoton/nuc505/StdDriver/src/spim.c \ hw/mcu/nuvoton/nuc505/StdDriver/src/sys.c \ hw/mcu/nuvoton/nuc505/StdDriver/src/timer.c \ hw/mcu/nuvoton/nuc505/StdDriver/src/uart.c \ - hw/mcu/nuvoton/nuc505/StdDriver/src/usbd.c \ hw/mcu/nuvoton/nuc505/StdDriver/src/wdt.c \ hw/mcu/nuvoton/nuc505/StdDriver/src/wwdt.c diff --git a/hw/bsp/pca10056/board.mk b/hw/bsp/pca10056/board.mk index b2f119626..0971e64c8 100644 --- a/hw/bsp/pca10056/board.mk +++ b/hw/bsp/pca10056/board.mk @@ -9,8 +9,8 @@ CFLAGS += \ -DCONFIG_GPIO_AS_PINRESET \ -DCFG_TUSB_MCU=OPT_MCU_NRF5X -# nrfx issue undef _ARMCC_VERSION usage https://github.com/NordicSemiconductor/nrfx/issues/49 -CFLAGS += -Wno-error=undef -Wno-error=unused-parameter +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=undef -Wno-error=unused-parameter -Wno-error=cast-align # due to tusb_hal_nrf_power_event GCCVERSION = $(firstword $(subst ., ,$(shell arm-none-eabi-gcc -dumpversion))) diff --git a/hw/bsp/pca10059/board.mk b/hw/bsp/pca10059/board.mk index 8cce65eb9..72dfefdcb 100644 --- a/hw/bsp/pca10059/board.mk +++ b/hw/bsp/pca10059/board.mk @@ -9,8 +9,8 @@ CFLAGS += \ -DCONFIG_GPIO_AS_PINRESET \ -DCFG_TUSB_MCU=OPT_MCU_NRF5X -# nrfx issue undef _ARMCC_VERSION usage https://github.com/NordicSemiconductor/nrfx/issues/49 -CFLAGS += -Wno-error=undef -Wno-error=unused-parameter +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=undef -Wno-error=unused-parameter -Wno-error=cast-align # due to tusb_hal_nrf_power_event GCCVERSION = $(firstword $(subst ., ,$(shell arm-none-eabi-gcc -dumpversion))) diff --git a/hw/bsp/pca10100/board.mk b/hw/bsp/pca10100/board.mk index 0ec8f0f69..5231aaf63 100644 --- a/hw/bsp/pca10100/board.mk +++ b/hw/bsp/pca10100/board.mk @@ -9,8 +9,8 @@ CFLAGS += \ -DCONFIG_GPIO_AS_PINRESET \ -DCFG_TUSB_MCU=OPT_MCU_NRF5X -# nrfx issue undef _ARMCC_VERSION usage https://github.com/NordicSemiconductor/nrfx/issues/49 -CFLAGS += -Wno-error=undef -Wno-error=unused-parameter +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=undef -Wno-error=unused-parameter -Wno-error=cast-align # due to tusb_hal_nrf_power_event GCCVERSION = $(firstword $(subst ., ,$(shell arm-none-eabi-gcc -dumpversion))) diff --git a/hw/bsp/raytac_mdbt50q_rx/board.mk b/hw/bsp/raytac_mdbt50q_rx/board.mk index 0960ffe55..47bb430fc 100644 --- a/hw/bsp/raytac_mdbt50q_rx/board.mk +++ b/hw/bsp/raytac_mdbt50q_rx/board.mk @@ -8,8 +8,8 @@ CFLAGS += \ -DNRF52840_XXAA \ -DCFG_TUSB_MCU=OPT_MCU_NRF5X -# nrfx issue undef _ARMCC_VERSION usage https://github.com/NordicSemiconductor/nrfx/issues/49 -CFLAGS += -Wno-error=undef -Wno-error=unused-parameter +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=undef -Wno-error=unused-parameter -Wno-error=cast-align # due to tusb_hal_nrf_power_event GCCVERSION = $(firstword $(subst ., ,$(shell arm-none-eabi-gcc -dumpversion))) diff --git a/hw/bsp/stm32f070rbnucleo/board.mk b/hw/bsp/stm32f070rbnucleo/board.mk index 8a073d524..8ae75dd96 100644 --- a/hw/bsp/stm32f070rbnucleo/board.mk +++ b/hw/bsp/stm32f070rbnucleo/board.mk @@ -9,8 +9,8 @@ CFLAGS += \ -DCFG_EXAMPLE_MSC_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_STM32F0 -# mcu driver cause following warnings -CFLAGS += -Wno-error=unused-parameter +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F0xx_HAL_Driver ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F0xx diff --git a/hw/bsp/stm32f072disco/board.mk b/hw/bsp/stm32f072disco/board.mk index 522459d61..e6787b266 100644 --- a/hw/bsp/stm32f072disco/board.mk +++ b/hw/bsp/stm32f072disco/board.mk @@ -9,8 +9,8 @@ CFLAGS += \ -DCFG_EXAMPLE_MSC_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_STM32F0 -# mcu driver cause following warnings -CFLAGS += -Wno-error=unused-parameter +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F0xx_HAL_Driver ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F0xx diff --git a/hw/bsp/stm32f407disco/board.mk b/hw/bsp/stm32f407disco/board.mk index 92e021538..df2ee4ba5 100644 --- a/hw/bsp/stm32f407disco/board.mk +++ b/hw/bsp/stm32f407disco/board.mk @@ -9,6 +9,9 @@ CFLAGS += \ -DSTM32F407xx \ -DCFG_TUSB_MCU=OPT_MCU_STM32F4 +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=cast-align + ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F4xx_HAL_Driver ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F4xx diff --git a/hw/bsp/stm32f411disco/board.mk b/hw/bsp/stm32f411disco/board.mk index a5ea8cab2..5e0d6c3a0 100644 --- a/hw/bsp/stm32f411disco/board.mk +++ b/hw/bsp/stm32f411disco/board.mk @@ -9,6 +9,9 @@ CFLAGS += \ -DSTM32F411xE \ -DCFG_TUSB_MCU=OPT_MCU_STM32F4 +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=cast-align + ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F4xx_HAL_Driver ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F4xx diff --git a/hw/bsp/stm32f412disco/board.mk b/hw/bsp/stm32f412disco/board.mk index 2a3ecbddd..5cf5e9b7a 100644 --- a/hw/bsp/stm32f412disco/board.mk +++ b/hw/bsp/stm32f412disco/board.mk @@ -9,8 +9,8 @@ CFLAGS += \ -DSTM32F412Zx \ -DCFG_TUSB_MCU=OPT_MCU_STM32F4 -# mcu driver cause following warnings -CFLAGS += -Wno-error=maybe-uninitialized +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=cast-align ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F4xx_HAL_Driver ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F4xx diff --git a/hw/bsp/stm32f746nucleo/board.mk b/hw/bsp/stm32f746nucleo/board.mk index 7e070c1c5..95445486a 100644 --- a/hw/bsp/stm32f746nucleo/board.mk +++ b/hw/bsp/stm32f746nucleo/board.mk @@ -9,8 +9,8 @@ CFLAGS += \ -DSTM32F746xx \ -DCFG_TUSB_MCU=OPT_MCU_STM32F7 -# mcu driver cause following warnings -CFLAGS += -Wno-error=shadow +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=cast-align -Wno-error=shadow ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F7xx_HAL_Driver ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F7xx diff --git a/hw/bsp/stm32f767nucleo/board.mk b/hw/bsp/stm32f767nucleo/board.mk index e5f0736df..fc638ddcb 100644 --- a/hw/bsp/stm32f767nucleo/board.mk +++ b/hw/bsp/stm32f767nucleo/board.mk @@ -9,8 +9,8 @@ CFLAGS += \ -DSTM32F767xx \ -DCFG_TUSB_MCU=OPT_MCU_STM32F7 -# mcu driver cause following warnings -CFLAGS += -Wno-error=shadow +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=cast-align -Wno-error=shadow ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F7xx_HAL_Driver ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F7xx diff --git a/hw/bsp/stm32h743nucleo/board.mk b/hw/bsp/stm32h743nucleo/board.mk index 94cc44b5f..30e52dfcc 100644 --- a/hw/bsp/stm32h743nucleo/board.mk +++ b/hw/bsp/stm32h743nucleo/board.mk @@ -10,7 +10,6 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_STM32H7 # mcu driver cause following warnings -CFLAGS += -Wno-error=maybe-uninitialized ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32H7xx_HAL_Driver ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32H7xx diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 2389bfcd4..f144cda73 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -106,7 +106,7 @@ static inline uint16_t tu_max16 (uint16_t x, uint16_t y) { return (x > y) ? x : static inline uint32_t tu_max32 (uint32_t x, uint32_t y) { return (x > y) ? x : y; } // Align -static inline uint32_t tu_align_n(uint32_t value, uint32_t alignment) +static inline uint32_t tu_align(uint32_t value, uint32_t alignment) { return value & ((uint32_t) ~(alignment-1)); } diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index fcedc1c0c..7baf43e23 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -273,7 +273,8 @@ typedef struct { dcd_qtd_t qtd[QHD_MAX] TU_ATTR_ALIGNED(32); // for portability, TinyUSB only queue 1 TD for each Qhd }dcd_data_t; -static dcd_data_t _dcd_data CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(2048); +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(2048) +static dcd_data_t _dcd_data; //--------------------------------------------------------------------+ // CONTROLLER API @@ -478,7 +479,8 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t // Force the CPU to flush the buffer. We increase the size by 32 because the call aligns the // address to 32-byte boundaries. - CleanInvalidateDCache_by_Addr((uint32_t*) buffer, total_bytes + 31); + // void* cast to suppress cast-align warning, buffer must be + CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) buffer, 4), total_bytes + 31); //------------- Prepare qtd -------------// qtd_init(p_qtd, buffer, total_bytes); -- cgit v1.3.1 From 550746097b81c07cdc2459371c809a3678fe1ff4 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 18 May 2020 13:03:41 +0700 Subject: fix cast-align warning for nuc505 --- hw/bsp/nutiny_sdk_nuc505/board.mk | 3 --- src/portable/nuvoton/nuc505/dcd_nuc505.c | 5 ++++- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/hw/bsp/nutiny_sdk_nuc505/board.mk b/hw/bsp/nutiny_sdk_nuc505/board.mk index 874d4ae42..5fb2119b8 100644 --- a/hw/bsp/nutiny_sdk_nuc505/board.mk +++ b/hw/bsp/nutiny_sdk_nuc505/board.mk @@ -7,9 +7,6 @@ CFLAGS += \ -mfpu=fpv4-sp-d16 \ -DCFG_TUSB_MCU=OPT_MCU_NUC505 -# TODO this cast-align is caused by dcd_nuc505 should be fixed -CFLAGS += -Wno-error=cast-align - # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/nuc505_flashtoram.ld diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 02f0b35a6..e67b69ab2 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -182,7 +182,10 @@ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) /* provided buffers are thankfully 32-bit aligned, allowing most data to be transfered as 32-bit */ while (countdown > 3) { - ep->EPDAT = *(uint32_t *)xfer->data_ptr; + uint32_t u32; + memcpy(&u32, xfer->data_ptr, 4); + + ep->EPDAT = u32; xfer->data_ptr += 4; countdown -= 4; } while (countdown--) -- cgit v1.3.1 From 81b1f97ef7510a12a2d2ee3e8c806d4824e8a720 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 18 May 2020 13:23:40 +0700 Subject: suppress cast-align warnings for net device driver --- examples/device/net_lwip_webserver/Makefile | 3 --- lib/networking/rndis_reports.c | 10 +++++----- src/class/net/net_device.c | 6 +++--- 3 files changed, 8 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/examples/device/net_lwip_webserver/Makefile b/examples/device/net_lwip_webserver/Makefile index 5279c49e2..fa93cf87f 100644 --- a/examples/device/net_lwip_webserver/Makefile +++ b/examples/device/net_lwip_webserver/Makefile @@ -6,9 +6,6 @@ CFLAGS += \ -DTCP_WND=2*TCP_MSS \ -DHTTPD_USE_CUSTOM_FSDATA=0 -# TODO rndis_reports.c and net_device cause cast algin warnings -CFLAGS += -Wno-error=cast-align - INC += \ src \ $(TOP)/hw \ diff --git a/lib/networking/rndis_reports.c b/lib/networking/rndis_reports.c index 6e24c57e9..ee611c883 100644 --- a/lib/networking/rndis_reports.c +++ b/lib/networking/rndis_reports.c @@ -74,7 +74,7 @@ static const uint32_t OIDSupportedList[] = #define OID_LIST_LENGTH TU_ARRAY_SIZE(OIDSupportedList) #define ENC_BUF_SIZE (OID_LIST_LENGTH * 4 + 32) -static uint8_t *encapsulated_buffer; +static void *encapsulated_buffer; static void rndis_report(void) { @@ -152,7 +152,7 @@ static void rndis_query(void) } } -#define INFBUF ((uint32_t *)((uint8_t *)&(m->RequestId) + m->InformationBufferOffset)) +#define INFBUF ((uint8_t *)&(m->RequestId) + m->InformationBufferOffset) static void rndis_handle_config_parm(const char *data, int keyoffset, int valoffset, int keylen, int vallen) { @@ -191,14 +191,14 @@ static void rndis_handle_set_msg(void) char *ptr = (char *)m; ptr += sizeof(rndis_generic_msg_t); ptr += m->InformationBufferOffset; - p = (rndis_config_parameter_t *)ptr; + p = (rndis_config_parameter_t *) ((void*) ptr); rndis_handle_config_parm(ptr, p->ParameterNameOffset, p->ParameterValueOffset, p->ParameterNameLength, p->ParameterValueLength); } break; /* Mandatory general OIDs */ case OID_GEN_CURRENT_PACKET_FILTER: - oid_packet_filter = *INFBUF; + memcpy(&oid_packet_filter, INFBUF, 4); if (oid_packet_filter) { rndis_packetFilter(oid_packet_filter); @@ -239,7 +239,7 @@ void rndis_class_set_handler(uint8_t *data, int size) encapsulated_buffer = data; (void)size; - switch (((rndis_generic_msg_t *)data)->MessageType) + switch (((rndis_generic_msg_t *)encapsulated_buffer)->MessageType) { case REMOTE_NDIS_INITIALIZE_MSG: { diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index fedd4db99..cbd662b10 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -326,7 +326,7 @@ bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request { if (request->bmRequestType_bit.direction == TUSB_DIR_IN) { - rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)notify.rndis_buf; + rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) 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); @@ -356,7 +356,7 @@ static void handle_incoming_packet(uint32_t len) } else { - rndis_data_packet_t *r = (rndis_data_packet_t *)pnt; + rndis_data_packet_t *r = (rndis_data_packet_t *) ((void*) 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) @@ -450,7 +450,7 @@ void tud_network_xmit(struct pbuf *p) if (!_netd_itf.ecm_mode) { - rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted; + rndis_data_packet_t *hdr = (rndis_data_packet_t *) ((void*) transmitted); memset(hdr, 0, sizeof(rndis_data_packet_t)); hdr->MessageType = REMOTE_NDIS_PACKET_MSG; hdr->MessageLength = len; -- cgit v1.3.1 From 58cedf4c061fbf9f95cd88cafb6e581fc04549ff Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 19 May 2020 00:55:43 +0700 Subject: usb0 host on mcb1800 work with fullspeed mode. use usbh_edpt_open() to correctly map ep2drv[] --- examples/host/cdc_msc_hid/Makefile | 3 +- .../host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject | 4 ++ examples/host/cdc_msc_hid/src/main.c | 15 +++-- examples/host/cdc_msc_hid/src/msc_app.c | 36 ++++++------ examples/host/cdc_msc_hid/src/tusb_config.h | 6 +- hw/bsp/ea4357/board.mk | 2 +- hw/bsp/mcb1800/board.mk | 4 +- hw/bsp/mcb1800/mcb1800.c | 3 +- src/class/cdc/cdc_host.c | 4 +- src/class/hid/hid_host.c | 2 +- src/class/msc/msc_host.c | 2 +- src/class/vendor/vendor_host.c | 2 +- src/host/ehci/ehci.c | 21 ++++++- src/host/ehci/ehci.h | 4 ++ src/host/hcd.h | 1 + src/host/hub.c | 2 +- src/host/usbh.c | 68 +++++++++++++--------- src/host/usbh.h | 2 + 18 files changed, 115 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index 20cd7ba69..373dbbf9e 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -15,8 +15,9 @@ SRC_C += \ src/host/usbh.c \ src/host/hub.c \ src/host/ehci/ehci.c \ - src/class/cdc/cdc_host.c \ src/host/ehci/ehci.c \ + src/class/cdc/cdc_host.c \ + src/class/msc/msc_host.c \ src/portable/nxp/lpc18_43/hcd_lpc18_43.c include ../../rules.mk diff --git a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject index 2b68bfa23..e0a2f6f97 100644 --- a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject +++ b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject @@ -124,6 +124,10 @@ + USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5); - -// LPC_USB0->PORTSC1_D |= (1<<24); // FIXME force full speed for debugging + LPC_USB0->PORTSC1_H |= (1<<24); // FIXME force full speed for debugging #else // TODO OTG LPC_USB0->USBMODE_D = USBMODE_DEVICE; LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/; diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 6b36ea94d..e62f47b72 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -158,7 +158,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it // notification endpoint tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT( hcd_edpt_open(rhport, dev_addr, ep_desc) ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, ep_desc) ); p_cdc->ep_notif = ep_desc->bEndpointAddress; (*p_length) += p_desc[DESC_OFFSET_LEN]; @@ -179,7 +179,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(hcd_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 69c49b012..8abb3cd22 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ static inline bool hidh_interface_open(uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *p_endpoint_desc, hidh_interface_info_t *p_hid) { - p_hid->pipe_hdl = hcd_edpt_open(dev_addr, p_endpoint_desc, TUSB_CLASS_HID); + p_hid->pipe_hdl = usbh_edpt_open(dev_addr, p_endpoint_desc, TUSB_CLASS_HID); p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor p_hid->interface_number = interface_number; diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index e20969f57..98c71eb70 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -293,7 +293,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(hcd_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { diff --git a/src/class/vendor/vendor_host.c b/src/class/vendor/vendor_host.c index 3e8dac0f6..0524cb981 100644 --- a/src/class/vendor/vendor_host.c +++ b/src/class/vendor/vendor_host.c @@ -107,7 +107,7 @@ tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_IN_MASK ) ? &custom_interface[dev_addr-1].pipe_in : &custom_interface[dev_addr-1].pipe_out; - *p_pipe_hdl = hcd_edpt_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); + *p_pipe_hdl = usbh_edpt_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); TU_ASSERT ( pipehandle_is_valid(*p_pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); p_desc = tu_desc_next(p_desc); diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 048affb1e..e2ead7b08 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -120,10 +120,27 @@ void hcd_port_reset(uint8_t rhport) ehci_registers_t* regs = ehci_data.regs; - regs->portsc_bm.port_enabled = 0; // disable port before reset - regs->portsc_bm.port_reset = 1; +// regs->portsc_bm.port_enabled = 0; // disable port before reset +// regs->portsc_bm.port_reset = 1; + + uint32_t portsc = regs->portsc; + + portsc &= ~(EHCI_PORTSC_MASK_PORT_EANBLED); + portsc |= EHCI_PORTSC_MASK_PORT_RESET; + + regs->portsc = portsc; } +#if 0 +void hcd_port_reset_end(uint8_t rhport) +{ + (void) rhport; + + ehci_registers_t* regs = ehci_data.regs; + regs->portsc_bm.port_reset = 0; +} +#endif + bool hcd_port_connect_status(uint8_t rhport) { (void) rhport; diff --git a/src/host/ehci/ehci.h b/src/host/ehci/ehci.h index f11c4536a..a6342b2d2 100644 --- a/src/host/ehci/ehci.h +++ b/src/host/ehci/ehci.h @@ -311,10 +311,14 @@ enum ehci_usbcmd_pos_ { }; enum ehci_portsc_change_mask_{ + EHCI_PORTSC_MASK_CURRENT_CONNECT_STATUS = TU_BIT(0), EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE = TU_BIT(1), + EHCI_PORTSC_MASK_PORT_EANBLED = TU_BIT(2), EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE = TU_BIT(3), EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE = TU_BIT(5), + EHCI_PORTSC_MASK_PORT_RESET = TU_BIT(8), + EHCI_PORTSC_MASK_ALL = EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE | EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE | diff --git a/src/host/hcd.h b/src/host/hcd.h index d9307ca09..f2ca0a1d6 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -104,6 +104,7 @@ static inline uint32_t hcd_frame_number(uint8_t rhport) /// return the current connect status of roothub port bool hcd_port_connect_status(uint8_t hostid); void hcd_port_reset(uint8_t hostid); +void hcd_port_reset_end(uint8_t rhport); tusb_speed_t hcd_port_speed_get(uint8_t hostid); // HCD closes all opened endpoints belong to this device diff --git a/src/host/hub.c b/src/host/hub.c index 00450b704..eb85dfa42 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -154,7 +154,7 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); TU_ASSERT(TUSB_XFER_INTERRUPT == ep_desc->bmAttributes.xfer); - TU_ASSERT(hcd_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); hub_data[dev_addr-1].itf_num = itf_desc->bInterfaceNumber; hub_data[dev_addr-1].ep_status = ep_desc->bEndpointAddress; diff --git a/src/host/usbh.c b/src/host/usbh.c index 7171f6bab..8536cec0a 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -116,7 +116,6 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _usbh_ctrl_buf[CFG_TUSB_H //------------- Helper Function Prototypes -------------// static inline uint8_t get_new_address(void); static inline uint8_t get_configure_number_for_device(tusb_desc_device_t* dev_desc); -static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) @@ -225,6 +224,30 @@ tusb_error_t usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) return TUSB_ERROR_NONE; } +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +{ + bool ret = hcd_edpt_open(rhport, dev_addr, ep_desc); + + if (ret) + { + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + // new endpoints belongs to latest interface (last valid value) + uint8_t drvid = 0xff; + for(uint8_t i=0; i < sizeof(dev->itf2drv); i++) + { + if ( dev->itf2drv[i] == 0xff ) break; + drvid = dev->itf2drv[i]; + } + TU_ASSERT(drvid < USBH_CLASS_DRIVER_COUNT); + + uint8_t const ep_addr = ep_desc->bEndpointAddress; + dev->ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = drvid; + } + + return ret; +} + //--------------------------------------------------------------------+ // USBH-HCD ISR/Callback API //--------------------------------------------------------------------+ @@ -358,6 +381,8 @@ bool enum_task(hcd_event_t* event) { if( hcd_port_connect_status(dev0->rhport) ) { + TU_LOG2("Connect \r\n"); + // connection event osal_task_delay(POWER_STABLE_DELAY); // wait until device is stable. Increase this if the first 8 bytes is failed to get @@ -371,6 +396,8 @@ bool enum_task(hcd_event_t* event) } else { + TU_LOG2("Disconnect \r\n"); + // disconnection event usbh_device_unplugged(dev0->rhport, 0, 0); return true; // restart task @@ -424,6 +451,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT_ERR( usbh_pipe_control_open(0, 8) ); //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// + TU_LOG2("Get 8 byte of Device Descriptor \r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, @@ -434,12 +462,16 @@ bool enum_task(hcd_event_t* event) bool is_ok = usbh_control_xfer(0, &request, _usbh_ctrl_buf); //------------- Reset device again before Set Address -------------// + TU_LOG2("Port reset \r\n"); + if (dev0->hub_addr == 0) { // connected directly to roothub TU_ASSERT(is_ok); // TODO some slow device is observed to fail the very fist controller xfer, can try more times hcd_port_reset( dev0->rhport ); // reset port after 8 byte descriptor osal_task_delay(RESET_DELAY); +// hcd_port_reset_end(dev0->rhport); +// osal_task_delay(RESET_DELAY); } #if CFG_TUH_HUB else @@ -458,6 +490,7 @@ bool enum_task(hcd_event_t* event) #endif //------------- Set new address -------------// + TU_LOG2("Set Address \r\n"); uint8_t const new_addr = get_new_address(); TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices @@ -484,6 +517,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT_ERR ( usbh_pipe_control_open(new_addr, ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0 ) ); //------------- Get full device descriptor -------------// + TU_LOG2("Get Device Descriptor \r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, @@ -502,6 +536,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT(configure_selected <= new_dev->configure_count); // TODO notify application when invalid configuration //------------- Get 9 bytes of configuration descriptor -------------// + TU_LOG2("Get 9 bytes of Configuration Descriptor \r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, @@ -515,6 +550,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT( CFG_TUSB_HOST_ENUM_BUFFER_SIZE >= ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength ); //------------- Get full configuration descriptor -------------// + TU_LOG2("Get full Configuration Descriptor \r\n"); request.wLength = ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength; // full length TU_ASSERT( usbh_control_xfer( new_addr, &request, _usbh_ctrl_buf ) ); @@ -522,6 +558,7 @@ bool enum_task(hcd_event_t* event) new_dev->interface_count = ((tusb_desc_configuration_t*) _usbh_ctrl_buf)->bNumInterfaces; //------------- Set Configure -------------// + TU_LOG2("Set Configuration Descriptor \r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, .bRequest = TUSB_REQ_SET_CONFIGURATION, @@ -577,11 +614,7 @@ bool enum_task(hcd_event_t* event) { uint16_t itf_len = 0; - if ( usbh_class_drivers[drv_id].open(new_dev->rhport, new_addr, desc_itf, &itf_len) ) - { - mark_interface_endpoint(new_dev->ep2drv, p_desc, itf_len, drv_id); - } - + TU_ASSERT( usbh_class_drivers[drv_id].open(new_dev->rhport, new_addr, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); p_desc += itf_len; } @@ -597,7 +630,7 @@ bool enum_task(hcd_event_t* event) /* USB Host Driver task * This top level thread manages all host controller event and delegates events to class-specific drivers. * This should be called periodically within the mainloop or rtos thread. - * + *_usbh_devices[dev_addr]. @code int main(void) { @@ -661,25 +694,4 @@ static inline uint8_t get_configure_number_for_device(tusb_desc_device_t* dev_de return config_num; } -// Helper marking endpoint of interface belongs to class driver -// TODO merge with usbd -static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) -{ - uint16_t len = 0; - - while( len < desc_len ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - - ep2drv[ tu_edpt_number(ep_addr) ][ tu_edpt_dir(ep_addr) ] = driver_id; - } - - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } -} - - #endif diff --git a/src/host/usbh.h b/src/host/usbh.h index 42a2bd095..bc0abcccc 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -94,6 +94,8 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); bool usbh_init(void); bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); + #ifdef __cplusplus } #endif -- cgit v1.3.1 From 4e8d414bc666d4636efd29e1c9feffd622d055c5 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 20 May 2020 13:38:41 +0700 Subject: added osal_queue_empty() API ported for osal none/freertos/mynewt --- src/osal/osal.h | 1 + src/osal/osal_freertos.h | 13 +++++++++---- src/osal/osal_mynewt.h | 6 ++++++ src/osal/osal_none.h | 12 ++++++++++-- 4 files changed, 26 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/osal/osal.h b/src/osal/osal.h index 0421b3294..3729ad94d 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -80,6 +80,7 @@ static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl); static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef); static inline bool osal_queue_receive(osal_queue_t const qhdl, void* data); static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, bool in_isr); +static inline bool osal_queue_empty(osal_queue_t const qhdl); #if 0 // TODO remove subtask related macros later // Sub Task diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 240206e33..839c1924f 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -118,14 +118,19 @@ static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq); } -static inline bool osal_queue_receive(osal_queue_t const queue_hdl, void* data) +static inline bool osal_queue_receive(osal_queue_t const qhdl, void* data) { - return xQueueReceive(queue_hdl, data, portMAX_DELAY); + return xQueueReceive(qhdl, data, portMAX_DELAY); } -static inline bool osal_queue_send(osal_queue_t const queue_hdl, void const * data, bool in_isr) +static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, bool in_isr) { - return in_isr ? xQueueSendToBackFromISR(queue_hdl, data, NULL) : xQueueSendToBack(queue_hdl, data, OSAL_TIMEOUT_WAIT_FOREVER); + return in_isr ? xQueueSendToBackFromISR(qhdl, data, NULL) : xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER); +} + +static inline bool osal_queue_empty(osal_queue_t const qhdl) +{ + return uxQueueMessagesWaiting(qhdl) > 0; } #ifdef __cplusplus diff --git a/src/osal/osal_mynewt.h b/src/osal/osal_mynewt.h index e47e140c1..f7c871c4b 100644 --- a/src/osal/osal_mynewt.h +++ b/src/osal/osal_mynewt.h @@ -161,6 +161,12 @@ static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, b return true; } +static inline bool osal_queue_empty(osal_queue_t const qhdl) +{ + return STAILQ_EMPTY(&qhdl->evq.evq_list); +} + + #ifdef __cplusplus } #endif diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index b27e628a9..c9b762915 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -142,7 +142,7 @@ typedef osal_queue_def_t* osal_queue_t; }\ } -// lock queue by disable usb isr +// lock queue by disable USB interrupt static inline void _osal_q_lock(osal_queue_t qhdl) { (void) qhdl; @@ -176,7 +176,6 @@ static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) return (osal_queue_t) qdef; } -// non blocking static inline bool osal_queue_receive(osal_queue_t const qhdl, void* data) { _osal_q_lock(qhdl); @@ -203,6 +202,15 @@ static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, b return success; } +static inline bool osal_queue_empty(osal_queue_t const qhdl) +{ + _osal_q_lock(qhdl); + bool is_empty = tu_fifo_empty(&qhdl->ff); + _osal_q_unlock(qhdl); + + return is_empty; +} + #ifdef __cplusplus } #endif -- cgit v1.3.1 From 88a455a9b99099bf27ce239006ecfd2da3894bcf Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 20 May 2020 14:31:45 +0700 Subject: added tud_task_event_ready() to check if there is pending events in the tud task without executing it. Useful to check before entering low power mode with WFI/WFE --- src/device/usbd.c | 8 ++++++++ src/device/usbd.h | 3 +++ 2 files changed, 11 insertions(+) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 06e724cb3..f7918c07e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -339,6 +339,14 @@ static void usbd_reset(uint8_t rhport) } } +bool tud_task_event_ready(void) +{ + // Skip if stack is not initialized + if ( !tusb_inited() ) return false; + + return !osal_queue_empty(_usbd_q); +} + /* USB Device Driver task * This top level thread manages all device controller event and delegates events to class-specific drivers. * This should be called periodically within the mainloop or rtos thread. diff --git a/src/device/usbd.h b/src/device/usbd.h index 713bee2b2..ecef63e18 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -47,6 +47,9 @@ bool tud_init (void); // Task function should be called in main/rtos loop void tud_task (void); +// Check if there is pending events need proccessing by tud_task() +bool tud_task_event_ready(void); + // Interrupt handler, name alias to DCD #define tud_int_handler dcd_int_handler -- cgit v1.3.1 From d8a15aca777abb0094935440f7cd551b36d62f43 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 20 May 2020 14:38:34 +0700 Subject: remove osal_queue_t const qhdl from osal API since it doesn't make any differences. --- src/osal/osal.h | 6 +++--- src/osal/osal_freertos.h | 6 +++--- src/osal/osal_mynewt.h | 6 +++--- src/osal/osal_none.h | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/osal/osal.h b/src/osal/osal.h index 3729ad94d..2e7a3539f 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -78,9 +78,9 @@ static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl); //------------- Queue -------------// static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef); -static inline bool osal_queue_receive(osal_queue_t const qhdl, void* data); -static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, bool in_isr); -static inline bool osal_queue_empty(osal_queue_t const qhdl); +static inline bool osal_queue_receive(osal_queue_t qhdl, void* data); +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr); +static inline bool osal_queue_empty(osal_queue_t qhdl); #if 0 // TODO remove subtask related macros later // Sub Task diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 839c1924f..d2d5f51c9 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -118,17 +118,17 @@ static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq); } -static inline bool osal_queue_receive(osal_queue_t const qhdl, void* data) +static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) { return xQueueReceive(qhdl, data, portMAX_DELAY); } -static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, bool in_isr) +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) { return in_isr ? xQueueSendToBackFromISR(qhdl, data, NULL) : xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER); } -static inline bool osal_queue_empty(osal_queue_t const qhdl) +static inline bool osal_queue_empty(osal_queue_t qhdl) { return uxQueueMessagesWaiting(qhdl) > 0; } diff --git a/src/osal/osal_mynewt.h b/src/osal/osal_mynewt.h index f7c871c4b..6882329c1 100644 --- a/src/osal/osal_mynewt.h +++ b/src/osal/osal_mynewt.h @@ -125,7 +125,7 @@ static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) return (osal_queue_t) qdef; } -static inline bool osal_queue_receive(osal_queue_t const qhdl, void* data) +static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) { struct os_event* ev; ev = os_eventq_get(&qhdl->evq); @@ -137,7 +137,7 @@ static inline bool osal_queue_receive(osal_queue_t const qhdl, void* data) return true; } -static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, bool in_isr) +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) { (void) in_isr; @@ -161,7 +161,7 @@ static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, b return true; } -static inline bool osal_queue_empty(osal_queue_t const qhdl) +static inline bool osal_queue_empty(osal_queue_t qhdl) { return STAILQ_EMPTY(&qhdl->evq.evq_list); } diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index c9b762915..3bbf15119 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -176,7 +176,7 @@ static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) return (osal_queue_t) qdef; } -static inline bool osal_queue_receive(osal_queue_t const qhdl, void* data) +static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) { _osal_q_lock(qhdl); bool success = tu_fifo_read(&qhdl->ff, data); @@ -185,7 +185,7 @@ static inline bool osal_queue_receive(osal_queue_t const qhdl, void* data) return success; } -static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, bool in_isr) +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) { if (!in_isr) { _osal_q_lock(qhdl); @@ -202,7 +202,7 @@ static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, b return success; } -static inline bool osal_queue_empty(osal_queue_t const qhdl) +static inline bool osal_queue_empty(osal_queue_t qhdl) { _osal_q_lock(qhdl); bool is_empty = tu_fifo_empty(&qhdl->ff); -- cgit v1.3.1 From a0fe3a80e74fceee6c97fcf734822280d1cfd62e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 20 May 2020 15:09:46 +0700 Subject: remove queue lock/unlock per review --- src/osal/osal_none.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 3bbf15119..0ac5e8aac 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -204,11 +204,9 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in static inline bool osal_queue_empty(osal_queue_t qhdl) { - _osal_q_lock(qhdl); - bool is_empty = tu_fifo_empty(&qhdl->ff); - _osal_q_unlock(qhdl); - - return is_empty; + // Skip queue lock/unlock since this function is primarily called + // with interrupt disabled before going into low power mode + return tu_fifo_empty(&qhdl->ff); } #ifdef __cplusplus -- cgit v1.3.1 From 8b66098335cb93504c7680fadad502b59ff73b48 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 20 May 2020 15:21:11 +0700 Subject: fix freeRTOS logic --- src/osal/osal_freertos.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index d2d5f51c9..42ea1fd19 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -130,7 +130,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in static inline bool osal_queue_empty(osal_queue_t qhdl) { - return uxQueueMessagesWaiting(qhdl) > 0; + return uxQueueMessagesWaiting(qhdl) == 0; } #ifdef __cplusplus -- cgit v1.3.1 From ff9994116e932170acd117db7732863d95a348f6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 21 May 2020 21:22:12 +0700 Subject: fix nrf hanged (blocking wait) when called within critical section --- examples/device/cdc_msc/ses/nrf5x/nrf5x.emProject | 29 ++++++---- src/portable/nordic/nrf5x/dcd_nrf5x.c | 68 +++++++++++++++++++---- 2 files changed, 73 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_msc/ses/nrf5x/nrf5x.emProject b/examples/device/cdc_msc/ses/nrf5x/nrf5x.emProject index fa5534635..f7714f269 100644 --- a/examples/device/cdc_msc/ses/nrf5x/nrf5x.emProject +++ b/examples/device/cdc_msc/ses/nrf5x/nrf5x.emProject @@ -19,8 +19,9 @@ arm_target_device_name="nRF52840_xxAA" arm_target_interface_type="SWD" build_treat_warnings_as_errors="Yes" - c_preprocessor_definitions="NRF52840_XXAA;__nRF_FAMILY;ARM_MATH_CM4;FLASH_PLACEMENT=1;CFG_TUSB_MCU=OPT_MCU_NRF5X" - c_user_include_directories="../../src;$(rootDir)/hw/mcu/nordic/cmsis/Include;$(rootDir)/hw;$(rootDir)/src;$(nrfxDir)/..;$(nrfxDir);$(nrfxDir)/mdk;$(nrfxDir)/hal;$(nrfxDir)/drivers/include;$(nrfxDir)/drivers/src" + c_additional_options="-Wno-error=undef;-Wno-error=unused-parameter;-Wno-error=cast-align;-Wno-error=cast-function-type" + c_preprocessor_definitions="NRF52840_XXAA;__nRF_FAMILY;ARM_MATH_CM4;FLASH_PLACEMENT=1;CFG_TUSB_MCU=OPT_MCU_NRF5X;CFG_TUSB_DEBUG=1" + c_user_include_directories="../../src;$(rootDir)/lib/CMSIS_4/CMSIS/Include;$(rootDir)/hw;$(rootDir)/src;$(nrfxDir)/..;$(nrfxDir);$(nrfxDir)/mdk;$(nrfxDir)/hal;$(nrfxDir)/drivers/include;$(nrfxDir)/drivers/src" debug_register_definition_file="nrf52840_Registers.xml" debug_target_connection="J-Link" gcc_enable_all_warnings="Yes" @@ -42,11 +43,12 @@ recurse="Yes" /> - - - + + + + @@ -103,16 +105,10 @@ - + + + + + + + + + diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index d788547b8..7ca32c4f6 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -51,6 +51,11 @@ enum USBD_INTENCLR_ENDISOIN_Msk | USBD_INTEN_ENDISOOUT_Msk }; +enum +{ + EP_COUNT = 8 +}; + // Transfer descriptor typedef struct { @@ -69,36 +74,73 @@ typedef struct static struct { // All 8 endpoints including control IN & OUT (offset 1) - xfer_td_t xfer[8][2]; + xfer_td_t xfer[EP_COUNT][2]; - // Only one DMA can run at a time - volatile bool dma_running; + // Number of pending DMA that is started but not handled yet by dcd_int_handler(). + // Since nRF can only carry one DMA can run at a time, this value is normally be either 0 or 1. + // However, in critical section with interrupt disabled, the DMA can be finished and added up + // until handled by dcd_init_handler() when exiting critical section. + volatile uint8_t dma_pending; }_dcd; /*------------------------------------------------------------------*/ /* Control / Bulk / Interrupt (CBI) Transfer *------------------------------------------------------------------*/ +// NVIC_GetEnableIRQ is only available in CMSIS v5 +#ifndef NVIC_GetEnableIRQ +static inline uint32_t NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif + // helper to start DMA static void edpt_dma_start(volatile uint32_t* reg_startep) { // Only one dma can be active - if ( _dcd.dma_running ) + if ( _dcd.dma_pending ) { if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) { - // If called within ISR, use usbd task to defer later + // Called within ISR, use usbd task to defer later usbd_defer_func( (osal_task_func_t) edpt_dma_start, (void*) reg_startep, true ); return; } else { - // Otherwise simply block wait - while ( _dcd.dma_running ) { } + if ( __get_PRIMASK() || !NVIC_GetEnableIRQ(USBD_IRQn) ) + { + // Called in critical section with interrupt disabled. We have to manually check + // for the DMA complete by comparing current pending DMA with number of ENDED Events + uint32_t ended = 0; + + while ( _dcd.dma_pending < ((uint8_t) ended) ) + { + ended = NRF_USBD->EVENTS_ENDISOIN + NRF_USBD->EVENTS_ENDISOOUT; + + for (uint8_t i=0; iEVENTS_ENDEPIN[i] + NRF_USBD->EVENTS_ENDEPOUT[i]; + } + } + }else + { + // Called in non-critical thread-mode, should be 99% of the time. + // Should be safe to blocking wait until previous DMA transfer complete + while ( _dcd.dma_pending ) { } + } } } - _dcd.dma_running = true; + _dcd.dma_pending++; (*reg_startep) = 1; __ISB(); __DSB(); @@ -107,8 +149,8 @@ static void edpt_dma_start(volatile uint32_t* reg_startep) // DMA is complete static void edpt_dma_end(void) { - TU_ASSERT(_dcd.dma_running, ); - _dcd.dma_running = false; + TU_ASSERT(_dcd.dma_pending, ); + _dcd.dma_pending = 0; } // helper getting td @@ -282,9 +324,11 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t if ( control_status ) { - // Status Phase also require Easy DMA has to be free as well !!!! + // Status Phase also requires Easy DMA has to be available as well !!!! + // However TASKS_EP0STATUS doesn't trigger any DMA transfer and got ENDED event subsequently + // Therefore dma_running state will be corrected right away edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS); - edpt_dma_end(); + if (_dcd.dma_pending) _dcd.dma_pending--; // correct the dma_running++ in dma start // The nRF doesn't interrupt on status transmit so we queue up a success response. dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, false); -- cgit v1.3.1 From 9be2f1bf3dc2c89bc23eed1e95c06de41ebb0946 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 22 May 2020 12:09:34 +0200 Subject: Add basic UAC2 structure - untested --- src/class/audio/audio.h | 466 ++++++++++++++-- src/class/audio/audio_device.c | 1193 ++++++++++++++++++++++++++++++++++++++++ src/class/audio/audio_device.h | 304 ++++++++++ src/device/usbd.c | 13 + src/device/usbd.h | 37 ++ src/tusb.h | 4 + 6 files changed, 1982 insertions(+), 35 deletions(-) create mode 100644 src/class/audio/audio_device.c create mode 100644 src/class/audio/audio_device.h (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 5bec14d88..f4f460c22 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -35,64 +35,460 @@ #include "common/tusb_common.h" #ifdef __cplusplus - extern "C" { +extern "C" { #endif +/// Isochronous End Point Attributes +typedef enum +{ + TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, + TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, + TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, + TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point + TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point +} tusb_iso_ep_attribute_t; + /// Audio Interface Subclass Codes typedef enum { - AUDIO_SUBCLASS_CONTROL = 0x01 , ///< Audio Control - AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming - AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming + AUDIO_SUBCLASS_UNDEFINED = 0x00, + AUDIO_SUBCLASS_CONTROL , ///< Audio Control + AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming + AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming } audio_subclass_type_t; /// Audio Protocol Codes typedef enum { - AUDIO_PROTOCOL_V1 = 0x00, ///< Version 1.0 - AUDIO_PROTOCOL_V2 = 0x20, ///< Version 2.0 - AUDIO_PROTOCOL_V3 = 0x30, ///< Version 3.0 + AUDIO_PROTOCOL_V1 = 0x00, ///< Version 1.0 + AUDIO_PROTOCOL_V2 = 0x20, ///< Version 2.0 + AUDIO_PROTOCOL_V3 = 0x30, ///< Version 3.0 } audio_protocol_type_t; /// Audio Function Category Codes typedef enum { - AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, - AUDIO_FUNC_HOME_THEATER = 0x02, - AUDIO_FUNC_MICROPHONE = 0x03, - AUDIO_FUNC_HEADSET = 0x04, - AUDIO_FUNC_TELEPHONE = 0x05, - AUDIO_FUNC_CONVERTER = 0x06, - AUDIO_FUNC_SOUND_RECODER = 0x07, - AUDIO_FUNC_IO_BOX = 0x08, - AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, - AUDIO_FUNC_PRO_AUDIO = 0x0A, - AUDIO_FUNC_AUDIO_VIDEO = 0x0B, - AUDIO_FUNC_CONTROL_PANEL = 0x0C + AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, + AUDIO_FUNC_HOME_THEATER = 0x02, + AUDIO_FUNC_MICROPHONE = 0x03, + AUDIO_FUNC_HEADSET = 0x04, + AUDIO_FUNC_TELEPHONE = 0x05, + AUDIO_FUNC_CONVERTER = 0x06, + AUDIO_FUNC_SOUND_RECODER = 0x07, + AUDIO_FUNC_IO_BOX = 0x08, + AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, + AUDIO_FUNC_PRO_AUDIO = 0x0A, + AUDIO_FUNC_AUDIO_VIDEO = 0x0B, + AUDIO_FUNC_CONTROL_PANEL = 0x0C, } audio_function_t; -/// Audio Class-Specific AC Interface Descriptor Subtypes +/// Audio Class-Specific AC Interface Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, + AUDIO_CS_AC_INTERFACE_HEADER = 0x01, + AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, + AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, + AUDIO_CS_AC_INTERFACE_MIXER_UNIT = 0x04, + AUDIO_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, + AUDIO_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, + AUDIO_CS_AC_INTERFACE_EFFECT_UNIT = 0x07, + AUDIO_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08, + AUDIO_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09, + AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A, + AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B, + AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C, + AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, +} audio_cs_ac_interface_subtype_t; + +/// Audio Class-Specific AS Interface Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, + AUDIO_CS_AS_INTERFACE_AS_GENERAL = 0x01, + AUDIO_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, + AUDIO_CS_AS_INTERFACE_ENCODER = 0x03, + AUDIO_CS_AS_INTERFACE_DECODER = 0x04, +} audio_cs_as_interface_subtype_t; + +/// Audio Class-Control Values UAC2 +typedef enum +{ + AUDIO_CTRL_NONE = 0x00, ///< No Host access + AUDIO_CTRL_R = 0x01, ///< Host read access only + AUDIO_CTRL_RW = 0x03, ///< Host read write access +} audio_control_t; + +/// Audio Class-Specific AC Interface Descriptor Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0, +} audio_cs_ac_interface_control_pos_t; + +/// Audio Class-Specific AS Interface Descriptor Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0, + AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, +} audio_cs_as_interface_control_pos_t; + +/// Audio Class-Specific EP Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_EP_SUBTYPE_DESCRIPTOR_UNDEFINED = 0x00, + AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, +} audio_cs_ep_subtype_t; + +/// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, + AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, +} audio_cs_as_iso_data_ep_attribute_t; + +/// Audio Class-Specific AS Isochronous Data EP Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0, + AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2, + AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4, +} audio_cs_as_iso_data_ep_control_pos_t; + +/// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, +} audio_cs_as_iso_data_ep_lock_delay_unit_t; + +/// Audio Class-Clock Source Attributes UAC2 +typedef enum +{ + AUDIO_CLOCK_SOURCE_ATT_EXT_CLK = 0x00, + AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01, + AUDIO_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02, + AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03, + AUDIO_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04, +} audio_clock_source_attribute_t; + +/// Audio Class-Clock Source Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0, + AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2, +} audio_clock_source_control_pos_t; + +/// Audio Class-Clock Selector Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_SELECTOR_CTRL_POS = 0, +} audio_clock_selector_control_pos_t; + +/// Audio Class-Clock Multiplier Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0, + AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, +} audio_clock_multiplier_control_pos_t; + +/// Audio Class-Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, + AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, + AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, +} audio_terminal_type_t; + +/// Audio Class-Input Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, + AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, + AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, + AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, + AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, + AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, + AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, +} audio_terminal_input_type_t; + +/// Audio Class-Input Terminal Controls UAC2 +typedef enum +{ + AUDIO_IN_TERM_CTRL_CPY_PROT_POS = 0, + AUDIO_IN_TERM_CTRL_CONNECTOR_POS = 2, + AUDIO_IN_TERM_CTRL_OVERLOAD_POS = 4, + AUDIO_IN_TERM_CTRL_CLUSTER_POS = 6, + AUDIO_IN_TERM_CTRL_UNDERFLOW_POS = 8, + AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, +} audio_terminal_input_control_pos_t; + +/// Audio Class-Output Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, + AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, + AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, + AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, + AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, + AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, + AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, + AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, +} audio_terminal_output_type_t; + +/// Audio Class-Output Terminal Controls UAC2 +typedef enum +{ + AUDIO_OUT_TERM_CTRL_CPY_PROT_POS = 0, + AUDIO_OUT_TERM_CTRL_CONNECTOR_POS = 2, + AUDIO_OUT_TERM_CTRL_OVERLOAD_POS = 4, + AUDIO_OUT_TERM_CTRL_UNDERFLOW_POS = 6, + AUDIO_OUT_TERM_CTRL_OVERFLOW_POS = 8, +} audio_terminal_output_control_pos_t; + +/// Audio Class-Feature Unit Controls UAC2 typedef enum { - AUDIO_CS_INTERFACE_HEADER = 0x01, - AUDIO_CS_INTERFACE_INPUT_TERMINAL = 0x02, - AUDIO_CS_INTERFACE_OUTPUT_TERMINAL = 0x03, - AUDIO_CS_INTERFACE_MIXER_UNIT = 0x04, - AUDIO_CS_INTERFACE_SELECTOR_UNIT = 0x05, - AUDIO_CS_INTERFACE_FEATURE_UNIT = 0x06, - AUDIO_CS_INTERFACE_EFFECT_UNIT = 0x07, - AUDIO_CS_INTERFACE_PROCESSING_UNIT = 0x08, - AUDIO_CS_INTERFACE_EXTENSION_UNIT = 0x09, - AUDIO_CS_INTERFACE_CLOCK_SOURCE = 0x0A, - AUDIO_CS_INTERFACE_CLOCK_SELECTOR = 0x0B, - AUDIO_CS_INTERFACE_CLOCK_MULTIPLIER = 0x0C, - AUDIO_CS_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, -} audio_cs_interface_subtype_t; + AUDIO_FEATURE_UNIT_CTRL_MUTE_POS = 0, + AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS = 2, + AUDIO_FEATURE_UNIT_CTRL_BASS_POS = 4, + AUDIO_FEATURE_UNIT_CTRL_MID_POS = 6, + AUDIO_FEATURE_UNIT_CTRL_TREBLE_POS = 8, + AUDIO_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10, + AUDIO_FEATURE_UNIT_CTRL_AGC_POS = 12, + AUDIO_FEATURE_UNIT_CTRL_DELAY_POS = 14, + AUDIO_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16, + AUDIO_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18, + AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20, + AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22, + AUDIO_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24, + AUDIO_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26, + AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, +} audio_feature_unit_control_pos_t; + +/// Audio Class-Format Type Codes UAC2 +typedef enum +{ + AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, + AUDIO_FORMAT_TYPE_I = 0x01, + AUDIO_FORMAT_TYPE_II = 0x02, + AUDIO_FORMAT_TYPE_III = 0x03, + AUDIO_FORMAT_TYPE_IV = 0x04, + AUDIO_EXT_FORMAT_TYPE_I = 0x81, + AUDIO_EXT_FORMAT_TYPE_II = 0x82, + AUDIO_EXT_FORMAT_TYPE_III = 0x83, +} audio_format_type_t; + +/// Audio Class-Audio Data Format Type I UAC2 +typedef enum +{ + AUDIO_DATA_FORMAT_TYPE_I_PCM = 0x00000000, + AUDIO_DATA_FORMAT_TYPE_I_PCM8 = 0x00000001, + AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = 0x00000002, + AUDIO_DATA_FORMAT_TYPE_I_ALAW = 0x00000003, + AUDIO_DATA_FORMAT_TYPE_I_MULAW = 0x00000004, +} audio_data_format_type_I_t; + +/// Audio Class-Audio Channel Configuration UAC2 +typedef enum +{ + AUDIO_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000, + AUDIO_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001, + AUDIO_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002, + AUDIO_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004, + AUDIO_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008, + AUDIO_CHANNEL_CONFIG_BACK_LEFT = 0x00000010, + AUDIO_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020, + AUDIO_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040, + AUDIO_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080, + AUDIO_CHANNEL_CONFIG_BACK_CENTER = 0x00000100, + AUDIO_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200, + AUDIO_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400, + AUDIO_CHANNEL_CONFIG_TOP_CENTER = 0x00000800, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000, + AUDIO_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000, + AUDIO_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000, + AUDIO_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000, + AUDIO_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000, + AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, + AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, + AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, + AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, +} audio_channel_config_t; + +/// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes: 9. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. + uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). + uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. + uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. + uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. +} audio_desc_cs_ac_interface_t; + +/// AUDIO Clock Source Descriptor (4.7.2.1) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes: 8. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. + uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. + uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. +} audio_desc_clock_source_t; + +/// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. + uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. + uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. +} audio_desc_clock_selector_t; + +/// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins +#define audio_desc_clock_selector_n_t(source_num) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength ; \ + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bClockID ; \ + uint8_t bNrInPins ; \ + struct TU_ATTR_PACKED { \ + uint8_t baSourceID ; \ + } sourceID[source_num] ; \ + uint8_t bmControls ; \ + uint8_t iClockSource ; \ + } + +/// AUDIO Clock Multiplier Descriptor (4.7.2.3) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. + uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. +} audio_desc_clock_multiplier_t; + +/// AUDIO Input Terminal Descriptor(4.7.2.4) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. + uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. + uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. + uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. +} audio_desc_input_terminal_t; + +/// AUDIO Output Terminal Descriptor(4.7.2.5) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. + uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. + uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. + uint16_t bmControls ; ///< See: audio_terminal_output_type_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. +} audio_desc_output_terminal_t; + +/// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. + uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. + struct TU_ATTR_PACKED { + uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. + } controls[2] ; + uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. +} audio_desc_feature_unit_t; + +/// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels +#define audio_desc_feature_unit_n_t(ch_num) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength ; /* 6+(ch_num+1)*4 */\ + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bUnitID ; \ + uint8_t bSourceID ; \ + struct TU_ATTR_PACKED { \ + uint32_t bmaControls ; \ + } controls[ch_num+1] ; \ + uint8_t iTerminal ; \ + } + +/// AUDIO Class-Specific AS Interface Descriptor(4.9.2) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. + uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. + uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. + uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. + uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. + uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. +} audio_desc_cs_as_interface_t; + +/// AUDIO Type I Format Type Descriptor(2.3.1.6 - Audio Formats) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. + uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. + uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. +} audio_desc_type_I_format_t; + +/// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. + uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. + uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. + uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. + uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. +} audio_desc_cs_as_iso_data_ep_t; + /** @} */ #ifdef __cplusplus - } +} #endif #endif diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c new file mode 100644 index 000000000..fbd412564 --- /dev/null +++ b/src/class/audio/audio_device.c @@ -0,0 +1,1193 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Reinhard Panhuber + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +/* + * This driver supports at most one out EP, one in EP, one control EP, and one feedback EP and one alternative interface other than zero. Hence, only one input terminal and one output terminal are support, if you need more adjust the driver! + * It supports multiple TX and RX channels. + * + * In case you need more alternate interfaces, you need to define additional defines for this specific alternate interface. Just define them and set them in the set_interface function. + * + * */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "audio_device.h" +#include "class/audio/audio.h" +#include "device/usbd_pvt.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function + +#if CFG_TUD_AUDIO_EPSIZE_IN + uint8_t ep_in; // Outgoing (out of uC) audio data EP. + uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT + uint8_t ep_out; // Incoming (into uC) audio data EP. + uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + uint8_t ep_fb; // Feedback EP. +#endif + +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + uint8_t ep_int_ctr; // Audio control interrupt EP. +#endif + +#if CFG_TUD_AUDIO_N_AS_INT + uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; +#endif + /*------------- From this point, data is not cleared by bus reset -------------*/ + // FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_USE_TX_FIFO + tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; + CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_BUFSIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; +#endif +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO + tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; + CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_BUFSIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; +#endif +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + tu_fifo_t int_ctr_ff; + CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t int_ctr_ff_mutex; +#endif +#endif + + // Endpoint Transfer buffers +#if CFG_TUD_AUDIO_EPSIZE_OUT + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) + + // TODO: required? + //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // uint16_t fb_val; // Feedback value for asynchronous mode! + //#endif + +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN]; +#endif + +} audiod_interface_t; + +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_USE_TX_FIFO +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, tx_ff) +#elif CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, rx_ff) +#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, int_ctr_ff) +#elif CFG_TUD_AUDIO_EPSIZE_OUT +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epout_buf) +#elif CFG_TUD_AUDIO_EPSIZE_IN +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epin_buf) +#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ep_int_ctr_buf) +#endif + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; + +extern const uint16_t tud_audio_desc_lengths[]; + +#if CFG_TUD_AUDIO_EPSIZE_OUT +static audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t const* buffer, uint32_t bufsize); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN +static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied); +#endif + +static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); +static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); + +static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); + +bool tud_audio_n_mounted(uint8_t itf) +{ + audiod_interface_t* audio = &_audiod_itf[itf]; + +#if CFG_TUD_AUDIO_EPSIZE_OUT + if (audio->ep_out == 0) + { + return false; + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN + if (audio->ep_in == 0) + { + return false; + } +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + if (audio->ep_int_ctr == 0) + { + return false; + } +#endif + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + if (audio->ep_fb == 0) + { + return false; + } +#endif + + return true; +} + +//--------------------------------------------------------------------+ +// READ API +//--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO + +uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId) +{ + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + return tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); +} + +uint16_t tud_audio_n_read(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) +{ + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); +} + +void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId) +{ + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); +} + +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + +uint16_t tud_audio_int_ctr_n_available(uint8_t itf) +{ + return tu_fifo_count(&_audiod_itf[itf].int_ctr_ff); +} + +uint16_t tud_audio_int_ctr_n_read(uint8_t itf, void* buffer, uint16_t bufsize) +{ + return tu_fifo_read_n(&_audiod_itf[itf].int_ctr_ff, buffer, bufsize); +} + +void tud_audio_int_ctr_n_read_flush (uint8_t itf) +{ + tu_fifo_clear(&_audiod_itf[itf].int_ctr_ff); +} + +#endif + +// This function is called once something is received by USB and is responsible for decoding received stream into audio channels. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_USE_RX_FIFO = 0. + +#if CFG_TUD_AUDIO_EPSIZE_OUT + +static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) +{ + switch (CFG_TUD_AUDIO_FORMAT_TYPE_RX) + { + case AUDIO_FORMAT_TYPE_UNDEFINED: + // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! + asm("nop"); + break; + + case AUDIO_FORMAT_TYPE_I: + + switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) + { + case AUDIO_DATA_FORMAT_TYPE_I_PCM: + +#if CFG_TUD_AUDIO_USE_RX_FIFO + TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); +#else +#error YOUR DECODING AND BUFFERING IS REQUIRED HERE! +#endif + break; + + default: + // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! + asm("nop"); + break; + } + break; + + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! + asm("nop"); + break; + } + + // Call a weak callback here - a possibility for user to get informed RX was completed + TTU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); + return true; +} + +#endif //CFG_TUD_AUDIO_EPSIZE_OUT + +// The following functions are used in case CFG_TUD_AUDIO_USE_RX_FIFO == 1 +#if CFG_TUD_AUDIO_USE_RX_FIFO +static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize) +{ + (void) rhport; + + // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel + if (bufsize % CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX*CFG_TUD_AUDIO_N_CHANNELS_RX != 0) { + return false; + } + + uint8_t chId = 0; + uint16_t cnt; +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 + uint8_t sample = 0; +#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 2 + uint16_t sample = 0; +#else + uint32_t sample = 0; +#endif + + for(cnt = 0; cnt < bufsize; cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) + { + // Let alignment problems be handled by memcpy + memcpy(&sample, &buffer[cnt], CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX); + if(tu_fifo_write_n(&audio->rx_ff[chId++], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE) != CFG_TUD_AUDIO_RX_ITEMSIZE) + { + // Buffer overflow + return false; + } + + if (chId == CFG_TUD_AUDIO_N_CHANNELS_RX) + { + chId = 0; + } + } +} } +#endif //CFG_TUD_AUDIO_USE_RX_FIFO + + +#if CFG_TUD_AUDIO_EPSIZE_OUT +TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize) +{ + (void) rhport; + (void) buffer; + (void) bufsize; + + /* NOTE: This function should not be modified, when the callback is needed, + the tud_audio_rx_done_cb could be implemented in the user file + */ + + return true; +} +#endif + +//--------------------------------------------------------------------+ +// WRITE API +//--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) +{ + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->p_desc == NULL) { + return 0; + } + + return tu_fifo_write_n(&audio->tx_ff[channelId], buffer, bufsize); +} +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 + +uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t bufsize) +{ + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->itf_num == 0) { + return 0; + } + + return tu_fifo_write_n(&audio->int_ctr_ff, buffer, bufsize); +} + +#endif + + +// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_USE_TX_FIFO = 0. +#if CFG_TUD_AUDIO_EPSIZE_IN +static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +{ + switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) + { + case AUDIO_FORMAT_TYPE_UNDEFINED: + // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! + asm("nop"); + break; + + case AUDIO_FORMAT_TYPE_I: + + switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_TX) + { + case AUDIO_DATA_FORMAT_TYPE_I_PCM: + +#if CFG_TUD_AUDIO_USE_TX_FIFO + TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); +#else +#error YOUR ENCODING AND BUFFERING IS REQUIRED HERE! +#endif + break; + + default: + // YOUR ENCODING AND SENDING IS REQUIRED HERE! + asm("nop"); + break; + } + break; + + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! + asm("nop"); + break; + } + + // Call a weak callback here - a possibility for user to get informed TX was completed + TU_VERIFY(tud_audio_tx_done_cb(rhport, n_bytes_copied)); + return true; +} + +#endif //CFG_TUD_AUDIO_EPSIZE_IN + +#if CFG_TUD_AUDIO_USE_TX_FIFO +static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +{ + // We encode directly into IN EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); + + // Determine amount of samples + uint16_t nSamplesPerChannelToSend = 0xFFFF; + uint8_t cntChannel; + + for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + { + if (audio->tx_ff[cntChannel].count < nSamplesPerChannelToSend) + { + nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count; + } + } + + // Check if there is enough + if (nSamplesPerChannelToSend == 0) + { + *n_bytes_copied = 0; + return true; + } + + // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! + if (nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX > CFG_TUD_AUDIO_EPSIZE_IN) + { + nSamplesPerChannelToSend = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + } + + // Encode + uint16_t cntSample; + uint8_t * pBuff = audio->epin_buf; +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 + uint8_t sample; +#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 + uint16_t sample; +#else + uint32_t sample; +#endif + + // TODO: Big endianess handling + for (cntSample = 0; cntSample < nSamplesPerChannelToSend; cntSample++) + { + for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + { + // Get sample from buffer + tu_fifo_read(&audio->tx_ff[cntChannel], &sample); + + // Put it into EP's buffer - Let alignment problems be handled by memcpy + memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); + + // Advance pointer + pBuff += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + } + } + + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX)); + *n_bytes_copied = nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + return true; +} + +#endif //CFG_TUD_AUDIO_USE_TX_FIFO + +// This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) +{ + (void) rhport; + (void) audio; + + // Here we need to return the feedback value +#error RETURN YOUR FEEDBACK VALUE HERE! + + TU_VERIFY(tud_audio_fb_done_cb(rhport)); + return 0; +} + +#endif + +// This function is called once a transmit of an interrupt control packet was successfully completed. Here, we get the remaining bytes to send + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +static bool audio_int_ctr_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +{ + // We write directly into the EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_int_ctr)); + + // TODO: Big endianess handling + uint16_t cnt = tu_fifo_read_n(audio->int_ctr_ff, audio->ep_int_ctr_buf, CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN); + + if (cnt > 0) + { + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_int_ctr, audio->ep_int_ctr_buf, cnt)); + } + + *n_bytes_copied = cnt; + + TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, n_bytes_copied)); + + return true; +} +#endif + +// Callback functions +// Currently the return value has to effect so far. The return value finally is discarded in tud_task(void) in usbd.c - we just incorporate that for later use + +#if CFG_TUD_AUDIO_EPSIZE_IN +TU_ATTR_WEAK bool tud_audio_tx_done_cb(uint8_t rhport, uint16_t * n_bytes_copied) +{ + (void) rhport; + (void) n_bytes_copied; + + /* NOTE: This function should not be modified, when the callback is needed, + the tud_audio_tx_done_cb could be implemented in the user file + */ + + return true; +} +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport) +{ + (void) rhport; + + /* NOTE: This function should not be modified, when the callback is needed, + the tud_audio_fb_done_cb could be implemented in the user file + */ + + return true; +} +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_copied) +{ + (void) rhport; + (void) n_bytes_copied; + + /* NOTE: This function should not be modified, when the callback is needed, + the tud_audio_int_ctr_done_cb could be implemented in the user file + */ + + return true; +} + +#endif + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void audiod_init(void) +{ + uint8_t cnt; + tu_memclr(_audiod_itf, sizeof(_audiod_itf)); + + for(uint8_t i=0; i 0 && CFG_TUD_AUDIO_USE_TX_FIFO + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + { + tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_BUFSIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); +#endif + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + { + tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_BUFSIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); +#endif + } +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 + tu_fifo_config(&audio->int_ctr_ff, &audio->int_ctr_ff_buf, CFG_TUD_AUDIO_INT_CTR_BUFSIZE, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->int_ctr_ff, osal_mutex_create(&audio->int_ctr_ff_mutex)); +#endif +#endif + } +} + +void audiod_reset(uint8_t rhport) +{ + (void) rhport; + + for(uint8_t i=0; i 0 && CFG_TUD_AUDIO_USE_TX_FIFO + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + { + tu_fifo_clear(&audio->tx_ff[cnt]); + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + { + tu_fifo_clear(&audio->rx_ff[cnt]); + } +#endif + } +} + +bool audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +{ + TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); + + // Verify version is correct - this check can be omitted + TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); + + // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted + if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed + { + TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); + } + + // Alternate setting MUST be zero - this check can be omitted + TU_VERIFY(itf_desc->bAlternateSetting == 0); + + // Find available audio driver interface + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (!_audiod_itf[i].p_desc) + { + _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one + break; + } + } + + // Verify we found a free one + TU_ASSERT( i < CFG_TUD_AUDIO ); + + // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) + + // Notify caller we read complete descriptor + (*p_length) += tud_audio_desc_lengths[i]; + + return true; +} + +static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + +#if CFG_TUD_AUDIO_N_AS_INT > 0 + uint8_t const itf = tu_u16_low(p_request->wIndex); + + // Find index of audio streaming interface + uint8_t idxDriver, idxItf; + uint8_t const *dummy; + + TU_VERIFY(audiod_get_interface_index(itf, &idxDriver, &idxItf, &dummy)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].altSetting[idxItf], 1)); + + return true; + +#else + (void) p_request; + return false; +#endif +} + +static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Here we need to do the following: + + // 1. Find the audio driver interface which was assigned to the given interface which is to be set + // Since one audio driver interface has to be able to cover an unknown number of interfaces (AC, AS + its alternate settings), the best memory efficient way to solve this is to always search through the descriptors. + // The audio driver interface is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching + + // 2. Close EPs which are currently open + // To do so it is not necessary to know the current active alternate interface since we already save the current EP addresses - we simply close them + + // 3. Open new EP + + uint8_t const itf = tu_u16_low(p_request->wIndex); + uint8_t const alt = tu_u16_low(p_request->wValue); + + // Find index of audio streaming interface and index of interface + uint8_t idxDriver, idxItf; + uint8_t const *p_desc; + TU_VERIFY(audiod_get_interface_index(itf, &idxDriver, &idxItf, &p_desc)); + + // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 + if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) + { + _audiod_itf[idxDriver].ep_in_as_intf_num = 0; + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); + _audiod_itf[idxDriver].ep_in = 0; // Necessary? + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT + if (_audiod_itf[idxDriver].ep_out_as_intf_num == itf) + { + _audiod_itf[idxDriver].ep_out_as_intf_num = 0; + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_out); + _audiod_itf[idxDriver].ep_out = 0; // Necessary? + + // Close corresponding feedback EP +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_fb); + _audiod_itf[idxDriver].ep_fb = 0; // Necessary? +#endif + } +#endif + + + // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[idxDriver].p_desc + tud_audio_desc_lengths[idxDriver]; + + // p_desc starts at required interface with alternate setting zero + while (p_desc < p_desc_end) + { + // Find correct interface + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) + { + // Open EPs + uint8_t foundEPs = 0; + while (foundEPs < ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints && p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) + { + TU_ASSERT(dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); + uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP + { + _audiod_itf[idxDriver].ep_in = ep_addr; + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT + + if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary + { + // Save address + _audiod_itf[idxDriver].ep_out = ep_addr; + + // Prepare for incoming data + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + } + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback + { + _audiod_itf[idxDriver].ep_fb = ep_addr; + } +#endif + +#endif + foundEPs += 1; + } + p_desc = tu_desc_next(p_desc); + } + + // We are done - abort loop + break; + } + + // Increase index, bytes read, and pointer + p_desc = tu_desc_next(p_desc); + } + + // Check for nothing found - we can rely on this since EP descriptors are never the last descriptors, there are always also class specific EP descriptors following! + TU_VERIFY(p_desc < p_desc_end); + + // Conduct audio driver function specific stuff + + // HERE DO WHAT YOU HAVE TO DO - E.G. START ADC OR SO + //#error Implementation specific setInterface code required here! + + // Save current alternative interface setting + _audiod_itf[idxDriver].altSetting[idxItf] = alt; + + return true; +} + +bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + (void) p_request; + return true; +} + +// Handle class control request +// return false to stall control endpoint (e.g unsupported request) +bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + switch (p_request->bRequest) + { + case TUSB_REQ_GET_INTERFACE: + return audiod_get_interface(rhport, p_request); + + case TUSB_REQ_SET_INTERFACE: + return audiod_set_interface(rhport, p_request); + + default: + return false; + } +} + +bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) result; + + // Search for interface belonging to given end point address and proceed as required + uint8_t idxDriver; + for (idxDriver = 0; idxDriver < CFG_TUD_AUDIO; idxDriver++) + { + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + + // Data transmission of control interrupt finished + if (_audiod_itf[idxDriver].ep_int_ctr == ep_addr) + { + // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) + // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? + // In case of an erroneous transmission a retransmission is conducted - this is taken care of by PHY ??? + + // Load new data + uint16 *n_bytes_copied; + TU_VERIFY(audio_int_ctr_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); + + if (*n_bytes_copied == 0 && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN))) + { + // There is no data left to send, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + } + +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN + + // Data transmission of audio packet finished + if (_audiod_itf[idxDriver].ep_in == ep_addr) + { + // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." + // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." + // This can only be solved reliably if we load a ZLP after every IN transmission since we can not say if the host requests samples earlier than we declared! Once all samples are collected we overwrite the loaded ZLP. + + // Check if there is data to load into EPs buffer - if not load it with ZLP + // Be aware - we as a device are not able to know if the host polls for data with a faster rate as we stated this in the descriptors. Therefore we always have to put something into the EPs buffer. However, once we did that, there is no way of aborting this or replacing what we put into the buffer before! + // This is the only place where we can fill something into the EPs buffer! + + // Load new data + uint16_t *n_bytes_copied = NULL; + TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); + + if (*n_bytes_copied == 0) + { + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + + return true; + } +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT + + // New audio packet received + if (_audiod_itf[idxDriver].ep_out == ep_addr) + { + // Save into buffer - do whatever has to be done + TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].epout_buf, xferred_bytes)); + + // prepare for next transmission + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + + return true; + } + + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // Transmission of feedback EP finished + if (_audiod_itf[idxDriver].ep_fb == ep_addr) + { + if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver])) + { + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + + return true; + } +#endif +#endif + } + + return false; + +} + +static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) +{ + // Loop over audio driver interfaces + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (!_audiod_itf[i].p_desc) + { + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + // Advance past AC descriptors + uint8_t const * p_desc = tu_desc_next(_audiod_itf[i].p_desc); + p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; + + uint8_t tmp = 0; + while (p_desc < p_desc_end) + { + // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + { + *idxItf = tmp; + *idxDriver = i; + *pp_desc_int = p_desc; + return true; + } + + // Increase index, bytes read, and pointer + tmp++; + p_desc = tu_desc_next(p_desc); + } + } + } + + return false; +} + +#endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO + +// OLD +//// In order that this function works the following is mandatory: +// // - An IAD descriptor is required and has to be placed directly before the Standard AC Interface Descriptor (4.7.1) ALSO if no Audio Streaming interfaces are used! +// // - The Standard AC Interface Descriptor (4.7.1) has to be the first interface listed (required by UAC2 specification) +// // - The alternate interfaces of the Standard AS Interface Descriptor(4.9.1) must be listed in increasing order and alternate 0 must have zero EPs +// +// TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && +// AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); +// +// // Verify version is correct - this check can be omitted +// TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); +// +// // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted +// if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed +// { +// TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); +// } +// +// // Alternate setting MUST be zero - this check can be omitted +// TU_VERIFY(itf_desc->bAlternateSetting == 0); +// +// // Since checks are successful we get the number of interfaces we have to process by exploiting the fact that an IAD descriptor has to be provided directly before this AC descriptor +// // We do not get this value delivered by the stack so we need to hack a little bit - the number of interfaces to be processed is listed in the IAD descriptor with an offset of exactly 5 +// uint8_t nItfs = *(((uint8_t const *) itf_desc) - 5) - 1; // -1 since we already process the (included) AC interface +// +// // Notify caller we have read Standard AC Interface Descriptor (4.7.1) +// (*p_length) = sizeof(tusb_desc_interface_t); +// +// // Go to next descriptor which has to be a Class-Specific AC Interface Header Descriptor(4.7.2) - always present +// audio_desc_cs_ac_interface_t const * p_desc_cs_ac = (audio_desc_cs_ac_interface_t const *) tu_desc_next ( (uint8_t const *) itf_desc ); +// +// // Verify its the correct descriptor - this check can be omitted +// TU_VERIFY(p_desc_cs_ac->bDescriptorType == TUSB_DESC_CS_INTERFACE +// && p_desc_cs_ac->bDescriptorSubType == AUDIO_CS_AC_INTERFACE_HEADER +// && p_desc_cs_ac->bcdADC == 0x0200); +// +// // We do not check the Audio Function Category Codes +// +// // We do not check all the following Clock Source, Unit and Terminal descriptors +// +// // We do not check the latency control +// +// // We jump over all the following descriptor to the next following interface (which should be a Standard AS Interface Descriptor(4.9.1) if nItfs > 0) +// (*p_length) += p_desc_cs_ac->wTotalLength; // Notify caller of read bytes +// itf_desc = (tusb_desc_interface_t const * )(((uint8_t const *)p_desc_cs_ac ) + p_desc_cs_ac->wTotalLength); // Move pointer +// +// // From this point on we have nItfs packs of audio streaming interfaces (consisting of multiple descriptors always starting with a Standard AS Interface Descriptor(4.9.1)) +// +// uint8_t cnt; +// uint8_t nEPs; +// audio_format_type_t formatType; +// uint8_t intNum; +// uint8_t altInt; +// +// for (cnt = 0; cnt < nItfs; cnt++) +// { +// +// // Here starts an unknown number of alternate interfaces - the art here is to find the end of this interface pack. We do not have the total number of descriptor bytes available (not provided by tinyUSB stack for .open() function) so we try to find the end of this interface pack by deducing it from the order and content of the descriptor pack +// while(1) +// { +// // At first this should be a Standard AS Interface Descriptor(4.9.1) - this check can be omitted +// TU_VERIFY(itf_desc->bDescriptorType == TUSB_DESC_INTERFACE && +// itf_desc->bInterfaceClass == TUSB_CLASS_AUDIO && +// itf_desc->bInterfaceSubClass == AUDIO_SUBCLASS_STREAMING && +// itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); +// +// // Remember number of EPs this interface has - required for later +// nEPs = itf_desc->bNumEndpoints; +// intNum = itf_desc->bInterfaceNumber; +// altInt = itf_desc->bAlternateSetting; +// +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// +// // It is possible now that the following interface is again a Standard AS Interface Descriptor(4.9.1) (in case the related terminal has more than zero EPs at all and this is the following alternative interface > 0 - the alternative (that this is not a Standard AS Interface Descriptor(4.9.1) but a Class-Specific AS Interface Descriptor(4.9.2)) could be in case the related terminal has no EPs at all e.g. SPDIF connector +// if (tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_INTERFACE) +// { +// // It is not possible, that a Standard AS Interface Descriptor(4.9.1) ends without a Class-Specific AS Interface Descriptor(4.9.2) +// // hence the next interface has to be an alternative interface with regard to the one we started above - continue +// continue; +// } +// +// // Second, this interface has to be a Class-Specific AS Interface Descriptor(4.9.2) - this check can be omitted +// TU_VERIFY(tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_CS_INTERFACE && +// ((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_AS_GENERAL); +// +// // Remember format type of this interface - required for later +// formatType = ((audio_desc_cs_as_interface_t *) itf_desc)->bFormatType; +// +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// +// // Every Class-Specific AS Interface Descriptor(4.9.2) defines a format type and thus a format type descriptor e.g. Type I Format Type Descriptor(2.3.1.6 - Audio Formats) should follow - only if the format type is undefined no format type descriptor follows +// if (formatType != AUDIO_FORMAT_TYPE_UNDEFINED) +// { +// // We do not need any information from this descriptor - we simply advance +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// } +// +// // Now there might be an encoder/decoder interface - i found no clue if this interface is mandatory (although examples found by google never use this descriptor) or if there is any way to determine if this descriptor is reliably present or not. Problem here: Since we need to find the end of this interface pack and we do not have the total amount of descriptor bytes available here (not given by the tinyUSB stack for the .open() function), we have to make a speculative check if the following is an encoder/decoder interface or not. +// // It could be possible that we ready over the total length of all descriptor bytes here - we simply hope that the combination of descriptor length, type, and sub type does not occur randomly in memory here. The only way to make this check waterproof is to know how many bytes we can read at all but this would be an information we need to be given by tinyUSB! +// if (tu_desc_len((uint8_t const *) itf_desc) == 21 && tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_CS_INTERFACE && (((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_ENCODER || ((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_DECODER)) +// { +// // We do not need any information from this descriptor - we simply advance +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// } +// +// // Here may be some EP descriptors +// for (uint8_t cntEP = 0; cntEP < nEPs; cntEP++) +// { +// // This check can be omitted +// TU_VERIFY(tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_ENDPOINT); +// +// // Here we can find information about our EPs address etc. but in the initialization process we do not set anything, we have to wait for the host to send a setInterface request where the EPs etc. are set up according +// +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// // If the usage type is something else than feedback there is a Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) following up +// if (((tusb_desc_endpoint_t *) itf_desc)->bmAttributes.usage != 0x10) +// { +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// +// // We do not need any information from this descriptor - we simply advance +// // Notify caller we have read bytes +// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); +// +// } +// +// // Advance pointer +// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); +// } +// +// // Okay we processed a complete pack - now we have to make a speculative check if the next interface is an alternate interface belonging to the ones processed before - since it is speculative we check a lot to reduce the chances we go wrong and hope for the best +// if (!(tu_desc_len((uint8_t const *) itf_desc) == 9 && tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_INTERFACE && itf_desc->bInterfaceNumber == intNum && itf_desc->bAlternateSetting == altInt + 1)) +// { +// // The current interface is not a consecutive alternate interface to the one processed above +// break; +// } +// } +// +// } + + +// Here follow the encoding steps + +//#if CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_UNDEFINED +// +//#error Individual encoding procedure required! +// +//#elif CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I +// +//#if CFG_TUD_AUDIO_FORMAT_TYPE_I_TX == AUDIO_DATA_FORMAT_TYPE_I_PCM +// +//#if CFG_TUD_AUDIO_USE_TX_FIFO +// TU_VERIFY(audio_tx_done_type_I_pcm_cb(rhport, audio, n_bytes_copied)); +//#else +//#error YOUR ENCODING AND SENDING IS REQUIRED HERE! +//#endif +// +//#else +//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX not implemented! +//#endif +// +//#else +//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! +//#endif +// +// // Call a weak callback here - a possibility for user to get informed TX was completed +// TU_VERIFY(tud_audio_tx_done_cb(rhport, n_bytes_copied)); +// return true; + +//#if CFG_TUD_AUDIO_EPSIZE_OUT +//static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) { +// +// // Here follow the decoding steps +// +//#if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_UNDEFINED +// +//#error Individual decoding procedure required! +// +//#elif CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I +// +//#if CFG_TUD_AUDIO_FORMAT_TYPE_I_RX == AUDIO_DATA_FORMAT_TYPE_I_PCM +// +//#if CFG_TUD_AUDIO_USE_RX_FIFO +// TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); +//#else +//#error YOUR DECODING AND BUFFERING IS REQUIRED HERE! +//#endif +// +//#else +//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_RX not implemented! +//#endif +// +//#else +//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! +//#endif +// +// TU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); +// return true; +//} +//#endif diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h new file mode 100644 index 000000000..5354adbd4 --- /dev/null +++ b/src/class/audio/audio_device.h @@ -0,0 +1,304 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ha Thach (tinyusb.org) and Reinhard Panhuber + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_AUDIO_DEVICE_H_ +#define _TUSB_AUDIO_DEVICE_H_ + +#include "assert.h" +#include "common/tusb_common.h" +#include "device/usbd.h" + +#include "audio.h" +#include "tusb_config.h" + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ + +// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just waste a few bytes) +#ifndef CFG_TUD_AUDIO_N_AS_INT +#define CFG_TUD_AUDIO_N_AS_INT 0 +#endif + +// Use internal FIFOs - In this case, audio.c implements FIFOs for RX and TX (whatever required) and implements encoding and decoding (parameterized by the defines below). +// For RX: the input stream gets decoded into its corresponding channels, where for each channel a FIFO is setup to hold its data -> see: audio_rx_done_cb(). +// For TX: the output stream is composed from CFG_TUD_AUDIO_N_CHANNELS_TX channels, where for each channel a FIFO is defined. +// If you disable this you need to fill in desired code into audio_rx_done_cb() and Y on your own, however, this allows for optimizations in byte processing. +#ifndef CFG_TUD_AUDIO_USE_RX_FIFO +#define CFG_TUD_AUDIO_USE_RX_FIFO 0 +#endif + +#ifndef CFG_TUD_AUDIO_USE_TX_FIFO +#define CFG_TUD_AUDIO_USE_TX_FIFO 0 +#endif + +// End point sizes - Limits: Full Speed <= 1023, High Speed <= 1024 +#ifndef CFG_TUD_AUDIO_EPSIZE_IN +#define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 +#ifndef CFG_TUD_AUDIO_TX_BUFSIZE +#define CFG_TUD_AUDIO_TX_BUFSIZE CFG_TUD_AUDIO_EPSIZE_IN // Buffer size per channel +#endif +#endif + +#ifndef CFG_TUD_AUDIO_EPSIZE_OUT +#define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 +#ifndef CFG_TUD_AUDIO_RX_BUFSIZE +#define CFG_TUD_AUDIO_RX_BUFSIZE CFG_TUD_AUDIO_EPSIZE_OUT // Buffer size per channel +#endif +#endif + +#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback +#endif + +#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +#ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE +#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#endif +#endif + +#ifndef CFG_TUD_AUDIO_N_CHANNELS_TX +#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 +#endif + +#ifndef CFG_TUD_AUDIO_N_CHANNELS_RX +#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 +#endif + +// Audio data format types +#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_TX +#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, an encoding function has to be implemented in audio_device.c +#endif + +#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_RX +#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, a decoding function has to be implemented in audio_device.c +#endif + +// Audio data format type I specifications +#if CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I + +// Type definitions - for possible formats see: audio_data_format_type_I_t and further in UAC2 specifications. +#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_TX +#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM +#endif + +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 +#endif + +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 +#define CFG_TUD_AUDIO_TX_ITEMSIZE 1 +#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 +#define CFG_TUD_AUDIO_TX_ITEMSIZE 2 +#else +#define CFG_TUD_AUDIO_TX_ITEMSIZE 4 +#endif + +#endif + +#if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I + +#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_RX +#define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM +#endif + +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 +#endif + +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 +#define CFG_TUD_AUDIO_RX_ITEMSIZE 1 +#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 2 +#define CFG_TUD_AUDIO_RX_ITEMSIZE 2 +#else +#define CFG_TUD_AUDIO_RX_ITEMSIZE 4 +#endif + +#endif + +//static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); + +// Supported types of this driver: +// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup AUDIO_Serial Serial + * @{ + * \defgroup AUDIO_Serial_Device Device + * @{ */ + +//--------------------------------------------------------------------+ +// Application API (Multiple Interfaces) +// CFG_TUD_AUDIO > 1 +//--------------------------------------------------------------------+ +bool tud_audio_n_mounted (uint8_t itf); + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +uint16_t tud_audio_n_available (uint8_t itf, uint8_t channelId); +uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); +void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +uint16_t tud_audio_int_ctr_n_available (uint8_t itf); +uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); +void tud_audio_int_ctr_n_read_flush (uint8_t itf); +uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t bufsize); +#endif + +//--------------------------------------------------------------------+ +// Application API (Interface0) +//--------------------------------------------------------------------+ + +inline bool tud_audio_mounted (void); + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +inline uint16_t tud_audio_available (void); +inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); +inline void tud_audio_read_flush (void); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +inline uint32_t tud_audio_int_ctr_available (void); +inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize); +inline void tud_audio_int_ctr_read_flush (void); +inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); +#endif + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_EPSIZE_IN +bool tud_audio_tx_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT +bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize); +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +bool tud_audio_fb_done_cb(uint8_t rhport); +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); +#endif + +//--------------------------------------------------------------------+ +// Inline Functions +//--------------------------------------------------------------------+ + +inline bool tud_audio_mounted(void) +{ + return tud_audio_n_mounted(0); +} + +#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used +{ + return tud_audio_n_write(0, channelId, buffer, bufsize); +} +#endif // CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO + +#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +inline uint16_t tud_audio_available(uint8_t channelId) +{ + return tud_audio_n_available(0, channelId); +} + +inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize) +{ + return tud_audio_n_read(0, channelId, buffer, bufsize); +} + +inline void tud_audio_read_flush(uint8_t channelId) +{ + tud_audio_n_read_flush(0, channelId); +} +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +inline uint16_t tud_audio_int_ctr_available(void) +{ + return tud_audio_int_ctr_n_available(0); +} + +inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize) +{ + return tud_audio_int_ctr_n_read(0, buffer, bufsize); +} + +inline void tud_audio_int_ctr_read_flush(void) +{ + return tud_audio_int_ctr_n_read_flush(0); +} + +inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) +{ + return tud_audio_int_ctr_n_write(0, buffer, bufsize); +} +#endif + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void audiod_init (void); +void audiod_reset (uint8_t rhport); +bool audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +bool audiod_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool audiod_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_AUDIO_DEVICE_H_ */ + +/** @} */ +/** @} */ diff --git a/src/device/usbd.c b/src/device/usbd.c index f7918c07e..a19993cad 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -135,6 +135,19 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif +#if CFG_TUD_AUDIO +{ + DRIVER_NAME("AUDIO") + .init = audiod_init, + .reset = audiod_reset, + .open = audiod_open, + .control_request = audiod_control_request, + .control_complete = audiod_control_complete, + .xfer_cb = audiod_xfer_cb, + .sof = NULL +}, +#endif + #if CFG_TUD_MIDI { DRIVER_NAME("MIDI") diff --git a/src/device/usbd.h b/src/device/usbd.h index ecef63e18..24a2332e3 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -307,6 +307,43 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ TUD_MIDI_JACKID_OUT_EMB(1) +//------------- AUDIO -------------// + +// Length of template descriptor (132 bytes) +#define TUD_AUDIO_MIC_DESC_LEN (8 + 9 + 9 + 8 + 17 + 12 + 14 + 9 + 9 + 16 + 6 + 7 + 8) +#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 + +// AUDIO simple descriptor (UAC2) for 1 microphone input +// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source +#define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ + /* Standard Interface Association Descriptor (IAD) */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 0x02, TUSB_CLASS_AUDIO, 0x00, AUDIO_PROTOCOL_V2, 0x00,\ + /* Standard AC Interface Descriptor(4.7.1) */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0x00, 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx,\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0200), AUDIO_FUNC_MICROPHONE, U16_TO_U8S_LE(9+8+17+12+6+(1+1)*4), AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS,\ + /* Clock Source Descriptor(4.7.2.1) */\ + 8, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, 0x04, AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), 0x00, \ + /* Input Terminal Descriptor(4.7.2.4) */\ + 17, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, 0x01, U16_TO_U8S_LE(AUDIO_TERM_TYPE_IN_GENERIC_MIC), 0x00, 0x04, 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, U16_TO_U8S_LE(AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), 0x00, \ + /* Output Terminal Descriptor(4.7.2.5) */\ + 12, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, 0x03, U16_TO_U8S_LE(AUDIO_TERM_TYPE_USB_STREAMING), 0x00, 0x02, 0x04, U16_TO_U8S_LE(0x0000), 0x00, \ + /* Feature Unit Descriptor(4.7.2.8) */\ + 6+(1+1)*4, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, 0x02, 0x01, U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), 0x00, \ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x00, /* number of EPs */ 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x01, /* number of EPs */ 0x01, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + 16, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, 0x03, AUDIO_CTRL_NONE, AUDIO_FORMAT_TYPE_I, U32_TO_U8S_LE(AUDIO_DATA_FORMAT_TYPE_I_PCM), 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, \ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + 6, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _nBytesPerSample, _nBitsUsedPerSample,\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + 7, TUSB_DESC_ENDPOINT, _epin, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), U16_TO_U8S_LE(_epsize), (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01,\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + 8, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, U16_TO_U8S_LE(0x0000)\ //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) diff --git a/src/tusb.h b/src/tusb.h index 55c105121..ecd885c26 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -76,6 +76,10 @@ #include "class/msc/msc_device.h" #endif +#if CFG_TUD_AUDIO + #include "class/audio/audio_device.h" +#endif + #if CFG_TUD_MIDI #include "class/midi/midi_device.h" #endif -- cgit v1.3.1 From d108ea4326d824da73da0a4f9632c5da6aa2e3ec Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 22 May 2020 21:45:34 +0700 Subject: implement hcd_uframe_number for ohci able to get 8 byte descriptors using LPC1769 + base, but failed to reset and set address. --- .../host/cdc_msc_hid/ses/lpc40xx/lpc40xx.emProject | 24 ++++++++++++++-------- src/host/ohci/ohci.c | 15 +++++++++++++- src/host/ohci/ohci.h | 2 ++ 3 files changed, 32 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/ses/lpc40xx/lpc40xx.emProject b/examples/host/cdc_msc_hid/ses/lpc40xx/lpc40xx.emProject index bfb7922a3..68995f1a5 100644 --- a/examples/host/cdc_msc_hid/ses/lpc40xx/lpc40xx.emProject +++ b/examples/host/cdc_msc_hid/ses/lpc40xx/lpc40xx.emProject @@ -18,8 +18,8 @@ arm_target_debug_interface_type="ADIv5" arm_target_device_name="LPC4088" arm_target_interface_type="SWD" - c_preprocessor_definitions="CORE_M4;__LPC4000_FAMILY;__LPC408x_SUBFAMILY;ARM_MATH_CM4;FLASH_PLACEMENT=1;BOARD_EA4088QS;CFG_TUSB_MCU=OPT_MCU_LPC40XX;CFG_TUSB_MEM_SECTION= __attribute__((section(".bss2")))" - c_user_include_directories="../../src;$(rootDir)/hw;$(rootDir)/src;$(lpcDir)/inc" + c_preprocessor_definitions="CORE_M4;__LPC4000_FAMILY;__LPC408x_SUBFAMILY;ARM_MATH_CM4;FLASH_PLACEMENT=1;BOARD_EA4088QS;CFG_TUSB_MCU=OPT_MCU_LPC40XX;CFG_TUSB_MEM_SECTION= __attribute__((section(".bss2")));CFG_TUSB_DEBUG=2;LOGGER_RTT" + c_user_include_directories="../../src;$(rootDir)/hw;$(rootDir)/src;$(lpcDir)/inc;$(rootDir)/lib/SEGGER_RTT/RTT" debug_register_definition_file="$(ProjectDir)/LPC408x_7x_Registers.xml" debug_target_connection="J-Link" gcc_enable_all_warnings="Yes" @@ -55,6 +55,7 @@ + @@ -91,12 +92,6 @@ - + + + + + + + + + + + + + interrupt_disable = OHCI_REG->interrupt_enable; // disable all interrupts OHCI_REG->interrupt_status = OHCI_REG->interrupt_status; // clear current set bits OHCI_REG->interrupt_enable = OHCI_INT_WRITEBACK_DONEHEAD_MASK | OHCI_INT_RESUME_DETECTED_MASK | - OHCI_INT_UNRECOVERABLE_ERROR_MASK | /*OHCI_INT_FRAME_OVERFLOW_MASK |*/ OHCI_INT_RHPORT_STATUS_CHANGE_MASK | + OHCI_INT_UNRECOVERABLE_ERROR_MASK | OHCI_INT_FRAME_OVERFLOW_MASK | OHCI_INT_RHPORT_STATUS_CHANGE_MASK | OHCI_INT_MASTER_ENABLE_MASK; OHCI_REG->control |= OHCI_CONTROL_CONTROL_BULK_RATIO | OHCI_CONTROL_LIST_CONTROL_ENABLE_MASK | @@ -181,6 +181,13 @@ bool hcd_init(void) return true; } +uint32_t hcd_uframe_number(uint8_t rhport) +{ + (void) rhport; + return (ohci_data.frame_number_hi << 16 | OHCI_REG->frame_number) << 3; +} + + //--------------------------------------------------------------------+ // PORT API //--------------------------------------------------------------------+ @@ -606,6 +613,12 @@ void hcd_isr(uint8_t hostid) if (int_status == 0) return; + // Frame number overflow + if ( int_status & OHCI_INT_FRAME_OVERFLOW_MASK ) + { + ohci_data.frame_number_hi++; + } + //------------- RootHub status -------------// if ( int_status & OHCI_INT_RHPORT_STATUS_CHANGE_MASK ) { diff --git a/src/host/ohci/ohci.h b/src/host/ohci/ohci.h index 6f6ef9676..bfcdaf9a3 100644 --- a/src/host/ohci/ohci.h +++ b/src/host/ohci/ohci.h @@ -180,6 +180,8 @@ typedef struct TU_ATTR_ALIGNED(256) ohci_ed_t ed_pool[HCD_MAX_ENDPOINT]; ohci_gtd_t gtd_pool[HCD_MAX_XFER]; + volatile uint16_t frame_number_hi; + } ohci_data_t; //--------------------------------------------------------------------+ -- cgit v1.3.1 From fad088719e7cc4d1cab9216eb81567dd67af65f7 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 26 May 2020 15:21:23 +0700 Subject: merge CFG_TUSB_RHPORT1_MODE into CFG_TUSB_RHPORT0_MODE each port is 1 byte for easy maintenance --- examples/device/cdc_msc/src/tusb_config.h | 25 +++++++++++----- hw/bsp/ea4357/ea4357.c | 8 ++--- hw/bsp/mcb1800/mcb1800.c | 8 ++--- hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c | 4 +-- hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c | 4 +-- hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c | 4 +-- hw/bsp/ngx4330/ngx4330.c | 8 ++--- hw/bsp/teensy_40/teensy40.c | 4 +-- src/tusb_option.h | 50 +++++++++++++++++-------------- 9 files changed, 66 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index 09e98b247..9beb9f6a2 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -34,19 +34,30 @@ // COMMON CONFIGURATION //-------------------------------------------------------------------- -// defined by compiler flags for flexibility +// defined by board.mk #ifndef CFG_TUSB_MCU #error CFG_TUSB_MCU must be defined #endif -#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 +// RHPort number used for device can be defined by board.mk, default to port 0 +#ifndef BOARD_DEVICE_RHPORT_NUM + #define BOARD_DEVICE_RHPORT_NUM 0 #endif -#define CFG_TUSB_OS OPT_OS_NONE +// RHPort max operational speed can defined by board.mk +// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed +#ifndef BOARD_DEVICE_RHPORT_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 BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED + #else + #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED + #endif +#endif + +// Device mode with rhport and speed defined by board.mk +#define CFG_TUSB_RHPORT0_MODE ((OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) << (8*BOARD_DEVICE_RHPORT_NUM)) +#define CFG_TUSB_OS OPT_OS_NONE // CFG_TUSB_DEBUG is defined by compiler in DEBUG build // #define CFG_TUSB_DEBUG 0 diff --git a/hw/bsp/ea4357/ea4357.c b/hw/bsp/ea4357/ea4357.c index b7e7f7a5c..04c4e60a6 100644 --- a/hw/bsp/ea4357/ea4357.c +++ b/hw/bsp/ea4357/ea4357.c @@ -149,7 +149,7 @@ void board_init(void) * status feedback from the distribution switch. GPIO54 is used for VBUS sensing. 15Kohm pull-down * resistors are always active */ -#if CFG_TUSB_RHPORT0_MODE +#if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE | OPT_MODE_HOST) Chip_USB0_Init(); // // Reset controller @@ -185,7 +185,7 @@ void board_init(void) * of VBUS can be read via U31. * JP16 shall not be inserted. */ -#if CFG_TUSB_RHPORT1_MODE +#if CFG_TUSB_RHPORT0_MODE & ((OPT_MODE_DEVICE | OPT_MODE_HOST) << 8) Chip_USB1_Init(); // // Reset controller @@ -232,11 +232,11 @@ void USB0_IRQHandler(void) void USB1_IRQHandler(void) { - #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST + #if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_HOST << 8) tuh_isr(1); #endif - #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE + #if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE << 8) tud_int_handler(1); #endif } diff --git a/hw/bsp/mcb1800/mcb1800.c b/hw/bsp/mcb1800/mcb1800.c index ae9f1b62f..6387f983e 100644 --- a/hw/bsp/mcb1800/mcb1800.c +++ b/hw/bsp/mcb1800/mcb1800.c @@ -43,11 +43,11 @@ void USB0_IRQHandler(void) void USB1_IRQHandler(void) { - #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST + #if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_HOST << 8) tuh_isr(1); #endif - #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE + #if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE << 8) tud_int_handler(1); #endif } @@ -163,7 +163,7 @@ void board_init(void) }; // USB0 -#if CFG_TUSB_RHPORT0_MODE +#if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE | OPT_MODE_HOST) Chip_USB0_Init(); // // Reset controller @@ -180,7 +180,7 @@ void board_init(void) #endif // USB1 -#if CFG_TUSB_RHPORT1_MODE +#if CFG_TUSB_RHPORT0_MODE & ((OPT_MODE_DEVICE | OPT_MODE_HOST) << 8) Chip_USB1_Init(); // // Reset controller diff --git a/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c b/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c index be0ae3ea8..8dae7a0c2 100644 --- a/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c +++ b/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c @@ -134,11 +134,11 @@ void USB_OTG1_IRQHandler(void) void USB_OTG2_IRQHandler(void) { - #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST + #if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_HOST << 8) tuh_isr(1); #endif - #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE + #if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE << 8) tud_int_handler(1); #endif } diff --git a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c index be0ae3ea8..8dae7a0c2 100644 --- a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c +++ b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c @@ -134,11 +134,11 @@ void USB_OTG1_IRQHandler(void) void USB_OTG2_IRQHandler(void) { - #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST + #if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_HOST << 8) tuh_isr(1); #endif - #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE + #if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE << 8) tud_int_handler(1); #endif } diff --git a/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c b/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c index be0ae3ea8..8dae7a0c2 100644 --- a/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c +++ b/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c @@ -134,11 +134,11 @@ void USB_OTG1_IRQHandler(void) void USB_OTG2_IRQHandler(void) { - #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST + #if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_HOST << 8) tuh_isr(1); #endif - #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE + #if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE << 8) tud_int_handler(1); #endif } diff --git a/hw/bsp/ngx4330/ngx4330.c b/hw/bsp/ngx4330/ngx4330.c index 5296ddcb3..85d11d6ad 100644 --- a/hw/bsp/ngx4330/ngx4330.c +++ b/hw/bsp/ngx4330/ngx4330.c @@ -161,7 +161,7 @@ void board_init(void) * status feedback from the distribution switch. GPIO54 is used for VBUS sensing. 15Kohm pull-down * resistors are always active */ -#if CFG_TUSB_RHPORT0_MODE +#if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE | OPT_MODE_HOST) Chip_USB0_Init(); // // Reset controller @@ -197,7 +197,7 @@ void board_init(void) * of VBUS can be read via U31. * JP16 shall not be inserted. */ -#if CFG_TUSB_RHPORT1_MODE +#if CFG_TUSB_RHPORT0_MODE & ((OPT_MODE_DEVICE | OPT_MODE_HOST) << 8) Chip_USB1_Init(); // // Reset controller @@ -235,11 +235,11 @@ void USB0_IRQHandler(void) void USB1_IRQHandler(void) { - #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST + #if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_HOST << 8) tuh_isr(1); #endif - #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE + #if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE << 8) tud_int_handler(1); #endif } diff --git a/hw/bsp/teensy_40/teensy40.c b/hw/bsp/teensy_40/teensy40.c index f45a98ef3..0ca86f602 100644 --- a/hw/bsp/teensy_40/teensy40.c +++ b/hw/bsp/teensy_40/teensy40.c @@ -135,11 +135,11 @@ void USB_OTG1_IRQHandler(void) void USB_OTG2_IRQHandler(void) { - #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST + #if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_HOST << 8) tuh_isr(1); #endif - #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE + #if CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE << 8) tud_int_handler(1); #endif } diff --git a/src/tusb_option.h b/src/tusb_option.h index 9e6a2b532..472656424 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -114,44 +114,50 @@ /** \addtogroup group_configuration * @{ */ + //-------------------------------------------------------------------- -// CONTROLLER -// Only 1 roothub port can be configured to be device and/or host. -// tinyusb does not support dual devices or dual host configuration +// RootHub Mode Configuration +// +// Each byte of the CFG_TUSB_RHPORTx_MODE contains operation mode for +// a roothub port (device or host). Therefore each macro can have up to +// 4 ports. //-------------------------------------------------------------------- -/** \defgroup group_mode Controller Mode Selection - * \brief CFG_TUSB_CONTROLLER_N_MODE must be defined with these - * @{ */ + +// Lower 4-bit is operational mode #define OPT_MODE_NONE 0x00 ///< Disabled #define OPT_MODE_DEVICE 0x01 ///< Device Mode #define OPT_MODE_HOST 0x02 ///< Host Mode -#define OPT_MODE_HIGH_SPEED 0x10 ///< High speed -/** @} */ + +// Higher 4-bit is max operational speed (corresponding to tusb_speed_t) +#define OPT_MODE_FULL_SPEED 0x00 ///< Max Full Speed +#define OPT_MODE_LOW_SPEED 0x10 ///< Max Low Speed +#define OPT_MODE_HIGH_SPEED 0x20 ///< Max High Speed + #ifndef CFG_TUSB_RHPORT0_MODE #define CFG_TUSB_RHPORT0_MODE OPT_MODE_NONE #endif -#ifndef CFG_TUSB_RHPORT1_MODE - #define CFG_TUSB_RHPORT1_MODE OPT_MODE_NONE -#endif +//#ifndef CFG_TUSB_RHPORT1_MODE +// #define CFG_TUSB_RHPORT1_MODE OPT_MODE_NONE +//#endif -#if ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST) && (CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST)) || \ - ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE) && (CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE)) - #error "tinyusb does not support same modes on more than 1 roothub port" +#if ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST ) && (CFG_TUSB_RHPORT0_MODE & (OPT_MODE_HOST << 8)) ) || \ + ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE) && (CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE << 8)) ) + #error "TinyUSB currently does not support same modes on more than 1 roothub port" #endif // Which roothub port is configured as host -#define TUH_OPT_RHPORT ( (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST) ? 0 : ((CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST) ? 1 : -1) ) +#define TUH_OPT_RHPORT ( (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST) ? 0 : ((CFG_TUSB_RHPORT0_MODE & (OPT_MODE_HOST << 8)) ? 1 : -1) ) #define TUSB_OPT_HOST_ENABLED ( TUH_OPT_RHPORT >= 0 ) // Which roothub port is configured as device -#define TUD_OPT_RHPORT ( (CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE) ? 0 : ((CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE) ? 1 : -1) ) +#define TUD_OPT_RHPORT ( (CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE) ? 0 : ((CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE << 8)) ? 1 : -1) ) #if TUD_OPT_RHPORT == 0 -#define TUD_OPT_HIGH_SPEED ( CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED ) + #define TUD_OPT_HIGH_SPEED ( CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED ) #else -#define TUD_OPT_HIGH_SPEED ( CFG_TUSB_RHPORT1_MODE & OPT_MODE_HIGH_SPEED ) + #define TUD_OPT_HIGH_SPEED ( CFG_TUSB_RHPORT0_MODE & (OPT_MODE_HIGH_SPEED << 8) ) #endif #define TUSB_OPT_DEVICE_ENABLED ( TUD_OPT_RHPORT >= 0 ) @@ -168,15 +174,15 @@ // place data in accessible RAM for usb controller #ifndef CFG_TUSB_MEM_SECTION -#define CFG_TUSB_MEM_SECTION + #define CFG_TUSB_MEM_SECTION #endif #ifndef CFG_TUSB_MEM_ALIGN -#define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) + #define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) #endif #ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_NONE + #define CFG_TUSB_OS OPT_OS_NONE #endif //-------------------------------------------------------------------- @@ -184,7 +190,7 @@ //-------------------------------------------------------------------- #ifndef CFG_TUD_ENDPOINT0_SIZE - #define CFG_TUD_ENDPOINT0_SIZE 64 + #define CFG_TUD_ENDPOINT0_SIZE 64 #endif #ifndef CFG_TUD_CDC -- cgit v1.3.1 From b7ab60aa44ff7803161196b579eafd6c26321df7 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 26 May 2020 15:52:02 +0700 Subject: suporting multiple port (OTG FS + HS) for stm32 --- src/portable/st/synopsys/dcd_synopsys.c | 149 +++++++++++++++++--------------- 1 file changed, 80 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 717a59db6..ee987b0de 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -82,6 +82,33 @@ #include "device/dcd.h" +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +typedef struct +{ + uint32_t regs; // registers + const IRQn_Type irqnum; // IRQ number +// const uint8_t ep_count; // Max bi-directional Endpoints +}dcd_rhport_t; + +// To be consistent across stm32 port. We will number OTG_FS as Rhport0, and OTG_HS as Rhport1 +static const dcd_rhport_t _dcd_rhport[] = +{ + { .regs = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn } + +#ifdef USB_OTG_HS + ,{ .regs = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn } +#endif +}; + +#define DEVICE_BASE(_port) (USB_OTG_DeviceTypeDef *) (_dcd_rhport[_port].regs + USB_OTG_DEVICE_BASE) +#define OUT_EP_BASE(_port) (USB_OTG_OUTEndpointTypeDef *) (_dcd_rhport[_port].regs + USB_OTG_OUT_ENDPOINT_BASE) +#define IN_EP_BASE(_port) (USB_OTG_INEndpointTypeDef *) (_dcd_rhport[_port].regs + USB_OTG_IN_ENDPOINT_BASE) +#define FIFO_BASE(_port, _x) ((volatile uint32_t *) (_dcd_rhport[_port].regs + USB_OTG_FIFO_BASE + (_x) * USB_OTG_FIFO_SIZE)) + + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ @@ -90,11 +117,6 @@ // We disable SOF for now until needed later on #define USE_SOF 0 -#define DEVICE_BASE (USB_OTG_DeviceTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_DEVICE_BASE) -#define OUT_EP_BASE (USB_OTG_OUTEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_OUT_ENDPOINT_BASE) -#define IN_EP_BASE (USB_OTG_INEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_IN_ENDPOINT_BASE) -#define FIFO_BASE(_x) ((volatile uint32_t *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_FIFO_BASE + (_x) * USB_OTG_FIFO_SIZE)) - static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[6]; static uint8_t _setup_offs; // We store up to 3 setup packets. @@ -113,9 +135,10 @@ xfer_ctl_t xfer_status[EP_MAX][2]; // Setup the control endpoint 0. -static void bus_reset(void) { - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; - USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE; +static void bus_reset(uint8_t rhport) +{ + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); for(uint8_t n = 0; n < EP_MAX; n++) { out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; @@ -163,9 +186,11 @@ static void bus_reset(void) { USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; } -static void end_of_reset(void) { - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE; +static void end_of_reset(uint8_t rhport) +{ + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + // On current silicon on the Full Speed core, speed is fixed to Full Speed. // However, keep for debugging and in case Low Speed is ever supported. uint32_t enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; @@ -191,8 +216,6 @@ static void end_of_reset(void) { *------------------------------------------------------------------*/ void dcd_init (uint8_t rhport) { - (void) rhport; - // Programming model begins in the last section of the chapter on the USB // peripheral in each Reference Manual. USB_OTG_FS->GAHBCFG |= USB_OTG_GAHBCFG_GINT; @@ -210,7 +233,7 @@ void dcd_init (uint8_t rhport) // the core to stop working/require reset. USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OTGINT | USB_OTG_GINTMSK_MMISM; - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); // If USB host misbehaves during status portion of control xfer // (non zero-length packet), send STALL back and discard. Full speed. @@ -226,21 +249,17 @@ void dcd_init (uint8_t rhport) void dcd_int_enable (uint8_t rhport) { - (void) rhport; - NVIC_EnableIRQ(OTG_FS_IRQn); + NVIC_EnableIRQ(_dcd_rhport[rhport].irqnum); } void dcd_int_disable (uint8_t rhport) { - (void) rhport; - NVIC_DisableIRQ(OTG_FS_IRQn); + NVIC_EnableIRQ(_dcd_rhport[rhport].irqnum); } void dcd_set_address (uint8_t rhport, uint8_t dev_addr) { - (void) rhport; - - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); dev->DCFG |= (dev_addr << USB_OTG_DCFG_DAD_Pos) & USB_OTG_DCFG_DAD_Msk; // Response with status after changing device address @@ -254,16 +273,14 @@ void dcd_remote_wakeup(uint8_t rhport) void dcd_connect(uint8_t rhport) { - (void) rhport; - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); dev->DCTL &= ~USB_OTG_DCTL_SDIS; } void dcd_disconnect(uint8_t rhport) { - (void) rhport; - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); dev->DCTL |= USB_OTG_DCTL_SDIS; } @@ -275,10 +292,9 @@ void dcd_disconnect(uint8_t rhport) bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { - (void) rhport; - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; - USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE; - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE; + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); @@ -345,10 +361,9 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { - (void) rhport; - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; - USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE; - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE; + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -393,10 +408,9 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // (send STALL versus NAK handshakes back). Refactor into resuable function. void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { - (void) rhport; - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; - USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE; - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE; + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -445,9 +459,8 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { - (void) rhport; - USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE; - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE; + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -480,8 +493,8 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) // TODO: Split into "receive on endpoint 0" and "receive generic"; endpoint 0's // DOEPTSIZ register is smaller than the others, and so is insufficient for // determining how much of an OUT transfer is actually remaining. -static void receive_packet(xfer_ctl_t * xfer, /* USB_OTG_OUTEndpointTypeDef * out_ep, */ uint16_t xfer_size) { - usb_fifo_t rx_fifo = FIFO_BASE(0); +static void receive_packet(uint8_t rhport, xfer_ctl_t * xfer, /* USB_OTG_OUTEndpointTypeDef * out_ep, */ uint16_t xfer_size) { + usb_fifo_t rx_fifo = FIFO_BASE(rhport, 0); // See above TODO // uint16_t remaining = (out_ep->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DOEPTSIZ_XFRSIZ_Pos; @@ -539,8 +552,8 @@ static void receive_packet(xfer_ctl_t * xfer, /* USB_OTG_OUTEndpointTypeDef * ou } // Write a single data packet to EPIN FIFO -static void write_fifo_packet(uint8_t fifo_num, uint8_t * src, uint16_t len){ - usb_fifo_t tx_fifo = FIFO_BASE(fifo_num); +static void write_fifo_packet(uint8_t rhport, uint8_t fifo_num, uint8_t * src, uint16_t len){ + usb_fifo_t tx_fifo = FIFO_BASE(rhport, fifo_num); // Pushing full available 32 bit words to fifo uint16_t full_words = len >> 2; @@ -564,8 +577,8 @@ static void write_fifo_packet(uint8_t fifo_num, uint8_t * src, uint16_t len){ } } -static void read_rx_fifo(USB_OTG_OUTEndpointTypeDef * out_ep) { - usb_fifo_t rx_fifo = FIFO_BASE(0); +static void read_rx_fifo(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ep) { + usb_fifo_t rx_fifo = FIFO_BASE(rhport, 0); // Pop control word off FIFO (completed xfers will have 2 control words, // we only pop one ctl word each interrupt). @@ -580,7 +593,7 @@ static void read_rx_fifo(USB_OTG_OUTEndpointTypeDef * out_ep) { case 0x02: // Out packet recvd { xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - receive_packet(xfer, bcnt); + receive_packet(rhport, xfer, bcnt); } break; case 0x03: // Out packet done (Interrupt) @@ -605,7 +618,7 @@ static void read_rx_fifo(USB_OTG_OUTEndpointTypeDef * out_ep) { } } -static void handle_epout_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTypeDef * out_ep) { +static void handle_epout_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTypeDef * out_ep) { // DAINT for a given EP clears when DOEPINTx is cleared. // OEPINT will be cleared when DAINT's out bits are cleared. for(uint8_t n = 0; n < EP_MAX; n++) { @@ -615,7 +628,7 @@ static void handle_epout_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTy // SETUP packet Setup Phase done. if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_STUP) { out_ep[n].DOEPINT = USB_OTG_DOEPINT_STUP; - dcd_event_setup_received(0, (uint8_t*) &_setup_packet[2*_setup_offs], true); + dcd_event_setup_received(rhport, (uint8_t*) &_setup_packet[2*_setup_offs], true); _setup_offs = 0; } @@ -631,7 +644,7 @@ static void handle_epout_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTy // Transfer complete if short packet or total len is transferred if(xfer->short_packet || (xfer->queued_len == xfer->total_len)) { xfer->short_packet = false; - dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); } else { // Schedule another packet to be received. out_ep[n].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | \ @@ -643,7 +656,7 @@ static void handle_epout_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTy } } -static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointTypeDef * in_ep) { +static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointTypeDef * in_ep) { // DAINT for a given EP clears when DIEPINTx is cleared. // IEPINT will be cleared when DAINT's out bits are cleared. for ( uint8_t n = 0; n < EP_MAX; n++ ) @@ -657,7 +670,7 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType if ( in_ep[n].DIEPINT & USB_OTG_DIEPINT_XFRC ) { in_ep[n].DIEPINT = USB_OTG_DIEPINT_XFRC; - dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); } // XFER FIFO empty @@ -686,7 +699,7 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType xfer->queued_len = xfer->total_len - remaining_bytes; // Push packet to Tx-FIFO - write_fifo_packet(n, (xfer->buffer + xfer->queued_len), packet_size); + write_fifo_packet(rhport, n, (xfer->buffer + xfer->queued_len), packet_size); } // Turn off TXFE if all bytes are written. @@ -699,20 +712,18 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType } } -void dcd_int_handler(uint8_t rhport) { - - (void) rhport; - - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; - USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE; - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE; +void dcd_int_handler(uint8_t rhport) +{ + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); uint32_t int_status = USB_OTG_FS->GINTSTS; if(int_status & USB_OTG_GINTSTS_USBRST) { // USBRST is start of reset. USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_USBRST; - bus_reset(); + bus_reset(rhport); } if(int_status & USB_OTG_GINTSTS_ENUMDNE) { @@ -720,20 +731,20 @@ void dcd_int_handler(uint8_t rhport) { // always expect the same value. This interrupt is considered // the end of reset. USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; - end_of_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + end_of_reset(rhport); + dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); } if(int_status & USB_OTG_GINTSTS_USBSUSP) { USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_USBSUSP; - dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); } if(int_status & USB_OTG_GINTSTS_WKUINT) { USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_WKUINT; - dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); } if(int_status & USB_OTG_GINTSTS_OTGINT) @@ -743,7 +754,7 @@ void dcd_int_handler(uint8_t rhport) { if (otg_int & USB_OTG_GOTGINT_SEDET) { - dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); } USB_OTG_FS->GOTGINT = otg_int; @@ -761,20 +772,20 @@ void dcd_int_handler(uint8_t rhport) { // Mask out RXFLVL while reading data from FIFO USB_OTG_FS->GINTMSK &= ~USB_OTG_GINTMSK_RXFLVLM; - read_rx_fifo(out_ep); + read_rx_fifo(rhport, out_ep); USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; } // OUT endpoint interrupt handling. if(int_status & USB_OTG_GINTSTS_OEPINT) { // OEPINT is read-only - handle_epout_ints(dev, out_ep); + handle_epout_ints(rhport, dev, out_ep); } // IN endpoint interrupt handling. if(int_status & USB_OTG_GINTSTS_IEPINT) { // IEPINT bit read-only - handle_epin_ints(dev, in_ep); + handle_epin_ints(rhport, dev, in_ep); } } -- cgit v1.3.1 From 947c3eb10dee55e7c05bee8e10d21a225e311263 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 26 May 2020 16:07:48 +0700 Subject: multiple port support for global otg base --- src/portable/st/synopsys/dcd_synopsys.c | 65 +++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index ee987b0de..b68794712 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -103,6 +103,7 @@ static const dcd_rhport_t _dcd_rhport[] = #endif }; +#define GLOBAL_BASE(_port) ((USB_OTG_GlobalTypeDef*) _dcd_rhport[_port].regs) #define DEVICE_BASE(_port) (USB_OTG_DeviceTypeDef *) (_dcd_rhport[_port].regs + USB_OTG_DEVICE_BASE) #define OUT_EP_BASE(_port) (USB_OTG_OUTEndpointTypeDef *) (_dcd_rhport[_port].regs + USB_OTG_OUT_ENDPOINT_BASE) #define IN_EP_BASE(_port) (USB_OTG_INEndpointTypeDef *) (_dcd_rhport[_port].regs + USB_OTG_IN_ENDPOINT_BASE) @@ -137,6 +138,7 @@ xfer_ctl_t xfer_status[EP_MAX][2]; // Setup the control endpoint 0. static void bus_reset(uint8_t rhport) { + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); @@ -176,14 +178,14 @@ static void bus_reset(uint8_t rhport) // * 1 location for global NAK (not required/used here). // * It is recommended to allocate 2 times the largest packet size, therefore // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 - USB_OTG_FS->GRXFSIZ = 52; + usb_otg->GRXFSIZ = 52; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - USB_OTG_FS->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | (USB_OTG_FS->GRXFSIZ & 0x0000ffffUL); + usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | (usb_otg->GRXFSIZ & 0x0000ffffUL); out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); - USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; } static void end_of_reset(uint8_t rhport) @@ -216,22 +218,24 @@ static void end_of_reset(uint8_t rhport) *------------------------------------------------------------------*/ void dcd_init (uint8_t rhport) { + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + // Programming model begins in the last section of the chapter on the USB // peripheral in each Reference Manual. - USB_OTG_FS->GAHBCFG |= USB_OTG_GAHBCFG_GINT; + usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; // No HNP/SRP (no OTG support), program timeout later, turnaround // programmed for 32+ MHz. // TODO: PHYSEL is read-only on some cores (STM32F407). Worth gating? - USB_OTG_FS->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos) | USB_OTG_GUSBCFG_PHYSEL; + usb_otg->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos) | USB_OTG_GUSBCFG_PHYSEL; // Clear all interrupts - USB_OTG_FS->GINTSTS |= USB_OTG_FS->GINTSTS; + usb_otg->GINTSTS |= usb_otg->GINTSTS; // Required as part of core initialization. // TODO: How should mode mismatch be handled? It will cause // the core to stop working/require reset. - USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OTGINT | USB_OTG_GINTMSK_MMISM; + usb_otg->GINTMSK |= USB_OTG_GINTMSK_OTGINT | USB_OTG_GINTMSK_MMISM; USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); @@ -239,12 +243,12 @@ void dcd_init (uint8_t rhport) // (non zero-length packet), send STALL back and discard. Full speed. dev->DCFG |= USB_OTG_DCFG_NZLSOHSK | (3 << USB_OTG_DCFG_DSPD_Pos); - USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | + usb_otg->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); // Enable USB transceiver. - USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_PWRDWN; + usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; } void dcd_int_enable (uint8_t rhport) @@ -292,6 +296,7 @@ void dcd_disconnect(uint8_t rhport) bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); @@ -348,12 +353,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // Both TXFD and TXSA are in unit of 32-bit words. // IN FIFO 0 was configured during enumeration, hence the "+ 16". - uint16_t const allocated_size = (USB_OTG_FS->GRXFSIZ & 0x0000ffff) + 16; + uint16_t const allocated_size = (usb_otg->GRXFSIZ & 0x0000ffff) + 16; uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_MAX-1); uint32_t const fifo_offset = allocated_size + fifo_size*(epnum-1); // DIEPTXF starts at FIFO #1. - USB_OTG_FS->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | fifo_offset; + usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | fifo_offset; } return true; @@ -408,6 +413,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // (send STALL versus NAK handshakes back). Refactor into resuable function. void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); @@ -431,9 +437,9 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) } // Flush the FIFO, and wait until we have confirmed it cleared. - USB_OTG_FS->GRSTCTL |= ((epnum - 1) << USB_OTG_GRSTCTL_TXFNUM_Pos); - USB_OTG_FS->GRSTCTL |= USB_OTG_GRSTCTL_TXFFLSH; - while((USB_OTG_FS->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH_Msk) != 0); + usb_otg->GRSTCTL |= ((epnum - 1) << USB_OTG_GRSTCTL_TXFNUM_Pos); + usb_otg->GRSTCTL |= USB_OTG_GRSTCTL_TXFFLSH; + while((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH_Msk) != 0); } else { // Only disable currently enabled non-control endpoint if ( (epnum == 0) || !(out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPENA) ){ @@ -444,7 +450,7 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) // anyway, and it can't be cleared by user code. If this while loop never // finishes, we have bigger problems than just the stack. dev->DCTL |= USB_OTG_DCTL_SGONAK; - while((USB_OTG_FS->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF_Msk) == 0); + while((usb_otg->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF_Msk) == 0); // Ditto here- disable the endpoint. out_ep[epnum].DOEPCTL |= (USB_OTG_DOEPCTL_STALL | USB_OTG_DOEPCTL_EPDIS); @@ -577,12 +583,14 @@ static void write_fifo_packet(uint8_t rhport, uint8_t fifo_num, uint8_t * src, u } } -static void read_rx_fifo(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ep) { +static void read_rx_fifo(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ep) +{ + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); usb_fifo_t rx_fifo = FIFO_BASE(rhport, 0); // Pop control word off FIFO (completed xfers will have 2 control words, // we only pop one ctl word each interrupt). - uint32_t ctl_word = USB_OTG_FS->GRXSTSP; + uint32_t ctl_word = usb_otg->GRXSTSP; uint8_t pktsts = (ctl_word & USB_OTG_GRXSTSP_PKTSTS_Msk) >> USB_OTG_GRXSTSP_PKTSTS_Pos; uint8_t epnum = (ctl_word & USB_OTG_GRXSTSP_EPNUM_Msk) >> USB_OTG_GRXSTSP_EPNUM_Pos; uint16_t bcnt = (ctl_word & USB_OTG_GRXSTSP_BCNT_Msk) >> USB_OTG_GRXSTSP_BCNT_Pos; @@ -714,15 +722,16 @@ static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OT void dcd_int_handler(uint8_t rhport) { + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); - uint32_t int_status = USB_OTG_FS->GINTSTS; + uint32_t int_status = usb_otg->GINTSTS; if(int_status & USB_OTG_GINTSTS_USBRST) { // USBRST is start of reset. - USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_USBRST; + usb_otg->GINTSTS = USB_OTG_GINTSTS_USBRST; bus_reset(rhport); } @@ -730,40 +739,40 @@ void dcd_int_handler(uint8_t rhport) // ENUMDNE detects speed of the link. For full-speed, we // always expect the same value. This interrupt is considered // the end of reset. - USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; + usb_otg->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; end_of_reset(rhport); dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); } if(int_status & USB_OTG_GINTSTS_USBSUSP) { - USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_USBSUSP; + usb_otg->GINTSTS = USB_OTG_GINTSTS_USBSUSP; dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); } if(int_status & USB_OTG_GINTSTS_WKUINT) { - USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_WKUINT; + usb_otg->GINTSTS = USB_OTG_GINTSTS_WKUINT; dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); } if(int_status & USB_OTG_GINTSTS_OTGINT) { // OTG INT bit is read-only - uint32_t const otg_int = USB_OTG_FS->GOTGINT; + uint32_t const otg_int = usb_otg->GOTGINT; if (otg_int & USB_OTG_GOTGINT_SEDET) { dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); } - USB_OTG_FS->GOTGINT = otg_int; + usb_otg->GOTGINT = otg_int; } #if USE_SOF if(int_status & USB_OTG_GINTSTS_SOF) { - USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_SOF; - dcd_event_bus_signal(0, DCD_EVENT_SOF, true); + usb_otg->GINTSTS = USB_OTG_GINTSTS_SOF; + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); } #endif @@ -771,9 +780,9 @@ void dcd_int_handler(uint8_t rhport) // RXFLVL bit is read-only // Mask out RXFLVL while reading data from FIFO - USB_OTG_FS->GINTMSK &= ~USB_OTG_GINTMSK_RXFLVLM; + usb_otg->GINTMSK &= ~USB_OTG_GINTMSK_RXFLVLM; read_rx_fifo(rhport, out_ep); - USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; + usb_otg->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; } // OUT endpoint interrupt handling. -- cgit v1.3.1 From 0482f0d6867835d3dbb3939452fbcfaf9727b555 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 26 May 2020 22:11:26 +0700 Subject: update h743eval with rhport=1 highspeed --- hw/bsp/stm32h743eval/board.mk | 7 +-- hw/bsp/stm32h743eval/stm32h743eval.c | 97 ++++++++++++++++++++++++++++++++---- src/tusb_option.h | 4 -- test/test/support/tusb_config.h | 5 -- 4 files changed, 89 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/hw/bsp/stm32h743eval/board.mk b/hw/bsp/stm32h743eval/board.mk index 5044cdc08..68d142435 100644 --- a/hw/bsp/stm32h743eval/board.mk +++ b/hw/bsp/stm32h743eval/board.mk @@ -8,11 +8,8 @@ CFLAGS += \ -nostdlib -nostartfiles \ -DSTM32H743xx \ -DCFG_TUSB_MCU=OPT_MCU_STM32H7 \ - -# Board specific for using usb ports -CFLAGS += \ - -DCFG_BOARD_DEVICE_RHPORT_NUM=1 \ - -DCFG_BOARD_DEVICE_RHPORT_HIGHSPEED + -DBOARD_DEVICE_RHPORT_NUM=1 \ + -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED # suppress warning caused by vendor mcu driver CFLAGS += -Wno-error=maybe-uninitialized diff --git a/hw/bsp/stm32h743eval/stm32h743eval.c b/hw/bsp/stm32h743eval/stm32h743eval.c index 5a7934ea2..fd3d33047 100644 --- a/hw/bsp/stm32h743eval/stm32h743eval.c +++ b/hw/bsp/stm32h743eval/stm32h743eval.c @@ -32,11 +32,22 @@ //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ + +// Despite being call USB2_OTG +// OTG_FS is marked as RHPort0 by TinyUSB to be consistent across stm32 port void OTG_FS_IRQHandler(void) { tud_int_handler(0); } +// Despite being call USB2_OTG +// OTG_HS is marked as RHPort1 by TinyUSB to be consistent across stm32 port +void OTG_HS_IRQHandler(void) +{ + tud_int_handler(1); +} + + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ @@ -53,7 +64,7 @@ void OTG_FS_IRQHandler(void) // enable all LED, Button, Uart, USB clock static void all_rcc_clk_enable(void) { - __HAL_RCC_GPIOA_CLK_ENABLE(); // LED, USB D+, D- + __HAL_RCC_GPIOA_CLK_ENABLE(); // LED __HAL_RCC_GPIOC_CLK_ENABLE(); // Button // __HAL_RCC_GPIOD_CLK_ENABLE(); // Uart tx, rx // __HAL_RCC_USART3_CLK_ENABLE(); // Uart module @@ -187,17 +198,13 @@ void board_init(void) GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); -#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - - // USB1 HS (ULPI Phy), internal FS PHY - // PB12 ID, PB13 VBUS, PB14 DM, PB15 DP - -#endif - -#if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - // USB2 FS Pin Init +#if BOARD_DEVICE_RHPORT_NUM == 0 + // Despite being call USB2_OTG + // OTG_FS is marked as RHPort0 by TinyUSB to be consistent across stm32 port // PA9 VUSB, PA10 ID, PA11 DM, PA12 DP + __HAL_RCC_GPIOA_CLK_ENABLE(); + /* Configure DM DP Pins */ GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; @@ -228,6 +235,76 @@ void board_init(void) // Enable VBUS sense (B device) via pin PA9 USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN; #endif + +#if BOARD_DEVICE_RHPORT_NUM == 1 + // Despite being call USB2_OTG + // OTG_HS is marked as RHPort1 by TinyUSB to be consistent across stm32 port + __GPIOA_CLK_ENABLE(); + __GPIOB_CLK_ENABLE(); + __GPIOC_CLK_ENABLE(); + __GPIOH_CLK_ENABLE(); + __GPIOI_CLK_ENABLE(); + + /* CLK */ + GPIO_InitStruct.Pin = GPIO_PIN_5; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG2_HS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* D0 */ + GPIO_InitStruct.Pin = GPIO_PIN_3; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG2_HS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* D1 D2 D3 D4 D5 D6 D7 */ + GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_5 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG2_HS; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* STP */ + GPIO_InitStruct.Pin = GPIO_PIN_0; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG2_HS; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /* NXT */ + GPIO_InitStruct.Pin = GPIO_PIN_4; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG2_HS; + HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); + + /* DIR */ + GPIO_InitStruct.Pin = GPIO_PIN_11; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG2_HS; + HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); + __HAL_RCC_USB1_OTG_HS_ULPI_CLK_ENABLE(); + + /* Enable USB HS Clocks */ + __HAL_RCC_USB1_OTG_HS_CLK_ENABLE(); + + // No VBUS sense + USB_OTG_HS->GCCFG &= ~USB_OTG_GCCFG_VBDEN; + + // Force device mode + // USB_OTG_HS->GUSBCFG &= ~USB_OTG_GUSBCFG_FHMOD; + // USB_OTG_HS->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + + // B-peripheral session valid override enabl +// USB_OTG_HS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN; +// USB_OTG_HS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; +#endif // rhport = 1 + } //--------------------------------------------------------------------+ diff --git a/src/tusb_option.h b/src/tusb_option.h index 472656424..c251d578a 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -138,10 +138,6 @@ #define CFG_TUSB_RHPORT0_MODE OPT_MODE_NONE #endif -//#ifndef CFG_TUSB_RHPORT1_MODE -// #define CFG_TUSB_RHPORT1_MODE OPT_MODE_NONE -//#endif - #if ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST ) && (CFG_TUSB_RHPORT0_MODE & (OPT_MODE_HOST << 8)) ) || \ ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE) && (CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE << 8)) ) #error "TinyUSB currently does not support same modes on more than 1 roothub port" diff --git a/test/test/support/tusb_config.h b/test/test/support/tusb_config.h index 5258513ec..76f975323 100644 --- a/test/test/support/tusb_config.h +++ b/test/test/support/tusb_config.h @@ -43,12 +43,7 @@ #define CFG_TUSB_MCU OPT_MCU_NRF5X #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) -#else -#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 -- cgit v1.3.1 From b4804d1592901ee202f661f4e44e621a05aca315 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 26 May 2020 22:15:38 +0700 Subject: random clean up for tdi --- src/portable/nxp/transdimension/dcd_transdimension.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 7baf43e23..68cf145ea 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -236,7 +236,7 @@ typedef struct { dcd_registers_t* regs; // registers const IRQn_Type irqnum; // IRQ number - const uint8_t ep_count; // Max bi-directional Endpoints + const uint8_t ep_count; // Max bi-directional Endpoints }dcd_controller_t; #if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX @@ -244,7 +244,7 @@ typedef struct // Therefore QHD_MAX is 2 x max endpoint count #define QHD_MAX (8*2) - dcd_controller_t _dcd_controller[] = + static const dcd_controller_t _dcd_controller[] = { // RT1010 and RT1020 only has 1 USB controller #if FSL_FEATURE_SOC_USBHS_COUNT == 1 @@ -258,7 +258,7 @@ typedef struct #else #define QHD_MAX (6*2) - dcd_controller_t _dcd_controller[] = + static const dcd_controller_t _dcd_controller[] = { { .regs = (dcd_registers_t*) LPC_USB0_BASE, .irqnum = USB0_IRQn, .ep_count = 6 }, { .regs = (dcd_registers_t*) LPC_USB1_BASE, .irqnum = USB1_IRQn, .ep_count = 4 } -- cgit v1.3.1 From d4bf777c943659a4e985ce8514ef077c5bf2b40d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 May 2020 11:01:33 +0700 Subject: try to get synopsys work with OTG HS + external PHY --- src/device/usbd.c | 1 + src/portable/st/synopsys/dcd_synopsys.c | 80 +++++++++++++++++++++++++++------ 2 files changed, 68 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index f7918c07e..bd892e389 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -384,6 +384,7 @@ void tud_task (void) { case DCD_EVENT_BUS_RESET: usbd_reset(event.rhport); + // TODO DCD should report operational speed (LS/FS/HS) break; case DCD_EVENT_UNPLUGGED: diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index b68794712..8ca67dbb4 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -99,7 +99,7 @@ static const dcd_rhport_t _dcd_rhport[] = { .regs = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn } #ifdef USB_OTG_HS - ,{ .regs = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn } + ,{ .regs = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn } #endif }; @@ -218,16 +218,48 @@ static void end_of_reset(uint8_t rhport) *------------------------------------------------------------------*/ void dcd_init (uint8_t rhport) { + dcd_disconnect(rhport); + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); - // Programming model begins in the last section of the chapter on the USB - // peripheral in each Reference Manual. - usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; + // No HNP/SRP (no OTG support), program timeout later. +#if TUD_OPT_HIGH_SPEED // TODO may pass parameter instead of using macro for HighSpeed + if ( rhport == 1 ) + { + // Highspeed with external ULPI PHY + + // deactivate internal PHY + usb_otg->GCCFG &= ~USB_OTG_GCCFG_PWRDWN; + + // On selected MCUs HS port1 can be used with external PHY via ULPI interface + // Select ULPI highspeed PHY with default external VBUS Indicator and Drive + usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL | + USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); + + // Turn around time for Highspeed is 0x09 + usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; + usb_otg->GUSBCFG |= (0x09 << USB_OTG_GUSBCFG_TRDT_Pos); + }else +#endif + { + // Turn around programmed for 32+ MHz is 0x06 + usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; + usb_otg->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos) | USB_OTG_GUSBCFG_PHYSEL; + } + + // Reset core after selecting PHY + // Wait AHB IDLE, reset then wait until it is cleared + while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U) {} + usb_otg->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; + while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST) {} + + // Force device mode + usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + + TU_LOG2_LOCATION(); - // No HNP/SRP (no OTG support), program timeout later, turnaround - // programmed for 32+ MHz. - // TODO: PHYSEL is read-only on some cores (STM32F407). Worth gating? - usb_otg->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos) | USB_OTG_GUSBCFG_PHYSEL; + // Restart PHY clock + *((volatile uint32_t *)(_dcd_rhport[rhport].regs + USB_OTG_PCGCCTL_BASE)) = 0; // Clear all interrupts usb_otg->GINTSTS |= usb_otg->GINTSTS; @@ -241,14 +273,33 @@ void dcd_init (uint8_t rhport) // If USB host misbehaves during status portion of control xfer // (non zero-length packet), send STALL back and discard. Full speed. - dev->DCFG |= USB_OTG_DCFG_NZLSOHSK | (3 << USB_OTG_DCFG_DSPD_Pos); + dev->DCFG |= USB_OTG_DCFG_NZLSOHSK; + +#if TUD_OPT_HIGH_SPEED + if ( rhport == 1 ) + { + // high speed = 0x00 + dev->DCFG &= ~(3 << USB_OTG_DCFG_DSPD_Pos); + + // Transceiver delay, necessary for some ULPI PHYs + dev->DCFG |= (1 << 14); + } +#endif + { + // full speed with internal phy + dev->DCFG |= (3 << USB_OTG_DCFG_DSPD_Pos); + + // Enable USB transceiver. + usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; + } usb_otg->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | - USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | - USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); + USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | + USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); - // Enable USB transceiver. - usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; + // Programming model begins in the last section of the chapter on the USB + // peripheral in each Reference Manual. + usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; } void dcd_int_enable (uint8_t rhport) @@ -739,6 +790,9 @@ void dcd_int_handler(uint8_t rhport) // ENUMDNE detects speed of the link. For full-speed, we // always expect the same value. This interrupt is considered // the end of reset. + + TU_LOG2_HEX(dev->DSTS); + usb_otg->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; end_of_reset(rhport); dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); -- cgit v1.3.1 From e3404049686adfd934a6444fadf9ae00f1f94f8a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 May 2020 19:01:59 +0700 Subject: changing usbd driver open() return type, add max_len only done with cdc and msc, push this interim for feedback first --- src/class/cdc/cdc_device.c | 26 ++++++++++++++------------ src/class/cdc/cdc_device.h | 12 ++++++------ src/class/msc/msc_device.c | 16 ++++++++++------ src/class/msc/msc_device.h | 12 ++++++------ src/device/usbd.c | 30 ++++++++++++++++++------------ 5 files changed, 54 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 2d8f986ae..a24f348f4 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -222,14 +222,16 @@ void cdcd_reset(uint8_t rhport) } } -bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { // Only support ACM subclass TU_VERIFY ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass); + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); // Note: 0xFF can be used with RNDIS - TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA)); + TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA), 0); + + uint16_t len = 0; // Find available interface cdcd_interface_t * p_cdc = NULL; @@ -242,29 +244,29 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t break; } } - TU_ASSERT(p_cdc); + TU_ASSERT(p_cdc, 0); //------------- Control Interface -------------// p_cdc->itf_num = itf_desc->bInterfaceNumber; uint8_t const * p_desc = tu_desc_next( itf_desc ); - (*p_length) = sizeof(tusb_desc_interface_t); + len = sizeof(tusb_desc_interface_t); // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && len <= max_len ) { - (*p_length) += tu_desc_len(p_desc); + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { // notification endpoint if any - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += tu_desc_len(p_desc); + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } @@ -276,15 +278,15 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t p_desc = tu_desc_next(p_desc); // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in) ); + TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 ); - (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + len += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); } // Prepare for incoming data _prep_out_transaction(cdc_id); - return true; + return len; } // Invoked when class request DATA stage is finished. diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 69542a3b3..a2523d8d0 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -229,12 +229,12 @@ static inline uint32_t tud_cdc_write_available(void) //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ -void cdcd_init (void); -void cdcd_reset (uint8_t rhport); -bool cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void cdcd_init (void); +void cdcd_reset (uint8_t rhport); +uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 70ba956aa..9955f2f05 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -154,25 +154,29 @@ void mscd_reset(uint8_t rhport) tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); } -bool mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len) +uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { // only support SCSI's BOT protocol TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass && MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && - MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol); + MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0); + // Max length mus be at least 1 interface + 2 endpoints + TU_VERIFY(max_len >= sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t), 0); + + uint16_t len = 0; mscd_interface_t * p_msc = &_mscd_itf; // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in) ); + TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 ); p_msc->itf_num = itf_desc->bInterfaceNumber; - (*p_len) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); // Prepare for Command Block Wrapper - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) ); + TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)), 0 ); - return true; + return len; } // Handle class control request diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 66180777e..30ffd02e1 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -151,12 +151,12 @@ TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void mscd_init (void); -void mscd_reset (uint8_t rhport); -bool mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool mscd_control_request (uint8_t rhport, tusb_control_request_t const * p_request); -bool mscd_control_complete (uint8_t rhport, tusb_control_request_t const * p_request); -bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void mscd_init (void); +void mscd_reset (uint8_t rhport); +uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool mscd_control_request (uint8_t rhport, tusb_control_request_t const * p_request); +bool mscd_control_complete (uint8_t rhport, tusb_control_request_t const * p_request); +bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index f7918c07e..971417a35 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -85,13 +85,13 @@ typedef struct char const* name; #endif - void (* init ) (void); - void (* reset ) (uint8_t rhport); - bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); - bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); - bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); - bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - void (* sof ) (uint8_t rhport); /* optional */ + void (* init ) (void); + void (* reset ) (uint8_t rhport); + uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); + bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + void (* sof ) (uint8_t rhport); /* optional */ } usbd_class_driver_t; static usbd_class_driver_t const _usbd_driver[] = @@ -713,6 +713,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; + uint16_t const remaining_len = desc_end-p_desc; + uint8_t drv_id; uint16_t drv_len; @@ -720,13 +722,17 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { usbd_class_driver_t const *driver = &_usbd_driver[drv_id]; - drv_len = 0; - if ( driver->open(rhport, desc_itf, &drv_len) ) + drv_len = driver->open(rhport, desc_itf, remaining_len); + + if ( drv_len > 0 ) { + // Open successfully, check if length is correct + TU_ASSERT( sizeof(tusb_desc_interface_t) <= drv_len && drv_len <= remaining_len); + // Interface number must not be used already TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); - TU_LOG2(" %s opened\r\n", _usbd_driver[drv_id].name); + TU_LOG2(" %s opened\r\n", driver->name); _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; // If IAD exist, assign all interfaces to the same driver @@ -748,8 +754,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } } - // Assert if cannot find supported driver - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) ); + // Failed if cannot find supported driver + TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT); mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor -- cgit v1.3.1 From 2eeeda1bcf37b0b5cc6f202e95ef5b05605ecf3d Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 00:46:32 +0700 Subject: change signature for dfu runtime --- src/class/dfu/dfu_rt_device.c | 13 +++++++------ src/class/dfu/dfu_rt_device.h | 12 ++++++------ 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 0ef5fe63f..426680e8e 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -56,24 +56,25 @@ void dfu_rtd_reset(uint8_t rhport) (void) rhport; } -bool dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { (void) rhport; + (void) max_len; // Ensure this is DFU Runtime - TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS); - TU_VERIFY(itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT); + TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && + itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT, 0); uint8_t const * p_desc = tu_desc_next( itf_desc ); - (*p_length) = sizeof(tusb_desc_interface_t); + uint16_t len = sizeof(tusb_desc_interface_t); if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) { - (*p_length) += p_desc[DESC_OFFSET_LEN]; + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } - return true; + return len; } bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request) diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 294d993e3..91ead88c6 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -63,12 +63,12 @@ TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb conventi //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void dfu_rtd_init(void); -void dfu_rtd_reset(uint8_t rhport); -bool dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request); -bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request); -bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void dfu_rtd_init(void); +void dfu_rtd_reset(uint8_t rhport); +uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request); +bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request); +bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } -- cgit v1.3.1 From 7a15d2e0d25a8fad65c27477c0dbf62bebac2196 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 00:56:33 +0700 Subject: improve msc --- src/class/msc/msc_device.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 9955f2f05..0ae25f89a 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -161,22 +161,22 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0); + // msc driver length is fixed + enum { _MSC_DRIVER_LEN = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) }; + // Max length mus be at least 1 interface + 2 endpoints - TU_VERIFY(max_len >= sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t), 0); + TU_VERIFY(max_len >= _MSC_DRIVER_LEN, 0); - uint16_t len = 0; mscd_interface_t * p_msc = &_mscd_itf; + p_msc->itf_num = itf_desc->bInterfaceNumber; // Open endpoint pair TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 ); - p_msc->itf_num = itf_desc->bInterfaceNumber; - len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); - // Prepare for Command Block Wrapper TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)), 0 ); - return len; + return _MSC_DRIVER_LEN; } // Handle class control request -- cgit v1.3.1 From 89a3d1f6d17822bed498b5b872b76348f7c520a2 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 11:19:12 +0700 Subject: update hid open() --- src/class/hid/hid_device.c | 21 +++++++++++---------- src/class/hid/hid_device.h | 12 ++++++------ src/class/msc/msc_device.c | 2 +- 3 files changed, 18 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index cbdc5bece..51bd153ec 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -158,11 +158,12 @@ void hidd_reset(uint8_t rhport) tu_memclr(_hidd_itf, sizeof(_hidd_itf)); } -bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_len) +uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) { - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); - uint8_t const *p_desc = (uint8_t const *) desc_itf; + // max length is at least interface + hid descriptor + 1 endpoint + TU_ASSERT(max_len >= sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_desc_endpoint_t), 0); // Find available interface hidd_interface_t * p_hid = NULL; @@ -175,16 +176,18 @@ bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t break; } } - TU_ASSERT(p_hid); + TU_ASSERT(p_hid, 0); + + uint8_t const *p_desc = (uint8_t const *) desc_itf; //------------- HID descriptor -------------// p_desc = tu_desc_next(p_desc); p_hid->hid_descriptor = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == p_hid->hid_descriptor->bDescriptorType); + TU_ASSERT(HID_DESC_TYPE_HID == p_hid->hid_descriptor->bDescriptorType, 0); //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in)); + TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0); if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->boot_protocol = desc_itf->bInterfaceProtocol; @@ -192,12 +195,10 @@ bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t p_hid->itf_num = desc_itf->bInterfaceNumber; memcpy(&p_hid->report_desc_len, &(p_hid->hid_descriptor->wReportLength), 2); - *p_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - // Prepare for output endpoint - if (p_hid->ep_out) TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); + if (p_hid->ep_out) TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)), 0); - return true; + return sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); } // Handle class control request diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index efdde9569..ad8c9ece4 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -300,12 +300,12 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hidd_init (void); -void hidd_reset (uint8_t rhport); -bool hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool hidd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool hidd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hidd_init (void); +void hidd_reset (uint8_t rhport); +uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool hidd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool hidd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 0ae25f89a..c3ce495e1 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -165,7 +165,7 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 enum { _MSC_DRIVER_LEN = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) }; // Max length mus be at least 1 interface + 2 endpoints - TU_VERIFY(max_len >= _MSC_DRIVER_LEN, 0); + TU_ASSERT(max_len >= _MSC_DRIVER_LEN, 0); mscd_interface_t * p_msc = &_mscd_itf; p_msc->itf_num = itf_desc->bInterfaceNumber; -- cgit v1.3.1 From 8f560bf275b9c0d6d6e524962deb4d7e2502623e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 11:41:37 +0700 Subject: update midi open() --- src/class/midi/midi_device.c | 55 ++++++++++++++++++++++---------------------- src/class/midi/midi_device.h | 12 +++++----- 2 files changed, 34 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 7bc8cef84..69dafe0a0 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -290,31 +290,30 @@ void midid_reset(uint8_t rhport) } } -bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_length) +uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) { - // 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); + AUDIO_PROTOCOL_V1 == desc_itf->bInterfaceProtocol, 0); 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) ) + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) { drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + p_desc = tu_desc_next(p_desc); } // 2nd Interface is MIDI Streaming - TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc)); + TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); 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 ); + AUDIO_PROTOCOL_V1 == desc_midi->bInterfaceProtocol, 0); // Find available interface midid_interface_t * p_midi = NULL; @@ -327,40 +326,42 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t } } - p_midi->itf_num = desc_midi->bInterfaceNumber; + p_midi->itf_num = desc_midi->bInterfaceNumber; // next descriptor drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + p_desc = tu_desc_next(p_desc); // Find and open endpoint descriptors uint8_t found_endpoints = 0; - while (found_endpoints < desc_midi->bNumEndpoints) + while ( (found_endpoints < desc_midi->bNumEndpoints) && (drv_len <= max_len) ) { - if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); - uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { - p_midi->ep_in = ep_addr; - } else { - p_midi->ep_out = ep_addr; - } + TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0); + uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) + { + p_midi->ep_in = ep_addr; + } else { + p_midi->ep_out = ep_addr; + } + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); - drv_len += p_desc[DESC_OFFSET_LEN]; - p_desc = tu_desc_next(p_desc); - found_endpoints += 1; + found_endpoints += 1; } - drv_len += p_desc[DESC_OFFSET_LEN]; - p_desc = tu_desc_next(p_desc); - } - *p_length = drv_len; + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } // Prepare for incoming data - TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false); + TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), 0 ); - return true; + return drv_len; } bool midid_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index e4d4f9d51..bec0984f2 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -136,12 +136,12 @@ static inline bool tud_midi_send (uint8_t const packet[4]) //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void midid_init (void); -void midid_reset (uint8_t rhport); -bool midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool midid_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool midid_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void midid_init (void); +void midid_reset (uint8_t rhport); +uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool midid_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool midid_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } -- cgit v1.3.1 From 13860e9f947af18265f53d6b8663016fbf025bc7 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 11:51:25 +0700 Subject: update net open() --- src/class/net/net_device.c | 38 +++++++++++++++++++------------------- src/class/net/net_device.h | 14 +++++++------- 2 files changed, 26 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index fedd4db99..2d2a0b46d 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -135,7 +135,7 @@ void netd_reset(uint8_t rhport) netd_init(); } -bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { bool const is_rndis = (TUD_RNDIS_ITF_CLASS == itf_desc->bInterfaceClass && TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass && @@ -145,10 +145,10 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass && 0x00 == itf_desc->bInterfaceProtocol); - TU_VERIFY ( is_rndis || is_ecm ); + TU_VERIFY(is_rndis || is_ecm, 0); // confirm interface hasn't already been allocated - TU_ASSERT(0 == _netd_itf.ep_notif); + TU_ASSERT(0 == _netd_itf.ep_notif, 0); // sanity check the descriptor _netd_itf.ecm_mode = is_ecm; @@ -156,25 +156,25 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t //------------- Management Interface -------------// _netd_itf.itf_num = itf_desc->bInterfaceNumber; - (*p_length) = sizeof(tusb_desc_interface_t); + uint16_t drv_len = sizeof(tusb_desc_interface_t); uint8_t const * p_desc = tu_desc_next( itf_desc ); // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) ) + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) { - (*p_length) += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } // notification endpoint (if any) if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) ); + TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } //------------- Data Interface -------------// @@ -182,19 +182,19 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t // - 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)); + TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); do { 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); + TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass, 0); - (*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)) ); + drv_len += 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)) && (drv_len <= max_len) ); // Pair of endpoints - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); if ( _netd_itf.ecm_mode ) { @@ -204,7 +204,7 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t }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) ); + TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in), 0 ); tud_network_init_cb(); @@ -215,9 +215,9 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t tud_network_recv_renew(); } - (*p_length) += 2*sizeof(tusb_desc_endpoint_t); + drv_len += 2*sizeof(tusb_desc_endpoint_t); - return true; + return drv_len; } // Invoked when class request DATA stage is finished. diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 67cd99933..fb72146b0 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -72,13 +72,13 @@ void tud_network_xmit(struct pbuf *p); //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ -void netd_init (void); -void netd_reset (uint8_t rhport); -bool netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void netd_report (uint8_t *buf, uint16_t len); +void netd_init (void); +void netd_reset (uint8_t rhport); +uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void netd_report (uint8_t *buf, uint16_t len); #ifdef __cplusplus } -- cgit v1.3.1 From bec5b5f9da8ecb82aed51452bedbcc5142df4c87 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 12:13:48 +0700 Subject: update usbtmc open() --- src/class/usbtmc/usbtmc_device.c | 43 +++++++++++++++++++++------------------- src/class/usbtmc/usbtmc_device.h | 12 +++++------ 2 files changed, 29 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index b14135146..a3ff76079 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -260,37 +260,39 @@ void usbtmcd_init_cb(void) usbtmcLock = osal_mutex_create(&usbtmcLockBuffer); } -bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { (void)rhport; + + uint16_t drv_len; 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); + TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS , 0); + TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS, 0); #ifndef NDEBUG // Only 2 or 3 endpoints are allowed for USBTMC. - TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3)); + TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3), 0); #endif - TU_ASSERT(usbtmc_state.state == STATE_CLOSED); + TU_ASSERT(usbtmc_state.state == STATE_CLOSED, 0); // Interface - (*p_length) = 0u; + drv_len = 0u; p_desc = (uint8_t const *) itf_desc; usbtmc_state.itf_id = itf_desc->bInterfaceNumber; usbtmc_state.rhport = rhport; - while (found_endpoints < itf_desc->bNumEndpoints) + while (found_endpoints < itf_desc->bNumEndpoints && drv_len <= max_len) { if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc; switch(ep_desc->bmAttributes.xfer) { case TUSB_XFER_BULK: - TU_ASSERT(ep_desc->wMaxPacketSize.size == USBTMCD_MAX_PACKET_SIZE); + TU_ASSERT(ep_desc->wMaxPacketSize.size == USBTMCD_MAX_PACKET_SIZE, 0); if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN) { usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress; @@ -301,45 +303,46 @@ bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin break; case TUSB_XFER_INTERRUPT: #ifndef NDEBUG - TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN); - TU_ASSERT(usbtmc_state.ep_int_in == 0); + TU_ASSERT(tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN, 0); + TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); #endif usbtmc_state.ep_int_in = ep_desc->bEndpointAddress; break; default: - TU_ASSERT(false); + TU_ASSERT(false, 0); } - TU_VERIFY( usbd_edpt_open(rhport, ep_desc)); + TU_ASSERT( usbd_edpt_open(rhport, ep_desc), 0); found_endpoints++; } - (*p_length) = (uint8_t)((*p_length) + p_desc[DESC_OFFSET_LEN]); - p_desc = tu_desc_next(p_desc); + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } // bulk endpoints are required, but interrupt IN is optional #ifndef NDEBUG - TU_ASSERT(usbtmc_state.ep_bulk_in != 0); - TU_ASSERT(usbtmc_state.ep_bulk_out != 0); + TU_ASSERT(usbtmc_state.ep_bulk_in != 0, 0); + TU_ASSERT(usbtmc_state.ep_bulk_out != 0, 0); if (itf_desc->bNumEndpoints == 2) { - TU_ASSERT(usbtmc_state.ep_int_in == 0); + TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); } else if (itf_desc->bNumEndpoints == 3) { - TU_ASSERT(usbtmc_state.ep_int_in != 0); + TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); } #if (CFG_TUD_USBTMC_ENABLE_488) if(usbtmc_state.capabilities->bmIntfcCapabilities488.is488_2 || usbtmc_state.capabilities->bmDevCapabilities488.SR1) { - TU_ASSERT(usbtmc_state.ep_int_in != 0); + TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); } #endif #endif atomicChangeState(STATE_CLOSED, STATE_NAK); tud_usbtmc_open_cb(itf_desc->iInterface); - return true; + return drv_len; } // Tell USBTMC class to set its bulk-in EP to ACK so that it can // receive USBTMC commands. diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index e231dd72d..a6b5e4cca 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -108,12 +108,12 @@ bool tud_usbtmc_start_bus_read(void); /* "callbacks" from USB device core */ -bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -void usbtmcd_reset_cb(uint8_t rhport); -bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); -bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); -void usbtmcd_init_cb(void); +uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +void usbtmcd_reset_cb(uint8_t rhport); +bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); +bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); +void usbtmcd_init_cb(void); /************************************************************ * USBTMC Descriptor Templates -- cgit v1.3.1 From c1db36a15c1e38adc142ec74fd5f3b0320053cc9 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 12:19:06 +0700 Subject: update vendor open() --- src/class/vendor/vendor_device.c | 14 +++++++------- src/class/vendor/vendor_device.h | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 7f2fe9793..98eafe44c 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -166,9 +166,9 @@ void vendord_reset(uint8_t rhport) } } -bool vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len) +uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { - TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass); + TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass, 0); // Find available interface vendord_interface_t* p_vendor = NULL; @@ -180,18 +180,18 @@ bool vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16 break; } } - TU_VERIFY(p_vendor); + TU_VERIFY(p_vendor, 0); // Open endpoint pair with usbd helper - TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in)); + TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in), 0); p_vendor->itf_num = itf_desc->bInterfaceNumber; - (*p_len) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints*sizeof(tusb_desc_endpoint_t); // Prepare for incoming data - TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf))); + TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)), drv_len); - return true; + return drv_len; } bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 30fe94c3a..a4235bfce 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -118,10 +118,10 @@ static inline uint32_t tud_vendor_write_available (void) //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void vendord_init(void); -void vendord_reset(uint8_t rhport); -bool vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); -bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void vendord_init(void); +void vendord_reset(uint8_t rhport); +uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } -- cgit v1.3.1 From 10cd3f24bf0af9b7a1f357505ebbb5ef2132e34b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 13:48:02 +0700 Subject: initial transfer failed in open() shouldn't cause the driver open to fail. --- src/class/cdc/cdc_device.c | 11 +++++------ src/class/hid/hid_device.c | 9 ++++++++- src/class/midi/midi_device.c | 6 +++++- src/class/msc/msc_device.c | 6 +++++- src/class/vendor/vendor_device.c | 9 ++++++--- src/common/tusb_common.h | 3 +++ 6 files changed, 32 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index a24f348f4..a8a58980a 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -231,8 +231,6 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 // Note: 0xFF can be used with RNDIS TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA), 0); - uint16_t len = 0; - // Find available interface cdcd_interface_t * p_cdc = NULL; uint8_t cdc_id; @@ -249,13 +247,13 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 //------------- Control Interface -------------// p_cdc->itf_num = itf_desc->bInterfaceNumber; + uint16_t len = sizeof(tusb_desc_interface_t); uint8_t const * p_desc = tu_desc_next( itf_desc ); - len = sizeof(tusb_desc_interface_t); // Communication Functional Descriptors while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && len <= max_len ) { - len += tu_desc_len(p_desc); + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } @@ -266,7 +264,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - len += tu_desc_len(p_desc); + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } @@ -275,12 +273,13 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // next to endpoint descriptor + len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); // Open endpoint pair TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 ); - len += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + len += 2*sizeof(tusb_desc_endpoint_t); } // Prepare for incoming data diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 51bd153ec..64a57e90e 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -196,7 +196,14 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 memcpy(&p_hid->report_desc_len, &(p_hid->hid_descriptor->wReportLength), 2); // Prepare for output endpoint - if (p_hid->ep_out) TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)), 0); + if (p_hid->ep_out) + { + if ( !usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)) ) + { + TU_LOG1_FAILED(); + TU_BREAKPOINT(); + } + } return sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); } diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 69dafe0a0..14fb3e50d 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -359,7 +359,11 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint } // Prepare for incoming data - TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), 0 ); + if ( !usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE) ) + { + TU_LOG1_FAILED(); + TU_BREAKPOINT(); + } return drv_len; } diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index c3ce495e1..00a5b4525 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -174,7 +174,11 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 ); // Prepare for Command Block Wrapper - TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)), 0 ); + if ( !usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) ) + { + TU_LOG1_FAILED(); + TU_BREAKPOINT(); + } return _MSC_DRIVER_LEN; } diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 98eafe44c..8f2dfef32 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -186,12 +186,15 @@ uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_vendor->ep_out, &p_vendor->ep_in), 0); p_vendor->itf_num = itf_desc->bInterfaceNumber; - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints*sizeof(tusb_desc_endpoint_t); // Prepare for incoming data - TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)), drv_len); + if ( !usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)) ) + { + TU_LOG1_FAILED(); + TU_BREAKPOINT(); + } - return drv_len; + return sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints*sizeof(tusb_desc_endpoint_t); } bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index f144cda73..4b4183ae6 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -228,6 +228,7 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize) for(uint32_t i=0; i 1 @@ -277,6 +279,7 @@ static inline char const* lookup_find(lookup_table_t const* p_table, uint32_t ke #define TU_LOG1_VAR(...) #define TU_LOG1_INT(...) #define TU_LOG1_HEX(...) + #define TU_LOG1_FAILED() #endif #ifndef TU_LOG2 -- cgit v1.3.1 From fb214f7cf792d3e8a3e1161c9797b68db71a1f68 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 13:57:49 +0700 Subject: rename to drv_len to be consistent --- src/class/cdc/cdc_device.c | 20 ++++++++++---------- src/class/dfu/dfu_rt_device.c | 8 ++++---- src/class/msc/msc_device.c | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index a8a58980a..9180065c4 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -247,14 +247,14 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 //------------- Control Interface -------------// p_cdc->itf_num = itf_desc->bInterfaceNumber; - uint16_t len = sizeof(tusb_desc_interface_t); + uint16_t drv_len = sizeof(tusb_desc_interface_t); uint8_t const * p_desc = tu_desc_next( itf_desc ); // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && len <= max_len ) + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) { - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) @@ -264,8 +264,8 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// @@ -273,19 +273,19 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // next to endpoint descriptor - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); // Open endpoint pair TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 ); - len += 2*sizeof(tusb_desc_endpoint_t); + drv_len += 2*sizeof(tusb_desc_endpoint_t); } // Prepare for incoming data _prep_out_transaction(cdc_id); - return len; + return drv_len; } // Invoked when class request DATA stage is finished. diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 426680e8e..01d4e3490 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -66,15 +66,15 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT, 0); uint8_t const * p_desc = tu_desc_next( itf_desc ); - uint16_t len = sizeof(tusb_desc_interface_t); + uint16_t drv_len = sizeof(tusb_desc_interface_t); if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) { - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } - return len; + return drv_len; } bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 00a5b4525..b038d00f7 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -162,10 +162,10 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol, 0); // msc driver length is fixed - enum { _MSC_DRIVER_LEN = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) }; + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); // Max length mus be at least 1 interface + 2 endpoints - TU_ASSERT(max_len >= _MSC_DRIVER_LEN, 0); + TU_ASSERT(max_len >= drv_len, 0); mscd_interface_t * p_msc = &_mscd_itf; p_msc->itf_num = itf_desc->bInterfaceNumber; @@ -180,7 +180,7 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 TU_BREAKPOINT(); } - return _MSC_DRIVER_LEN; + return drv_len; } // Handle class control request -- cgit v1.3.1 From 53b749fd72e9e4573c80f0bc4083c5cf9e82177c Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 14:44:26 +0700 Subject: check max_len for vendor and hid --- src/class/hid/hid_device.c | 7 ++++--- src/class/vendor/vendor_device.c | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 64a57e90e..2a20bc173 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -162,8 +162,9 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 { TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); - // max length is at least interface + hid descriptor + 1 endpoint - TU_ASSERT(max_len >= sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_desc_endpoint_t), 0); + // len = interface + hid + n*endpoints + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + TU_ASSERT(max_len >= drv_len, 0); // Find available interface hidd_interface_t * p_hid = NULL; @@ -205,7 +206,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 } } - return sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + return drv_len; } // Handle class control request diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 8f2dfef32..3fcea89c4 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -170,6 +170,9 @@ uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui { TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass, 0); + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + TU_VERIFY(max_len >= drv_len, 0); + // Find available interface vendord_interface_t* p_vendor = NULL; for(uint8_t i=0; ibNumEndpoints*sizeof(tusb_desc_endpoint_t); + return drv_len; } bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -- cgit v1.3.1 From 077437b3dc2772ba87e6d43baf906d29b7539ca5 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 13 May 2020 16:45:01 +0200 Subject: Add non standard request handling in class For some reason bluetooth stack implementations send class requests to device instead of interface. To implement HCI interface over USB non device addressed requests for class need to be handled. --- src/device/usbd.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 971417a35..3cbd50644 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -507,6 +507,18 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { //------------- Device Requests e.g in enumeration -------------// case TUSB_REQ_RCPT_DEVICE: + if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) + { + uint8_t const itf = tu_u16_low(p_request->wIndex); + TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)); + + uint8_t const drvid = _usbd_dev.itf2drv[itf]; + TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT); + + // forward to class driver: "non-STD request to Interface" + TU_VERIFY(invoke_class_control(rhport, drvid, p_request)); + return true; + } if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { // Non standard request is not supported -- cgit v1.3.1 From 56d46483e48879cb8a38dc13d7327daa15165754 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 13 May 2020 17:04:10 +0200 Subject: Add bt hci device class Code implements USB transport for bluetooth HCI. --- src/class/bth/bth_device.c | 252 +++++++++++++++++++++++++++++++++++++++++++++ src/class/bth/bth_device.h | 110 ++++++++++++++++++++ src/device/usbd.c | 13 +++ src/device/usbd.h | 54 ++++++++++ src/tusb.h | 4 + src/tusb_option.h | 4 + 6 files changed, 437 insertions(+) create mode 100755 src/class/bth/bth_device.c create mode 100755 src/class/bth/bth_device.h (limited to 'src') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c new file mode 100755 index 000000000..04011bcdb --- /dev/null +++ b/src/class/bth/bth_device.c @@ -0,0 +1,252 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jerzy Kasenberg + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_BTH) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "bth_device.h" +#include +#include + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct +{ + uint8_t itf_num; + uint8_t ep_ev; + uint8_t ep_acl_in; + uint8_t ep_acl_out; + uint8_t ep_voice[2]; // Not used yet + uint8_t ep_voice_size[2][CFG_TUD_BTH_ISO_ALT_COUNT]; + + // Endpoint Transfer buffer + CFG_TUSB_MEM_ALIGN bt_hci_cmd_t hci_cmd; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_BTH_DATA_EPSIZE]; + +} btd_interface_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION btd_interface_t _btd_itf; + +static bool bt_tx_data(uint8_t ep, void *data, uint16_t len) +{ + // skip if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(TUD_OPT_RHPORT, ep)); + + TU_ASSERT(usbd_edpt_xfer(TUD_OPT_RHPORT, ep, data, len)); + + return true; +} + +//--------------------------------------------------------------------+ +// READ API +//--------------------------------------------------------------------+ + + +//--------------------------------------------------------------------+ +// WRITE API +//--------------------------------------------------------------------+ + +bool tud_bt_event_send(void *event, uint16_t event_len) +{ + return bt_tx_data(_btd_itf.ep_ev, event, event_len); +} + +bool tud_bt_acl_data_send(void *event, uint16_t event_len) +{ + return bt_tx_data(_btd_itf.ep_acl_in, event, event_len); +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void btd_init(void) +{ + tu_memclr(&_btd_itf, sizeof(_btd_itf)); +} + +void btd_reset(uint8_t rhport) +{ + (void)rhport; +} + +uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +{ + tusb_desc_endpoint_t const *desc_ep; + uint16_t drv_len = 0; + // Size of single alternative of ISO interface + const uint16_t iso_alt_itf_size = sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t); + // Size of hci interface + const uint16_t hci_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t); + // Ensure this is BT Primary Controller + TU_VERIFY(TUSB_CLASS_WIRELESS_CONTROLLER == itf_desc->bInterfaceClass && + TUD_BT_APP_SUBCLASS == itf_desc->bInterfaceSubClass && + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER == itf_desc->bInterfaceProtocol, 0); + + // Distinguish interface by number of endpoints, as both interface have same class, subclass and protocol + if (itf_desc->bNumEndpoints == 3 && max_len >= hci_itf_size) + { + _btd_itf.itf_num = itf_desc->bInterfaceNumber; + + desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); + TU_ASSERT(dcd_edpt_open(rhport, desc_ep), 0); + _btd_itf.ep_ev = desc_ep->bEndpointAddress; + + // Open endpoint pair + TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(desc_ep), 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out, + &_btd_itf.ep_acl_in), 0); + + // Prepare for incoming data from host + TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0); + + drv_len = hci_itf_size; + } + else if (itf_desc->bNumEndpoints == 2 && max_len >= iso_alt_itf_size) + { + uint8_t dir; + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); + TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; + // Store endpoint size for alternative + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT, 0); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + _btd_itf.ep_voice[dir] = desc_ep->bEndpointAddress; + // Store endpoint size for alternative + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + drv_len += iso_alt_itf_size; + + for (int i = 1; i < CFG_TUD_BTH_ISO_ALT_COUNT && drv_len + iso_alt_itf_size <= max_len; ++i) { + // Make sure rest of alternatives matches + itf_desc = (tusb_desc_interface_t const *)tu_desc_next(desc_ep); + if (itf_desc->bDescriptorType != TUSB_DESC_INTERFACE || + TUSB_CLASS_WIRELESS_CONTROLLER != itf_desc->bInterfaceClass || + TUD_BT_APP_SUBCLASS != itf_desc->bInterfaceSubClass || + TUD_BT_PROTOCOL_PRIMARY_CONTROLLER != itf_desc->bInterfaceProtocol) + { + // Not an Iso interface instance + break; + } + TU_ASSERT(itf_desc->bAlternateSetting < CFG_TUD_BTH_ISO_ALT_COUNT, 0); + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(itf_desc); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + // Verify that alternative endpoint are same as first ones + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && + _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + + desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep); + dir = tu_edpt_dir(desc_ep->bEndpointAddress); + // Verify that alternative endpoint are same as first ones + TU_ASSERT(desc_ep->bDescriptorType == TUSB_DESC_ENDPOINT && + _btd_itf.ep_voice[dir] == desc_ep->bEndpointAddress, 0); + _btd_itf.ep_voice_size[dir][itf_desc->bAlternateSetting] = (uint8_t)desc_ep->wMaxPacketSize.size; + drv_len += iso_alt_itf_size; + } + } + + return drv_len; +} + +bool btd_control_complete(uint8_t rhport, tusb_control_request_t const *request) +{ + (void)rhport; + + // Handle class request only + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength); + + return true; +} + +bool btd_control_request(uint8_t rhport, tusb_control_request_t const *request) +{ + (void)rhport; + + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) + { + // HCI command packet addressing for single function Primary Controllers + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); + } + else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) + { + if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) + { + // TODO: Set interface it would involve changing size of endpoint size + } + else + { + // HCI command packet for Primary Controller function in a composite device + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); + } + } + else return false; + + return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength); +} + +bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void)result; + + // received new data from host + if (ep_addr == _btd_itf.ep_acl_out) + { + if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_itf.epout_buf, xferred_bytes); + + // prepare for next data + TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE)); + } + else if (ep_addr == _btd_itf.ep_ev) + { + if (tud_bt_event_sent_cb) tud_bt_event_sent_cb((uint16_t)xferred_bytes); + } + else if (ep_addr == _btd_itf.ep_acl_in) + { + if (tud_bt_acl_data_sent_cb) tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes); + } + + return TUSB_ERROR_NONE; +} + +#endif diff --git a/src/class/bth/bth_device.h b/src/class/bth/bth_device.h new file mode 100755 index 000000000..5e5468084 --- /dev/null +++ b/src/class/bth/bth_device.h @@ -0,0 +1,110 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jerzy Kasenberg + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_BTH_DEVICE_H_ +#define _TUSB_BTH_DEVICE_H_ + +#include +#include + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ +#ifndef CFG_TUD_BTH_EVENT_EPSIZE +#define CFG_TUD_BTH_EVENT_EPSIZE 16 +#endif +#ifndef CFG_TUD_BTH_DATA_EPSIZE +#define CFG_TUD_BTH_DATA_EPSIZE 64 +#endif + +typedef struct TU_ATTR_PACKED +{ + uint16_t op_code; + uint8_t param_length; + uint8_t param[255]; +} bt_hci_cmd_t; + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +// Invoked when HCI command was received over USB from Bluetooth host. +// Detailed format is described in Bluetooth core specification Vol 2, +// Part E, 5.4.1. +// Length of the command is from 3 bytes (2 bytes for OpCode, +// 1 byte for parameter total length) to 258. +TU_ATTR_WEAK void tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len); + +// Invoked when ACL data was received over USB from Bluetooth host. +// Detailed format is described in Bluetooth core specification Vol 2, +// Part E, 5.4.2. +// Length is from 4 bytes, (12 bits for Handle, 4 bits for flags +// and 16 bits for data total length) to endpoint size. +TU_ATTR_WEAK void tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len); + +// Called when event sent with tud_bt_event_send() was delivered to BT stack. +// Controller can release/reuse buffer with Event packet at this point. +TU_ATTR_WEAK void tud_bt_event_sent_cb(uint16_t sent_bytes); + +// Called when ACL data that was sent with tud_bt_acl_data_send() +// was delivered to BT stack. +// Controller can release/reuse buffer with ACL packet at this point. +TU_ATTR_WEAK void tud_bt_acl_data_sent_cb(uint16_t sent_bytes); + +// Bluetooth controller calls this function when it wants to send even packet +// as described in Bluetooth core specification Vol 2, Part E, 5.4.4. +// Event has at least 2 bytes, first is Event code second contains parameter +// total length. Controller can release/reuse event memory after +// tud_bt_event_sent_cb() is called. +bool tud_bt_event_send(void *event, uint16_t event_len); + +// Bluetooth controller calls this to send ACL data packet +// as described in Bluetooth core specification Vol 2, Part E, 5.4.2 +// Minimum length is 4 bytes, (12 bits for Handle, 4 bits for flags +// and 16 bits for data total length). Upper limit is not limited +// to endpoint size since buffer is allocate by controller +// and must not be reused till tud_bt_acl_data_sent_cb() is called. +bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void btd_init (void); +void btd_reset (uint8_t rhport); +uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool btd_control_request (uint8_t rhport, tusb_control_request_t const * request); +bool btd_control_complete (uint8_t rhport, tusb_control_request_t const * request); +bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_BTH_DEVICE_H_ */ diff --git a/src/device/usbd.c b/src/device/usbd.c index 3cbd50644..fe392ef6e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -199,6 +199,19 @@ static usbd_class_driver_t const _usbd_driver[] = .sof = NULL, }, #endif + + #if CFG_TUD_BTH + { + DRIVER_NAME("BTH") + .init = btd_init, + .reset = btd_reset, + .open = btd_open, + .control_request = btd_control_request, + .control_complete = btd_control_complete, + .xfer_cb = btd_xfer_cb, + .sof = NULL + }, + #endif }; enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; diff --git a/src/device/usbd.h b/src/device/usbd.h index ecef63e18..2070b50c6 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -438,6 +438,60 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Endpoint Out */\ 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 +//------------- BT Radio -------------// +#define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER) +#define TUD_BT_APP_SUBCLASS 0x01 +#define TUD_BT_PROTOCOL_PRIMARY_CONTROLLER 0x01 +#define TUD_BT_PROTOCOL_AMP_CONTROLLER 0x02 + +#ifndef CFG_TUD_BTH_ISO_ALT_COUNT +#define CFG_TUD_BTH_ISO_ALT_COUNT 0 +#endif + +// Length of template descriptor: 30 bytes + number of ISO alternatives * 23 +#define TUD_BTH_DESC_LEN (9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7)) + +/* Primary Interface */ +#define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ + 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Endpoint In for events */ \ + 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ + /* Endpoint In for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ + /* Endpoint Out for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 + +#define TUD_BTH_ISO_ITF(_itfnum, _alt, _ep_in, _ep_out, _n) ,\ + /* Interface with 2 endpoints */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Isochronous endpoints */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 + +#define _FIRST(a, ...) a +#define _REST(a, ...) __VA_ARGS__ + +#define TUD_BTH_ISO_ITF_0(_itfnum, ...) +#define TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 1, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 2, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 3, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 4, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 5, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) +#define TUD_BTH_ISO_ITF_6(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 6, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ + TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + +#define TUD_BTH_ISO_ITFS(_itfnum, _ep_in, _ep_out, ...) \ + TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) + +// BT Primary controller descriptor +// Interface number, string index, attributes, event endpoint, event endpoint size, interval, data in, data out, data endpoint size, iso endpoint sizes +#define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \ + TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ + TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) #ifdef __cplusplus } diff --git a/src/tusb.h b/src/tusb.h index 55c105121..defbc54fb 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -95,6 +95,10 @@ #if CFG_TUD_NET #include "class/net/net_device.h" #endif + + #if CFG_TUD_BTH + #include "class/bth/bth_device.h" + #endif #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 9e6a2b532..0a227483f 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -219,6 +219,10 @@ #define CFG_TUD_NET 0 #endif +#ifndef CFG_TUD_BTH + #define CFG_TUD_BTH 0 +#endif + //-------------------------------------------------------------------- // HOST OPTIONS //-------------------------------------------------------------------- -- cgit v1.3.1 From d6d29897f38ebc8bc8b660d2749e472b39537b34 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 May 2020 23:16:16 +0700 Subject: add get device qualifier descriptor --- src/device/usbd.c | 24 +++++++++++++++++++++--- src/device/usbd.h | 10 ++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 971417a35..3af9491e2 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -867,9 +867,27 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const case TUSB_DESC_DEVICE_QUALIFIER: TU_LOG2(" Device Qualifier\r\n"); - // TODO If not highspeed capable stall this request otherwise - // return the descriptor that could work in highspeed - return false; + // Host sends this request to ask why our device with USB BCD from 2.0 + // but is running at Full/Low Speed. If not highspeed capable stall this request, + // otherwise return the descriptor that could work in highspeed mode + if ( tud_descriptor_device_qualifier_cb ) + { + uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); + TU_ASSERT(desc_qualifier); + + // first byte of descriptor is its size + return tud_control_xfer(rhport, p_request, (void*) desc_qualifier, desc_qualifier[0]); + }else + { + return false; + } + break; + + case TUSB_DESC_OTHER_SPEED_CONFIG: + TU_LOG2(" Other Speed Configuration\r\n"); + + // After Device Qualifier descriptor is received host will ask for this descriptor + return false; // not supported break; default: return false; diff --git a/src/device/usbd.h b/src/device/usbd.h index ecef63e18..9af700886 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -68,6 +68,8 @@ static inline bool tud_ready(void) // Remote wake up host, only if suspended and enabled by host bool tud_remote_wakeup(void); +// Enable pull-up resistor on D+ D- +// Return false on unsupported MCUs static inline bool tud_disconnect(void) { TU_VERIFY(dcd_disconnect); @@ -75,6 +77,8 @@ static inline bool tud_disconnect(void) return true; } +// Disable pull-up resistor on D+ D- +// Return false on unsupported MCUs static inline bool tud_connect(void) { TU_VERIFY(dcd_connect); @@ -110,6 +114,10 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index); // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void); + // Invoked when device is mounted (configured) TU_ATTR_WEAK void tud_mount_cb(void); @@ -125,6 +133,8 @@ TU_ATTR_WEAK void tud_resume_cb(void); // Invoked when received control request with VENDOR TYPE TU_ATTR_WEAK bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); + +// Invoked when vendor control request is complete TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); -- cgit v1.3.1 From 5ffba8536dfaa4602e3e7f1c94be124bfeb3a5ae Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 31 May 2020 19:41:22 +0700 Subject: able to detect as hs --- hw/bsp/stm32h743eval/stm32h743eval.c | 13 +++++++++---- src/common/tusb_common.h | 4 +++- src/portable/st/synopsys/dcd_synopsys.c | 10 ++++++---- 3 files changed, 18 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/hw/bsp/stm32h743eval/stm32h743eval.c b/hw/bsp/stm32h743eval/stm32h743eval.c index d149c1230..836f1ecab 100644 --- a/hw/bsp/stm32h743eval/stm32h743eval.c +++ b/hw/bsp/stm32h743eval/stm32h743eval.c @@ -265,6 +265,7 @@ void board_init(void) #endif #if BOARD_DEVICE_RHPORT_NUM == 1 + // Despite being call USB2_OTG // OTG_HS is marked as RHPort1 by TinyUSB to be consistent across stm32 port __GPIOA_CLK_ENABLE(); @@ -316,6 +317,8 @@ void board_init(void) GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Alternate = GPIO_AF10_OTG2_HS; HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); + + // Enable ULPI clock __HAL_RCC_USB1_OTG_HS_ULPI_CLK_ENABLE(); /* Enable USB HS Clocks */ @@ -325,12 +328,14 @@ void board_init(void) USB_OTG_HS->GCCFG &= ~USB_OTG_GCCFG_VBDEN; // Force device mode - // USB_OTG_HS->GUSBCFG &= ~USB_OTG_GUSBCFG_FHMOD; - // USB_OTG_HS->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + USB_OTG_HS->GUSBCFG &= ~USB_OTG_GUSBCFG_FHMOD; + USB_OTG_HS->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; // B-peripheral session valid override enabl -// USB_OTG_HS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN; -// USB_OTG_HS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; + USB_OTG_HS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN; + USB_OTG_HS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; + + HAL_PWREx_EnableUSBVoltageDetector(); #endif // rhport = 1 } diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index f144cda73..d77893b6b 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -241,9 +241,9 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize) #define TU_LOG2 TU_LOG1 #define TU_LOG2_MEM TU_LOG1_MEM #define TU_LOG2_VAR TU_LOG1_VAR - #define TU_LOG2_LOCATION() TU_LOG1_LOCATION() #define TU_LOG2_INT TU_LOG1_INT #define TU_LOG2_HEX TU_LOG1_HEX + #define TU_LOG2_LOCATION() TU_LOG1_LOCATION() #endif @@ -277,6 +277,7 @@ static inline char const* lookup_find(lookup_table_t const* p_table, uint32_t ke #define TU_LOG1_VAR(...) #define TU_LOG1_INT(...) #define TU_LOG1_HEX(...) + #define TU_LOG1_LOCATION() #endif #ifndef TU_LOG2 @@ -285,6 +286,7 @@ static inline char const* lookup_find(lookup_table_t const* p_table, uint32_t ke #define TU_LOG2_VAR(...) #define TU_LOG2_INT(...) #define TU_LOG2_HEX(...) + #define TU_LOG2_LOCATION() #endif #ifdef __cplusplus diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 8ca67dbb4..fe6fe5cea 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -197,6 +197,8 @@ static void end_of_reset(uint8_t rhport) // However, keep for debugging and in case Low Speed is ever supported. uint32_t enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; + // TODO set turnaround in GUSBCFG accordingly to the speed + // Maximum packet size for EP 0 is set for both directions by writing // DIEPCTL. if(enum_spd == 0x03) { @@ -239,7 +241,8 @@ void dcd_init (uint8_t rhport) // Turn around time for Highspeed is 0x09 usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; usb_otg->GUSBCFG |= (0x09 << USB_OTG_GUSBCFG_TRDT_Pos); - }else + } + else #endif { // Turn around programmed for 32+ MHz is 0x06 @@ -256,8 +259,6 @@ void dcd_init (uint8_t rhport) // Force device mode usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; - TU_LOG2_LOCATION(); - // Restart PHY clock *((volatile uint32_t *)(_dcd_rhport[rhport].regs + USB_OTG_PCGCCTL_BASE)) = 0; @@ -282,8 +283,9 @@ void dcd_init (uint8_t rhport) dev->DCFG &= ~(3 << USB_OTG_DCFG_DSPD_Pos); // Transceiver delay, necessary for some ULPI PHYs - dev->DCFG |= (1 << 14); + //dev->DCFG |= (1 << 14); } + else #endif { // full speed with internal phy -- cgit v1.3.1 From f771afe6af894a5f3ee029756d4521b56d74c1c0 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 31 May 2020 23:43:29 +0700 Subject: fixed EP0 size to 64 since LS is not supported in device mode - set turn-around and report actual speed in Enum Done - add dcd_event_bus_reset() helper to report speed --- src/device/dcd.h | 15 ++++-- src/device/usbd.c | 9 +++- src/portable/st/synopsys/dcd_synopsys.c | 85 ++++++++++++++++----------------- 3 files changed, 62 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index 68798c259..a4635346b 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -60,11 +60,17 @@ typedef struct TU_ATTR_ALIGNED(4) uint8_t rhport; uint8_t event_id; - union { - // USBD_EVT_SETUP_RECEIVED + union + { + // BUS RESET + struct { + tusb_speed_t speed; + } bus_reset; + + // SETUP_RECEIVED tusb_control_request_t setup_received; - // USBD_EVT_XFER_COMPLETE + // XFER_COMPLETE struct { uint8_t ep_addr; uint8_t result; @@ -143,6 +149,9 @@ extern void dcd_event_handler(dcd_event_t const * event, bool in_isr); // helper to send bus signal event extern void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr); +// helper to send bus reset event +extern void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr); + // helper to send setup received extern void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr); diff --git a/src/device/usbd.c b/src/device/usbd.c index bd892e389..275792ab9 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -920,7 +920,14 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) { - dcd_event_t event = { .rhport = rhport, .event_id = eid, }; + dcd_event_t event = { .rhport = rhport, .event_id = eid }; + dcd_event_handler(&event, in_isr); +} + +void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr) +{ + dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_BUS_RESET }; + event.bus_reset.speed = speed; dcd_event_handler(&event, in_isr); } diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index fe6fe5cea..ed16308da 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -109,6 +109,13 @@ static const dcd_rhport_t _dcd_rhport[] = #define IN_EP_BASE(_port) (USB_OTG_INEndpointTypeDef *) (_dcd_rhport[_port].regs + USB_OTG_IN_ENDPOINT_BASE) #define FIFO_BASE(_port, _x) ((volatile uint32_t *) (_dcd_rhport[_port].regs + USB_OTG_FIFO_BASE + (_x) * USB_OTG_FIFO_SIZE)) +enum +{ + DCD_HIGH_SPEED = 0, // Highspeed mode + DCD_FULL_SPEED_USE_HS = 1, // Full speed in Highspeed port (probably with internal PHY) + DCD_FULL_SPEED = 3, // Full speed with internal PHY +}; + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM @@ -141,6 +148,7 @@ static void bus_reset(uint8_t rhport) USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); for(uint8_t n = 0; n < EP_MAX; n++) { out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; @@ -183,34 +191,29 @@ static void bus_reset(uint8_t rhport) // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | (usb_otg->GRXFSIZ & 0x0000ffffUL); + // Fixed control EP0 size to 64 bytes + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; + out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; } -static void end_of_reset(uint8_t rhport) +// speed is native DCD speed +static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, uint32_t speed) { - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; - // On current silicon on the Full Speed core, speed is fixed to Full Speed. - // However, keep for debugging and in case Low Speed is ever supported. - uint32_t enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; - - // TODO set turnaround in GUSBCFG accordingly to the speed - - // Maximum packet size for EP 0 is set for both directions by writing - // DIEPCTL. - if(enum_spd == 0x03) { - // 64 bytes - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; - } else { - // 8 bytes - in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = 8; - xfer_status[0][TUSB_DIR_IN].max_size = 8; + if ( speed == DCD_HIGH_SPEED ) + { + // Use fixed 0x09 for Highspeed + usb_otg->GUSBCFG |= (0x09 << USB_OTG_GUSBCFG_TRDT_Pos); + } + else + { + // Fullspeed depends on MCU clocks, but we will use 0x06 for 32+ Mhz + usb_otg->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos); } } @@ -220,7 +223,8 @@ static void end_of_reset(uint8_t rhport) *------------------------------------------------------------------*/ void dcd_init (uint8_t rhport) { - dcd_disconnect(rhport); + // Programming model begins in the last section of the chapter on the USB + // peripheral in each Reference Manual. USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); @@ -238,16 +242,15 @@ void dcd_init (uint8_t rhport) usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); - // Turn around time for Highspeed is 0x09 - usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; - usb_otg->GUSBCFG |= (0x09 << USB_OTG_GUSBCFG_TRDT_Pos); + set_turnaround(usb_otg, DCD_HIGH_SPEED); } else #endif { - // Turn around programmed for 32+ MHz is 0x06 - usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; - usb_otg->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos) | USB_OTG_GUSBCFG_PHYSEL; + set_turnaround(usb_otg, DCD_FULL_SPEED); + + // Enable internal PHY + usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; } // Reset core after selecting PHY @@ -256,9 +259,6 @@ void dcd_init (uint8_t rhport) usb_otg->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST) {} - // Force device mode - usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; - // Restart PHY clock *((volatile uint32_t *)(_dcd_rhport[rhport].regs + USB_OTG_PCGCCTL_BASE)) = 0; @@ -273,7 +273,7 @@ void dcd_init (uint8_t rhport) USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); // If USB host misbehaves during status portion of control xfer - // (non zero-length packet), send STALL back and discard. Full speed. + // (non zero-length packet), send STALL back and discard. dev->DCFG |= USB_OTG_DCFG_NZLSOHSK; #if TUD_OPT_HIGH_SPEED @@ -288,10 +288,10 @@ void dcd_init (uint8_t rhport) else #endif { - // full speed with internal phy + // full speed with internal PHY dev->DCFG |= (3 << USB_OTG_DCFG_DSPD_Pos); - // Enable USB transceiver. + // Enable internal USB transceiver. usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; } @@ -299,8 +299,8 @@ void dcd_init (uint8_t rhport) USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); - // Programming model begins in the last section of the chapter on the USB - // peripheral in each Reference Manual. + + // Enable global interrupt usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; } @@ -789,15 +789,14 @@ void dcd_int_handler(uint8_t rhport) } if(int_status & USB_OTG_GINTSTS_ENUMDNE) { - // ENUMDNE detects speed of the link. For full-speed, we - // always expect the same value. This interrupt is considered - // the end of reset. - - TU_LOG2_HEX(dev->DSTS); + // ENUMDNE is the end of reset where speed of the link is detected usb_otg->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; - end_of_reset(rhport); - dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); + + uint32_t const enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; + + set_turnaround(usb_otg, enum_spd); + dcd_event_bus_reset(rhport, (enum_spd == DCD_HIGH_SPEED) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL, true); } if(int_status & USB_OTG_GINTSTS_USBSUSP) -- cgit v1.3.1 From 710c54f8cbee2134334262cf872f538909b264c5 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 1 Jun 2020 01:36:09 +0700 Subject: allow hs ep open with 512 bytes --- examples/device/cdc_msc/src/usb_descriptors.c | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 30 ++++++++++++++++++--------- 2 files changed, 21 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 7b22d46a7..62ab4f10f 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -123,7 +123,7 @@ uint8_t const desc_configuration[] = TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), }; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index ed16308da..739361da9 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -185,8 +185,9 @@ static void bus_reset(uint8_t rhport) // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) // * 1 location for global NAK (not required/used here). // * It is recommended to allocate 2 times the largest packet size, therefore - // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 - usb_otg->GRXFSIZ = 52; + // Recommended value = 10 + 1 + 2 x (16+2) = 47. To make it scale better with large FIFO size + // and work better with Highspeed. We use 1/5 of total FIFO size + usb_otg->GRXFSIZ = (EP_FIFO_SIZE/4)/5; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | (usb_otg->GRXFSIZ & 0x0000ffffUL); @@ -201,11 +202,11 @@ static void bus_reset(uint8_t rhport) } // speed is native DCD speed -static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, uint32_t speed) +static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, tusb_speed_t speed) { usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; - if ( speed == DCD_HIGH_SPEED ) + if ( speed == TUSB_SPEED_HIGH ) { // Use fixed 0x09 for Highspeed usb_otg->GUSBCFG |= (0x09 << USB_OTG_GUSBCFG_TRDT_Pos); @@ -217,6 +218,12 @@ static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, uint32_t speed) } } +static tusb_speed_t get_speed(USB_OTG_DeviceTypeDef* dev) +{ + uint32_t const enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; + return (enum_spd == DCD_HIGH_SPEED) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL; +} + /*------------------------------------------------------------------*/ /* Controller API @@ -242,12 +249,12 @@ void dcd_init (uint8_t rhport) usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); - set_turnaround(usb_otg, DCD_HIGH_SPEED); + set_turnaround(usb_otg, TUSB_SPEED_HIGH); } else #endif { - set_turnaround(usb_otg, DCD_FULL_SPEED); + set_turnaround(usb_otg, TUSB_SPEED_FULL); // Enable internal PHY usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; @@ -357,9 +364,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 64); TU_ASSERT(epnum < EP_MAX); + // TODO ISO endpoint can be up to 1024 bytes + TU_ASSERT(desc_edpt->wMaxPacketSize.size <= (get_speed(dev) == TUSB_SPEED_HIGH ? 512 : 64)); + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = desc_edpt->wMaxPacketSize.size; @@ -447,6 +456,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t ((total_bytes & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) << USB_OTG_DIEPTSIZ_XFRSIZ_Pos); in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; + // Enable fifo empty interrupt only if there are something to put in the fifo. if(total_bytes != 0) { dev->DIEPEMPMSK |= (1 << epnum); @@ -793,10 +803,10 @@ void dcd_int_handler(uint8_t rhport) usb_otg->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; - uint32_t const enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; + tusb_speed_t const speed = get_speed(dev); - set_turnaround(usb_otg, enum_spd); - dcd_event_bus_reset(rhport, (enum_spd == DCD_HIGH_SPEED) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL, true); + set_turnaround(usb_otg, speed); + dcd_event_bus_reset(rhport, speed, true); } if(int_status & USB_OTG_GINTSTS_USBSUSP) -- cgit v1.3.1 From e92118635cc8055a5ca599eaf9919d99a55bf584 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 1 Jun 2020 13:40:18 +0700 Subject: adding speed detect on bus reset --- hw/bsp/stm32h743eval/board.mk | 2 +- src/device/usbd.c | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/hw/bsp/stm32h743eval/board.mk b/hw/bsp/stm32h743eval/board.mk index 5c6c6ea4f..cbf37a95d 100644 --- a/hw/bsp/stm32h743eval/board.mk +++ b/hw/bsp/stm32h743eval/board.mk @@ -48,7 +48,7 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = stm32h743xi -JLINK_IF = jtag +JLINK_IF = swd # flash target using on-board stlink flash: flash-stlink diff --git a/src/device/usbd.c b/src/device/usbd.c index 275792ab9..eeb5011ec 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -40,7 +40,8 @@ //--------------------------------------------------------------------+ // Device Data //--------------------------------------------------------------------+ -typedef struct { +typedef struct +{ struct TU_ATTR_PACKED { volatile uint8_t connected : 1; @@ -53,6 +54,8 @@ typedef struct { uint8_t self_powered : 1; // configuration descriptor's attribute }; + uint8_t speed; + uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid ) @@ -384,7 +387,7 @@ void tud_task (void) { case DCD_EVENT_BUS_RESET: usbd_reset(event.rhport); - // TODO DCD should report operational speed (LS/FS/HS) + _usbd_dev.speed = event.bus_reset.speed; break; case DCD_EVENT_UNPLUGGED: -- cgit v1.3.1 From 0635bafe0af9452fd3cf0fbca391e9dbf123f382 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 9 Jun 2020 15:22:16 +0200 Subject: Add DCD for Dialog DA1469x MCU Dialog Semiconductor's BLE MCU DA1469x comes with full speed USB. It's base on National Semiconductor discrete USB controller USBN9603/4. This adds support for: - control/interrupt/bulk endpoints (up to 64 bytes) - ISO endpoint were not tested and may not work correctly - reset/sleep/wakeup are handled - code for VBUS changes is provided --- src/portable/dialog/da146xx/dcd_da146xx.c | 842 ++++++++++++++++++++++++++++++ src/tusb_option.h | 3 + 2 files changed, 845 insertions(+) create mode 100644 src/portable/dialog/da146xx/dcd_da146xx.c (limited to 'src') diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c new file mode 100644 index 000000000..3a3459b7d --- /dev/null +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -0,0 +1,842 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jerzy Kasenberg + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_DA1469X + +#include "DA1469xAB.h" + +#include "device/dcd.h" + +/*------------------------------------------------------------------*/ +/* MACRO TYPEDEF CONSTANT ENUM + *------------------------------------------------------------------*/ + +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#define USE_SOF 0 + +#define EP_MAX 4 + +#define NFSR_NODE_RESET 0 +#define NFSR_NODE_RESUME 1 +#define NFSR_NODE_OPERATIONAL 2 +#define NFSR_NODE_SUSPEND 3 + +static TU_ATTR_ALIGNED(4) uint8_t _setup_packet[8]; + +typedef struct +{ + union + { + __IOM uint32_t epc_in; + __IOM uint32_t USB_EPC0_REG; /*!< (@ 0x00000080) Endpoint Control 0 Register */ + __IOM uint32_t USB_EPC1_REG; /*!< (@ 0x000000A0) Endpoint Control Register 1 */ + __IOM uint32_t USB_EPC3_REG; /*!< (@ 0x000000C0) Endpoint Control Register 3 */ + __IOM uint32_t USB_EPC5_REG; /*!< (@ 0x000000E0) Endpoint Control Register 5 */ + }; + union + { + __IOM uint32_t txd; + __IOM uint32_t USB_TXD0_REG; /*!< (@ 0x00000084) Transmit Data 0 Register */ + __IOM uint32_t USB_TXD1_REG; /*!< (@ 0x000000A4) Transmit Data Register 1 */ + __IOM uint32_t USB_TXD2_REG; /*!< (@ 0x000000C4) Transmit Data Register 2 */ + __IOM uint32_t USB_TXD3_REG; /*!< (@ 0x000000E4) Transmit Data Register 3 */ + }; + union + { + __IOM uint32_t txs; + __IOM uint32_t USB_TXS0_REG; /*!< (@ 0x00000088) Transmit Status 0 Register */ + __IOM uint32_t USB_TXS1_REG; /*!< (@ 0x000000A8) Transmit Status Register 1 */ + __IOM uint32_t USB_TXS2_REG; /*!< (@ 0x000000C8) Transmit Status Register 2 */ + __IOM uint32_t USB_TXS3_REG; /*!< (@ 0x000000E8) Transmit Status Register 3 */ + }; + union + { + __IOM uint32_t txc; + __IOM uint32_t USB_TXC0_REG; /*!< (@ 0x0000008C) Transmit command 0 Register */ + __IOM uint32_t USB_TXC1_REG; /*!< (@ 0x000000AC) Transmit Command Register 1 */ + __IOM uint32_t USB_TXC2_REG; /*!< (@ 0x000000CC) Transmit Command Register 2 */ + __IOM uint32_t USB_TXC3_REG; /*!< (@ 0x000000EC) Transmit Command Register 3 */ + }; + union + { + __IOM uint32_t epc_out; + __IOM uint32_t USB_EP0_NAK_REG; /*!< (@ 0x00000090) EP0 INNAK and OUTNAK Register */ + __IOM uint32_t USB_EPC2_REG; /*!< (@ 0x000000B0) Endpoint Control Register 2 */ + __IOM uint32_t USB_EPC4_REG; /*!< (@ 0x000000D0) Endpoint Control Register 4 */ + __IOM uint32_t USB_EPC6_REG; /*!< (@ 0x000000F0) Endpoint Control Register 6 */ + }; + union + { + __IOM uint32_t rxd; + __IOM uint32_t USB_RXD0_REG; /*!< (@ 0x00000094) Receive Data 0 Register */ + __IOM uint32_t USB_RXD1_REG; /*!< (@ 0x000000B4) Receive Data Register,1 */ + __IOM uint32_t USB_RXD2_REG; /*!< (@ 0x000000D4) Receive Data Register 2 */ + __IOM uint32_t USB_RXD3_REG; /*!< (@ 0x000000F4) Receive Data Register 3 */ + }; + union + { + __IOM uint32_t rxs; + __IOM uint32_t USB_RXS0_REG; /*!< (@ 0x00000098) Receive Status 0 Register */ + __IOM uint32_t USB_RXS1_REG; /*!< (@ 0x000000B8) Receive Status Register 1 */ + __IOM uint32_t USB_RXS2_REG; /*!< (@ 0x000000D8) Receive Status Register 2 */ + __IOM uint32_t USB_RXS3_REG; /*!< (@ 0x000000F8) Receive Status Register 3 */ + }; + union + { + __IOM uint32_t rxc; + __IOM uint32_t USB_RXC0_REG; /*!< (@ 0x0000009C) Receive Command 0 Register */ + __IOM uint32_t USB_RXC1_REG; /*!< (@ 0x000000BC) Receive Command Register 1 */ + __IOM uint32_t USB_RXC2_REG; /*!< (@ 0x000000DC) Receive Command Register 2 */ + __IOM uint32_t USB_RXC3_REG; /*!< (@ 0x000000FC) Receive Command Register 3 */ + }; +} EPx_REGS; + +#define EP_REGS(first_ep_reg) (EPx_REGS*)(&USB->first_ep_reg) + +// Dialog register fields and bit mask are very long. Filed masks repeat register names. +// Those convenience macros are a way to reduce complexity of register modification lines. +#define GET_BIT(val, field) (val & field ## _Msk) >> field ## _Pos +#define REG_GET_BIT(reg, field) (USB->reg & USB_ ## reg ## _ ## field ## _Msk) +#define REG_SET_BIT(reg, field) USB->reg |= USB_ ## reg ## _ ## field ## _Msk +#define REG_CLR_BIT(reg, field) USB->reg &= ~USB_ ## reg ## _ ## field ## _Msk +#define REG_SET_VAL(reg, field, val) USB->reg = (USB->reg & ~USB_ ## reg ## _ ## field ## _Msk) | (val << USB_ ## reg ## _ ## field ## _Pos) + +typedef struct { + EPx_REGS * regs; + uint8_t * buffer; + // Total length of current transfer + uint16_t total_len; + // Bytes transferred so far + uint16_t transferred; + uint16_t max_packet_size; + // Packet size sent or received so far. It is used to modify transferred field + // after ACK is received or when filling ISO endpoint with size larger then + // FIFO size. + uint16_t last_packet_size; + uint8_t ep_addr; + // DATA0/1 toggle bit 1 DATA1 is expected or transmitted + uint8_t data1 : 1; + // Endpoint is stalled + uint8_t stall : 1; +} xfer_ctl_t; + +static struct +{ + bool vbus_present; + bool in_reset; + xfer_ctl_t xfer_status[EP_MAX][2]; +} _dcd = +{ + .vbus_present = false, + .xfer_status = + { + { { .regs = EP_REGS(USB_EPC0_REG) }, { .regs = EP_REGS(USB_EPC0_REG) } }, + { { .regs = EP_REGS(USB_EPC1_REG) }, { .regs = EP_REGS(USB_EPC1_REG) } }, + { { .regs = EP_REGS(USB_EPC3_REG) }, { .regs = EP_REGS(USB_EPC3_REG) } }, + { { .regs = EP_REGS(USB_EPC5_REG) }, { .regs = EP_REGS(USB_EPC5_REG) } }, + } +}; + +// Two endpoint 0 descriptor definition for unified dcd_edpt_open() +static const tusb_desc_endpoint_t ep0OUT_desc = +{ + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + + .bEndpointAddress = 0x00, + .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, + .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, + .bInterval = 0 +}; + +static const tusb_desc_endpoint_t ep0IN_desc = +{ + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + + .bEndpointAddress = 0x80, + .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, + .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, + .bInterval = 0 +}; + +#define XFER_CTL_BASE(_ep, _dir) &_dcd.xfer_status[_ep][_dir] + +// Function could be called when VBUS change was detected. +void tusb_vbus_changed(bool present) +{ + if (present != _dcd.vbus_present) + { + _dcd.vbus_present = present; + if (present) + { + USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk; + USB->USB_NFSR_REG = 0; + USB->USB_FAR_REG = 0x80; + USB->USB_NFSR_REG = NFSR_NODE_RESET; + USB->USB_TXMSK_REG = 0; + USB->USB_RXMSK_REG = 0; + + USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk | + USB_USB_MAMSK_REG_USB_M_ALT_Msk | + USB_USB_MAMSK_REG_USB_M_WARN_Msk; + USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk; + } + else + { + USB->USB_MCTRL_REG = 0; + } + } +} + +static void transmit_packet(xfer_ctl_t * xfer) +{ + int left_to_send; + uint8_t const *src; + EPx_REGS *regs = xfer->regs; + uint32_t txc; + + txc = USB_USB_TXC1_REG_USB_TX_EN_Msk; + if (xfer->data1) txc |= USB_USB_TXC1_REG_USB_TOGGLE_TX_Msk; + + src = &xfer->buffer[xfer->transferred]; + left_to_send = xfer->total_len - xfer->transferred; + if (left_to_send > xfer->max_packet_size - xfer->last_packet_size) + { + left_to_send = xfer->max_packet_size - xfer->last_packet_size; + } + + // Loop checks TCOUNT all the time since this value is saturated to 31 + // and can't be read just once before. + while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && left_to_send > 0) + { + regs->txd = *src++; + xfer->last_packet_size++; + left_to_send--; + } + if (tu_edpt_number(xfer->ep_addr) != 0) + { + if (left_to_send > 0) + { + // Max packet size is set to value greater then FIFO. Enable fifo level warning + // to handle larger packets. + txc |= USB_USB_TXC1_REG_USB_TFWL_Msk; + } + else + { + // Whole packet already in fifo, no need to refill it later. Mark last. + txc |= USB_USB_TXC1_REG_USB_LAST_Msk; + } + } + // Enable transfer with correct interrupts enabled + regs->txc = txc; +} + +static void receive_packet(xfer_ctl_t *xfer, uint16_t bytes_in_fifo) +{ + EPx_REGS *regs = xfer->regs; + uint16_t remaining = xfer->total_len - xfer->transferred; + uint16_t receive_this_time = bytes_in_fifo; + + if (remaining <= bytes_in_fifo) receive_this_time = remaining; + + uint8_t *buf = xfer->buffer + xfer->transferred + xfer->last_packet_size; + + for (int i = 0; i < receive_this_time; ++i) buf[i] = regs->rxd; + + xfer->transferred += receive_this_time; + xfer->last_packet_size += receive_this_time; +} + +static void handle_ep0_rx(void) +{ + int packet_size; + uint32_t rxs0 = USB->USB_RXS0_REG; + + xfer_ctl_t *xfer = XFER_CTL_BASE(0, TUSB_DIR_OUT); + + packet_size = GET_BIT(rxs0, USB_USB_RXS0_REG_USB_RCOUNT); + if (rxs0 & USB_USB_RXS0_REG_USB_SETUP_Msk) + { + xfer_ctl_t *xfer_in = XFER_CTL_BASE(0, TUSB_DIR_IN); + // Setup packet is in + for (int i = 0; i < packet_size; ++i) _setup_packet[i] = USB->USB_RXD0_REG; + + xfer->stall = 0; + xfer->data1 = 1; + xfer_in->stall = 0; + xfer_in->data1 = 1; + REG_SET_BIT(USB_TXC0_REG, USB_TOGGLE_TX0); + REG_CLR_BIT(USB_EPC0_REG, USB_STALL); + dcd_event_setup_received(0, _setup_packet,true); + } + else + { + if (GET_BIT(rxs0, USB_USB_RXS0_REG_USB_TOGGLE_RX0) != xfer->data1) + { + // Toggle bit does not match discard packet + REG_SET_BIT(USB_RXC0_REG, USB_FLUSH); + } + else + { + receive_packet(xfer, packet_size); + xfer->data1 ^= 1; + + if (xfer->total_len == xfer->transferred || xfer->last_packet_size < xfer->max_packet_size) + { + dcd_event_xfer_complete(0, 0, xfer->transferred, XFER_RESULT_SUCCESS, true); + } + else + { + xfer->last_packet_size = 0; + // Re-enable reception + REG_SET_BIT(USB_RXC0_REG, USB_RX_EN); + } + } + } +} + +static void handle_ep0_tx(void) +{ + uint32_t txs0; + xfer_ctl_t *xfer = XFER_CTL_BASE(0, TUSB_DIR_IN); + EPx_REGS *regs = xfer->regs; + + txs0 = regs->USB_TXS0_REG; + + if (GET_BIT(txs0, USB_USB_TXS0_REG_USB_TX_DONE)) + { + // ACK received + if (GET_BIT(txs0, USB_USB_TXS0_REG_USB_ACK_STAT)) + { + xfer->transferred += xfer->last_packet_size; + xfer->last_packet_size = 0; + xfer->data1 ^= 1; + REG_SET_VAL(USB_TXC0_REG, USB_TOGGLE_TX0, xfer->data1); + if (xfer->transferred == xfer->total_len) + { + dcd_event_xfer_complete(0, 0 | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + return; + } + } + else + { + // Start from the beginning + xfer->last_packet_size = 0; + } + transmit_packet(xfer); + } +} + +static void handle_epx_rx_ev(uint8_t ep) +{ + uint32_t rxs; + int packet_size; + xfer_ctl_t *xfer = XFER_CTL_BASE(ep, TUSB_DIR_OUT); + + EPx_REGS *regs = xfer->regs; + + rxs = regs->rxs; + + if (GET_BIT(rxs, USB_USB_RXS1_REG_USB_RX_ERR)) + { + regs->rxc |= USB_USB_RXC1_REG_USB_FLUSH_Msk; + } + else + { + packet_size = GET_BIT(rxs, USB_USB_RXS1_REG_USB_RXCOUNT); + receive_packet(xfer, packet_size); + if (GET_BIT(rxs, USB_USB_RXS1_REG_USB_RX_LAST)) + { + if (GET_BIT(rxs, USB_USB_RXS1_REG_USB_TOGGLE_RX) != xfer->data1) + { + // Toggle bit does not match discard packet + regs->rxc |= USB_USB_RXC1_REG_USB_FLUSH_Msk; + } + else + { + xfer->data1 ^= 1; + if (xfer->total_len == xfer->transferred || xfer->last_packet_size < xfer->max_packet_size) + { + dcd_event_xfer_complete(0, xfer->ep_addr, xfer->transferred, XFER_RESULT_SUCCESS, true); + } + else + { + xfer->last_packet_size = 0; + // Re-enable reception + regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk; + } + } + } + } +} + +static void handle_rx_ev(void) +{ + if (USB->USB_RXEV_REG & 1) + handle_epx_rx_ev(1); + if (USB->USB_RXEV_REG & 2) + handle_epx_rx_ev(2); + if (USB->USB_RXEV_REG & 4) + handle_epx_rx_ev(3); +} + +static void handle_epx_tx_ev(xfer_ctl_t *xfer) +{ + uint32_t usb_txs1_reg; + EPx_REGS *regs = xfer->regs; + + usb_txs1_reg = regs->USB_TXS1_REG; + + if (GET_BIT(usb_txs1_reg, USB_USB_TXS1_REG_USB_TX_DONE)) + { + if (GET_BIT(usb_txs1_reg, USB_USB_TXS1_REG_USB_ACK_STAT)) + { + // ACK received, update transfer state and DATA0/1 bit + xfer->transferred += xfer->last_packet_size; + xfer->last_packet_size = 0; + xfer->data1 ^= 1; + + if (xfer->transferred == xfer->total_len) + { + dcd_event_xfer_complete(0, xfer->ep_addr, xfer->total_len, XFER_RESULT_SUCCESS, true); + return; + } + } + else + { + xfer->last_packet_size = 0; + } + transmit_packet(xfer); + } +} + +static void handle_tx_ev(void) +{ + if (USB->USB_TXEV_REG & 1) + handle_epx_tx_ev(XFER_CTL_BASE(1, TUSB_DIR_IN)); + if (USB->USB_TXEV_REG & 2) + handle_epx_tx_ev(XFER_CTL_BASE(2, TUSB_DIR_IN)); + if (USB->USB_TXEV_REG & 4) + handle_epx_tx_ev(XFER_CTL_BASE(3, TUSB_DIR_IN)); +} + +static void handle_bus_reset(void) +{ + USB->USB_NFSR_REG = 0; + USB->USB_FAR_REG = 0x80; + USB->USB_ALTMSK_REG = 0; + USB->USB_NFSR_REG = NFSR_NODE_RESET; + USB->USB_TXMSK_REG = 0; + USB->USB_RXMSK_REG = 0; + (void)USB->USB_ALTEV_REG; + _dcd.in_reset = true; + + dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + + USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk | +#if USE_SOF + USB_USB_MAMSK_REG_USB_M_FRAME_Msk | +#endif + USB_USB_MAMSK_REG_USB_M_WARN_Msk | + USB_USB_MAMSK_REG_USB_M_ALT_Msk; + USB->USB_NFSR_REG = NFSR_NODE_OPERATIONAL; + USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_SD3_Msk | + USB_USB_ALTMSK_REG_USB_M_RESUME_Msk; + // There is no information about end of reset state + // USB_FRAME event will be used to enable reset detection again + REG_SET_BIT(USB_MAEV_REG, USB_FRAME); + dcd_edpt_open (0, &ep0OUT_desc); + dcd_edpt_open (0, &ep0IN_desc); +} + +static void handle_alt_ev(void) +{ + uint32_t alt_ev = USB->USB_ALTEV_REG; + + if (GET_BIT(alt_ev, USB_USB_ALTEV_REG_USB_RESET)) + { + handle_bus_reset(); + } + else + { + if (GET_BIT(alt_ev, USB_USB_ALTEV_REG_USB_RESUME)) + { + USB->USB_NFSR_REG = NFSR_NODE_OPERATIONAL; + USB->USB_ALTMSK_REG &= ~USB_USB_ALTMSK_REG_USB_M_RESUME_Msk; + USB->USB_ALTMSK_REG |= USB_USB_ALTMSK_REG_USB_M_SD3_Msk; + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + if (GET_BIT(alt_ev, USB_USB_ALTEV_REG_USB_SD3)) + { + USB->USB_NFSR_REG = NFSR_NODE_SUSPEND; + USB->USB_ALTMSK_REG |= USB_USB_ALTMSK_REG_USB_M_RESUME_Msk; + USB->USB_ALTMSK_REG &= ~USB_USB_ALTMSK_REG_USB_M_SD3_Msk | USB_USB_ALTMSK_REG_USB_M_SD5_Msk; + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + } + } +} + +static void handle_epx_tx_refill(uint8_t ep) +{ + transmit_packet(XFER_CTL_BASE(ep, TUSB_DIR_IN)); +} + +static void handle_fifo_warning(void) +{ + uint32_t fifo_warning = USB->USB_FWEV_REG; + + if (fifo_warning & 0x01) + handle_epx_tx_refill(1); + if (fifo_warning & 0x02) + handle_epx_tx_refill(2); + if (fifo_warning & 0x04) + handle_epx_tx_refill(3); + if (fifo_warning & 0x10) + handle_epx_rx_ev(1); + if (fifo_warning & 0x20) + handle_epx_rx_ev(2); + if (fifo_warning & 0x40) + handle_epx_rx_ev(3); +} + +static void handle_ep0_nak(void) +{ + uint32_t ep0_nak = USB->USB_EP0_NAK_REG; + + if (REG_GET_BIT(USB_EPC0_REG, USB_STALL)) + { + if (GET_BIT(ep0_nak, USB_USB_EP0_NAK_REG_USB_EP0_INNAK)) + { + // EP0 is stalled and NAK was sent, it means that RX is enabled + // Disable RX for now. + REG_CLR_BIT(USB_RXC0_REG, USB_RX_EN); + REG_SET_BIT(USB_TXC0_REG, USB_TX_EN); + } + if (GET_BIT(ep0_nak, USB_USB_EP0_NAK_REG_USB_EP0_OUTNAK)) + { + REG_SET_BIT(USB_RXC0_REG, USB_RX_EN); + } + } + else + { + REG_CLR_BIT(USB_MAMSK_REG, USB_M_EP0_NAK); + } +} + +/*------------------------------------------------------------------*/ +/* Controller API + *------------------------------------------------------------------*/ +void dcd_init(uint8_t rhport) +{ + (void)rhport; + + USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk; + tusb_vbus_changed((CRG_TOP->ANA_STATUS_REG & CRG_TOP_ANA_STATUS_REG_VBUS_AVAILABLE_Msk) != 0); +} + +void dcd_int_enable(uint8_t rhport) +{ + (void)rhport; + + NVIC_EnableIRQ(USB_IRQn); +} + +void dcd_int_disable(uint8_t rhport) +{ + (void)rhport; + + NVIC_DisableIRQ(USB_IRQn); +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void)rhport; + + // Set default address for one ZLP + USB->USB_EPC0_REG = USB_USB_EPC0_REG_USB_DEF_Msk; + USB->USB_FAR_REG = (dev_addr & USB_USB_FAR_REG_USB_AD_Msk) | USB_USB_FAR_REG_USB_AD_EN_Msk; + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void)rhport; +} + +void dcd_connect(uint8_t rhport) +{ + (void)rhport; + + REG_SET_BIT(USB_MCTRL_REG, USB_NAT); +} + +void dcd_disconnect(uint8_t rhport) +{ + (void)rhport; + + REG_CLR_BIT(USB_MCTRL_REG, USB_NAT); +} + + +/*------------------------------------------------------------------*/ +/* DCD Endpoint port + *------------------------------------------------------------------*/ + +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) +{ + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + uint8_t iso_mask = 0; + + (void)rhport; + + TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 1023); + TU_ASSERT(epnum < EP_MAX); + + xfer->max_packet_size = desc_edpt->wMaxPacketSize.size; + xfer->ep_addr = desc_edpt->bEndpointAddress; + xfer->data1 = 0; + + if (epnum != 0 && desc_edpt->bmAttributes.xfer == 1) iso_mask = USB_USB_EPC1_REG_USB_ISO_Msk; + + if (epnum == 0) + { + USB->USB_MAMSK_REG |= USB_USB_MAMSK_REG_USB_M_EP0_RX_Msk | + USB_USB_MAMSK_REG_USB_M_EP0_TX_Msk; + } + else + { + if (dir == TUSB_DIR_OUT) + { + xfer->regs->epc_out = epnum | USB_USB_EPC1_REG_USB_EP_EN_Msk | iso_mask; + USB->USB_RXMSK_REG |= 0x101 << (epnum - 1); + REG_SET_BIT(USB_MAMSK_REG, USB_M_RX_EV); + } + else + { + xfer->regs->epc_in = epnum | USB_USB_EPC1_REG_USB_EP_EN_Msk | iso_mask; + USB->USB_TXMSK_REG |= 0x101 << (epnum - 1); + REG_SET_BIT(USB_MAMSK_REG, USB_M_TX_EV); + } + } + + return true; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + + (void)rhport; + + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->last_packet_size = 0; + xfer->transferred = 0; + + if (dir == TUSB_DIR_OUT) + { + if (epnum != 0) + { + if (xfer->max_packet_size > 64) + { + // For endpoint size greater then FIFO size enable FIFO level warning interrupt + // when FIFO has less then 17 bytes free. + xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RFWL_Msk; + } + else + { + // If max_packet_size would fit in FIFO no need for FIFO level warning interrupt. + xfer->regs->rxc &= ~USB_USB_RXC1_REG_USB_RFWL_Msk; + } + } + // USB_RX_EN bit is in same place for all endpoints. + xfer->regs->rxc = USB_USB_RXC0_REG_USB_RX_EN_Msk; + } + else // IN + { + transmit_packet(xfer); + } + + return true; +} + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + (void)rhport; + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->stall = 1; + + if (epnum == 0) + { + // EP0 has just one registers to control stall for IN and OUT + REG_SET_BIT(USB_EPC0_REG, USB_STALL); + if (dir == TUSB_DIR_OUT) + { + xfer->regs->USB_RXC0_REG = USB_USB_RXC0_REG_USB_RX_EN_Msk; + } + else + { + if (xfer->regs->USB_RXC0_REG & USB_USB_RXC0_REG_USB_RX_EN_Msk) + { + // If RX is also enabled TX will not be stalled since RX has + // higher priority. Enable NAK interrupt to handle stall. + REG_SET_BIT(USB_MAMSK_REG, USB_M_EP0_NAK); + } + else + { + xfer->regs->USB_TXC0_REG |= USB_USB_TXC0_REG_USB_TX_EN_Msk; + } + } + } + else + { + if (dir == TUSB_DIR_OUT) + { + xfer->regs->epc_out |= USB_USB_EPC1_REG_USB_STALL_Msk; + xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk; + } + else + { + xfer->regs->epc_in |= USB_USB_EPC1_REG_USB_STALL_Msk; + xfer->regs->txc |= USB_USB_TXC1_REG_USB_TX_EN_Msk | USB_USB_TXC1_REG_USB_LAST_Msk; + } + } +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + (void)rhport; + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + + // Clear stall is called in response to Clear Feature ENDPOINT_HALT, reset toggle + xfer->data1 = 0; + xfer->stall = 0; + + if (dir == TUSB_DIR_OUT) + { + xfer->regs->epc_out &= ~USB_USB_EPC1_REG_USB_STALL_Msk; + } + else + { + xfer->regs->epc_in &= ~USB_USB_EPC1_REG_USB_STALL_Msk; + } + if (epnum == 0) + { + REG_CLR_BIT(USB_MAMSK_REG, USB_M_EP0_NAK); + } +} + +/*------------------------------------------------------------------*/ +/* Interrupt Handler + *------------------------------------------------------------------*/ + +void dcd_int_handler(uint8_t rhport) +{ + uint32_t int_status = USB->USB_MAEV_REG; + + (void)rhport; + + if (GET_BIT(int_status, USB_USB_MAEV_REG_USB_WARN)) + { + handle_fifo_warning(); + } + + if (GET_BIT(int_status, USB_USB_MAEV_REG_USB_CH_EV)) + { + // TODO: for now just clear interrupt + (void)USB->USB_CHARGER_STAT_REG; + } + + if (GET_BIT(int_status, USB_USB_MAEV_REG_USB_EP0_NAK)) + { + handle_ep0_nak(); + } + + if (GET_BIT(int_status, USB_USB_MAEV_REG_USB_EP0_RX)) + { + handle_ep0_rx(); + } + + if (GET_BIT(int_status, USB_USB_MAEV_REG_USB_EP0_TX)) + { + handle_ep0_tx(); + } + + if (GET_BIT(int_status, USB_USB_MAEV_REG_USB_RX_EV)) + { + handle_rx_ev(); + } + + if (GET_BIT(int_status, USB_USB_MAEV_REG_USB_NAK)) + { + (void)USB->USB_NAKEV_REG; + } + + if (GET_BIT(int_status, USB_USB_MAEV_REG_USB_FRAME)) + { + if (_dcd.in_reset) + { + // Enable reset detection + _dcd.in_reset = false; + (void)USB->USB_ALTEV_REG; + } +#if USE_SOF + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); +#else + // SOF was used to re-enable reset detection + // No need to keep it enabled + USB->USB_MAMSK_REG &= ~USB_USB_MAMSK_REG_USB_M_FRAME_Msk; +#endif + } + + if (GET_BIT(int_status, USB_USB_MAEV_REG_USB_TX_EV)) + { + handle_tx_ev(); + } + + if (GET_BIT(int_status, USB_USB_MAEV_REG_USB_ALT)) + { + handle_alt_ev(); + } +} + +#endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 0a227483f..706a94584 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -92,6 +92,9 @@ // Espressif #define OPT_MCU_ESP32S2 900 ///< Espressif ESP32-S2 +// Dialog +#define OPT_MCU_DA1469X 1000 ///< Dialog Semiconductor DA1469x + /** @} */ /** \defgroup group_supported_os Supported RTOS -- cgit v1.3.1 From 4362665fb3ec1ef0d749bbcdaabe161ce1c06614 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 13 Jun 2020 12:36:05 +0200 Subject: Fix mic audio descriptor, fix too strict check on IAD desc. in usbd.c --- src/class/audio/audio.h | 6 + src/class/audio/audio_device.c | 8 +- src/class/audio/audio_device.h | 2 +- src/device/usbd.c | 2 +- src/device/usbd.h | 521 +++++++++++++++++++++++++---------------- 5 files changed, 330 insertions(+), 209 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index f4f460c22..022f3118f 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -57,6 +57,12 @@ typedef enum AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming } audio_subclass_type_t; +/// Audio Function Subclass Codes +typedef enum +{ + AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, +} audio_function_subclass_type_t; + /// Audio Protocol Codes typedef enum { diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index fbd412564..1c9e0494e 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -632,7 +632,7 @@ void audiod_reset(uint8_t rhport) } } -bool audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) +uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); @@ -666,9 +666,11 @@ bool audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_ // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) // Notify caller we read complete descriptor - (*p_length) += tud_audio_desc_lengths[i]; +// (*p_length) += tud_audio_desc_lengths[i]; + // TODO: Find a way to find end of current audio function and avoid necessity of tud_audio_desc_lengths - since now max_length is available we could do this surely somehow + uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor - return true; + return drv_len; } static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 5354adbd4..3e1fa7a92 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -289,7 +289,7 @@ inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) //--------------------------------------------------------------------+ void audiod_init (void); void audiod_reset (uint8_t rhport); -bool audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); +uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool audiod_control_request (uint8_t rhport, tusb_control_request_t const * request); bool audiod_control_complete (uint8_t rhport, tusb_control_request_t const * request); bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); diff --git a/src/device/usbd.c b/src/device/usbd.c index 26c7d3936..912c922c5 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -779,7 +779,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // 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->bFunctionSubClass == desc_itf->bInterfaceSubClass && desc_itf_assoc->bFunctionProtocol == desc_itf->bInterfaceProtocol); for(uint8_t i=1; ibInterfaceCount; i++) diff --git a/src/device/usbd.h b/src/device/usbd.h index 7bc79a6f6..39ad7639e 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -31,7 +31,7 @@ #define _TUSB_USBD_H_ #ifdef __cplusplus - extern "C" { +extern "C" { #endif #include "common/tusb_common.h" @@ -62,7 +62,7 @@ bool tud_suspended(void); // Check if device is ready to transfer static inline bool tud_ready(void) { - return tud_mounted() && !tud_suspended(); + return tud_mounted() && !tud_suspended(); } // Remote wake up host, only if suspended and enabled by host @@ -72,18 +72,18 @@ bool tud_remote_wakeup(void); // Return false on unsupported MCUs static inline bool tud_disconnect(void) { - TU_VERIFY(dcd_disconnect); - dcd_disconnect(TUD_OPT_RHPORT); - return true; + TU_VERIFY(dcd_disconnect); + dcd_disconnect(TUD_OPT_RHPORT); + return true; } // Disable pull-up resistor on D+ D- // Return false on unsupported MCUs static inline bool tud_connect(void) { - TU_VERIFY(dcd_connect); - dcd_connect(TUD_OPT_RHPORT); - return true; + TU_VERIFY(dcd_connect); + dcd_connect(TUD_OPT_RHPORT); + return true; } // Carry out Data and Status stage of control transfer @@ -146,11 +146,11 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // total length, number of device caps #define TUD_BOS_DESCRIPTOR(_total_len, _caps_num) \ - 5, TUSB_DESC_BOS, U16_TO_U8S_LE(_total_len), _caps_num + 5, TUSB_DESC_BOS, U16_TO_U8S_LE(_total_len), _caps_num // Device Capability Platform 128-bit UUID + Data #define TUD_BOS_PLATFORM_DESCRIPTOR(...) \ - 4+TU_ARGS_NUM(__VA_ARGS__), TUSB_DESC_DEVICE_CAPABILITY, DEVICE_CAPABILITY_PLATFORM, 0x00, __VA_ARGS__ + 4+TU_ARGS_NUM(__VA_ARGS__), TUSB_DESC_DEVICE_CAPABILITY, DEVICE_CAPABILITY_PLATFORM, 0x00, __VA_ARGS__ //------------- WebUSB BOS Platform -------------// @@ -159,22 +159,22 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Vendor Code, iLandingPage #define TUD_BOS_WEBUSB_DESCRIPTOR(_vendor_code, _ipage) \ - TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_WEBUSB_UUID, U16_TO_U8S_LE(0x0100), _vendor_code, _ipage) + TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_WEBUSB_UUID, U16_TO_U8S_LE(0x0100), _vendor_code, _ipage) #define TUD_BOS_WEBUSB_UUID \ - 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, \ - 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 + 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, \ + 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 //------------- Microsoft OS 2.0 Platform -------------// #define TUD_BOS_MICROSOFT_OS_DESC_LEN 28 // Total Length of descriptor set, vendor code #define TUD_BOS_MS_OS_20_DESCRIPTOR(_desc_set_len, _vendor_code) \ - TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_MS_OS_20_UUID, U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(_desc_set_len), _vendor_code, 0) + TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_MS_OS_20_UUID, U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(_desc_set_len), _vendor_code, 0) #define TUD_BOS_MS_OS_20_UUID \ - 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, \ - 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F + 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, \ + 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F //--------------------------------------------------------------------+ // Configuration & Interface Descriptor Templates @@ -185,7 +185,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Config number, interface count, string index, total length, attribute, power in mA #define TUD_CONFIG_DESCRIPTOR(config_num, _itfcount, _stridx, _total_len, _attribute, _power_ma) \ - 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 + 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 //------------- CDC -------------// @@ -195,26 +195,26 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // CDC Descriptor Template // 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_NONE, 0,\ - /* CDC Control Interface */\ - 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 */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* CDC ACM: support line request */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ - /* CDC Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface Associate */\ + 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_NONE, _stridx,\ + /* CDC Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC Call */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* CDC ACM: support line request */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\ + /* CDC Data Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- MSC -------------// @@ -223,12 +223,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, string index, EP Out & EP In address, EP size #define TUD_MSC_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_MSC, MSC_SUBCLASS_SCSI, MSC_PROTOCOL_BOT, _stridx,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_MSC, MSC_SUBCLASS_SCSI, MSC_PROTOCOL_BOT, _stridx,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- HID -------------// @@ -238,12 +238,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // HID Input only descriptor // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval #define TUD_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ - /* HID descriptor */\ - 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + /* HID descriptor */\ + 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval // Length of template descriptor: 32 bytes #define TUD_HID_INOUT_DESC_LEN (9 + 9 + 7 + 7) @@ -251,57 +251,57 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // HID Input & Output descriptor // Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval #define TUD_HID_INOUT_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epout, _epin, _epsize, _ep_interval) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ - /* HID descriptor */\ - 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval, \ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + /* HID descriptor */\ + 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval, \ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval //------------- MIDI -------------// #define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) #define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ - /* Audio Control (AC) Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V1, _stridx,\ - /* AC Header */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ - /* MIDI Streaming (MS) Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\ - /* MS Header */\ - 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) + /* Audio Control (AC) Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V1, _stridx,\ + /* AC Header */\ + 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ + /* MIDI Streaming (MS) Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\ + /* MS Header */\ + 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) #define TUD_MIDI_JACKID_IN_EMB(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 1) + (uint8_t)(((_cablenum) - 1) * 4 + 1) #define TUD_MIDI_JACKID_IN_EXT(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 2) + (uint8_t)(((_cablenum) - 1) * 4 + 2) #define TUD_MIDI_JACKID_OUT_EMB(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 3) + (uint8_t)(((_cablenum) - 1) * 4 + 3) #define TUD_MIDI_JACKID_OUT_EXT(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 4) + (uint8_t)(((_cablenum) - 1) * 4 + 4) #define TUD_MIDI_DESC_JACK_LEN (6 + 6 + 9 + 9) #define TUD_MIDI_DESC_JACK(_cablenum) \ - /* MS In Jack (Embedded) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ - /* MS In Jack (External) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ - /* MS Out Jack (Embedded), connected to In Jack External */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ - /* MS Out Jack (External), connected to In Jack Embedded */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 + /* MS In Jack (Embedded) */\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ + /* MS In Jack (External) */\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ + /* MS Out Jack (Embedded), connected to In Jack External */\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ + /* MS Out Jack (External), connected to In Jack Embedded */\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 #define TUD_MIDI_DESC_EP_LEN(_numcables) (7 + 4 + (_numcables)) #define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ - /* Endpoint */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* MS Endpoint (connected to embedded jack) */\ - (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables + /* Endpoint */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* MS Endpoint (connected to embedded jack) */\ + (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables // Length of template descriptor (88 bytes) #define TUD_MIDI_DESC_LEN (TUD_MIDI_DESC_HEAD_LEN + TUD_MIDI_DESC_JACK_LEN + TUD_MIDI_DESC_EP_LEN(1) * 2) @@ -310,50 +310,163 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // - 1 Embedded Jack In connected to 1 External Jack Out // - 1 Embedded Jack out connected to 1 External Jack In #define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ - TUD_MIDI_DESC_JACK(1),\ - TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ - TUD_MIDI_JACKID_IN_EMB(1),\ - TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ - TUD_MIDI_JACKID_OUT_EMB(1) + TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ + TUD_MIDI_DESC_JACK(1),\ + TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ + TUD_MIDI_JACKID_IN_EMB(1),\ + TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ + TUD_MIDI_JACKID_OUT_EMB(1) //------------- AUDIO -------------// -// Length of template descriptor (132 bytes) -#define TUD_AUDIO_MIC_DESC_LEN (8 + 9 + 9 + 8 + 17 + 12 + 14 + 9 + 9 + 16 + 6 + 7 + 8) -#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 +/* Standard Interface Association Descriptor (IAD) */ +#define TUD_AUDIO_DESC_IAD_LEN 8 +#define TUD_AUDIO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ + TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_PROTOCOL_V2, _stridx + +/* Standard AC Interface Descriptor(4.7.1) */ +#define TUD_AUDIO_DESC_STD_AC_LEN 9 +#define TUD_AUDIO_DESC_STD_AC(_itfnum, _nEPs, _stridx) /* _nEPs is 0 or 1 */\ + TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx + +/* Class-Specific AC Interface Header Descriptor(4.7.2) */ +#define TUD_AUDIO_DESC_CS_AC_LEN 9 +#define TUD_AUDIO_DESC_CS_AC(_bcdADC, _category, _totallen, _ctrl) /* _bcdADC : Audio Device Class Specification Release Number in Binary-Coded Decimal, _category : see audio_function_t, _totallen : Total number of bytes returned for the class-specific AudioControl interface i.e. Clock Source, Unit and Terminal descriptors - Do not include TUD_AUDIO_DESC_CS_AC_LEN, we already do this here*/ \ + TUD_AUDIO_DESC_CS_AC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(_bcdADC), _category, U16_TO_U8S_LE(_totallen + TUD_AUDIO_DESC_CS_AC_LEN), _ctrl + +/* Clock Source Descriptor(4.7.2.1) */ +#define TUD_AUDIO_DESC_CLK_SRC_LEN 8 +#define TUD_AUDIO_DESC_CLK_SRC(_clkid, _attr, _ctrl, _assocTerm, _stridx) \ + TUD_AUDIO_DESC_CLK_SRC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, _clkid, _attr, _ctrl, _assocTerm, _stridx + +/* Input Terminal Descriptor(4.7.2.4) */ +#define TUD_AUDIO_DESC_INPUT_TERM_LEN 17 +#define TUD_AUDIO_DESC_INPUT_TERM(_termid, _termtype, _assocTerm, _clkid, _nchannelslogical, _channelcfg, _idxchannelnames, _ctrl, _stridx) \ + TUD_AUDIO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _clkid, _nchannelslogical, U32_TO_U8S_LE(_channelcfg), _idxchannelnames, U16_TO_U8S_LE(_ctrl), _stridx + +/* Output Terminal Descriptor(4.7.2.5) */ +#define TUD_AUDIO_DESC_OUTPUT_TERM_LEN 12 +#define TUD_AUDIO_DESC_OUTPUT_TERM(_termid, _termtype, _assocTerm, _srcid, _clkid, _ctrl, _stridx) \ + TUD_AUDIO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _srcid, _clkid, U16_TO_U8S_LE(_ctrl), _stridx + +/* Feature Unit Descriptor(4.7.2.8) */ +// 1 - Channel +#define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN 6+(1+1)*4 +#define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _stridx) \ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), _stridx + +// For more channels, add definitions here + +/* Standard AS Interface Descriptor(4.9.1) */ +#define TUD_AUDIO_DESC_STD_AS_INT_LEN 9 +#define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ + TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, _stridx + +/* Class-Specific AS Interface Descriptor(4.9.2) */ +#define TUD_AUDIO_DESC_CS_AS_INT_LEN 16 +#define TUD_AUDIO_DESC_CS_AS_INT(_termid, _ctrl, _formattype, _formats, _nchannelsphysical, _channelcfg, _stridx) \ + TUD_AUDIO_DESC_CS_AS_INT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, _termid, _ctrl, _formattype, U32_TO_U8S_LE(_formats), _nchannelsphysical, U32_TO_U8S_LE(_channelcfg), _stridx + +/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */ +#define TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN 6 +#define TUD_AUDIO_DESC_TYPE_I_FORMAT(_subslotsize, _bitresolution) /* _subslotsize is number of bytes per sample (i.e. subslot) and can be 1,2,3, or 4 */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _subslotsize, _bitresolution + +/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */ +#define TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN 7 +#define TUD_AUDIO_DESC_STD_AS_ISO_EP(_ep, _attr, _maxEPsize, _interval) \ + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN, TUSB_DESC_ENDPOINT, _ep, _attr, U16_TO_U8S_LE(_maxEPsize), _interval + +/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ +#define TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN 8 +#define TUD_AUDIO_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source + +#define TUD_AUDIO_MIC_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) + +#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 // Number of AS interfaces + #define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ - /* Standard Interface Association Descriptor (IAD) */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 0x02, TUSB_CLASS_AUDIO, 0x00, AUDIO_PROTOCOL_V2, 0x00,\ - /* Standard AC Interface Descriptor(4.7.1) */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0x00, 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx,\ - /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0200), AUDIO_FUNC_MICROPHONE, U16_TO_U8S_LE(9+8+17+12+6+(1+1)*4), AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS,\ - /* Clock Source Descriptor(4.7.2.1) */\ - 8, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, 0x04, AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), 0x00, \ - /* Input Terminal Descriptor(4.7.2.4) */\ - 17, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, 0x01, U16_TO_U8S_LE(AUDIO_TERM_TYPE_IN_GENERIC_MIC), 0x00, 0x04, 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, U16_TO_U8S_LE(AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), 0x00, \ - /* Output Terminal Descriptor(4.7.2.5) */\ - 12, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, 0x03, U16_TO_U8S_LE(AUDIO_TERM_TYPE_USB_STREAMING), 0x00, 0x02, 0x04, U16_TO_U8S_LE(0x0000), 0x00, \ - /* Feature Unit Descriptor(4.7.2.8) */\ - 6+(1+1)*4, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, 0x02, 0x01, U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), 0x00, \ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x00, /* number of EPs */ 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x01, /* number of EPs */ 0x01, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ - /* Class-Specific AS Interface Descriptor(4.9.2) */\ - 16, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, 0x03, AUDIO_CTRL_NONE, AUDIO_FORMAT_TYPE_I, U32_TO_U8S_LE(AUDIO_DATA_FORMAT_TYPE_I_PCM), 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, \ - /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - 6, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _nBytesPerSample, _nBitsUsedPerSample,\ - /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - 7, TUSB_DESC_ENDPOINT, _epin, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), U16_TO_U8S_LE(_epsize), (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01,\ - /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - 8, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, U16_TO_U8S_LE(0x0000)\ + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + +// Length of template descriptor (132 bytes) +//#define TUD_AUDIO_MIC_DESC_LEN (8 + 9 + 9 + 8 + 17 + 12 + 14 + 9 + 9 + 16 + 6 + 7 + 8) +//#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 +// +// // AUDIO simple descriptor (UAC2) for 1 microphone input +// // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source +// #define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ +// /* Standard Interface Association Descriptor (IAD) */\ +// 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 0x02, TUSB_CLASS_AUDIO, 0x00, AUDIO_PROTOCOL_V2, 0x00,\ +// /* Standard AC Interface Descriptor(4.7.1) */\ +// 9, TUSB_DESC_INTERFACE, _itfnum, 0x00, 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx,\ +// /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ +// 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0200), AUDIO_FUNC_MICROPHONE, U16_TO_U8S_LE(9+8+17+12+6+(1+1)*4), AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS,\ +// /* Clock Source Descriptor(4.7.2.1) */\ +// 8, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, 0x04, AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), 0x00, \ +// /* Input Terminal Descriptor(4.7.2.4) */\ +// 17, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, 0x01, U16_TO_U8S_LE(AUDIO_TERM_TYPE_IN_GENERIC_MIC), 0x00, 0x04, 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, U16_TO_U8S_LE(AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), 0x00, \ +// /* Output Terminal Descriptor(4.7.2.5) */\ +// 12, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, 0x03, U16_TO_U8S_LE(AUDIO_TERM_TYPE_USB_STREAMING), 0x00, 0x02, 0x04, U16_TO_U8S_LE(0x0000), 0x00, \ +// /* Feature Unit Descriptor(4.7.2.8) */\ +// 6+(1+1)*4, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, 0x02, 0x01, U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), 0x00, \ +// /* Standard AS Interface Descriptor(4.9.1) */\ +// /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ +// 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x00, /* number of EPs */ 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ +// /* Standard AS Interface Descriptor(4.9.1) */\ +// /* Interface 1, Alternate 1 - alternate interface for data streaming */\ +// 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x01, /* number of EPs */ 0x01, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ +// /* Class-Specific AS Interface Descriptor(4.9.2) */\ +// 16, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, 0x03, AUDIO_CTRL_NONE, AUDIO_FORMAT_TYPE_I, U32_TO_U8S_LE(AUDIO_DATA_FORMAT_TYPE_I_PCM), 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00,\ +// /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ +// 6, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _nBytesPerSample, _nBitsUsedPerSample,\ +// /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ +// 7, TUSB_DESC_ENDPOINT, _epin, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), U16_TO_U8S_LE(_epsize), (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01,\ +// /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ +// 8, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, U16_TO_U8S_LE(0x0000) + //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) @@ -365,23 +478,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 */ \ - 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx + /* 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) @@ -391,12 +504,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, string index, EP Out & IN address, EP size #define TUD_VENDOR_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _stridx,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _stridx,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- DFU Runtime -------------// #define TUD_DFU_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) @@ -408,10 +521,10 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // DFU runtime descriptor // Interface number, string index, attributes, detach timeout, transfer size #define TUD_DFU_RT_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \ - /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_RT, _stridx, \ - /* Function */ \ - 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_RT, _stridx, \ + /* Function */ \ + 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) //------------- CDC-ECM -------------// @@ -422,40 +535,40 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // 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 */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ - /* CDC-ECM Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* CDC-ECM Functional Descriptor */\ - 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 (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 */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* 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 */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC-ECM Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* CDC-ECM Functional Descriptor */\ + 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 (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 */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- RNDIS -------------// #if 0 - /* 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 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */ +/* 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 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */ #else - /* Windows 7+ */ - #define TUD_RNDIS_ITF_CLASS TUSB_CLASS_WIRELESS_CONTROLLER - #define TUD_RNDIS_ITF_SUBCLASS 0x01 - #define TUD_RNDIS_ITF_PROTOCOL 0x03 +/* Windows 7+ */ +#define TUD_RNDIS_ITF_CLASS TUSB_CLASS_WIRELESS_CONTROLLER +#define TUD_RNDIS_ITF_SUBCLASS 0x01 +#define TUD_RNDIS_ITF_PROTOCOL 0x03 #endif // Length of template descriptor: 66 bytes @@ -464,26 +577,26 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // RNDIS Descriptor Template // Interface number, string index, EP notification address and size, EP data address (out, in) and size. #define TUD_RNDIS_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ - /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ - /* CDC-ACM Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ - /* CDC Call Management */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* ACM */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ - /* CDC Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* 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,\ - /* 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 + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ + /* CDC-ACM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ + /* CDC Call Management */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* ACM */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* 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,\ + /* 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 //------------- BT Radio -------------// #define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER) @@ -500,20 +613,20 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Primary Interface */ #define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ - /* Endpoint In for events */ \ - 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ - /* Endpoint In for ACL data */ \ - 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ - /* Endpoint Out for ACL data */ \ - 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 + 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Endpoint In for events */ \ + 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ + /* Endpoint In for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ + /* Endpoint Out for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 #define TUD_BTH_ISO_ITF(_itfnum, _alt, _ep_in, _ep_out, _n) ,\ - /* Interface with 2 endpoints */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ - /* Isochronous endpoints */ \ - 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ - 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 + /* Interface with 2 endpoints */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Isochronous endpoints */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 #define _FIRST(a, ...) a #define _REST(a, ...) __VA_ARGS__ @@ -521,27 +634,27 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re #define TUD_BTH_ISO_ITF_0(_itfnum, ...) #define TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 1, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 2, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 3, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 4, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 5, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_6(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 6, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITFS(_itfnum, _ep_in, _ep_out, ...) \ - TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) + TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) // BT Primary controller descriptor // Interface number, string index, attributes, event endpoint, event endpoint size, interval, data in, data out, data endpoint size, iso endpoint sizes #define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \ - TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) + TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ + TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) #ifdef __cplusplus - } +} #endif #endif /* _TUSB_USBD_H_ */ -- cgit v1.3.1 From 48b2e6cf78a3c3a321715938e40166138ed605f5 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 13 Jun 2020 13:51:50 +0200 Subject: Fix too strict checks on subclass and interface of iad descriptor. --- src/device/usbd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 3708a9aff..040155d41 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -765,9 +765,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { // 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); + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); for(uint8_t i=1; ibInterfaceCount; i++) { -- cgit v1.3.1 From 862d1667f0c7e94af29f92d575a7d14dbe126a66 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Jun 2020 12:55:52 +0200 Subject: Fix alignment. --- src/device/usbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 6e2e5635a..ff127a3c1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -777,8 +777,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) 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); + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); for(uint8_t i=1; ibInterfaceCount; i++) { -- cgit v1.3.1 From 3012175351fa1f262533527c0444ce9d44917943 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Jun 2020 12:57:00 +0200 Subject: Fix alignment. --- src/device/usbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 040155d41..f11696e78 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -764,8 +764,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) 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); + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); for(uint8_t i=1; ibInterfaceCount; i++) { -- cgit v1.3.1 From b25bbf4776cb992f25faf607077f39810165eebe Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Jun 2020 12:58:16 +0200 Subject: Fix alignment. --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index f11696e78..e5ff52542 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -764,7 +764,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) 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 && + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); for(uint8_t i=1; ibInterfaceCount; i++) -- cgit v1.3.1 From a347de6e50e98b339a1605dc927c0417e79b86a5 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 14 Jun 2020 18:28:45 +0700 Subject: revert CFG_TUSB_RHPORT0_MODE to previous way --- examples/device/cdc_msc/src/tusb_config.h | 9 ++++++++- hw/bsp/stm32h743eval/stm32h743eval.c | 3 +-- src/tusb_option.h | 23 ++++++++++++----------- 3 files changed, 21 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index 9beb9f6a2..b05d219c6 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -56,7 +56,14 @@ #endif // Device mode with rhport and speed defined by board.mk -#define CFG_TUSB_RHPORT0_MODE ((OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) << (8*BOARD_DEVICE_RHPORT_NUM)) +#if BOARD_DEVICE_RHPORT_NUM == 0 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) +#elif BOARD_DEVICE_RHPORT_NUM == 1 + #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) +#else + #error "Incorrect RHPort configuration" +#endif + #define CFG_TUSB_OS OPT_OS_NONE // CFG_TUSB_DEBUG is defined by compiler in DEBUG build diff --git a/hw/bsp/stm32h743eval/stm32h743eval.c b/hw/bsp/stm32h743eval/stm32h743eval.c index 836f1ecab..a28110920 100644 --- a/hw/bsp/stm32h743eval/stm32h743eval.c +++ b/hw/bsp/stm32h743eval/stm32h743eval.c @@ -262,9 +262,8 @@ void board_init(void) // Enable VBUS sense (B device) via pin PA9 USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN; -#endif -#if BOARD_DEVICE_RHPORT_NUM == 1 +#elif BOARD_DEVICE_RHPORT_NUM == 1 // Despite being call USB2_OTG // OTG_HS is marked as RHPort1 by TinyUSB to be consistent across stm32 port diff --git a/src/tusb_option.h b/src/tusb_option.h index c251d578a..01bb1301a 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -117,10 +117,7 @@ //-------------------------------------------------------------------- // RootHub Mode Configuration -// -// Each byte of the CFG_TUSB_RHPORTx_MODE contains operation mode for -// a roothub port (device or host). Therefore each macro can have up to -// 4 ports. +// CFG_TUSB_RHPORTx_MODE contains operation mode and speed for that port //-------------------------------------------------------------------- // Lower 4-bit is operational mode @@ -138,27 +135,31 @@ #define CFG_TUSB_RHPORT0_MODE OPT_MODE_NONE #endif -#if ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST ) && (CFG_TUSB_RHPORT0_MODE & (OPT_MODE_HOST << 8)) ) || \ - ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE) && (CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE << 8)) ) + +#ifndef CFG_TUSB_RHPORT1_MODE + #define CFG_TUSB_RHPORT1_MODE OPT_MODE_NONE +#endif + +#if ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST ) && (CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST )) || \ + ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE) && (CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE)) #error "TinyUSB currently does not support same modes on more than 1 roothub port" #endif // Which roothub port is configured as host -#define TUH_OPT_RHPORT ( (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST) ? 0 : ((CFG_TUSB_RHPORT0_MODE & (OPT_MODE_HOST << 8)) ? 1 : -1) ) +#define TUH_OPT_RHPORT ( (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST) ? 0 : ((CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST) ? 1 : -1) ) #define TUSB_OPT_HOST_ENABLED ( TUH_OPT_RHPORT >= 0 ) // Which roothub port is configured as device -#define TUD_OPT_RHPORT ( (CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE) ? 0 : ((CFG_TUSB_RHPORT0_MODE & (OPT_MODE_DEVICE << 8)) ? 1 : -1) ) +#define TUD_OPT_RHPORT ( (CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE) ? 0 : ((CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE) ? 1 : -1) ) #if TUD_OPT_RHPORT == 0 - #define TUD_OPT_HIGH_SPEED ( CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED ) +#define TUD_OPT_HIGH_SPEED ( CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED ) #else - #define TUD_OPT_HIGH_SPEED ( CFG_TUSB_RHPORT0_MODE & (OPT_MODE_HIGH_SPEED << 8) ) +#define TUD_OPT_HIGH_SPEED ( CFG_TUSB_RHPORT1_MODE & OPT_MODE_HIGH_SPEED ) #endif #define TUSB_OPT_DEVICE_ENABLED ( TUD_OPT_RHPORT >= 0 ) - //--------------------------------------------------------------------+ // COMMON OPTIONS //--------------------------------------------------------------------+ -- cgit v1.3.1 From 95966c22010bf01579f39847624395724298c459 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 14 Jun 2020 18:29:02 +0700 Subject: improve usbd log for control transfer --- src/device/usbd.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index eeb5011ec..c337f1be1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -380,17 +380,21 @@ void tud_task (void) if ( !osal_queue_receive(_usbd_q, &event) ) return; - TU_LOG2("USBD %s", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); - TU_LOG2("%s", (event.event_id != DCD_EVENT_XFER_COMPLETE && event.event_id != DCD_EVENT_SETUP_RECEIVED) ? "\r\n" : " "); +#if CFG_TUSB_DEBUG >= 2 + if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG2("\r\n"); // extra line for setup + TU_LOG2("USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); +#endif switch ( event.event_id ) { case DCD_EVENT_BUS_RESET: + TU_LOG2("\r\n"); usbd_reset(event.rhport); _usbd_dev.speed = event.bus_reset.speed; break; case DCD_EVENT_UNPLUGGED: + TU_LOG2("\r\n"); usbd_reset(event.rhport); // invoke callback @@ -442,14 +446,17 @@ void tud_task (void) break; case DCD_EVENT_SUSPEND: + TU_LOG2("\r\n"); if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); break; case DCD_EVENT_RESUME: + TU_LOG2("\r\n"); if (tud_resume_cb) tud_resume_cb(); break; case DCD_EVENT_SOF: + TU_LOG2("\r\n"); for ( uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++ ) { if ( _usbd_driver[i].sof ) @@ -460,6 +467,7 @@ void tud_task (void) break; case USBD_EVENT_FUNC_CALL: + TU_LOG2("\r\n"); if ( event.func_call.func ) event.func_call.func(event.func_call.param); break; -- cgit v1.3.1 From f438aedccba2b48d4ea9e606c3529c9fd6cb6985 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 14 Jun 2020 18:29:38 +0700 Subject: overwrite setup packet --- src/portable/st/synopsys/dcd_synopsys.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 739361da9..39d8fe73d 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -125,8 +125,7 @@ enum // We disable SOF for now until needed later on #define USE_SOF 0 -static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[6]; -static uint8_t _setup_offs; // We store up to 3 setup packets. +static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2]; typedef struct { uint8_t * buffer; @@ -670,17 +669,14 @@ static void read_rx_fifo(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ep) case 0x03: // Out packet done (Interrupt) break; case 0x04: // Setup packet done (Interrupt) - _setup_offs = 2 - ((out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_STUPCNT_Msk) >> USB_OTG_DOEPTSIZ_STUPCNT_Pos); out_ep[epnum].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); break; case 0x06: // Setup packet recvd { - uint8_t setup_left = ((out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_STUPCNT_Msk) >> USB_OTG_DOEPTSIZ_STUPCNT_Pos); - // We can receive up to three setup packets in succession, but // only the last one is valid. - _setup_packet[4 - 2*setup_left] = (* rx_fifo); - _setup_packet[5 - 2*setup_left] = (* rx_fifo); + _setup_packet[0] = (* rx_fifo); + _setup_packet[1] = (* rx_fifo); } break; default: // Invalid @@ -699,8 +695,7 @@ static void handle_epout_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_O // SETUP packet Setup Phase done. if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_STUP) { out_ep[n].DOEPINT = USB_OTG_DOEPINT_STUP; - dcd_event_setup_received(rhport, (uint8_t*) &_setup_packet[2*_setup_offs], true); - _setup_offs = 0; + dcd_event_setup_received(rhport, (uint8_t*) &_setup_packet[0], true); } // OUT XFER complete (single packet). @@ -736,7 +731,6 @@ static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OT if ( dev->DAINT & (1 << (USB_OTG_DAINT_IEPINT_Pos + n)) ) { - // IN XFER complete (entire xfer). if ( in_ep[n].DIEPINT & USB_OTG_DIEPINT_XFRC ) { -- cgit v1.3.1 From 4399dd1b068ae5ffff4b78848d69a41aa1915045 Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Fri, 15 May 2020 18:21:44 +0200 Subject: cherry pick PR399 commit : Interrupt time improvements --- src/portable/st/synopsys/dcd_synopsys.c | 133 +++++++++++--------------------- 1 file changed, 46 insertions(+), 87 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 39d8fe73d..24cfadfe4 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -130,9 +130,7 @@ static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2]; typedef struct { uint8_t * buffer; uint16_t total_len; - uint16_t queued_len; uint16_t max_size; - bool short_packet; } xfer_ctl_t; typedef volatile uint32_t * usb_fifo_t; @@ -437,8 +435,6 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->buffer = buffer; xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->short_packet = false; uint16_t num_packets = (total_bytes / xfer->max_size); uint8_t short_packet_size = total_bytes % xfer->max_size; @@ -461,9 +457,10 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t dev->DIEPEMPMSK |= (1 << epnum); } } else { - // Each complete packet for OUT xfers triggers XFRC. - out_ep[epnum].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | - ((xfer->max_size & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) << USB_OTG_DOEPTSIZ_XFRSIZ_Pos); + // A full OUT transfer (multiple packets, possibly) triggers XFRC. + out_ep[epnum].DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT_Msk | USB_OTG_DOEPTSIZ_XFRSIZ); + out_ep[epnum].DOEPTSIZ |= (num_packets << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | + ((total_bytes << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) & USB_OTG_DOEPTSIZ_XFRSIZ_Msk); out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; } @@ -558,65 +555,33 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) /*------------------------------------------------------------------*/ -// TODO: Split into "receive on endpoint 0" and "receive generic"; endpoint 0's -// DOEPTSIZ register is smaller than the others, and so is insufficient for -// determining how much of an OUT transfer is actually remaining. -static void receive_packet(uint8_t rhport, xfer_ctl_t * xfer, /* USB_OTG_OUTEndpointTypeDef * out_ep, */ uint16_t xfer_size) { +// Read a single data packet from receive FIFO +static void read_fifo_packet(uint8_t rhport, uint8_t * dst, uint16_t len){ usb_fifo_t rx_fifo = FIFO_BASE(rhport, 0); - // See above TODO - // uint16_t remaining = (out_ep->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DOEPTSIZ_XFRSIZ_Pos; - // xfer->queued_len = xfer->total_len - remaining; - - uint16_t remaining = xfer->total_len - xfer->queued_len; - uint16_t to_recv_size; - - if(remaining <= xfer->max_size) { - // Avoid buffer overflow. - to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; - } else { - // Room for full packet, choose recv_size based on what the microcontroller - // claims. - to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; - } - - uint8_t to_recv_rem = to_recv_size % 4; - uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; - - // Do not assume xfer buffer is aligned. - uint8_t * base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to collect. - if(to_recv_size >= 4) { - for(uint16_t i = 0; i < to_recv_size_aligned; i += 4) { - uint32_t tmp = (* rx_fifo); - base[i] = tmp & 0x000000FF; - base[i + 1] = (tmp & 0x0000FF00) >> 8; - base[i + 2] = (tmp & 0x00FF0000) >> 16; - base[i + 3] = (tmp & 0xFF000000) >> 24; - } + // Reading full available 32 bit words from fifo + uint16_t full_words = len >> 2; + for(uint16_t i = 0; i < full_words; i++) { + uint32_t tmp = *rx_fifo; + dst[0] = tmp & 0x000000FF; + dst[1] = (tmp & 0x0000FF00) >> 8; + dst[2] = (tmp & 0x00FF0000) >> 16; + dst[3] = (tmp & 0xFF000000) >> 24; + dst += 4; } - // Do not read invalid bytes from RX FIFO. - if(to_recv_rem != 0) { - uint32_t tmp = (* rx_fifo); - uint8_t * last_32b_bound = base + to_recv_size_aligned; - - last_32b_bound[0] = tmp & 0x000000FF; - if(to_recv_rem > 1) { - last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; + // Read the remaining 1-3 bytes from fifo + uint8_t bytes_rem = len & 0x03; + if(bytes_rem != 0) { + uint32_t tmp = *rx_fifo; + dst[0] = tmp & 0x000000FF; + if(bytes_rem > 1) { + dst[1] = (tmp & 0x0000FF00) >> 8; } - if(to_recv_rem > 2) { - last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; + if(bytes_rem > 2) { + dst[2] = (tmp & 0x00FF0000) >> 16; } } - - xfer->queued_len += xfer_size; - - // Per USB spec, a short OUT packet (including length 0) is always - // indicative of the end of a transfer (at least for ctl, bulk, int). - xfer->short_packet = (xfer_size < xfer->max_size); } // Write a single data packet to EPIN FIFO @@ -645,13 +610,11 @@ static void write_fifo_packet(uint8_t rhport, uint8_t fifo_num, uint8_t * src, u } } -static void read_rx_fifo(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ep) -{ +static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ep) { USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); usb_fifo_t rx_fifo = FIFO_BASE(rhport, 0); - // Pop control word off FIFO (completed xfers will have 2 control words, - // we only pop one ctl word each interrupt). + // Pop control word off FIFO uint32_t ctl_word = usb_otg->GRXSTSP; uint8_t pktsts = (ctl_word & USB_OTG_GRXSTSP_PKTSTS_Msk) >> USB_OTG_GRXSTSP_PKTSTS_Pos; uint8_t epnum = (ctl_word & USB_OTG_GRXSTSP_EPNUM_Msk) >> USB_OTG_GRXSTSP_EPNUM_Pos; @@ -663,7 +626,13 @@ static void read_rx_fifo(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ep) case 0x02: // Out packet recvd { xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - receive_packet(rhport, xfer, bcnt); + + // Use BCNT to calculate correct bytes before data entry popped out from RxFIFO + uint16_t remaining_bytes = ((out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) \ + >> USB_OTG_DOEPTSIZ_XFRSIZ_Pos) + bcnt; + + // Read packet off RxFIFO + read_fifo_packet(rhport, (xfer->buffer + xfer->total_len - remaining_bytes), bcnt); } break; case 0x03: // Out packet done (Interrupt) @@ -698,25 +667,10 @@ static void handle_epout_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_O dcd_event_setup_received(rhport, (uint8_t*) &_setup_packet[0], true); } - // OUT XFER complete (single packet). + // OUT XFER complete if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_XFRC) { out_ep[n].DOEPINT = USB_OTG_DOEPINT_XFRC; - - // TODO: Because of endpoint 0's constrained size, we handle XFRC - // on a packet-basis. The core can internally handle multiple OUT - // packets; it would be more efficient to only trigger XFRC on a - // completed transfer for non-0 endpoints. - - // Transfer complete if short packet or total len is transferred - if(xfer->short_packet || (xfer->queued_len == xfer->total_len)) { - xfer->short_packet = false; - dcd_event_xfer_complete(rhport, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); - } else { - // Schedule another packet to be received. - out_ep[n].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | \ - ((xfer->max_size & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) << USB_OTG_DOEPTSIZ_XFRSIZ_Pos); - out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; - } + dcd_event_xfer_complete(rhport, n, xfer->total_len, XFER_RESULT_SUCCESS, true); } } } @@ -760,11 +714,8 @@ static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OT break; } - // TODO: queued_len can be removed later - xfer->queued_len = xfer->total_len - remaining_bytes; - // Push packet to Tx-FIFO - write_fifo_packet(rhport, n, (xfer->buffer + xfer->queued_len), packet_size); + write_fifo_packet(rhport, n, (xfer->buffer + xfer->total_len - remaining_bytes), packet_size); } // Turn off TXFE if all bytes are written. @@ -835,12 +786,20 @@ void dcd_int_handler(uint8_t rhport) } #endif - if(int_status & USB_OTG_GINTSTS_RXFLVL) { + // Use while loop to handle more than one fifo data entry + // within a single interrupt call + while(usb_otg->GINTSTS & USB_OTG_GINTSTS_RXFLVL) { // RXFLVL bit is read-only // Mask out RXFLVL while reading data from FIFO usb_otg->GINTMSK &= ~USB_OTG_GINTMSK_RXFLVLM; - read_rx_fifo(rhport, out_ep); + + // Loop until all available packets were handled + do { + handle_rxflvl_ints(rhport, out_ep); + int_status = usb_otg->GINTSTS; + } while(int_status & USB_OTG_GINTSTS_RXFLVL); + usb_otg->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; } -- cgit v1.3.1 From bc7e24b659e0d184f3405681af5f13bd4a5094aa Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Jun 2020 14:22:10 +0200 Subject: Fix wrong comment for IAD checks. --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index e5ff52542..29b10c0fa 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -763,7 +763,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // 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 + // IAD's first interface number and class should match with opened interface TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); -- cgit v1.3.1 From 2dd1be13e5780509cc6ab4e5877dd8c4ffe77e45 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Jun 2020 23:17:49 +0700 Subject: Enhance EP FIFO allocation for both Fullspeed and Highspeed - Update shared RX FIFO calculation with FS/HS - IN FIFO EP - Interrupt -> use EPSize - Bulk/ISO -> use max(EPSize, remaining-fifo / non-opened-EPIN) --- src/portable/st/synopsys/dcd_synopsys.c | 113 +++++++++++++++++++++----------- 1 file changed, 76 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 24cfadfe4..030c089aa 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -116,7 +116,6 @@ enum DCD_FULL_SPEED = 3, // Full speed with internal PHY }; - /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ @@ -138,6 +137,8 @@ typedef volatile uint32_t * usb_fifo_t; xfer_ctl_t xfer_status[EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] +// FIFO RAM allocation so far in words +static uint16_t _allocated_fifo_words; // Setup the control endpoint 0. static void bus_reset(uint8_t rhport) @@ -147,6 +148,8 @@ static void bus_reset(uint8_t rhport) USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + tu_memclr(xfer_status, sizeof(xfer_status)); + for(uint8_t n = 0; n < EP_MAX; n++) { out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; } @@ -177,17 +180,36 @@ static void bus_reset(uint8_t rhport) // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN // // - All EP OUT shared a unique OUT FIFO which uses - // * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets). - // * 2 locations for OUT endpoint control words. - // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) - // * 1 location for global NAK (not required/used here). - // * It is recommended to allocate 2 times the largest packet size, therefore - // Recommended value = 10 + 1 + 2 x (16+2) = 47. To make it scale better with large FIFO size - // and work better with Highspeed. We use 1/5 of total FIFO size - usb_otg->GRXFSIZ = (EP_FIFO_SIZE/4)/5; + // - 13 for setup packets + control words (up to 3 setup packets). + // - 1 for global NAK (not required/used here). + // - Largest-EPsize / 4 + 1. ( FS: 64 bytes, HS: 512 bytes). Recommended is "2 x (Largest-EPsize/4) + 1" + // - 2 for each used OUT endpoint + // + // Therefore GRXFSIZ = 13 + 1 + 1 + 2 x (Largest-EPsize/4) + 2 x EPOUTnum + // - FullSpeed (64 Bytes ): GRXFSIZ = 15 + 2 x 16 + 2 x EP_MAX = 47 + 2 x EP_MAX + // - Highspeed (512 bytes): GRXFSIZ = 15 + 2 x 128 + 2 x EP_MAX = 271 + 2 x EP_MAX + // + // NOTE: Largest-EPsize & EPOUTnum is actual used endpoints in configuration. Since DCD has no knowledge + // of the overall picture yet. We will use the worst scenario: largest possible + EP_MAX + // + // FIXME: for Isochronous, largest EP size can be 1023/1024 for FS/HS respectively. In addition if multiple ISO + // are enabled at least "2 x (Largest-EPsize/4) + 1" are recommended. Maybe provide a macro for application to + // overwrite this. + +#if TUD_OPT_HIGH_SPEED + _allocated_fifo_words = 271 + 2*EP_MAX; +#else + _allocated_fifo_words = 47 + 2*EP_MAX; +#endif + + usb_otg->GRXFSIZ = _allocated_fifo_words; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | (usb_otg->GRXFSIZ & 0x0000ffffUL); + usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; + + _allocated_fifo_words += 16; + + // TU_LOG2_INT(_allocated_fifo_words); // Fixed control EP0 size to 64 bytes in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); @@ -221,7 +243,6 @@ static tusb_speed_t get_speed(USB_OTG_DeviceTypeDef* dev) return (enum_spd == DCD_HIGH_SPEED) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL; } - /*------------------------------------------------------------------*/ /* Controller API *------------------------------------------------------------------*/ @@ -242,9 +263,11 @@ void dcd_init (uint8_t rhport) usb_otg->GCCFG &= ~USB_OTG_GCCFG_PWRDWN; // On selected MCUs HS port1 can be used with external PHY via ULPI interface - // Select ULPI highspeed PHY with default external VBUS Indicator and Drive - usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL | - USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); + // Init ULPI Interface + usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL); + + // Select default internal VBUS Indicator and Drive for ULPI + usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); set_turnaround(usb_otg, TUSB_SPEED_HIGH); } @@ -303,7 +326,6 @@ void dcd_init (uint8_t rhport) USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); - // Enable global interrupt usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; } @@ -397,10 +419,40 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // | ( Shared ) | // --------------- 0 // - // Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints - // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1) - // - Offset: GRXFSIZ + 16 + Size*(epnum-1) + // In FIFO is allocated by following rules: // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". + // - Offset: allocated so far + // - Size + // - Interrupt is EPSize + // - Bulk/ISO is max(EPSize, remaining-fifo / non-opened-EPIN) + + uint16_t const fifo_remaining = EP_FIFO_SIZE/4 - _allocated_fifo_words; + uint16_t fifo_size = desc_edpt->wMaxPacketSize.size / 4; + + if ( desc_edpt->bmAttributes.xfer != TUSB_XFER_INTERRUPT ) + { + uint8_t opened = 0; + for(uint8_t i = 0; i < EP_MAX; i++) + { + if ( (i != epnum) && (xfer_status[i][TUSB_DIR_IN].max_size > 0) ) opened++; + } + + // EP Size or equally divided of remaining whichever is larger + fifo_size = tu_max16(fifo_size, fifo_remaining / (EP_MAX - opened)); + } + + + // FIFO overflows, we probably need a better allocating scheme + TU_ASSERT(fifo_size <= fifo_remaining); + + // DIEPTXF starts at FIFO #1. + // Both TXFD and TXSA are in unit of 32-bit words. + usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; + + _allocated_fifo_words += fifo_size; + + //TU_LOG2_INT(fifo_size); + //TU_LOG2_INT(_allocated_fifo_words); in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) | @@ -409,15 +461,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) (desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos); dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); - - // Both TXFD and TXSA are in unit of 32-bit words. - // IN FIFO 0 was configured during enumeration, hence the "+ 16". - uint16_t const allocated_size = (usb_otg->GRXFSIZ & 0x0000ffff) + 16; - uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_MAX-1); - uint32_t const fifo_offset = allocated_size + fifo_size*(epnum-1); - - // DIEPTXF starts at FIFO #1. - usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | fifo_offset; } return true; @@ -433,8 +476,8 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t uint8_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = buffer; - xfer->total_len = total_bytes; + xfer->buffer = buffer; + xfer->total_len = total_bytes; uint16_t num_packets = (total_bytes / xfer->max_size); uint8_t short_packet_size = total_bytes % xfer->max_size; @@ -533,20 +576,16 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) if(dir == TUSB_DIR_IN) { in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_STALL; - uint8_t eptype = (in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPTYP_Msk) >> \ - USB_OTG_DIEPCTL_EPTYP_Pos; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt - // and bulk endpoints. + uint8_t eptype = (in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPTYP_Msk) >> USB_OTG_DIEPCTL_EPTYP_Pos; + // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt and bulk endpoints. if(eptype == 2 || eptype == 3) { in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; } } else { out_ep[epnum].DOEPCTL &= ~USB_OTG_DOEPCTL_STALL; - uint8_t eptype = (out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPTYP_Msk) >> \ - USB_OTG_DOEPCTL_EPTYP_Pos; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt - // and bulk endpoints. + uint8_t eptype = (out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPTYP_Msk) >> USB_OTG_DOEPCTL_EPTYP_Pos; + // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt and bulk endpoints. if(eptype == 2 || eptype == 3) { out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; } -- cgit v1.3.1 From 667eaa6dd693226d2595e2d19aa3f4798f0a4092 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 16 Jun 2020 00:03:52 +0700 Subject: fix stm32h743 priority with freeRTOS --- hw/bsp/stm32h743eval/stm32h743eval.c | 12 ++++++++---- src/portable/st/synopsys/dcd_synopsys.c | 9 +++++++-- 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/hw/bsp/stm32h743eval/stm32h743eval.c b/hw/bsp/stm32h743eval/stm32h743eval.c index 8bafc32cb..772edf33c 100644 --- a/hw/bsp/stm32h743eval/stm32h743eval.c +++ b/hw/bsp/stm32h743eval/stm32h743eval.c @@ -185,10 +185,14 @@ void board_init(void) SystemClock_Config(); all_rcc_clk_enable(); - #if CFG_TUSB_OS == OPT_OS_NONE - // 1ms tick timer - SysTick_Config(SystemCoreClock / 1000); - #endif + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); + +#if CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(OTG_FS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); + NVIC_SetPriority(OTG_HS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif GPIO_InitTypeDef GPIO_InitStruct; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 030c089aa..d636e581c 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -48,36 +48,41 @@ (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \ ) -// TODO Support OTG_HS // EP_MAX : Max number of bi-directional endpoints including EP0 // EP_FIFO_SIZE : Size of dedicated USB SRAM #if CFG_TUSB_MCU == OPT_MCU_STM32F1 #include "stm32f1xx.h" #define EP_MAX 4 #define EP_FIFO_SIZE 1280 + #elif CFG_TUSB_MCU == OPT_MCU_STM32F2 #include "stm32f2xx.h" #define EP_MAX USB_OTG_FS_MAX_IN_ENDPOINTS #define EP_FIFO_SIZE USB_OTG_FS_TOTAL_FIFO_SIZE + #elif CFG_TUSB_MCU == OPT_MCU_STM32F4 #include "stm32f4xx.h" #define EP_MAX USB_OTG_FS_MAX_IN_ENDPOINTS #define EP_FIFO_SIZE USB_OTG_FS_TOTAL_FIFO_SIZE + #elif CFG_TUSB_MCU == OPT_MCU_STM32H7 #include "stm32h7xx.h" #define EP_MAX 9 #define EP_FIFO_SIZE 4096 - // TODO The official name of the USB FS peripheral on H7 is "USB2_OTG_FS". + #elif CFG_TUSB_MCU == OPT_MCU_STM32F7 #include "stm32f7xx.h" #define EP_MAX 6 #define EP_FIFO_SIZE 1280 + #elif CFG_TUSB_MCU == OPT_MCU_STM32L4 #include "stm32l4xx.h" #define EP_MAX 6 #define EP_FIFO_SIZE 1280 + #else #error "Unsupported MCUs" + #endif #include "device/dcd.h" -- cgit v1.3.1 From 2b1c7730b719c6d4abd7d1bfbfdb80b0d64ee892 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 16 Jun 2020 00:53:06 +0700 Subject: fix hs port1 build with net endpoint --- src/class/net/net_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 67cd99933..964bc8a00 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -37,7 +37,7 @@ #include "netif/ethernet.h" /* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ -#define CFG_TUD_NET_ENDPOINT_SIZE ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64) +#define CFG_TUD_NET_ENDPOINT_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) /* Maximum Tranmission Unit (in bytes) of the network, including Ethernet header */ #define CFG_TUD_NET_MTU (1500 + SIZEOF_ETH_HDR) -- cgit v1.3.1 From 57b553e023ccac4c623bd7f57a7370fb43411ec1 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Tue, 16 Jun 2020 14:13:30 +0200 Subject: Fix IAR warnings. Pa039 : use of address of unaligned structure member. Pe188: enumerated type mixed with another type. --- src/class/hid/hid_device.c | 4 +++- src/class/msc/msc_device.c | 6 ++++-- src/device/usbd.c | 13 +++++++------ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 1 - 4 files changed, 14 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 2a20bc173..526394d4a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -194,7 +194,9 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 p_hid->boot_mode = false; // default mode is REPORT p_hid->itf_num = desc_itf->bInterfaceNumber; - memcpy(&p_hid->report_desc_len, &(p_hid->hid_descriptor->wReportLength), 2); + + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&p_hid->report_desc_len, (uint8_t*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength), 2); // Prepare for output endpoint if (p_hid->ep_out) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index b038d00f7..3ddcd4e49 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -80,7 +80,8 @@ static inline uint32_t rdwr10_get_lba(uint8_t const command[]) // copy first to prevent mis-aligned access uint32_t lba; - memcpy(&lba, &p_rdwr10->lba, 4); + // use offsetof to avoid pointer to the odd/misaligned address + memcpy(&lba, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, lba), 4); // lba is in Big Endian format return tu_ntohl(lba); @@ -93,7 +94,8 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) // copy first to prevent mis-aligned access uint16_t block_count; - memcpy(&block_count, &p_rdwr10->block_count, 2); + // use offsetof to avoid pointer to the odd/misaligned address + memcpy(&block_count, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, block_count), 2); return tu_ntohs(block_count); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 29b10c0fa..03ef655bc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -437,7 +437,7 @@ void tud_task (void) if ( 0 == epnum ) { - usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } else { @@ -445,7 +445,7 @@ void tud_task (void) TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,); 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); + _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } } break; @@ -846,8 +846,10 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const if (!tud_descriptor_bos_cb) return false; tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb(); + uint16_t total_len; - memcpy(&total_len, &desc_bos->wTotalLength, 2); // possibly mis-aligned memory + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength), 2); return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); } @@ -861,7 +863,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_ASSERT(desc_config); uint16_t total_len; - memcpy(&total_len, &desc_config->wTotalLength, 2); // possibly mis-aligned memory + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); } @@ -915,8 +918,6 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const default: return false; } - - return true; } //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index c5666421b..b539f4795 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -698,7 +698,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc default: TU_ASSERT(false); - return false; } pcd_set_eptype(USB, epnum, wType); -- cgit v1.3.1 From 8fe887198b63520c23af9f4c27d9733f6bb18e90 Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Thu, 18 Jun 2020 01:13:44 -0700 Subject: Add tx callback to cdc device Useful for continuous transmission of data, which is difficult currently because there is no notification of tx completion. --- src/class/cdc/cdc_device.c | 3 +++ src/class/cdc/cdc_device.h | 3 +++ 2 files changed, 6 insertions(+) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 9180065c4..b979b11f1 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -416,6 +416,9 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Though maybe the baudrate is not really important !!! if ( ep_addr == p_cdc->ep_in ) { + // invoke transmit callback to possibly refill tx fifo + if ( tud_cdc_tx_cb && !tu_fifo_full(&p_cdc->tx_ff) ) tud_cdc_tx_cb(itf); + if ( 0 == tud_cdc_n_write_flush(itf) ) { // There is no data left, a ZLP should be sent if diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index a2523d8d0..13b59416b 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -128,6 +128,9 @@ TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); // Invoked when received `wanted_char` TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); +// Invoked when space becomes available in TX buffer +TU_ATTR_WEAK void tud_cdc_tx_cb(uint8_t itf); + // Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); -- cgit v1.3.1 From 9ffb9b69a4cbd6448ac04d8482abe7582ae55528 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 17 Jun 2020 12:43:49 +0200 Subject: Disable SOF in dcd_stm32_fsdev Signed-off-by: Mengsk --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index b539f4795..da184abe7 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -144,6 +144,12 @@ # define DCD_STM32_BTABLE_LENGTH (PMA_LENGTH - DCD_STM32_BTABLE_BASE) #endif +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#ifndef USE_SOF +# define USE_SOF 0 +#endif + /*************************************************** * Checks, structs, defines, function definitions, etc. */ @@ -235,7 +241,7 @@ void dcd_init (uint8_t rhport) pcd_set_endpoint(USB,i,0u); } - USB->CNTR |= USB_CNTR_RESETM | USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; + USB->CNTR |= USB_CNTR_RESETM | (USE_SOF ? USB_CNTR_SOFM : 0) | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; dcd_handle_bus_reset(); // Data-line pull-up is left disconnected. @@ -542,10 +548,12 @@ void dcd_int_handler(uint8_t rhport) { dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } +#if USE_SOF if(int_status & USB_ISTR_SOF) { reg16_clear_bits(&USB->ISTR, USB_ISTR_SOF); dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } +#endif if(int_status & USB_ISTR_ESOF) { if(remoteWakeCountdown == 1u) -- cgit v1.3.1 From 067287ef918705aaf95e61c8e907021af730d5a6 Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Thu, 18 Jun 2020 17:18:28 +0200 Subject: Add transaction (edpt_xact) as sub transfer A transfer can have one or multiple transactions. Usually only EP0 splits one xfer into multiple xact. --- src/portable/st/synopsys/dcd_synopsys.c | 97 +++++++++++++++++---------------- 1 file changed, 49 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 06f41ceec..8292a2db4 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -186,6 +186,40 @@ static void end_of_reset(void) { } } +static void edpt_xact(uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, uint16_t total_bytes) { + USB_OTG_DeviceTypeDef * const dev = DEVICE_BASE; + USB_OTG_OUTEndpointTypeDef * const out_ep = OUT_EP_BASE; + USB_OTG_INEndpointTypeDef * const in_ep = IN_EP_BASE; + + // EP0 is limited to one packet each xfer + // We use multiple transaction of xfer->max_size length to get a whole transfer done + if(epnum == 0) { + xfer_ctl_t * const xfer = XFER_CTL_BASE(epnum, dir); + total_bytes = tu_min16(ep0_pending[dir], xfer->max_size); + ep0_pending[dir] -= total_bytes; + } + + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them here. + if(dir == TUSB_DIR_IN) { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + in_ep[epnum].DIEPTSIZ = (num_packets << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | + ((total_bytes << USB_OTG_DIEPTSIZ_XFRSIZ_Pos) & USB_OTG_DIEPTSIZ_XFRSIZ_Msk); + + in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; + // Enable fifo empty interrupt only if there are something to put in the fifo. + if(total_bytes != 0) { + dev->DIEPEMPMSK |= (1 << epnum); + } + } else { + // A full OUT transfer (multiple packets, possibly) triggers XFRC. + out_ep[epnum].DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT_Msk | USB_OTG_DOEPTSIZ_XFRSIZ); + out_ep[epnum].DOEPTSIZ |= (num_packets << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | + ((total_bytes << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) & USB_OTG_DOEPTSIZ_XFRSIZ_Msk); + + out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + } +} + /*------------------------------------------------------------------*/ /* Controller API @@ -347,9 +381,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { (void) rhport; - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; - USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE; - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -358,6 +389,14 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->buffer = buffer; xfer->total_len = total_bytes; + // EP0 can only handle one packet + if(epnum == 0) { + ep0_pending[dir] = total_bytes; + // Schedule the first transaction for EP0 transfer + edpt_xact(epnum, dir, 1, ep0_pending[dir]); + return true; + } + uint16_t num_packets = (total_bytes / xfer->max_size); uint8_t const short_packet_size = total_bytes % xfer->max_size; @@ -366,38 +405,8 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t num_packets++; } - // EP0 can only handle one packet - if(epnum == 0) { - num_packets = 1; - if(total_bytes > xfer->max_size) { - ep0_pending[dir] = total_bytes - xfer->max_size; - total_bytes = xfer->max_size; - // Decrement pointer to make EP0 buffers compatible with existing routines. - xfer->buffer -= ep0_pending[dir]; - } else { - ep0_pending[dir] = 0; - } - } - - // IN and OUT endpoint xfers are interrupt-driven, we just schedule them here. - if(dir == TUSB_DIR_IN) { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - in_ep[epnum].DIEPTSIZ = (num_packets << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | - ((total_bytes & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) << USB_OTG_DIEPTSIZ_XFRSIZ_Pos); - - in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; - // Enable fifo empty interrupt only if there are something to put in the fifo. - if(total_bytes != 0) { - dev->DIEPEMPMSK |= (1 << epnum); - } - } else { - // A full OUT transfer (multiple packets, possibly) triggers XFRC. - out_ep[epnum].DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT_Msk | USB_OTG_DOEPTSIZ_XFRSIZ); - out_ep[epnum].DOEPTSIZ |= (num_packets << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | - ((total_bytes << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) & USB_OTG_DOEPTSIZ_XFRSIZ_Msk); - - out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; - } + // Schedule the transaction for endpoint transfer + edpt_xact(epnum, dir, num_packets, total_bytes); return true; } @@ -613,13 +622,9 @@ static void handle_epout_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTy out_ep[n].DOEPINT = USB_OTG_DOEPINT_XFRC; // EP0 can only handle one packet - if((n == 0) && ep0_pending[TUSB_DIR_OUT]){ - uint16_t const total_bytes = tu_min16(ep0_pending[TUSB_DIR_OUT], xfer->max_size); - ep0_pending[TUSB_DIR_OUT] -= total_bytes; + if((n == 0) && ep0_pending[TUSB_DIR_OUT]) { // Schedule another packet to be received. - out_ep[0].DOEPTSIZ |= (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | - ((total_bytes << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) & USB_OTG_DOEPTSIZ_XFRSIZ_Msk); - out_ep[0].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + edpt_xact(n, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); } else { dcd_event_xfer_complete(0, n, xfer->total_len, XFER_RESULT_SUCCESS, true); } @@ -644,13 +649,9 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType in_ep[n].DIEPINT = USB_OTG_DIEPINT_XFRC; // EP0 can only handle one packet - if((n == 0) && ep0_pending[TUSB_DIR_IN]){ - uint16_t const total_bytes = tu_min16(ep0_pending[TUSB_DIR_IN], xfer->max_size); - ep0_pending[TUSB_DIR_IN] -= total_bytes; - // Schedule another packet to be received. - in_ep[0].DIEPTSIZ |= (1 << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | - ((total_bytes << USB_OTG_DIEPTSIZ_XFRSIZ_Pos) & USB_OTG_DIEPTSIZ_XFRSIZ_Msk); - in_ep[0].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; + if((n == 0) && ep0_pending[TUSB_DIR_IN]) { + // Schedule another packet to be transmitted. + edpt_xact(n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]); } else { dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); } -- cgit v1.3.1 From ada82b840f642681f8012cb2a46aa7577393dd30 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 20 Jun 2020 10:51:21 +0200 Subject: Get update from tinyusb. --- src/class/hid/hid_device.c | 4 +++- src/class/msc/msc_device.c | 6 ++++-- src/device/usbd.c | 21 ++++++++++----------- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 1 - 4 files changed, 17 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 2a20bc173..526394d4a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -194,7 +194,9 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 p_hid->boot_mode = false; // default mode is REPORT p_hid->itf_num = desc_itf->bInterfaceNumber; - memcpy(&p_hid->report_desc_len, &(p_hid->hid_descriptor->wReportLength), 2); + + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&p_hid->report_desc_len, (uint8_t*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength), 2); // Prepare for output endpoint if (p_hid->ep_out) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index b038d00f7..3ddcd4e49 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -80,7 +80,8 @@ static inline uint32_t rdwr10_get_lba(uint8_t const command[]) // copy first to prevent mis-aligned access uint32_t lba; - memcpy(&lba, &p_rdwr10->lba, 4); + // use offsetof to avoid pointer to the odd/misaligned address + memcpy(&lba, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, lba), 4); // lba is in Big Endian format return tu_ntohl(lba); @@ -93,7 +94,8 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) // copy first to prevent mis-aligned access uint16_t block_count; - memcpy(&block_count, &p_rdwr10->block_count, 2); + // use offsetof to avoid pointer to the odd/misaligned address + memcpy(&block_count, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, block_count), 2); return tu_ntohs(block_count); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 3708a9aff..03ef655bc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -437,7 +437,7 @@ void tud_task (void) if ( 0 == epnum ) { - usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } else { @@ -445,7 +445,7 @@ void tud_task (void) TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,); 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); + _usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } } break; @@ -763,11 +763,9 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // 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); + // IAD's first interface number and class should match with opened interface + TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && + desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); for(uint8_t i=1; ibInterfaceCount; i++) { @@ -848,8 +846,10 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const if (!tud_descriptor_bos_cb) return false; tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb(); + uint16_t total_len; - memcpy(&total_len, &desc_bos->wTotalLength, 2); // possibly mis-aligned memory + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength), 2); return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); } @@ -863,7 +863,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_ASSERT(desc_config); uint16_t total_len; - memcpy(&total_len, &desc_config->wTotalLength, 2); // possibly mis-aligned memory + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); } @@ -917,8 +918,6 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const default: return false; } - - return true; } //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index c5666421b..b539f4795 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -698,7 +698,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc default: TU_ASSERT(false); - return false; } pcd_set_eptype(USB, epnum, wType); -- cgit v1.3.1 From 7ae47a93979071ec3c7724c35f1ef55572ad1a1f Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Sat, 20 Jun 2020 22:12:10 -0700 Subject: Call tud_cdc_tx_cb right after flush to keep tx fifo full --- src/class/cdc/cdc_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index b979b11f1..d8be48688 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -416,9 +416,6 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Though maybe the baudrate is not really important !!! if ( ep_addr == p_cdc->ep_in ) { - // invoke transmit callback to possibly refill tx fifo - if ( tud_cdc_tx_cb && !tu_fifo_full(&p_cdc->tx_ff) ) tud_cdc_tx_cb(itf); - if ( 0 == tud_cdc_n_write_flush(itf) ) { // There is no data left, a ZLP should be sent if @@ -428,6 +425,9 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); } } + + // invoke transmit callback to possibly refill tx fifo + if ( tud_cdc_tx_cb && !tu_fifo_full(&p_cdc->tx_ff) ) tud_cdc_tx_cb(itf); } // nothing to do with notif endpoint for now -- cgit v1.3.1 From d4d6e06c1dac7fa50e86794a05feff0c7ab9c32d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Jun 2020 00:53:17 +0700 Subject: added OPT_MCU_SAME5X option --- src/portable/microchip/samd/dcd_samd.c | 3 ++- src/tusb_option.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index a859b72b9..06959b98d 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -26,7 +26,8 @@ #include "tusb_option.h" -#if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAMD21) +#if TUSB_OPT_DEVICE_ENABLED && \ + (CFG_TUSB_MCU == OPT_MCU_SAMD21 || CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X) #include "sam.h" #include "device/dcd.h" diff --git a/src/tusb_option.h b/src/tusb_option.h index 0a227483f..6ce43f885 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -58,6 +58,7 @@ #define OPT_MCU_SAMD21 200 ///< MicroChip SAMD21 #define OPT_MCU_SAMD51 201 ///< MicroChip SAMD51 #define OPT_MCU_SAMG 202 ///< MicroChip SAMDG series +#define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x // STM32 #define OPT_MCU_STM32F0 300 ///< ST STM32F0 -- cgit v1.3.1 From b2ef8cdd42552e2ac82fa9df3fd03b8442a7225d Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 25 Jun 2020 18:51:04 -0500 Subject: dcd_samd: Provide implementation for OPT_MCU_SAME5X --- src/portable/microchip/samd/dcd_samd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 06959b98d..45bff2511 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -91,7 +91,7 @@ void dcd_init (uint8_t rhport) USB->DEVICE.INTENSET.reg = /* USB_DEVICE_INTENSET_SOF | */ USB_DEVICE_INTENSET_EORST; } -#if CFG_TUSB_MCU == OPT_MCU_SAMD51 +#if CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X void dcd_int_enable(uint8_t rhport) { @@ -124,6 +124,11 @@ void dcd_int_disable(uint8_t rhport) (void) rhport; NVIC_DisableIRQ(USB_IRQn); } + +#else + +#error "No implementation available for dcd_int_enable / dcd_int_disable" + #endif void dcd_set_address (uint8_t rhport, uint8_t dev_addr) -- cgit v1.3.1 From 4f69bcea7ed18778a6616cbe062ea388da5043dc Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Fri, 26 Jun 2020 17:18:25 +0200 Subject: Remove EP0 remaining bytes manipulation Renaming edpt_xact to edpt_schedule_packets --- src/portable/st/synopsys/dcd_synopsys.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 8292a2db4..d35d2036a 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -186,7 +186,7 @@ static void end_of_reset(void) { } } -static void edpt_xact(uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, uint16_t total_bytes) { +static void edpt_schedule_packets(uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, uint16_t total_bytes) { USB_OTG_DeviceTypeDef * const dev = DEVICE_BASE; USB_OTG_OUTEndpointTypeDef * const out_ep = OUT_EP_BASE; USB_OTG_INEndpointTypeDef * const in_ep = IN_EP_BASE; @@ -393,7 +393,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t if(epnum == 0) { ep0_pending[dir] = total_bytes; // Schedule the first transaction for EP0 transfer - edpt_xact(epnum, dir, 1, ep0_pending[dir]); + edpt_schedule_packets(epnum, dir, 1, ep0_pending[dir]); return true; } @@ -405,8 +405,8 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t num_packets++; } - // Schedule the transaction for endpoint transfer - edpt_xact(epnum, dir, num_packets, total_bytes); + // Schedule packets to be sent within interrupt + edpt_schedule_packets(epnum, dir, num_packets, total_bytes); return true; } @@ -570,15 +570,11 @@ static void handle_rxflvl_ints(USB_OTG_OUTEndpointTypeDef * out_ep) { { xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - // Use BCNT to calculate correct bytes before data entry popped out from RxFIFO - uint16_t remaining_bytes = ((out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) \ - >> USB_OTG_DOEPTSIZ_XFRSIZ_Pos) + bcnt; - - // Adjust remaining bytes in case of multi packet EP0 transfer - if(epnum == 0) remaining_bytes += ep0_pending[TUSB_DIR_OUT]; - // Read packet off RxFIFO - read_fifo_packet((xfer->buffer + xfer->total_len - remaining_bytes), bcnt); + read_fifo_packet(xfer->buffer, bcnt); + + // Increment pointer to xfer data + xfer->buffer += bcnt; } break; case 0x03: // Out packet done (Interrupt) @@ -624,7 +620,7 @@ static void handle_epout_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTy // EP0 can only handle one packet if((n == 0) && ep0_pending[TUSB_DIR_OUT]) { // Schedule another packet to be received. - edpt_xact(n, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); + edpt_schedule_packets(n, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); } else { dcd_event_xfer_complete(0, n, xfer->total_len, XFER_RESULT_SUCCESS, true); } @@ -651,7 +647,7 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType // EP0 can only handle one packet if((n == 0) && ep0_pending[TUSB_DIR_IN]) { // Schedule another packet to be transmitted. - edpt_xact(n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]); + edpt_schedule_packets(n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]); } else { dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); } @@ -679,11 +675,11 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType break; } - // Adjust remaining bytes in case of multi packet EP0 transfer - if(n == 0) remaining_bytes += ep0_pending[TUSB_DIR_IN]; - // Push packet to Tx-FIFO - write_fifo_packet(n, (xfer->buffer + xfer->total_len - remaining_bytes), packet_size); + write_fifo_packet(n, xfer->buffer, packet_size); + + // Increment pointer to xfer data + xfer->buffer += packet_size; } // Turn off TXFE if all bytes are written. -- cgit v1.3.1 From 99df7789a75f739cf5dd2338dbd2597bab7ec2ab Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Mon, 29 Jun 2020 10:55:03 +0200 Subject: Add author name to dcd_synopsys.c --- src/portable/st/synopsys/dcd_synopsys.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index d35d2036a..b47101e60 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -3,6 +3,7 @@ * * Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2020 Jan Duempelmann * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal -- cgit v1.3.1 From 05bfd9ac4a804f6f8053bdbc8ee83813ad623fa0 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Tue, 23 Jun 2020 13:07:33 +0200 Subject: dcd_synopsys: Handle HS and FS IP in one device FIXME: Allow run-time selection to allow to handle both HS and FS with one file F746 HS port enumerates with error config 1 interface 2 altsetting 0 bulk endpoint 0x3 has invalid maxpacket 64 --- src/portable/st/synopsys/dcd_synopsys.c | 44 ++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 845aecf1e..6e26fd09a 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -53,33 +53,39 @@ // EP_FIFO_SIZE : Size of dedicated USB SRAM #if CFG_TUSB_MCU == OPT_MCU_STM32F1 #include "stm32f1xx.h" - #define EP_MAX 4 - #define EP_FIFO_SIZE 1280 + #define EP_MAX_FS 4 + #define EP_FIFO_SIZE_FS 1280 #elif CFG_TUSB_MCU == OPT_MCU_STM32F2 #include "stm32f2xx.h" - #define EP_MAX USB_OTG_FS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE USB_OTG_FS_TOTAL_FIFO_SIZE + #define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS + #define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE #elif CFG_TUSB_MCU == OPT_MCU_STM32F4 #include "stm32f4xx.h" - #define EP_MAX USB_OTG_FS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE USB_OTG_FS_TOTAL_FIFO_SIZE + #define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS + #define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE + #define EP_MAX_HS USB_OTG_HS_MAX_IN_ENDPOINTS + #define EP_FIFO_SIZE_HS USB_OTG_HS_TOTAL_FIFO_SIZE #elif CFG_TUSB_MCU == OPT_MCU_STM32H7 #include "stm32h7xx.h" - #define EP_MAX 9 - #define EP_FIFO_SIZE 4096 + #define EP_MAX_FS 9 + #define EP_FIFO_SIZE_FS 4096 + #define EP_MAX_HS 9 + #define EP_FIFO_SIZE_HS 4096 #elif CFG_TUSB_MCU == OPT_MCU_STM32F7 #include "stm32f7xx.h" - #define EP_MAX 6 - #define EP_FIFO_SIZE 1280 + #define EP_MAX_FS 6 + #define EP_FIFO_SIZE_FS 1280 + #define EP_MAX_HS 9 + #define EP_FIFO_SIZE_HS 4096 #elif CFG_TUSB_MCU == OPT_MCU_STM32L4 #include "stm32l4xx.h" - #define EP_MAX 6 - #define EP_FIFO_SIZE 1280 + #define EP_MAX_FS 6 + #define EP_FIFO_SIZE_FS 1280 #else #error "Unsupported MCUs" @@ -140,7 +146,15 @@ typedef struct { typedef volatile uint32_t * usb_fifo_t; -xfer_ctl_t xfer_status[EP_MAX][2]; +#if TUD_OPT_RHPORT == 1 +xfer_ctl_t xfer_status[EP_MAX_HS][2]; +# define EP_MAX EP_MAX_HS +# define EP_FIFO_SIZE EP_FIFO_SIZE_HS +#else +xfer_ctl_t xfer_status[EP_MAX_FS][2]; +# define EP_MAX EP_MAX_FS +# define EP_FIFO_SIZE EP_FIFO_SIZE_FS +#endif #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] // EP0 transfers are limited to 1 packet - larger sizes has to be split @@ -206,9 +220,9 @@ static void bus_reset(uint8_t rhport) // overwrite this. #if TUD_OPT_HIGH_SPEED - _allocated_fifo_words = 271 + 2*EP_MAX; + _allocated_fifo_words = 271 + 2*EP_MAX_HS; #else - _allocated_fifo_words = 47 + 2*EP_MAX; + _allocated_fifo_words = 47 + 2*EP_MAX_FS; #endif usb_otg->GRXFSIZ = _allocated_fifo_words; -- cgit v1.3.1 From 30a18e260562194b0541584600a0cfc88b1ef178 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 24 Jun 2020 16:25:23 +0200 Subject: stm32f723disco: USB HS enumerates. --- hw/bsp/stm32f723disco/stm32f723disco.c | 6 ++- src/portable/st/synopsys/dcd_synopsys.c | 87 ++++++++++++++++++++++++++++++--- 2 files changed, 85 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/hw/bsp/stm32f723disco/stm32f723disco.c b/hw/bsp/stm32f723disco/stm32f723disco.c index 03057edc7..eeedd2a66 100644 --- a/hw/bsp/stm32f723disco/stm32f723disco.c +++ b/hw/bsp/stm32f723disco/stm32f723disco.c @@ -217,7 +217,7 @@ void board_init(void) GPIO_InitStruct.Pin = (GPIO_PIN_14 | GPIO_PIN_15); GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_VERY_HIGH; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); @@ -231,8 +231,12 @@ void board_init(void) GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + /* Enable PHYC Clocks */ + __HAL_RCC_OTGPHYC_CLK_ENABLE(); + /* Enable USB HS Clocks */ __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); + __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); // Enable VBUS sense (B device) via pin PA9 USB_OTG_HS->GCCFG &= ~USB_OTG_GCCFG_VBDEN; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 6e26fd09a..ba3cc3460 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -27,6 +27,7 @@ */ #include "tusb_option.h" +#include "../../../../hw/bsp//board.h" #if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ defined (STM32F107xB) || defined (STM32F107xC) @@ -147,14 +148,13 @@ typedef struct { typedef volatile uint32_t * usb_fifo_t; #if TUD_OPT_RHPORT == 1 -xfer_ctl_t xfer_status[EP_MAX_HS][2]; # define EP_MAX EP_MAX_HS # define EP_FIFO_SIZE EP_FIFO_SIZE_HS #else -xfer_ctl_t xfer_status[EP_MAX_FS][2]; # define EP_MAX EP_MAX_FS # define EP_FIFO_SIZE EP_FIFO_SIZE_FS #endif +xfer_ctl_t xfer_status[EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] // EP0 transfers are limited to 1 packet - larger sizes has to be split @@ -220,9 +220,9 @@ static void bus_reset(uint8_t rhport) // overwrite this. #if TUD_OPT_HIGH_SPEED - _allocated_fifo_words = 271 + 2*EP_MAX_HS; + _allocated_fifo_words = 271 + 2*EP_MAX; #else - _allocated_fifo_words = 47 + 2*EP_MAX_FS; + _allocated_fifo_words = 47 + 2*EP_MAX; #endif usb_otg->GRXFSIZ = _allocated_fifo_words; @@ -301,6 +301,59 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c } +# if defined(USB_HS_PHYC) && TUD_OPT_HIGH_SPEED +static bool USB_HS_PHYCInit(void) +{ + USB_HS_PHYC_GlobalTypeDef *usb_hs_phyc = (USB_HS_PHYC_GlobalTypeDef *)USB_HS_PHYC_CONTROLLER_BASE; + // Enable LDO + usb_hs_phyc->USB_HS_PHYC_LDO |= USB_HS_PHYC_LDO_ENABLE; + int32_t count = 2000000; + while(1) { + if (usb_hs_phyc->USB_HS_PHYC_LDO & USB_HS_PHYC_LDO_STATUS) + break; + TU_ASSERT(count > 0); + } + uint32_t phyc_pll = 0; + switch (HSE_VALUE) { + case 12000000: + phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12MHZ; + break; + case 12500000: + phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12_5MHZ; + break; + case 16000000: + phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_16MHZ; + break; + case 24000000: + phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_24MHZ; + break; + case 25000000: + phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_25MHZ; + break; + case 32000000: + // Value not defined in header + phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_Msk; + break; + default: + TU_ASSERT(0); + } + usb_hs_phyc->USB_HS_PHYC_PLL = phyc_pll; + + // Use magic value as in stm32f7xx_ll_usb. +# if !defined (USB_HS_PHYC_TUNE_VALUE) +# define USB_HS_PHYC_TUNE_VALUE 0x00000F13U /*!< Value of USB HS PHY Tune */ +# endif /* USB_HS_PHYC_TUNE_VALUE */ + // Control the tuning interface of the High Speed PHY */ + usb_hs_phyc->USB_HS_PHYC_TUNE |= USB_HS_PHYC_TUNE_VALUE; + + // Enable PLL internal PHY + usb_hs_phyc->USB_HS_PHYC_PLL = phyc_pll | USB_HS_PHYC_PLL_PLLEN; + + board_delay(2); + return true; +} +# endif + /*------------------------------------------------------------------*/ /* Controller API *------------------------------------------------------------------*/ @@ -315,12 +368,31 @@ void dcd_init (uint8_t rhport) #if TUD_OPT_HIGH_SPEED // TODO may pass parameter instead of using macro for HighSpeed if ( rhport == 1 ) { - // Highspeed with external ULPI PHY - // deactivate internal PHY usb_otg->GCCFG &= ~USB_OTG_GCCFG_PWRDWN; - // On selected MCUs HS port1 can be used with external PHY via ULPI interface + // TODO may pass parameter instead of using macro for HighSpeed +#if defined(USB_HS_PHYC) + // Highspeed with embedded UTMI PHYC + // Init The UTMI Interface + usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL); + + // Select vbus source + usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); + + // Select UTMI Interace + usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_ULPI_UTMI_SEL; + usb_otg->GCCFG |= USB_OTG_GCCFG_PHYHSEN; + + //Enables control of a High Speed USB PHY + USB_HS_PHYCInit(); + + // Disable external VBUS detection + usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_ULPIEVBUSD; + +# else// On selected MCUs HS port1 can be used with external PHY via ULPI interface + // Highspeed with external ULPI PHY + // Init ULPI Interface usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL); @@ -328,6 +400,7 @@ void dcd_init (uint8_t rhport) usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); set_turnaround(usb_otg, TUSB_SPEED_HIGH); +# endif } else #endif -- cgit v1.3.1 From 9e35ef73f7ea4813eea5531b4b8edc871cbc9e8d Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Tue, 30 Jun 2020 12:55:39 +0200 Subject: Fix receiving of short packet data (ep out) --- src/portable/st/synopsys/dcd_synopsys.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index b47101e60..0e8743ad8 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -576,6 +576,12 @@ static void handle_rxflvl_ints(USB_OTG_OUTEndpointTypeDef * out_ep) { // Increment pointer to xfer data xfer->buffer += bcnt; + + // Truncate transfer length in case of short packet + if(bcnt < xfer->max_size){ + xfer->total_len -= (out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DOEPTSIZ_XFRSIZ_Pos; + if(epnum == 0) xfer->total_len -= ep0_pending[TUSB_DIR_OUT]; + } } break; case 0x03: // Out packet done (Interrupt) -- cgit v1.3.1 From 378e6aab8cfba70dff135f6ba083eb1adefdae80 Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Tue, 30 Jun 2020 17:56:25 +0200 Subject: Clear ep0_pending if rx short packet --- src/portable/st/synopsys/dcd_synopsys.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 0e8743ad8..84430ec98 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -578,9 +578,12 @@ static void handle_rxflvl_ints(USB_OTG_OUTEndpointTypeDef * out_ep) { xfer->buffer += bcnt; // Truncate transfer length in case of short packet - if(bcnt < xfer->max_size){ + if(bcnt < xfer->max_size) { xfer->total_len -= (out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DOEPTSIZ_XFRSIZ_Pos; - if(epnum == 0) xfer->total_len -= ep0_pending[TUSB_DIR_OUT]; + if(epnum == 0) { + xfer->total_len -= ep0_pending[TUSB_DIR_OUT]; + ep0_pending[TUSB_DIR_OUT] = 0; + } } } break; -- cgit v1.3.1 From 12a145b27db28a55cc99a89487bdd531bc5f950e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 1 Jul 2020 01:33:02 +0700 Subject: fix dfu-rt to response to SET_INTERFACE and DFU_GETSTATUS fix #450 --- src/class/cdc/cdc_device.c | 2 +- src/class/dfu/dfu_rt_device.c | 29 +++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 9180065c4..4d6e57878 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -364,7 +364,7 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request tud_control_status(rhport, request); // Invoke callback - if ( tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, dtr, rts); + if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); } break; diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 01d4e3490..d4c3ecb62 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -44,6 +44,14 @@ typedef enum { DFU_REQUEST_ABORT = 6, } dfu_requests_t; +typedef struct TU_ATTR_PACKED +{ + uint8_t status; + uint8_t poll_timeout[3]; + uint8_t state; + uint8_t istring; +} dfu_status_t; + //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ @@ -88,10 +96,19 @@ bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * req bool dfu_rtd_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); TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request + if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && + TUSB_REQ_SET_INTERFACE == request->bRequest ) + { + tud_control_status(rhport, request); + return true; + } + + // Handle class request only from here + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + switch ( request->bRequest ) { case DFU_REQUEST_DETACH: @@ -99,6 +116,14 @@ bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * requ tud_dfu_rt_reboot_to_dfu(); break; + case DFU_REQUEST_GETSTATUS: + { + // status = OK, poll timeout = 0, state = app idle, istring = 0 + uint8_t status_response[6] = { 0, 0, 0, 0, 0, 0 }; + tud_control_xfer(rhport, request, status_response, sizeof(status_response)); + } + break; + default: return false; // stall unsupported request } -- cgit v1.3.1 From 6178f8de2f0a0a766d7e4ff202c2528c1ecce7c6 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 1 Jul 2020 13:38:59 +0300 Subject: ESP32-S2: Handle the fact that available EP IN FIFOs are less than the number of available EP INs ESP32-S2 has only 5 available endpoint-in FIFOs (including EP0) but 7 available EP IN numbers. This change decouples the fifo number from the endpoint number, providing FIFO numbers until they reach the limit, at which point it will return false and assert an error that too many endpoints were allocated. --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 31 ++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index d49b69a10..21bad327a 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -71,6 +71,20 @@ static uint32_t _setup_packet[2]; #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] static xfer_ctl_t xfer_status[EP_MAX][2]; +// Max number of IN EP FIFOs +#define USB_FIFO_NUM 5 + +// Keep count of how many FIFOs are in use +static uint8_t dcd_allocated_fifos = 1; //FIFO0 is always in use + +// Will either return an unused FIFO number, or 0 if all are used. +static uint8_t dcd_get_free_fifo(){ + if (dcd_allocated_fifos < USB_FIFO_NUM) { + return dcd_allocated_fifos++; + } + return 0; +} + // Setup the control endpoint 0. static void bus_reset(void) { @@ -271,8 +285,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) // - Offset: GRXFSIZ + 16 + Size*(epnum-1) // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". + uint8_t fifo_num = dcd_get_free_fifo(); + TU_ASSERT(fifo_num != 0); + + in_ep[epnum].diepctl &= ~(USB_D_TXFNUM1_M | USB_D_EPTYPE1_M | USB_DI_SETD0PID1 | USB_D_MPS1_M); in_ep[epnum].diepctl |= USB_D_USBACTEP1_M | - epnum << USB_D_TXFNUM1_S | + fifo_num << USB_D_TXFNUM1_S | desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | desc_edpt->wMaxPacketSize.size << 0; @@ -282,8 +300,8 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) // Both TXFD and TXSA are in unit of 32-bit words. // IN FIFO 0 was configured during enumeration, hence the "+ 16". uint16_t const allocated_size = (USB0.grxfsiz & 0x0000ffff) + 16; - uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_MAX-1); - uint32_t const fifo_offset = allocated_size + fifo_size*(epnum-1); + uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (USB_FIFO_NUM-1); + uint32_t const fifo_offset = allocated_size + fifo_size*(fifo_num-1); // DIEPTXF starts at FIFO #1. USB0.dieptxf[epnum - 1] = (fifo_size << USB_NPTXFDEP_S) | fifo_offset; @@ -361,7 +379,8 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) } // Flush the FIFO, and wait until we have confirmed it cleared. - USB0.grstctl |= ((epnum - 1) << USB_TXFNUM_S); + uint8_t const fifo_num = ((in_ep[epnum].diepctl >> USB_D_TXFNUM1_S) & USB_D_TXFNUM1_V); + USB0.grstctl |= (fifo_num << USB_TXFNUM_S); USB0.grstctl |= USB_TXFFLSH_M; while ((USB0.grstctl & USB_TXFFLSH_M) != 0) ; } else { @@ -653,6 +672,8 @@ static void _dcd_int_handler(void* arg) // start of reset ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); USB0.gintsts = USB_USBRST_M; + // FIFOs will be reassigned when the endpoints are reopen + dcd_allocated_fifos = 1; bus_reset(); } @@ -681,6 +702,8 @@ static void _dcd_int_handler(void* arg) if (otg_int & USB_SESENDDET_M) { dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + // FIFOs will be reassigned when the endpoints are reopen + dcd_allocated_fifos = 1; } USB0.gotgint = otg_int; -- cgit v1.3.1 From ed1b670c55053c1fdb6b5ec0c543fe81d95989e4 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 1 Jul 2020 17:57:37 +0700 Subject: clean up code --- src/portable/st/synopsys/dcd_synopsys.c | 48 +++++++++++++-------------------- 1 file changed, 19 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index ba3cc3460..f6d064228 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -243,7 +243,7 @@ static void bus_reset(uint8_t rhport) usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; } -// speed is native DCD speed +// Set turn-around timeout according to link speed static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, tusb_speed_t speed) { usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; @@ -368,47 +368,40 @@ void dcd_init (uint8_t rhport) #if TUD_OPT_HIGH_SPEED // TODO may pass parameter instead of using macro for HighSpeed if ( rhport == 1 ) { + // On selected MCUs HS port1 can be used with external PHY via ULPI interface + // deactivate internal PHY usb_otg->GCCFG &= ~USB_OTG_GCCFG_PWRDWN; - // TODO may pass parameter instead of using macro for HighSpeed -#if defined(USB_HS_PHYC) - // Highspeed with embedded UTMI PHYC // Init The UTMI Interface usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL); - // Select vbus source + // Select default internal VBUS Indicator and Drive for ULPI usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); - // Select UTMI Interace +#if defined(USB_HS_PHYC) + // Highspeed with embedded UTMI PHYC + + // Select UTMI Interface usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_ULPI_UTMI_SEL; usb_otg->GCCFG |= USB_OTG_GCCFG_PHYHSEN; - //Enables control of a High Speed USB PHY + // Enables control of a High Speed USB PHY USB_HS_PHYCInit(); // Disable external VBUS detection usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_ULPIEVBUSD; +#endif -# else// On selected MCUs HS port1 can be used with external PHY via ULPI interface // Highspeed with external ULPI PHY - - // Init ULPI Interface - usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL); - - // Select default internal VBUS Indicator and Drive for ULPI - usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); - set_turnaround(usb_otg, TUSB_SPEED_HIGH); -# endif - } - else + } else #endif { - set_turnaround(usb_otg, TUSB_SPEED_FULL); - // Enable internal PHY usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; + + set_turnaround(usb_otg, TUSB_SPEED_FULL); } // Reset core after selecting PHY @@ -434,20 +427,17 @@ void dcd_init (uint8_t rhport) // (non zero-length packet), send STALL back and discard. dev->DCFG |= USB_OTG_DCFG_NZLSOHSK; -#if TUD_OPT_HIGH_SPEED + // Clear speed bits + dev->DCFG &= ~(3 << USB_OTG_DCFG_DSPD_Pos); + if ( rhport == 1 ) { - // high speed = 0x00 - dev->DCFG &= ~(3 << USB_OTG_DCFG_DSPD_Pos); - - // Transceiver delay, necessary for some ULPI PHYs - //dev->DCFG |= (1 << 14); + if ( !TUD_OPT_HIGH_SPEED ) dev->DCFG |= ((TUD_OPT_HIGH_SPEED ? DCD_HIGH_SPEED : DCD_FULL_SPEED_USE_HS) << USB_OTG_DCFG_DSPD_Pos); } else -#endif { - // full speed with internal PHY - dev->DCFG |= (3 << USB_OTG_DCFG_DSPD_Pos); + // full speed = 0x03 + dev->DCFG |= (DCD_FULL_SPEED << USB_OTG_DCFG_DSPD_Pos); // Enable internal USB transceiver. usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; -- cgit v1.3.1 From e3974d6869fb091609ccffc342031dc779a37f7e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 1 Jul 2020 18:44:52 +0700 Subject: correctly set turn around according to cpu clock help to run with low speed mcu --- src/portable/st/synopsys/dcd_synopsys.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 7ba6b2378..ee8cab5c4 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -255,8 +255,33 @@ static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, tusb_speed_t speed) } else { + // Turnaround timeout depends on the MCU clock + extern uint32_t SystemCoreClock; + uint32_t turnaround; + + if ( SystemCoreClock >= 32000000U ) + turnaround = 0x6U; + else if ( SystemCoreClock >= 27500000U ) + turnaround = 0x7U; + else if ( SystemCoreClock >= 24000000U ) + turnaround = 0x8U; + else if ( SystemCoreClock >= 21800000U ) + turnaround = 0x9U; + else if ( SystemCoreClock >= 20000000U ) + turnaround = 0xAU; + else if ( SystemCoreClock >= 18500000U ) + turnaround = 0xBU; + else if ( SystemCoreClock >= 17200000U ) + turnaround = 0xCU; + else if ( SystemCoreClock >= 16000000U ) + turnaround = 0xDU; + else if ( SystemCoreClock >= 15000000U ) + turnaround = 0xEU; + else + turnaround = 0xFU; + // Fullspeed depends on MCU clocks, but we will use 0x06 for 32+ Mhz - usb_otg->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos); + usb_otg->GUSBCFG |= (turnaround << USB_OTG_GUSBCFG_TRDT_Pos); } } -- cgit v1.3.1 From d2450abaafee659cd30ba2fbd14ff9bdb06f6725 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 1 Jul 2020 18:49:58 +0700 Subject: only set turnaround in reset complete --- src/portable/st/synopsys/dcd_synopsys.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index ee8cab5c4..2adaa762e 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -417,16 +417,11 @@ void dcd_init (uint8_t rhport) // Disable external VBUS detection usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_ULPIEVBUSD; #endif - - // Highspeed with external ULPI PHY - set_turnaround(usb_otg, TUSB_SPEED_HIGH); } else #endif { // Enable internal PHY usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; - - set_turnaround(usb_otg, TUSB_SPEED_FULL); } // Reset core after selecting PHY @@ -457,7 +452,7 @@ void dcd_init (uint8_t rhport) if ( rhport == 1 ) { - if ( !TUD_OPT_HIGH_SPEED ) dev->DCFG |= ((TUD_OPT_HIGH_SPEED ? DCD_HIGH_SPEED : DCD_FULL_SPEED_USE_HS) << USB_OTG_DCFG_DSPD_Pos); + dev->DCFG |= ((TUD_OPT_HIGH_SPEED ? DCD_HIGH_SPEED : DCD_FULL_SPEED_USE_HS) << USB_OTG_DCFG_DSPD_Pos); } else { -- cgit v1.3.1 From 196bdbc7024fcfd3f94e4609cee6580df5bab70b Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 1 Jul 2020 14:45:07 +0200 Subject: st/synopsys/dcd_synopsys.c: Remove USBC PHY PLL stabilization delay for now While the ST code has a 2 ms stabilization delay for the USBC PHY PLL, running without this delay showed no problem for at leat 10 USB un/replug cycles. Observe for problems! --- src/portable/st/synopsys/dcd_synopsys.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index ba3cc3460..4a372348a 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -27,7 +27,6 @@ */ #include "tusb_option.h" -#include "../../../../hw/bsp//board.h" #if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ defined (STM32F107xB) || defined (STM32F107xC) @@ -349,7 +348,12 @@ static bool USB_HS_PHYCInit(void) // Enable PLL internal PHY usb_hs_phyc->USB_HS_PHYC_PLL = phyc_pll | USB_HS_PHYC_PLL_PLLEN; - board_delay(2); + /* Original ST code has 2 ms delay for PLL stabilization. + * Primitive test shows that more than 10 USB un/replug cycle + * showed no error with enumeration + * //#include "../../../../hw/bsp//board.h" + * //board_delay(2); + */ return true; } # endif -- cgit v1.3.1 From 4966fb2e13ca2629763e76d82b67e531c3e20ede Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 2 Jul 2020 01:22:26 +0700 Subject: clean up --- src/portable/st/synopsys/dcd_synopsys.c | 99 +++++++++++++-------------------- 1 file changed, 39 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index d5e36a97a..03238f8e2 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -147,12 +147,13 @@ typedef struct { typedef volatile uint32_t * usb_fifo_t; #if TUD_OPT_RHPORT == 1 -# define EP_MAX EP_MAX_HS -# define EP_FIFO_SIZE EP_FIFO_SIZE_HS + #define EP_MAX EP_MAX_HS + #define EP_FIFO_SIZE EP_FIFO_SIZE_HS #else -# define EP_MAX EP_MAX_FS -# define EP_FIFO_SIZE EP_FIFO_SIZE_FS + #define EP_MAX EP_MAX_FS + #define EP_FIFO_SIZE EP_FIFO_SIZE_FS #endif + xfer_ctl_t xfer_status[EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] @@ -325,63 +326,44 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c } -# if defined(USB_HS_PHYC) && TUD_OPT_HIGH_SPEED +#if defined(USB_HS_PHYC) && TUD_OPT_HIGH_SPEED static bool USB_HS_PHYCInit(void) { - USB_HS_PHYC_GlobalTypeDef *usb_hs_phyc = (USB_HS_PHYC_GlobalTypeDef *)USB_HS_PHYC_CONTROLLER_BASE; - // Enable LDO - usb_hs_phyc->USB_HS_PHYC_LDO |= USB_HS_PHYC_LDO_ENABLE; - int32_t count = 2000000; - while(1) { - if (usb_hs_phyc->USB_HS_PHYC_LDO & USB_HS_PHYC_LDO_STATUS) - break; - TU_ASSERT(count > 0); - } - uint32_t phyc_pll = 0; - switch (HSE_VALUE) { - case 12000000: - phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12MHZ; - break; - case 12500000: - phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12_5MHZ; - break; - case 16000000: - phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_16MHZ; - break; - case 24000000: - phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_24MHZ; - break; - case 25000000: - phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_25MHZ; - break; - case 32000000: - // Value not defined in header - phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_Msk; - break; + USB_HS_PHYC_GlobalTypeDef *usb_hs_phyc = (USB_HS_PHYC_GlobalTypeDef*) USB_HS_PHYC_CONTROLLER_BASE; + + // Enable LDO + usb_hs_phyc->USB_HS_PHYC_LDO |= USB_HS_PHYC_LDO_ENABLE; + + // Wait until LDO ready + while ( 0 == (usb_hs_phyc->USB_HS_PHYC_LDO & USB_HS_PHYC_LDO_STATUS) ) {} + + uint32_t phyc_pll = 0; + switch ( HSE_VALUE ) + { + case 12000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12MHZ ; break; + case 12500000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12_5MHZ ; break; + case 16000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_16MHZ ; break; + case 24000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_24MHZ ; break; + case 25000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_25MHZ ; break; + case 32000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_Msk ; break; // Value not defined in header default: - TU_ASSERT(0); - } - usb_hs_phyc->USB_HS_PHYC_PLL = phyc_pll; - - // Use magic value as in stm32f7xx_ll_usb. -# if !defined (USB_HS_PHYC_TUNE_VALUE) -# define USB_HS_PHYC_TUNE_VALUE 0x00000F13U /*!< Value of USB HS PHY Tune */ -# endif /* USB_HS_PHYC_TUNE_VALUE */ - // Control the tuning interface of the High Speed PHY */ - usb_hs_phyc->USB_HS_PHYC_TUNE |= USB_HS_PHYC_TUNE_VALUE; - - // Enable PLL internal PHY - usb_hs_phyc->USB_HS_PHYC_PLL = phyc_pll | USB_HS_PHYC_PLL_PLLEN; - - /* Original ST code has 2 ms delay for PLL stabilization. - * Primitive test shows that more than 10 USB un/replug cycle - * showed no error with enumeration - * //#include "../../../../hw/bsp//board.h" - * //board_delay(2); - */ - return true; + TU_ASSERT(0); + } + usb_hs_phyc->USB_HS_PHYC_PLL = phyc_pll; + + // Control the tuning interface of the High Speed PHY + // Use magic value from ST driver + usb_hs_phyc->USB_HS_PHYC_TUNE |= 0x00000F13U; + + // Enable PLL internal PHY + usb_hs_phyc->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN; + + // Original ST code has 2 ms delay for PLL stabilization. + // Primitive test shows that more than 10 USB un/replug cycle showed no error with enumeration + + return true; } -# endif +#endif /*------------------------------------------------------------------*/ /* Controller API @@ -417,9 +399,6 @@ void dcd_init (uint8_t rhport) // Enables control of a High Speed USB PHY USB_HS_PHYCInit(); - - // Disable external VBUS detection - usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_ULPIEVBUSD; #endif } else #endif -- cgit v1.3.1 From 9a290febcdd7aaa50657f3d31da31bd493fa3a0e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 2 Jul 2020 11:58:40 +0700 Subject: change default port some stm bsp - f769disco default port is highspeed port1 - remove PORT0 on stlink since the board only populated HS connector --- hw/bsp/stlinkv3mini/board.mk | 12 ++----- hw/bsp/stm32f723disco/board.mk | 9 ++--- hw/bsp/stm32h743eval/board.mk | 13 ++++++-- src/portable/st/synopsys/dcd_synopsys.c | 58 ++++++++++++++++++--------------- 4 files changed, 49 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/hw/bsp/stlinkv3mini/board.mk b/hw/bsp/stlinkv3mini/board.mk index 8576eeaa8..1a64c3735 100644 --- a/hw/bsp/stlinkv3mini/board.mk +++ b/hw/bsp/stlinkv3mini/board.mk @@ -1,5 +1,3 @@ -PORT ?= 1 - CFLAGS += \ -flto \ -mthumb \ @@ -11,14 +9,8 @@ CFLAGS += \ -DSTM32F723xx \ -DHSE_VALUE=25000000 \ -DCFG_TUSB_MCU=OPT_MCU_STM32F7 \ - -DBOARD_DEVICE_RHPORT_NUM=$(PORT) - -ifeq ($(PORT), 1) -CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED -$(info "PORT1 HS") -else -$(info "PORT0") -endif + -DBOARD_DEVICE_RHPORT_NUM=1 \ + -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED # mcu driver cause following warnings CFLAGS += -Wno-error=shadow -Wno-error=cast-align diff --git a/hw/bsp/stm32f723disco/board.mk b/hw/bsp/stm32f723disco/board.mk index 2bd3b0756..2cf3ac633 100644 --- a/hw/bsp/stm32f723disco/board.mk +++ b/hw/bsp/stm32f723disco/board.mk @@ -1,4 +1,5 @@ -PORT ?= 0 +# Default is Highspeed port +PORT ?= 1 CFLAGS += \ -flto \ @@ -14,10 +15,10 @@ CFLAGS += \ -DBOARD_DEVICE_RHPORT_NUM=$(PORT) ifeq ($(PORT), 1) -CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED -$(info "PORT1 HS") + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + $(info "PORT1 High Speed") else -$(info "PORT0") + $(info "PORT0 Full Speed") endif # mcu driver cause following warnings diff --git a/hw/bsp/stm32h743eval/board.mk b/hw/bsp/stm32h743eval/board.mk index cbf37a95d..47d592c58 100644 --- a/hw/bsp/stm32h743eval/board.mk +++ b/hw/bsp/stm32h743eval/board.mk @@ -1,3 +1,6 @@ +# Default is Highspeed port +PORT ?= 1 + CFLAGS += \ -flto \ -mthumb \ @@ -8,8 +11,14 @@ CFLAGS += \ -nostdlib -nostartfiles \ -DSTM32H743xx \ -DCFG_TUSB_MCU=OPT_MCU_STM32H7 \ - -DBOARD_DEVICE_RHPORT_NUM=1 \ - -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + -DBOARD_DEVICE_RHPORT_NUM=$(PORT) + +ifeq ($(PORT), 1) + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + $(info "PORT1 High Speed") +else + $(info "PORT0 Full Speed") +endif # suppress warning caused by vendor mcu driver CFLAGS += -Wno-error=maybe-uninitialized -Wno-error=cast-align diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 03238f8e2..a2d1983c2 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -390,7 +390,7 @@ void dcd_init (uint8_t rhport) // Select default internal VBUS Indicator and Drive for ULPI usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); -#if defined(USB_HS_PHYC) + #if defined(USB_HS_PHYC) // Highspeed with embedded UTMI PHYC // Select UTMI Interface @@ -399,8 +399,9 @@ void dcd_init (uint8_t rhport) // Enables control of a High Speed USB PHY USB_HS_PHYCInit(); -#endif - } else + #endif + } + else #endif { // Enable internal PHY @@ -770,43 +771,46 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ switch(pktsts) { case 0x01: // Global OUT NAK (Interrupt) - break; + break; + case 0x02: // Out packet recvd - { - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + { + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - // Read packet off RxFIFO - read_fifo_packet(rhport, xfer->buffer, bcnt); + // Read packet off RxFIFO + read_fifo_packet(rhport, xfer->buffer, bcnt); - // Increment pointer to xfer data - xfer->buffer += bcnt; + // Increment pointer to xfer data + xfer->buffer += bcnt; - // Truncate transfer length in case of short packet - if(bcnt < xfer->max_size) { - xfer->total_len -= (out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DOEPTSIZ_XFRSIZ_Pos; - if(epnum == 0) { - xfer->total_len -= ep0_pending[TUSB_DIR_OUT]; - ep0_pending[TUSB_DIR_OUT] = 0; - } + // Truncate transfer length in case of short packet + if(bcnt < xfer->max_size) { + xfer->total_len -= (out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DOEPTSIZ_XFRSIZ_Pos; + if(epnum == 0) { + xfer->total_len -= ep0_pending[TUSB_DIR_OUT]; + ep0_pending[TUSB_DIR_OUT] = 0; } } - break; + } + break; + case 0x03: // Out packet done (Interrupt) break; + case 0x04: // Setup packet done (Interrupt) out_ep[epnum].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); - break; + break; + case 0x06: // Setup packet recvd - { - // We can receive up to three setup packets in succession, but - // only the last one is valid. - _setup_packet[0] = (* rx_fifo); - _setup_packet[1] = (* rx_fifo); - } - break; + // We can receive up to three setup packets in succession, but + // only the last one is valid. + _setup_packet[0] = (* rx_fifo); + _setup_packet[1] = (* rx_fifo); + break; + default: // Invalid TU_BREAKPOINT(); - break; + break; } } -- cgit v1.3.1 From 4cec866994f32f729844d0159e14c178f5aa904f Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 2 Jul 2020 14:57:00 +0700 Subject: correct HSE_VALUE in hal_conf - although it is define in CFLAGS, it is worth to correct to be consistent with other build - extract set_speed() --- README.md | 2 +- docs/boards.md | 5 ++ hw/bsp/stlinkv3mini/stm32f7xx_hal_conf.h | 2 +- hw/bsp/stm32f723disco/stm32f7xx_hal_conf.h | 2 +- hw/bsp/stm32f769disco/stm32f7xx_hal_conf.h | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 106 ++++++++++++++++------------- 6 files changed, 66 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index f9a7d0b73..8246ff460 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ The stack supports the following MCUs: - LPC Series: 11Uxx, 13xx, 175x_6x, 177x_8x, 18xx, 40xx, 43xx, 51Uxx, 54xxx, 55xx - iMX RT Series: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064 - **Sony:** CXD56 -- **ST:** STM32 series: L0, F0, F1, F2, F3, F4, F7, H7 (device only) +- **ST:** STM32 series: L0, F0, F1, F2, F3, F4, F7, H7 both FullSpeed and HighSpeed - **TI:** MSP430 - **[ValentyUSB](https://github.com/im-tomu/valentyusb)** eptri diff --git a/docs/boards.md b/docs/boards.md index 57b1410bc..d3dcec375 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -85,6 +85,7 @@ This code base already had supported for a handful of following boards (sorted a - [Adafruit Feather STM32F405](https://www.adafruit.com/product/4382) - [Micro Python PyBoard v1.1](https://store.micropython.org/product/PYBv1.1) +- [STLink-V3 Mini](https://www.st.com/en/development-tools/stlink-v3mini.html) - [STM32 L035c8 Discovery](https://www.st.com/en/evaluation-tools/32l0538discovery.html) - [STM32 F070rb Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f070rb.html) - [STM32 F072rb Discovery](https://www.st.com/en/evaluation-tools/32f072bdiscovery.html) @@ -96,9 +97,13 @@ This code base already had supported for a handful of following boards (sorted a - STM32 F411ce Black Pill - [STM32 F411ve Discovery](https://www.st.com/en/evaluation-tools/32f411ediscovery.html) - [STM32 F412zg Discovery](https://www.st.com/en/evaluation-tools/32f412gdiscovery.html) +- [STM32 F723e Discovery](https://www.st.com/en/evaluation-tools/32f723ediscovery.html) - [STM32 F746zg Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f746zg.html) +- [STM32 F746g Discovery](https://www.st.com/en/evaluation-tools/32f746gdiscovery.html) - [STM32 F767zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f767zi.html) +- [STM32 F769i Discovery](https://www.st.com/en/evaluation-tools/32f769idiscovery.html) - [STM32 H743zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html) +- [STM32 H743i Evaluation](https://www.st.com/en/evaluation-tools/stm32h743i-eval.html) ### TI diff --git a/hw/bsp/stlinkv3mini/stm32f7xx_hal_conf.h b/hw/bsp/stlinkv3mini/stm32f7xx_hal_conf.h index 03dec8f0d..581f0e46a 100644 --- a/hw/bsp/stlinkv3mini/stm32f7xx_hal_conf.h +++ b/hw/bsp/stlinkv3mini/stm32f7xx_hal_conf.h @@ -87,7 +87,7 @@ * (when HSE is used as system clock source, directly or through the PLL). */ #if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */ + #define HSE_VALUE ((uint32_t)25000000U) /*!< Value of the External oscillator in Hz */ #endif /* HSE_VALUE */ #if !defined (HSE_STARTUP_TIMEOUT) diff --git a/hw/bsp/stm32f723disco/stm32f7xx_hal_conf.h b/hw/bsp/stm32f723disco/stm32f7xx_hal_conf.h index 03dec8f0d..581f0e46a 100644 --- a/hw/bsp/stm32f723disco/stm32f7xx_hal_conf.h +++ b/hw/bsp/stm32f723disco/stm32f7xx_hal_conf.h @@ -87,7 +87,7 @@ * (when HSE is used as system clock source, directly or through the PLL). */ #if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */ + #define HSE_VALUE ((uint32_t)25000000U) /*!< Value of the External oscillator in Hz */ #endif /* HSE_VALUE */ #if !defined (HSE_STARTUP_TIMEOUT) diff --git a/hw/bsp/stm32f769disco/stm32f7xx_hal_conf.h b/hw/bsp/stm32f769disco/stm32f7xx_hal_conf.h index 03dec8f0d..581f0e46a 100644 --- a/hw/bsp/stm32f769disco/stm32f7xx_hal_conf.h +++ b/hw/bsp/stm32f769disco/stm32f7xx_hal_conf.h @@ -87,7 +87,7 @@ * (when HSE is used as system clock source, directly or through the PLL). */ #if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */ + #define HSE_VALUE ((uint32_t)25000000U) /*!< Value of the External oscillator in Hz */ #endif /* HSE_VALUE */ #if !defined (HSE_STARTUP_TIMEOUT) diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index a2d1983c2..50984c830 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -285,47 +285,33 @@ static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, tusb_speed_t speed) } } -static tusb_speed_t get_speed(USB_OTG_DeviceTypeDef* dev) +static tusb_speed_t get_speed(uint8_t rhport) { + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); uint32_t const enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; return (enum_spd == DCD_HIGH_SPEED) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL; } -static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, uint16_t total_bytes) { - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); +static void set_speed(uint8_t rhport, tusb_speed_t speed) +{ + uint32_t bitvalue; - // EP0 is limited to one packet each xfer - // We use multiple transaction of xfer->max_size length to get a whole transfer done - if(epnum == 0) { - xfer_ctl_t * const xfer = XFER_CTL_BASE(epnum, dir); - total_bytes = tu_min16(ep0_pending[dir], xfer->max_size); - ep0_pending[dir] -= total_bytes; + if ( rhport == 1 ) + { + bitvalue = ((TUSB_SPEED_HIGH == speed) ? DCD_HIGH_SPEED : DCD_FULL_SPEED_USE_HS); + } + else + { + bitvalue = DCD_FULL_SPEED; } - // IN and OUT endpoint xfers are interrupt-driven, we just schedule them here. - if(dir == TUSB_DIR_IN) { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - in_ep[epnum].DIEPTSIZ = (num_packets << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | - ((total_bytes << USB_OTG_DIEPTSIZ_XFRSIZ_Pos) & USB_OTG_DIEPTSIZ_XFRSIZ_Msk); - - in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; - // Enable fifo empty interrupt only if there are something to put in the fifo. - if(total_bytes != 0) { - dev->DIEPEMPMSK |= (1 << epnum); - } - } else { - // A full OUT transfer (multiple packets, possibly) triggers XFRC. - out_ep[epnum].DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT_Msk | USB_OTG_DOEPTSIZ_XFRSIZ); - out_ep[epnum].DOEPTSIZ |= (num_packets << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | - ((total_bytes << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) & USB_OTG_DOEPTSIZ_XFRSIZ_Msk); + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; - } + // Clear and set speed bits + dev->DCFG &= ~(3 << USB_OTG_DCFG_DSPD_Pos); + dev->DCFG |= (bitvalue << USB_OTG_DCFG_DSPD_Pos); } - #if defined(USB_HS_PHYC) && TUD_OPT_HIGH_SPEED static bool USB_HS_PHYCInit(void) { @@ -338,6 +324,8 @@ static bool USB_HS_PHYCInit(void) while ( 0 == (usb_hs_phyc->USB_HS_PHYC_LDO & USB_HS_PHYC_LDO_STATUS) ) {} uint32_t phyc_pll = 0; + + // TODO Try to get HSE_VALUE from registers instead of depending CFLAGS switch ( HSE_VALUE ) { case 12000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12MHZ ; break; @@ -365,6 +353,40 @@ static bool USB_HS_PHYCInit(void) } #endif +static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, uint16_t total_bytes) { + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + + // EP0 is limited to one packet each xfer + // We use multiple transaction of xfer->max_size length to get a whole transfer done + if(epnum == 0) { + xfer_ctl_t * const xfer = XFER_CTL_BASE(epnum, dir); + total_bytes = tu_min16(ep0_pending[dir], xfer->max_size); + ep0_pending[dir] -= total_bytes; + } + + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them here. + if(dir == TUSB_DIR_IN) { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + in_ep[epnum].DIEPTSIZ = (num_packets << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | + ((total_bytes << USB_OTG_DIEPTSIZ_XFRSIZ_Pos) & USB_OTG_DIEPTSIZ_XFRSIZ_Msk); + + in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; + // Enable fifo empty interrupt only if there are something to put in the fifo. + if(total_bytes != 0) { + dev->DIEPEMPMSK |= (1 << epnum); + } + } else { + // A full OUT transfer (multiple packets, possibly) triggers XFRC. + out_ep[epnum].DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT_Msk | USB_OTG_DOEPTSIZ_XFRSIZ); + out_ep[epnum].DOEPTSIZ |= (num_packets << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | + ((total_bytes << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) & USB_OTG_DOEPTSIZ_XFRSIZ_Msk); + + out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + } +} + /*------------------------------------------------------------------*/ /* Controller API *------------------------------------------------------------------*/ @@ -431,21 +453,10 @@ void dcd_init (uint8_t rhport) // (non zero-length packet), send STALL back and discard. dev->DCFG |= USB_OTG_DCFG_NZLSOHSK; - // Clear speed bits - dev->DCFG &= ~(3 << USB_OTG_DCFG_DSPD_Pos); - - if ( rhport == 1 ) - { - dev->DCFG |= ((TUD_OPT_HIGH_SPEED ? DCD_HIGH_SPEED : DCD_FULL_SPEED_USE_HS) << USB_OTG_DCFG_DSPD_Pos); - } - else - { - // full speed = 0x03 - dev->DCFG |= (DCD_FULL_SPEED << USB_OTG_DCFG_DSPD_Pos); + set_speed(rhport, TUD_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL); - // Enable internal USB transceiver. - usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; - } + // Enable internal USB transceiver. + if ( rhport == 0 ) usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; usb_otg->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | @@ -511,7 +522,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) TU_ASSERT(epnum < EP_MAX); // TODO ISO endpoint can be up to 1024 bytes - TU_ASSERT(desc_edpt->wMaxPacketSize.size <= (get_speed(dev) == TUSB_SPEED_HIGH ? 512 : 64)); + TU_ASSERT(desc_edpt->wMaxPacketSize.size <= (get_speed(rhport) == TUSB_SPEED_HIGH ? 512 : 64)); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = desc_edpt->wMaxPacketSize.size; @@ -575,9 +586,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) _allocated_fifo_words += fifo_size; - //TU_LOG2_INT(fifo_size); - //TU_LOG2_INT(_allocated_fifo_words); - in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) | (desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos) | @@ -925,7 +933,7 @@ void dcd_int_handler(uint8_t rhport) usb_otg->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; - tusb_speed_t const speed = get_speed(dev); + tusb_speed_t const speed = get_speed(rhport); set_turnaround(usb_otg, speed); dcd_event_bus_reset(rhport, speed, true); -- cgit v1.3.1 From d493724a7bd0f4dca718f478aec301d299bd5416 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 2 Jul 2020 13:05:17 +0300 Subject: ESP32-S2: Detect EP IN Xfer Timeout In some rare ocasions (bad cable, noise, etc.) data transfer might timeout and hang the endpoint, unless the interrupt flag is cleared. This pull request targets to solve that case. --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index d49b69a10..3d30b6016 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -637,6 +637,13 @@ static void handle_epin_ints(void) USB0.dtknqr4_fifoemptymsk &= ~(1 << n); } } + + // XFER Timeout + if (USB0.in_ep_reg[n].diepint & USB_D_TIMEOUT0_M) { + // Clear interrupt or enpoint will hang. + USB0.in_ep_reg[n].diepint = USB_D_TIMEOUT0_M; + // Maybe retry? + } } } } -- cgit v1.3.1 From a09a86d29931adf801d4293df879ec54164f689d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 3 Jul 2020 01:19:02 +0700 Subject: fix NVIC disable typo --- src/portable/st/synopsys/dcd_synopsys.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 50984c830..288b4e50c 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -340,7 +340,7 @@ static bool USB_HS_PHYCInit(void) usb_hs_phyc->USB_HS_PHYC_PLL = phyc_pll; // Control the tuning interface of the High Speed PHY - // Use magic value from ST driver + // Use magic value (USB_HS_PHYC_TUNE_VALUE) from ST driver usb_hs_phyc->USB_HS_PHYC_TUNE |= 0x00000F13U; // Enable PLL internal PHY @@ -473,7 +473,7 @@ void dcd_int_enable (uint8_t rhport) void dcd_int_disable (uint8_t rhport) { - NVIC_EnableIRQ(_dcd_rhport[rhport].irqnum); + NVIC_DisableIRQ(_dcd_rhport[rhport].irqnum); } void dcd_set_address (uint8_t rhport, uint8_t dev_addr) -- cgit v1.3.1 From ad5ae8c31d286d17fc8bab81b42a19d77173aadb Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 3 Jul 2020 14:50:39 +0700 Subject: update per review --- src/portable/st/synopsys/dcd_synopsys.c | 89 +++++++++++++++++---------------- 1 file changed, 47 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 288b4e50c..ff227b55b 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -28,6 +28,10 @@ #include "tusb_option.h" +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#define USE_SOF 0 + #if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ defined (STM32F107xB) || defined (STM32F107xC) #define STM32F1_SYNOPSYS @@ -95,31 +99,28 @@ #include "device/dcd.h" //--------------------------------------------------------------------+ -// +// MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ -typedef struct -{ - uint32_t regs; // registers - const IRQn_Type irqnum; // IRQ number -// const uint8_t ep_count; // Max bi-directional Endpoints -}dcd_rhport_t; - -// To be consistent across stm32 port. We will number OTG_FS as Rhport0, and OTG_HS as Rhport1 -static const dcd_rhport_t _dcd_rhport[] = -{ - { .regs = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn } +// On STM32 we associate Port0 to OTG_FS, and Port1 to OTG_HS +#if TUD_OPT_RHPORT == 0 + #define EP_MAX EP_MAX_FS + #define EP_FIFO_SIZE EP_FIFO_SIZE_FS + #define RHPORT_REGS_BASE USB_OTG_FS_PERIPH_BASE + #define RHPORT_IRQn OTG_FS_IRQn -#ifdef USB_OTG_HS - ,{ .regs = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn } +#else + #define EP_MAX EP_MAX_HS + #define EP_FIFO_SIZE EP_FIFO_SIZE_HS + #define RHPORT_REGS_BASE USB_OTG_HS_PERIPH_BASE + #define RHPORT_IRQn OTG_HS_IRQn #endif -}; -#define GLOBAL_BASE(_port) ((USB_OTG_GlobalTypeDef*) _dcd_rhport[_port].regs) -#define DEVICE_BASE(_port) (USB_OTG_DeviceTypeDef *) (_dcd_rhport[_port].regs + USB_OTG_DEVICE_BASE) -#define OUT_EP_BASE(_port) (USB_OTG_OUTEndpointTypeDef *) (_dcd_rhport[_port].regs + USB_OTG_OUT_ENDPOINT_BASE) -#define IN_EP_BASE(_port) (USB_OTG_INEndpointTypeDef *) (_dcd_rhport[_port].regs + USB_OTG_IN_ENDPOINT_BASE) -#define FIFO_BASE(_port, _x) ((volatile uint32_t *) (_dcd_rhport[_port].regs + USB_OTG_FIFO_BASE + (_x) * USB_OTG_FIFO_SIZE)) +#define GLOBAL_BASE(_port) ((USB_OTG_GlobalTypeDef*) RHPORT_REGS_BASE) +#define DEVICE_BASE(_port) (USB_OTG_DeviceTypeDef *) (RHPORT_REGS_BASE + USB_OTG_DEVICE_BASE) +#define OUT_EP_BASE(_port) (USB_OTG_OUTEndpointTypeDef *) (RHPORT_REGS_BASE + USB_OTG_OUT_ENDPOINT_BASE) +#define IN_EP_BASE(_port) (USB_OTG_INEndpointTypeDef *) (RHPORT_REGS_BASE + USB_OTG_IN_ENDPOINT_BASE) +#define FIFO_BASE(_port, _x) ((volatile uint32_t *) (RHPORT_REGS_BASE + USB_OTG_FIFO_BASE + (_x) * USB_OTG_FIFO_SIZE)) enum { @@ -128,14 +129,6 @@ enum DCD_FULL_SPEED = 3, // Full speed with internal PHY }; -/*------------------------------------------------------------------*/ -/* MACRO TYPEDEF CONSTANT ENUM - *------------------------------------------------------------------*/ - -// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) -// We disable SOF for now until needed later on -#define USE_SOF 0 - static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2]; typedef struct { @@ -146,14 +139,6 @@ typedef struct { typedef volatile uint32_t * usb_fifo_t; -#if TUD_OPT_RHPORT == 1 - #define EP_MAX EP_MAX_HS - #define EP_FIFO_SIZE EP_FIFO_SIZE_HS -#else - #define EP_MAX EP_MAX_FS - #define EP_FIFO_SIZE EP_FIFO_SIZE_FS -#endif - xfer_ctl_t xfer_status[EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] @@ -166,6 +151,8 @@ static uint16_t _allocated_fifo_words; // Setup the control endpoint 0. static void bus_reset(uint8_t rhport) { + (void) rhport; + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); @@ -287,6 +274,7 @@ static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, tusb_speed_t speed) static tusb_speed_t get_speed(uint8_t rhport) { + (void) rhport; USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); uint32_t const enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; return (enum_spd == DCD_HIGH_SPEED) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL; @@ -353,7 +341,10 @@ static bool USB_HS_PHYCInit(void) } #endif -static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, uint16_t total_bytes) { +static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, uint16_t total_bytes) +{ + (void) rhport; + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); @@ -437,7 +428,7 @@ void dcd_init (uint8_t rhport) while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST) {} // Restart PHY clock - *((volatile uint32_t *)(_dcd_rhport[rhport].regs + USB_OTG_PCGCCTL_BASE)) = 0; + *((volatile uint32_t *)(RHPORT_REGS_BASE + USB_OTG_PCGCCTL_BASE)) = 0; // Clear all interrupts usb_otg->GINTSTS |= usb_otg->GINTSTS; @@ -468,12 +459,14 @@ void dcd_init (uint8_t rhport) void dcd_int_enable (uint8_t rhport) { - NVIC_EnableIRQ(_dcd_rhport[rhport].irqnum); + (void) rhport; + NVIC_EnableIRQ(RHPORT_IRQn); } void dcd_int_disable (uint8_t rhport) { - NVIC_DisableIRQ(_dcd_rhport[rhport].irqnum); + (void) rhport; + NVIC_DisableIRQ(RHPORT_IRQn); } void dcd_set_address (uint8_t rhport, uint8_t dev_addr) @@ -492,6 +485,7 @@ void dcd_remote_wakeup(uint8_t rhport) void dcd_connect(uint8_t rhport) { + (void) rhport; USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); dev->DCTL &= ~USB_OTG_DCTL_SDIS; @@ -499,6 +493,7 @@ void dcd_connect(uint8_t rhport) void dcd_disconnect(uint8_t rhport) { + (void) rhport; USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); dev->DCTL |= USB_OTG_DCTL_SDIS; @@ -633,6 +628,8 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // (send STALL versus NAK handshakes back). Refactor into resuable function. void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { + (void) rhport; + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); @@ -685,6 +682,8 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { + (void) rhport; + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); @@ -713,7 +712,10 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) /*------------------------------------------------------------------*/ // Read a single data packet from receive FIFO -static void read_fifo_packet(uint8_t rhport, uint8_t * dst, uint16_t len){ +static void read_fifo_packet(uint8_t rhport, uint8_t * dst, uint16_t len) +{ + (void) rhport; + usb_fifo_t rx_fifo = FIFO_BASE(rhport, 0); // Reading full available 32 bit words from fifo @@ -742,7 +744,10 @@ static void read_fifo_packet(uint8_t rhport, uint8_t * dst, uint16_t len){ } // Write a single data packet to EPIN FIFO -static void write_fifo_packet(uint8_t rhport, uint8_t fifo_num, uint8_t * src, uint16_t len){ +static void write_fifo_packet(uint8_t rhport, uint8_t fifo_num, uint8_t * src, uint16_t len) +{ + (void) rhport; + usb_fifo_t tx_fifo = FIFO_BASE(rhport, fifo_num); // Pushing full available 32 bit words to fifo -- cgit v1.3.1 From fd3817818921981aa67e1fb845f926c010444fea Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 1 Jul 2020 23:07:18 +0200 Subject: STM32/OTG_HS: Allow OTG_HS port to run at FS speed. Add "REDUCE_SPEED=1" to the compile options. --- hw/bsp/stlinkv3mini/board.mk | 18 ++++++++++++++++-- hw/bsp/stm32f723disco/board.mk | 13 +++++++++---- hw/bsp/stm32f746disco/board.mk | 10 ++++++++-- hw/bsp/stm32f769disco/board.mk | 11 ++++++++++- hw/mcu/nordic/nrfx | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 8 +++----- 6 files changed, 47 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/hw/bsp/stlinkv3mini/board.mk b/hw/bsp/stlinkv3mini/board.mk index 1a64c3735..47148ec4d 100644 --- a/hw/bsp/stlinkv3mini/board.mk +++ b/hw/bsp/stlinkv3mini/board.mk @@ -1,3 +1,6 @@ +PORT ?= 1 +REDUCE_SPEED ?= 0 + CFLAGS += \ -flto \ -mthumb \ @@ -9,8 +12,19 @@ CFLAGS += \ -DSTM32F723xx \ -DHSE_VALUE=25000000 \ -DCFG_TUSB_MCU=OPT_MCU_STM32F7 \ - -DBOARD_DEVICE_RHPORT_NUM=1 \ - -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + -DBOARD_DEVICE_RHPORT_NUM=$(PORT) + +ifeq ($(PORT), 1) + ifeq ($(REDUCE_SPEED), 0) +CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED +$(info "Using OTG_HS in HS mode") + else +CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_FULL_SPEED +$(info "Using OTG_HS in FS mode") + endif +else +$(info "Using OTG_FS") +endif # mcu driver cause following warnings CFLAGS += -Wno-error=shadow -Wno-error=cast-align diff --git a/hw/bsp/stm32f723disco/board.mk b/hw/bsp/stm32f723disco/board.mk index 2cf3ac633..47148ec4d 100644 --- a/hw/bsp/stm32f723disco/board.mk +++ b/hw/bsp/stm32f723disco/board.mk @@ -1,5 +1,5 @@ -# Default is Highspeed port PORT ?= 1 +REDUCE_SPEED ?= 0 CFLAGS += \ -flto \ @@ -15,10 +15,15 @@ CFLAGS += \ -DBOARD_DEVICE_RHPORT_NUM=$(PORT) ifeq ($(PORT), 1) - CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED - $(info "PORT1 High Speed") + ifeq ($(REDUCE_SPEED), 0) +CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED +$(info "Using OTG_HS in HS mode") + else +CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_FULL_SPEED +$(info "Using OTG_HS in FS mode") + endif else - $(info "PORT0 Full Speed") +$(info "Using OTG_FS") endif # mcu driver cause following warnings diff --git a/hw/bsp/stm32f746disco/board.mk b/hw/bsp/stm32f746disco/board.mk index 76a54cdfd..d7329a28f 100644 --- a/hw/bsp/stm32f746disco/board.mk +++ b/hw/bsp/stm32f746disco/board.mk @@ -1,4 +1,5 @@ PORT ?= 0 +REDUCE_SPEED ?= 0 CFLAGS += \ -flto \ @@ -14,10 +15,15 @@ CFLAGS += \ -DBOARD_DEVICE_RHPORT_NUM=$(PORT) ifeq ($(PORT), 1) + ifeq ($(REDUCE_SPEED), 0) CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED -$(info "PORT1 HS") +$(info "Using OTG_HS in HS mode") + else +CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_FULL_SPEED +$(info "Using OTG_HS in FS mode") + endif else -$(info "PORT0") +$(info "Using OTG_FS") endif # mcu driver cause following warnings diff --git a/hw/bsp/stm32f769disco/board.mk b/hw/bsp/stm32f769disco/board.mk index 62c05cca5..43b677ddd 100644 --- a/hw/bsp/stm32f769disco/board.mk +++ b/hw/bsp/stm32f769disco/board.mk @@ -1,3 +1,5 @@ +REDUCE_SPEED ?= 0 + CFLAGS += \ -flto \ -mthumb \ @@ -10,7 +12,14 @@ CFLAGS += \ -DHSE_VALUE=25000000 \ -DCFG_TUSB_MCU=OPT_MCU_STM32F7 \ -DBOARD_DEVICE_RHPORT_NUM=1 \ - -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + +ifeq ($(REDUCE_SPEED), 0) +CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED +$(info "Using OTG_HS in HS mode") +else +CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_FULL_SPEED +$(info "Using OTG_HS in FS mode") +endif # suppress warning caused by vendor mcu driver CFLAGS += -Wno-error=cast-align -Wno-error=shadow diff --git a/hw/mcu/nordic/nrfx b/hw/mcu/nordic/nrfx index a5397bea5..281cc2e17 160000 --- a/hw/mcu/nordic/nrfx +++ b/hw/mcu/nordic/nrfx @@ -1 +1 @@ -Subproject commit a5397bea558fb4b6838081a22d1ee679289d7417 +Subproject commit 281cc2e178fd9a470d844b3afdea9eb322a0b0e8 diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 50984c830..6c3a10b00 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -312,7 +312,8 @@ static void set_speed(uint8_t rhport, tusb_speed_t speed) dev->DCFG |= (bitvalue << USB_OTG_DCFG_DSPD_Pos); } -#if defined(USB_HS_PHYC) && TUD_OPT_HIGH_SPEED + +#if defined(USB_HS_PHYC) static bool USB_HS_PHYCInit(void) { USB_HS_PHYC_GlobalTypeDef *usb_hs_phyc = (USB_HS_PHYC_GlobalTypeDef*) USB_HS_PHYC_CONTROLLER_BASE; @@ -398,7 +399,6 @@ void dcd_init (uint8_t rhport) USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); // No HNP/SRP (no OTG support), program timeout later. -#if TUD_OPT_HIGH_SPEED // TODO may pass parameter instead of using macro for HighSpeed if ( rhport == 1 ) { // On selected MCUs HS port1 can be used with external PHY via ULPI interface @@ -421,10 +421,8 @@ void dcd_init (uint8_t rhport) // Enables control of a High Speed USB PHY USB_HS_PHYCInit(); - #endif - } - else #endif + } else { // Enable internal PHY usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; -- cgit v1.3.1 From 0fd074afd85d84f162ddebbc9b8e009f9136809b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 8 Jul 2020 16:29:48 +0700 Subject: change REDUCE_SPEED=0/1 to explicitly SPEED=high/full update readme, boards.md to add link to new stm boards --- docs/boards.md | 2 ++ examples/readme.md | 31 +++++++++++++++++++++---------- hw/bsp/stlinkv3mini/board.mk | 13 +++++++------ hw/bsp/stm32f723disco/board.mk | 18 +++++++++--------- hw/bsp/stm32f746disco/board.mk | 18 +++++++++--------- hw/bsp/stm32f769disco/board.mk | 14 ++++++++------ src/portable/st/synopsys/dcd_synopsys.c | 2 +- 7 files changed, 57 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/docs/boards.md b/docs/boards.md index d3dcec375..271ca2844 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -87,6 +87,7 @@ This code base already had supported for a handful of following boards (sorted a - [Micro Python PyBoard v1.1](https://store.micropython.org/product/PYBv1.1) - [STLink-V3 Mini](https://www.st.com/en/development-tools/stlink-v3mini.html) - [STM32 L035c8 Discovery](https://www.st.com/en/evaluation-tools/32l0538discovery.html) +- [STM32 L4R5zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-l4r5zi.html) - [STM32 F070rb Nucleo](https://www.st.com/en/evaluation-tools/nucleo-f070rb.html) - [STM32 F072rb Discovery](https://www.st.com/en/evaluation-tools/32f072bdiscovery.html) - STM32 F103c Blue Pill @@ -104,6 +105,7 @@ This code base already had supported for a handful of following boards (sorted a - [STM32 F769i Discovery](https://www.st.com/en/evaluation-tools/32f769idiscovery.html) - [STM32 H743zi Nucleo](https://www.st.com/en/evaluation-tools/nucleo-h743zi.html) - [STM32 H743i Evaluation](https://www.st.com/en/evaluation-tools/stm32h743i-eval.html) +- [STM32 H745i Discovery](https://www.st.com/en/evaluation-tools/stm32h745i-disco.html) ### TI diff --git a/examples/readme.md b/examples/readme.md index 790427cd2..f6cd380b6 100644 --- a/examples/readme.md +++ b/examples/readme.md @@ -32,28 +32,39 @@ Then compile with `make BOARD=[your_board] all`, for example $ make BOARD=feather_nrf52840_express all ``` +**Port Selection** -To compile for debugging with debug symbols add DEBUG=1, for example +If a board has several ports, one port is chosen by default in the individual board.mk file. Use option `PORT=x` To choose another port. For example to select the HS port of a STM32F746Disco board, use: ``` -$ make BOARD=feather_nrf52840_express DEBUG=1 all -If a board has several ports, one port is choosen by default in the individual board.mk file. Choose another port with PORT=x. For example to select the HS port of a STM32F746Disco board, use: +$ make BOARD=stm32f746disco PORT=1 all +``` + +**Port Speed** + +A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option `SPEED=full/high` e.g To force F723 operate at full instead of default high speed ``` -$ make BOARD=stm32f746disco PORT=1 all +$ make BOARD=stm32f746disco SPEED=full all ``` -### Debug Log +### Debug + +To compile for debugging with debug symbols add `DEBUG=1`, for example + +``` +$ make BOARD=feather_nrf52840_express DEBUG=1 all +``` -### Log Level +#### Log Should you have an issue running example and/or submitting an bug report. You could enable TinyUSB built-in debug logging with optional `LOG=`. LOG=1 will only print out error message, LOG=2 print more information with on-going events. LOG=3 or higher is not used yet. ``` -$ make LOG=2 BOARD=feather_nrf52840_express all +$ make BOARD=feather_nrf52840_express LOG=2 all ``` -### Logger +#### Logger By default log message is printed via on-board UART which is slow and take lots of CPU time comparing to USB speed. If your board support on-board/external debugger, it would be more efficient to use it for logging. There are 2 protocols: @@ -67,8 +78,8 @@ By default log message is printed via on-board UART which is slow and take lots - Software viewer should be provided along with your debugger driver. ``` -$ make LOG=2 LOGGER=rtt BOARD=feather_nrf52840_express all -$ make LOG=2 LOGGER=swo BOARD=feather_nrf52840_express all +$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=rtt all +$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=swo all ``` ## Flash diff --git a/hw/bsp/stlinkv3mini/board.mk b/hw/bsp/stlinkv3mini/board.mk index b77fb5a51..4ca6cfd68 100644 --- a/hw/bsp/stlinkv3mini/board.mk +++ b/hw/bsp/stlinkv3mini/board.mk @@ -1,6 +1,6 @@ # Only OTG-HS has a connector on this board -REDUCE_SPEED ?= 0 +SPEED ?= high CFLAGS += \ -flto \ @@ -14,12 +14,13 @@ CFLAGS += \ -DHSE_VALUE=25000000 \ -DCFG_TUSB_MCU=OPT_MCU_STM32F7 \ -DBOARD_DEVICE_RHPORT_NUM=1 -ifeq ($(REDUCE_SPEED), 0) -CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED -$(info "Using OTG_HS in HS mode") + +ifeq ($(SPEED), high) + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + $(info "Using OTG_HS in HighSpeed mode") else -CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_FULL_SPEED -$(info "Using OTG_HS in FS mode") + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_FULL_SPEED + $(info "Using OTG_HS in FullSpeed mode") endif # mcu driver cause following warnings diff --git a/hw/bsp/stm32f723disco/board.mk b/hw/bsp/stm32f723disco/board.mk index 47148ec4d..9ec23bfde 100644 --- a/hw/bsp/stm32f723disco/board.mk +++ b/hw/bsp/stm32f723disco/board.mk @@ -1,5 +1,5 @@ PORT ?= 1 -REDUCE_SPEED ?= 0 +SPEED ?= high CFLAGS += \ -flto \ @@ -15,15 +15,15 @@ CFLAGS += \ -DBOARD_DEVICE_RHPORT_NUM=$(PORT) ifeq ($(PORT), 1) - ifeq ($(REDUCE_SPEED), 0) -CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED -$(info "Using OTG_HS in HS mode") - else -CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_FULL_SPEED -$(info "Using OTG_HS in FS mode") - endif + ifeq ($(SPEED), high) + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + $(info "Using OTG_HS in HighSpeed mode") + else + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_FULL_SPEED + $(info "Using OTG_HS in FullSpeed mode") + endif else -$(info "Using OTG_FS") + $(info "Using OTG_FS") endif # mcu driver cause following warnings diff --git a/hw/bsp/stm32f746disco/board.mk b/hw/bsp/stm32f746disco/board.mk index d7329a28f..48cb3f141 100644 --- a/hw/bsp/stm32f746disco/board.mk +++ b/hw/bsp/stm32f746disco/board.mk @@ -1,5 +1,5 @@ PORT ?= 0 -REDUCE_SPEED ?= 0 +SPEED ?= high CFLAGS += \ -flto \ @@ -15,15 +15,15 @@ CFLAGS += \ -DBOARD_DEVICE_RHPORT_NUM=$(PORT) ifeq ($(PORT), 1) - ifeq ($(REDUCE_SPEED), 0) -CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED -$(info "Using OTG_HS in HS mode") - else -CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_FULL_SPEED -$(info "Using OTG_HS in FS mode") - endif + ifeq ($(SPEED), high) + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + $(info "Using OTG_HS in HighSpeed mode") + else + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_FULL_SPEED + $(info "Using OTG_HS in FullSpeed mode") + endif else -$(info "Using OTG_FS") + $(info "Using OTG_FS") endif # mcu driver cause following warnings diff --git a/hw/bsp/stm32f769disco/board.mk b/hw/bsp/stm32f769disco/board.mk index 43b677ddd..962dddc68 100644 --- a/hw/bsp/stm32f769disco/board.mk +++ b/hw/bsp/stm32f769disco/board.mk @@ -1,4 +1,6 @@ -REDUCE_SPEED ?= 0 +# Only OTG-HS has a connector on this board + +SPEED ?= high CFLAGS += \ -flto \ @@ -13,12 +15,12 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_STM32F7 \ -DBOARD_DEVICE_RHPORT_NUM=1 \ -ifeq ($(REDUCE_SPEED), 0) -CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED -$(info "Using OTG_HS in HS mode") +ifeq ($(SPEED), high) + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + $(info "Using OTG_HS in HighSpeed mode") else -CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_FULL_SPEED -$(info "Using OTG_HS in FS mode") + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_FULL_SPEED + $(info "Using OTG_HS in FullSpeed mode") endif # suppress warning caused by vendor mcu driver diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 35b7f44f9..7eb63e52f 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -403,7 +403,7 @@ void dcd_init (uint8_t rhport) // Select default internal VBUS Indicator and Drive for ULPI usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); - #if defined(USB_HS_PHYC) +#if defined(USB_HS_PHYC) // Highspeed with embedded UTMI PHYC // Select UTMI Interface -- cgit v1.3.1 From 323ae5a84fec36e1ad6233d8721b4648a3cf406b Mon Sep 17 00:00:00 2001 From: Craig Hutchinson <54269136+CraigHutchinson@users.noreply.github.com> Date: Fri, 10 Jul 2020 12:24:09 +0100 Subject: Improve comment on CDC tud_cdc_write_available() Fixes #460 --- src/class/cdc/cdc_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index a2523d8d0..897fd272b 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -95,7 +95,7 @@ uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str); // Force sending data if possible, return number of forced bytes uint32_t tud_cdc_n_write_flush (uint8_t itf); -// Return number of characters available for writing +// Return the number of bytes (characters) available for writing to TX FIFO buffer in a single n_write operation. uint32_t tud_cdc_n_write_available (uint8_t itf); //--------------------------------------------------------------------+ -- cgit v1.3.1 From 706413f7510a78e262cf3cb398256e06fadbd500 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Jul 2020 00:44:09 +0700 Subject: add tud_speed_get() - define both fs and hs configuration descriptor - rename CFG_TUD_CDC_EPSIZE to CFG_TUD_CDC_EP_BUFSIZE with default size of 64 for FS, and 512 for HS --- .../device/cdc_dual_ports/src/usb_descriptors.c | 48 +++++++++++++++++----- examples/device/cdc_msc/src/usb_descriptors.c | 28 +++++++++++-- .../device/webusb_serial/src/usb_descriptors.c | 6 +-- examples/rules.mk | 8 +++- src/class/cdc/cdc_device.c | 14 +++---- src/class/cdc/cdc_device.h | 4 +- src/device/usbd.c | 5 +++ src/device/usbd.h | 3 ++ tools/build_all.py | 2 +- 9 files changed, 90 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index a4674b7a9..a27a2cdbd 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -74,10 +74,10 @@ uint8_t const * tud_descriptor_device_cb(void) //--------------------------------------------------------------------+ enum { - ITF_NUM_CDC1 = 0, - ITF_NUM_CDC_DATA1, - ITF_NUM_CDC2, - ITF_NUM_CDC_DATA2, + ITF_NUM_CDC_0 = 0, + ITF_NUM_CDC_0_DATA, + ITF_NUM_CDC_1, + ITF_NUM_CDC_1_DATA, ITF_NUM_TOTAL }; @@ -86,30 +86,58 @@ enum #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 ... - #define EPNUM_CDC 2 + #define EPNUM_CDC_0_NOTIF 0x81 + #define EPNUM_CDC_0_DATA 0x02 + + #define EPNUM_CDC_1_NOTIF 0x84 + #define EPNUM_CDC_1_DATA 0x05 #else - #define EPNUM_CDC 2 + #define EPNUM_CDC_0_NOTIF 0x81 + #define EPNUM_CDC_0_DATA 0x02 + + #define EPNUM_CDC_1_NOTIF 0x83 + #define EPNUM_CDC_1_DATA 0x04 #endif -uint8_t const desc_configuration[] = +uint8_t const desc_fs_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), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_DATA, 0x80 | EPNUM_CDC_0_DATA, 64), // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC2, 4, 0x83, 8, EPNUM_CDC + 2, 0x80 | (EPNUM_CDC + 2), TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_DATA, 0x80 | EPNUM_CDC_1_DATA, 64), }; +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_hs_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), + + // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_DATA, 0x80 | EPNUM_CDC_0_DATA, 512), + + // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_DATA, 0x80 | EPNUM_CDC_1_DATA, 512), +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // 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; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH ) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 9a4d71f24..447dc2644 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -114,18 +114,32 @@ enum #endif -uint8_t const desc_configuration[] = +uint8_t const desc_fs_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), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), }; +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_hs_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), + + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512), +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor @@ -133,7 +147,13 @@ uint8_t const desc_configuration[] = uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return desc_configuration; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH ) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/webusb_serial/src/usb_descriptors.c b/examples/device/webusb_serial/src/usb_descriptors.c index a39b34c3c..935731c0b 100644 --- a/examples/device/webusb_serial/src/usb_descriptors.c +++ b/examples/device/webusb_serial/src/usb_descriptors.c @@ -86,10 +86,10 @@ enum #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 ... - #define EPNUM_CDC 2 + #define EPNUM_CDC_0 2 #define EPNUM_VENDOR 5 #else - #define EPNUM_CDC 2 + #define EPNUM_CDC_0 2 #define EPNUM_VENDOR 3 #endif @@ -99,7 +99,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC, 0x80 | EPNUM_CDC, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, EPNUM_CDC_0, 0x80 | EPNUM_CDC_0, TUD_OPT_HIGH_SPEED ? 512 : 64), // Interface number, string index, EP Out & IN address, EP size TUD_VENDOR_DESCRIPTOR(ITF_NUM_VENDOR, 5, EPNUM_VENDOR, 0x80 | EPNUM_VENDOR, TUD_OPT_HIGH_SPEED ? 512 : 64) diff --git a/examples/rules.mk b/examples/rules.mk index eeb548d08..dacb81363 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -131,8 +131,14 @@ size: $(BUILD)/$(BOARD)-firmware.elf @$(SIZE) $< -@echo '' +.PHONY: clean clean: - rm -rf $(BUILD) + $(RM) -rf $(BUILD) + +# Print out the value of a make variable. +# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile +print-%: + @echo $* = $($*) # Flash binary using Jlink ifeq ($(OS),Windows_NT) diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 4d6e57878..89326f71d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -61,8 +61,8 @@ typedef struct #endif // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EPSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EPSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE]; }cdcd_interface_t; @@ -82,9 +82,9 @@ static void _prep_out_transaction (uint8_t itf) // Prepare for incoming data but only allow what we can store in the ring buffer. uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff); - if ( max_read >= TU_ARRAY_SIZE(p_cdc->epout_buf) ) + if ( max_read >= sizeof(p_cdc->epout_buf) ) { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, TU_ARRAY_SIZE(p_cdc->epout_buf)); + usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); } } @@ -148,7 +148,7 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) #if 0 // TODO issue with circuitpython's REPL // flush if queue more than endpoint size - if ( tu_fifo_count(&_cdcd_itf[itf].tx_ff) >= CFG_TUD_CDC_EPSIZE ) + if ( tu_fifo_count(&_cdcd_itf[itf].tx_ff) >= CFG_TUD_CDC_EP_BUFSIZE ) { tud_cdc_n_write_flush(itf); } @@ -164,7 +164,7 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) // skip if previous transfer not complete yet TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in), 0 ); - uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, TU_ARRAY_SIZE(p_cdc->epin_buf)); + uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); if ( count ) { TU_VERIFY( tud_cdc_n_connected(itf), 0 ); // fifo is empty if not connected @@ -420,7 +420,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ { // There is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EPSIZE)) ) + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) { usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 897fd272b..39ccf6b76 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -34,8 +34,8 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUD_CDC_EPSIZE -#define CFG_TUD_CDC_EPSIZE 64 +#ifndef CFG_TUD_CDC_EP_BUFSIZE +#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif #ifdef __cplusplus diff --git a/src/device/usbd.c b/src/device/usbd.c index b607f5939..f59b19427 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -294,6 +294,11 @@ void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ +tusb_speed_t tud_speed_get(void) +{ + return (tusb_speed_t) _usbd_dev.speed; +} + bool tud_mounted(void) { return _usbd_dev.configured; diff --git a/src/device/usbd.h b/src/device/usbd.h index e9b82747a..d9facf719 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -53,6 +53,9 @@ bool tud_task_event_ready(void); // Interrupt handler, name alias to DCD #define tud_int_handler dcd_int_handler +// Get current bus speed +tusb_speed_t tud_speed_get(void); + // Check if device is connected and configured bool tud_mounted(void); diff --git a/tools/build_all.py b/tools/build_all.py index 25cdc9778..af57cdd5c 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -38,7 +38,7 @@ all_boards.sort() def build_example(example, board): subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - return subprocess.run("make -j 4 -C examples/device/{} BOARD={} all".format(example, board), shell=True, + return subprocess.run("make -j -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) def build_size(example, board): -- cgit v1.3.1 From fea6fb73a1ef65afd848ec71d49d65cc87a9eec9 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Jul 2020 13:02:20 +0700 Subject: add fs & hs config for cdc_msc_freertos, midi_test, msc_dual_lun --- .../device/cdc_msc_freertos/src/usb_descriptors.c | 25 +++++++++++++++++++--- examples/device/midi_test/src/usb_descriptors.c | 23 +++++++++++++++++--- examples/device/msc_dual_lun/src/usb_descriptors.c | 23 +++++++++++++++++--- src/class/cdc/cdc_device.h | 2 +- src/class/midi/midi_device.c | 10 ++++----- src/class/midi/midi_device.h | 2 +- 6 files changed, 69 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_msc_freertos/src/usb_descriptors.c b/examples/device/cdc_msc_freertos/src/usb_descriptors.c index 62ab4f10f..e167ac05f 100644 --- a/examples/device/cdc_msc_freertos/src/usb_descriptors.c +++ b/examples/device/cdc_msc_freertos/src/usb_descriptors.c @@ -114,7 +114,7 @@ enum #endif -uint8_t const desc_configuration[] = +uint8_t const desc_fs_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), @@ -123,9 +123,22 @@ uint8_t const desc_configuration[] = TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), }; +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_hs_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), + + // Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512), +}; +#endif // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor @@ -133,7 +146,13 @@ uint8_t const desc_configuration[] = uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return desc_configuration; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH ) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c index 2867a205f..d529a0547 100644 --- a/examples/device/midi_test/src/usb_descriptors.c +++ b/examples/device/midi_test/src/usb_descriptors.c @@ -88,22 +88,39 @@ enum #define EPNUM_MIDI 0x01 #endif -uint8_t const desc_configuration[] = +uint8_t const desc_fs_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), // Interface number, string index, EP Out & EP In address, EP size - TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, TUD_OPT_HIGH_SPEED ? 512 : 64) + TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 64) }; +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_fs_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), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 512) +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // 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; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH ) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/msc_dual_lun/src/usb_descriptors.c b/examples/device/msc_dual_lun/src/usb_descriptors.c index d0c915b1d..a4e03e68c 100644 --- a/examples/device/msc_dual_lun/src/usb_descriptors.c +++ b/examples/device/msc_dual_lun/src/usb_descriptors.c @@ -96,22 +96,39 @@ enum #endif -uint8_t const desc_configuration[] = +uint8_t const desc_fs_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), // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), }; +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_hs_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), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512), +}; +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // 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; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH ) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 39ccf6b76..2d3312b21 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -35,7 +35,7 @@ // Class Driver Configuration //--------------------------------------------------------------------+ #ifndef CFG_TUD_CDC_EP_BUFSIZE -#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) + #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif #ifdef __cplusplus diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 14fb3e50d..d4ed21c78 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -67,8 +67,8 @@ typedef struct uint8_t read_target_length; // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EPSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EPSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EP_BUFSIZE]; } midid_interface_t; @@ -160,7 +160,7 @@ static bool maybe_transmit(midid_interface_t* midi, uint8_t itf_index) // skip if previous transfer not complete TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, midi->ep_in) ); - uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EPSIZE); + uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); if (count > 0) { TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, midi->ep_in, midi->epin_buf, count) ); @@ -359,7 +359,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint } // Prepare for incoming data - if ( !usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE) ) + if ( !usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE) ) { TU_LOG1_FAILED(); TU_BREAKPOINT(); @@ -404,7 +404,7 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 midi_rx_done_cb(p_midi, p_midi->epout_buf, xferred_bytes); // prepare for next - TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false ); + TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE), false ); } else if ( ep_addr == p_midi->ep_in ) { maybe_transmit(p_midi, itf); } diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index bec0984f2..8f60d264a 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -37,7 +37,7 @@ // Class Driver Configuration //--------------------------------------------------------------------+ #ifndef CFG_TUD_MIDI_EPSIZE -#define CFG_TUD_MIDI_EPSIZE 64 + #define CFG_TUD_MIDI_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif #ifdef __cplusplus -- cgit v1.3.1 From 5ca748a68e01deec929e846b7263cf736bf891fb Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Jul 2020 15:34:16 +0700 Subject: rename CFG_TUD_MSC_BUFSIZE to CFG_TUD_MSC_EP_BUFSIZE rename CFG_TUD_HID_BUFSIZE to CFG_TUD_HID_EP_BUFSIZE --- examples/device/board_test/src/tusb_config.h | 5 +---- examples/device/cdc_msc/src/tusb_config.h | 6 +----- examples/device/cdc_msc_freertos/src/tusb_config.h | 6 +----- .../device/dynamic_configuration/src/tusb_config.h | 24 +++++++++------------- examples/device/hid_composite/src/tusb_config.h | 12 +++++------ .../device/hid_composite/src/usb_descriptors.c | 2 +- .../hid_composite_freertos/src/tusb_config.h | 12 +++++------ .../hid_composite_freertos/src/usb_descriptors.c | 2 +- .../device/hid_generic_inout/src/tusb_config.h | 12 +++++------ .../device/hid_generic_inout/src/usb_descriptors.c | 4 ++-- examples/device/midi_test/src/tusb_config.h | 4 ++-- examples/device/midi_test/src/usb_descriptors.c | 2 +- examples/device/msc_dual_lun/src/tusb_config.h | 12 +++++------ examples/device/usbtmc/src/tusb_config.h | 6 +++--- examples/device/webusb_serial/src/tusb_config.h | 4 ++-- src/class/hid/hid_device.c | 8 ++++---- src/class/hid/hid_device.h | 10 +++++++-- src/class/msc/msc_device.c | 4 ++-- src/class/msc/msc_device.h | 13 +++++++++--- test/test/support/tusb_config.h | 2 +- 20 files changed, 74 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/examples/device/board_test/src/tusb_config.h b/examples/device/board_test/src/tusb_config.h index 0587d48e3..da33729e7 100644 --- a/examples/device/board_test/src/tusb_config.h +++ b/examples/device/board_test/src/tusb_config.h @@ -73,14 +73,11 @@ //------------- CLASS -------------// #define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 1 +#define CFG_TUD_MSC 0 #define CFG_TUD_HID 0 #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 -// MSC Buffer size of Device Mass storage -#define CFG_TUD_MSC_BUFSIZE 512 - #ifdef __cplusplus } #endif diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index 13021d5d3..1370e61c5 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -97,7 +97,6 @@ #define CFG_TUD_CDC 1 #define CFG_TUD_MSC 1 #define CFG_TUD_HID 0 - #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 @@ -106,10 +105,7 @@ #define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) // MSC Buffer size of Device Mass storage -#define CFG_TUD_MSC_BUFSIZE 512 - -// HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_BUFSIZE 16 +#define CFG_TUD_MSC_EP_BUFSIZE 512 #ifdef __cplusplus } diff --git a/examples/device/cdc_msc_freertos/src/tusb_config.h b/examples/device/cdc_msc_freertos/src/tusb_config.h index f7e48f66e..712f328ea 100644 --- a/examples/device/cdc_msc_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_freertos/src/tusb_config.h @@ -99,7 +99,6 @@ #define CFG_TUD_CDC 1 #define CFG_TUD_MSC 1 #define CFG_TUD_HID 0 - #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 @@ -108,10 +107,7 @@ #define CFG_TUD_CDC_TX_BUFSIZE 64 // MSC Buffer size of Device Mass storage -#define CFG_TUD_MSC_BUFSIZE 512 - -// HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_BUFSIZE 16 +#define CFG_TUD_MSC_EP_BUFSIZE 512 #ifdef __cplusplus } diff --git a/examples/device/dynamic_configuration/src/tusb_config.h b/examples/device/dynamic_configuration/src/tusb_config.h index 0950305eb..2f8072f89 100644 --- a/examples/device/dynamic_configuration/src/tusb_config.h +++ b/examples/device/dynamic_configuration/src/tusb_config.h @@ -94,26 +94,22 @@ #endif //------------- CLASS -------------// -#define CFG_TUD_CDC 1 -#define CFG_TUD_MSC 1 -#define CFG_TUD_HID 0 - -#define CFG_TUD_MIDI 1 -#define CFG_TUD_VENDOR 0 +#define CFG_TUD_CDC 1 +#define CFG_TUD_MSC 1 +#define CFG_TUD_MIDI 1 +#define CFG_TUD_HID 0 +#define CFG_TUD_VENDOR 0 // CDC FIFO size of TX and RX -#define CFG_TUD_CDC_RX_BUFSIZE 64 -#define CFG_TUD_CDC_TX_BUFSIZE 64 +#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) // MIDI FIFO size of TX and RX -#define CFG_TUD_MIDI_RX_BUFSIZE 64 -#define CFG_TUD_MIDI_TX_BUFSIZE 64 +#define CFG_TUD_MIDI_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#define CFG_TUD_MIDI_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) // MSC Buffer size of Device Mass storage -#define CFG_TUD_MSC_BUFSIZE 512 - -// HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_BUFSIZE 16 +#define CFG_TUD_MSC_EP_BUFSIZE 512 #ifdef __cplusplus } diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index abc243436..d8e6b73e8 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -94,14 +94,14 @@ #endif //------------- CLASS -------------// -#define CFG_TUD_HID 1 -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 +#define CFG_TUD_HID 1 +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 // HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_BUFSIZE 16 +#define CFG_TUD_HID_EP_BUFSIZE 16 #ifdef __cplusplus } diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index 02cbc17f6..fe46f7d69 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -105,7 +105,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_BUFSIZE, 10) + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_composite_freertos/src/tusb_config.h b/examples/device/hid_composite_freertos/src/tusb_config.h index 677a9b2c6..4b0458ef0 100644 --- a/examples/device/hid_composite_freertos/src/tusb_config.h +++ b/examples/device/hid_composite_freertos/src/tusb_config.h @@ -94,14 +94,14 @@ #endif //------------- CLASS -------------// -#define CFG_TUD_HID 1 -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 +#define CFG_TUD_HID 1 +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 // HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_BUFSIZE 16 +#define CFG_TUD_HID_EP_BUFSIZE 16 #ifdef __cplusplus } diff --git a/examples/device/hid_composite_freertos/src/usb_descriptors.c b/examples/device/hid_composite_freertos/src/usb_descriptors.c index 02cbc17f6..fe46f7d69 100644 --- a/examples/device/hid_composite_freertos/src/usb_descriptors.c +++ b/examples/device/hid_composite_freertos/src/usb_descriptors.c @@ -105,7 +105,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_BUFSIZE, 10) + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_generic_inout/src/tusb_config.h b/examples/device/hid_generic_inout/src/tusb_config.h index 39eebbbeb..347cb06d6 100644 --- a/examples/device/hid_generic_inout/src/tusb_config.h +++ b/examples/device/hid_generic_inout/src/tusb_config.h @@ -94,14 +94,14 @@ #endif //------------- CLASS -------------// -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_HID 1 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_HID 1 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 // HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_BUFSIZE 64 +#define CFG_TUD_HID_EP_BUFSIZE 64 #ifdef __cplusplus } diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index 5c769c9c9..290e12dfd 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -72,7 +72,7 @@ uint8_t const * tud_descriptor_device_cb(void) uint8_t const desc_hid_report[] = { - TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_BUFSIZE) + TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE) }; // Invoked when received GET HID REPORT DESCRIPTOR @@ -103,7 +103,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval - TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_BUFSIZE, 10) + TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/midi_test/src/tusb_config.h b/examples/device/midi_test/src/tusb_config.h index fd109ad32..d0c327e27 100644 --- a/examples/device/midi_test/src/tusb_config.h +++ b/examples/device/midi_test/src/tusb_config.h @@ -101,8 +101,8 @@ #define CFG_TUD_VENDOR 0 // MIDI FIFO size of TX and RX -#define CFG_TUD_MIDI_RX_BUFSIZE 64 -#define CFG_TUD_MIDI_TX_BUFSIZE 64 +#define CFG_TUD_MIDI_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#define CFG_TUD_MIDI_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #ifdef __cplusplus } diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c index d529a0547..3c556a156 100644 --- a/examples/device/midi_test/src/usb_descriptors.c +++ b/examples/device/midi_test/src/usb_descriptors.c @@ -98,7 +98,7 @@ uint8_t const desc_fs_configuration[] = }; #if TUD_OPT_HIGH_SPEED -uint8_t const desc_fs_configuration[] = +uint8_t const desc_hs_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), diff --git a/examples/device/msc_dual_lun/src/tusb_config.h b/examples/device/msc_dual_lun/src/tusb_config.h index 1ee3faec4..e153a7967 100644 --- a/examples/device/msc_dual_lun/src/tusb_config.h +++ b/examples/device/msc_dual_lun/src/tusb_config.h @@ -94,14 +94,14 @@ #endif //------------- CLASS -------------// -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 1 -#define CFG_TUD_HID 0 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 1 +#define CFG_TUD_HID 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 // MSC Buffer size of Device Mass storage -#define CFG_TUD_MSC_BUFSIZE 512 +#define CFG_TUD_MSC_EP_BUFSIZE 512 #ifdef __cplusplus } diff --git a/examples/device/usbtmc/src/tusb_config.h b/examples/device/usbtmc/src/tusb_config.h index 3fab286a9..603e67453 100644 --- a/examples/device/usbtmc/src/tusb_config.h +++ b/examples/device/usbtmc/src/tusb_config.h @@ -77,9 +77,9 @@ //------------- CLASS -------------// -#define CFG_TUD_USBTMC 1 -#define CFG_TUD_USBTMC_ENABLE_INT_EP 1 -#define CFG_TUD_USBTMC_ENABLE_488 1 +#define CFG_TUD_USBTMC 1 +#define CFG_TUD_USBTMC_ENABLE_INT_EP 1 +#define CFG_TUD_USBTMC_ENABLE_488 1 #ifdef __cplusplus } diff --git a/examples/device/webusb_serial/src/tusb_config.h b/examples/device/webusb_serial/src/tusb_config.h index a9b7a82d5..48c9ddad6 100644 --- a/examples/device/webusb_serial/src/tusb_config.h +++ b/examples/device/webusb_serial/src/tusb_config.h @@ -101,8 +101,8 @@ #define CFG_TUD_VENDOR 1 // CDC FIFO size of TX and RX -#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) -#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) // Vendor FIFO size of TX and RX // If not configured vendor endpoints will not be buffered diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 526394d4a..c46fc591a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -48,8 +48,8 @@ typedef struct uint8_t idle_rate; // up to application to handle idle rate uint16_t report_desc_len; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE]; tusb_hid_descriptor_hid_t const * hid_descriptor; } hidd_interface_t; @@ -86,7 +86,7 @@ bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) if (report_id) { - len = tu_min8(len, CFG_TUD_HID_BUFSIZE-1); + len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE-1); p_hid->epin_buf[0] = report_id; memcpy(p_hid->epin_buf+1, report, len); @@ -94,7 +94,7 @@ bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) }else { // If report id = 0, skip ID field - len = tu_min8(len, CFG_TUD_HID_BUFSIZE); + len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE); memcpy(p_hid->epin_buf, report, len); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index ad8c9ece4..ad26ab369 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -39,8 +39,14 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -#ifndef CFG_TUD_HID_BUFSIZE -#define CFG_TUD_HID_BUFSIZE 16 +#if !defined(CFG_TUD_HID_EP_BUFSIZE) & defined(CFG_TUD_HID_BUFSIZE) + // TODO warn user to use new name later on + // #warning CFG_TUD_HID_BUFSIZE is renamed to CFG_TUD_HID_EP_BUFSIZE + #define CFG_TUD_HID_EP_BUFSIZE CFG_TUD_HID_BUFSIZE +#endif + +#ifndef CFG_TUD_HID_EP_BUFSIZE + #define CFG_TUD_HID_EP_BUFSIZE 16 #endif //--------------------------------------------------------------------+ diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 3ddcd4e49..692fd2441 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -65,7 +65,7 @@ typedef struct }mscd_interface_t; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static mscd_interface_t _mscd_itf; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_BUFSIZE]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_EP_BUFSIZE]; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION @@ -564,7 +564,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t else { // READ10 & WRITE10 Can be executed with large bulk of data e.g write 8K bytes (several flash write) - // We break it into multiple smaller command whose data size is up to CFG_TUD_MSC_BUFSIZE + // We break it into multiple smaller command whose data size is up to CFG_TUD_MSC_EP_BUFSIZE if (SCSI_CMD_READ_10 == p_cbw->command[0]) { proc_read10_cmd(rhport, p_msc); diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 30ffd02e1..995491ec4 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -38,12 +38,19 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ -TU_VERIFY_STATIC(CFG_TUD_MSC_BUFSIZE < UINT16_MAX, "Size is not correct"); -#ifndef CFG_TUD_MSC_BUFSIZE - #error CFG_TUD_MSC_BUFSIZE must be defined, value of a block size should work well, the more the better +#if !defined(CFG_TUD_MSC_EP_BUFSIZE) & defined(CFG_TUD_MSC_BUFSIZE) + // TODO warn user to use new name later on + // #warning CFG_TUD_MSC_BUFSIZE is renamed to CFG_TUD_MSC_EP_BUFSIZE + #define CFG_TUD_MSC_EP_BUFSIZE CFG_TUD_MSC_BUFSIZE #endif +#ifndef CFG_TUD_MSC_EP_BUFSIZE + #error CFG_TUD_MSC_EP_BUFSIZE must be defined, value of a block size should work well, the more the better +#endif + +TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); + /** \addtogroup ClassDriver_MSC * @{ * \defgroup MSC_Device Device diff --git a/test/test/support/tusb_config.h b/test/test/support/tusb_config.h index 76f975323..80ea0a1ea 100644 --- a/test/test/support/tusb_config.h +++ b/test/test/support/tusb_config.h @@ -94,7 +94,7 @@ //------------- HID -------------// // Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_BUFSIZE 16 +#define CFG_TUD_HID_EP_BUFSIZE 16 #ifdef __cplusplus } -- cgit v1.3.1 From 0517f4a2f1d7e115cabab7c850463f1836a35a05 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Jul 2020 16:12:21 +0700 Subject: dcd tdi report link speed on reset --- src/portable/nxp/transdimension/dcd_transdimension.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 68cf145ea..46751cf5d 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -82,11 +82,14 @@ enum { }; // PORTSC1 +#define PORTSC1_PORT_SPEED_POS 26 + enum { PORTSC1_CURRENT_CONNECT_STATUS = TU_BIT(0), PORTSC1_FORCE_PORT_RESUME = TU_BIT(6), PORTSC1_SUSPEND = TU_BIT(7), PORTSC1_FORCE_FULL_SPEED = TU_BIT(24), + PORTSC1_PORT_SPEED = TU_BIT(26) | TU_BIT(27) }; // OTGSC @@ -512,7 +515,8 @@ void dcd_int_handler(uint8_t rhport) if (int_status & INTR_RESET) { bus_reset(rhport); - dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); + uint32_t speed = (dcd_reg->PORTSC1 & PORTSC1_PORT_SPEED) >> PORTSC1_PORT_SPEED_POS; + dcd_event_bus_reset(rhport, (tusb_speed_t) speed, true); } if (int_status & INTR_SUSPEND) -- cgit v1.3.1 From dc00f0cae10ec43c9f035938276b7000c3120ec2 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Jul 2020 20:44:06 +0700 Subject: update link speed detection for nuc505 --- hw/bsp/nutiny_sdk_nuc505/board.mk | 10 ++++++++++ src/portable/nuvoton/nuc505/dcd_nuc505.c | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/hw/bsp/nutiny_sdk_nuc505/board.mk b/hw/bsp/nutiny_sdk_nuc505/board.mk index 5fb2119b8..8752ef8ea 100644 --- a/hw/bsp/nutiny_sdk_nuc505/board.mk +++ b/hw/bsp/nutiny_sdk_nuc505/board.mk @@ -46,6 +46,16 @@ FREERTOS_PORT = ARM_CM4F JLINK_DEVICE = NUC505YO13Y JLINK_IF = swd +# Note +# To be able to program the SPI flash, it need to boot with ICP mode "1011". +# However, in ICP mode, opencod cannot establish connection to the mcu. +# Therefore, there is no easy command line flash for NUC505 +# It is probably better to just use Nuvoton NuMicro ICP programming on windows to program the board +# - 1111 "SPI" (run from internal flash) +# - 1110 "USB" (mass storage emulator that accepts a .bin file) +# - 0111 "ICE-SPI" (allow external debugger access, but may not be programmable) +# - 1011 ICP mode (programmable via NuMicro ICP programming tool) + # Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton # Please compile and install it from github source flash: $(BUILD)/$(BOARD)-firmware.elf diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index e67b69ab2..a7961a687 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -452,7 +452,9 @@ void dcd_int_handler(uint8_t rhport) USBD->CEPINTEN = USBD_CEPINTEN_SETUPPKIEN_Msk; USBD->BUSINTEN = USBD_BUSINTEN_RSTIEN_Msk | USBD_BUSINTEN_RESUMEIEN_Msk | USBD_BUSINTEN_SUSPENDIEN_Msk | USBD_BUSINTEN_DMADONEIEN_Msk; USBD->CEPINTSTS = 0x1ffc; - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + + tusb_speed_t speed = (USBD->OPER & USBD_OPER_CURSPD_Msk) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL; + dcd_event_bus_reset(0, speed, true); } if (bus_state & USBD_BUSINTSTS_RESUMEIF_Msk) -- cgit v1.3.1 From d0f3d039332cf22637d191cc62bed620c4f14dce Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 17 Jul 2020 08:40:10 +0200 Subject: Intermediate commit. --- src/class/audio/audio.h | 332 ++++++++++++++++++++++++++++++----------- src/class/audio/audio_device.c | 268 ++++++++++++++++++++++++++++++--- src/class/audio/audio_device.h | 21 +++ src/device/usbd.h | 43 +----- src/tusb_option.h | 6 +- 5 files changed, 525 insertions(+), 145 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 022f3118f..f1784a006 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -38,17 +38,22 @@ extern "C" { #endif -/// Isochronous End Point Attributes +/// Audio Device Class Codes + +/// A.2 - Audio Function Subclass Codes typedef enum { - TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, - TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, - TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, - TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point - TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point -} tusb_iso_ep_attribute_t; + AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, +} audio_function_subclass_type_t; -/// Audio Interface Subclass Codes +/// A.3 - Audio Function Protocol Codes +typedef enum +{ + AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +} audio_function_protocol_code_t; + +/// A.5 - Audio Interface Subclass Codes typedef enum { AUDIO_SUBCLASS_UNDEFINED = 0x00, @@ -57,23 +62,17 @@ typedef enum AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming } audio_subclass_type_t; -/// Audio Function Subclass Codes -typedef enum -{ - AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, -} audio_function_subclass_type_t; - -/// Audio Protocol Codes +/// A.6 - Audio Interface Protocol Codes typedef enum { - AUDIO_PROTOCOL_V1 = 0x00, ///< Version 1.0 - AUDIO_PROTOCOL_V2 = 0x20, ///< Version 2.0 - AUDIO_PROTOCOL_V3 = 0x30, ///< Version 3.0 -} audio_protocol_type_t; + AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +} audio_interface_protocol_code_t; -/// Audio Function Category Codes +/// A.7 - Audio Function Category Codes typedef enum { + AUDIO_FUNC_UNDEF = 0x00, AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, AUDIO_FUNC_HOME_THEATER = 0x02, AUDIO_FUNC_MICROPHONE = 0x03, @@ -86,9 +85,10 @@ typedef enum AUDIO_FUNC_PRO_AUDIO = 0x0A, AUDIO_FUNC_AUDIO_VIDEO = 0x0B, AUDIO_FUNC_CONTROL_PANEL = 0x0C, -} audio_function_t; + AUDIO_FUNC_OTHER = 0xFF, +} audio_function_code_t; -/// Audio Class-Specific AC Interface Descriptor Subtypes UAC2 +/// A.9 - Audio Class-Specific AC Interface Descriptor Subtypes UAC2 typedef enum { AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, @@ -107,7 +107,7 @@ typedef enum AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, } audio_cs_ac_interface_subtype_t; -/// Audio Class-Specific AS Interface Descriptor Subtypes UAC2 +/// A.10 - Audio Class-Specific AS Interface Descriptor Subtypes UAC2 typedef enum { AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, @@ -117,6 +117,150 @@ typedef enum AUDIO_CS_AS_INTERFACE_DECODER = 0x04, } audio_cs_as_interface_subtype_t; +/// A.11 - Effect Unit Effect Types +typedef enum +{ + AUDIO_EFFECT_TYPE_UNDEF = 0x00, + AUDIO_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01, + AUDIO_EFFECT_TYPE_REVERBERATION = 0x02, + AUDIO_EFFECT_TYPE_MOD_DELAY = 0x03, + AUDIO_EFFECT_TYPE_DYN_RANGE_COMP = 0x04, +} audio_effect_unit_effect_type_t; + +/// A.12 - Processing Unit Process Types +typedef enum +{ + AUDIO_PROCESS_TYPE_UNDEF = 0x00, + AUDIO_PROCESS_TYPE_UP_DOWN_MIX = 0x01, + AUDIO_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02, + AUDIO_PROCESS_TYPE_STEREO_EXTENDER = 0x03, +} audio_processing_unit_process_type_t; + +/// A.13 - Audio Class-Specific EP Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_EP_SUBTYPE_UNDEF = 0x00, + AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, +} audio_cs_ep_subtype_t; + +/// A.14 - Audio Class-Specific Request Codes +typedef enum +{ + AUDIO_CS_REQ_UNDEF = 0x00, + AUDIO_CS_REQ_CUR = 0x01, + AUDIO_CS_REQ_RANGE = 0x02, + AUDIO_CS_REQ_MEM = 0x03, +} audio_cs_req_t; + +/// A.17 - Control Selector Codes + +/// A.17.1 - Clock Source Control Selectors +typedef enum +{ + AUDIO_CLK_SRC_CTRL_UNDEF = 0x00, + AUDIO_CLK_SRC_CTRL_SAM_FREQ = 0x01, + AUDIO_CLK_SRC_CTRL_CLK_VALID = 0x02, +} audio_clock_src_control_selector_t; + +/// A.17.7 - Feature Unit Control Selectors +typedef enum +{ + AUDIO_FU_CTRL_UNDEF = 0x00, + AUDIO_FU_CTRL_MUTE = 0x01, + AUDIO_FU_CTRL_VOLUME = 0x02, + AUDIO_FU_CTRL_BASS = 0x03, + AUDIO_FU_CTRL_MID = 0x04, + AUDIO_FU_CTRL_TREBLE = 0x05, + AUDIO_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, + AUDIO_FU_CTRL_AGC = 0x07, + AUDIO_FU_CTRL_DELAY = 0x08, + AUDIO_FU_CTRL_BASS_BOOST = 0x09, + AUDIO_FU_CTRL_LOUDNESS = 0x0A, + AUDIO_FU_CTRL_INPUT_GAIN = 0x0B, + AUDIO_FU_CTRL_GAIN_PAD = 0x0C, + AUDIO_FU_CTRL_INVERTER = 0x0D, + AUDIO_FU_CTRL_UNDERFLOW = 0x0E, + AUDIO_FU_CTRL_OVERVLOW = 0x0F, + AUDIO_FU_CTRL_LATENCY = 0x10, +} audio_feature_unit_control_selector_t; + +// Rest is yet to be implemented! + +/// Terminal Types + +/// 2.1 - Audio Class-Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, + AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, + AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, +} audio_terminal_type_t; + +/// 2.2 - Audio Class-Input Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, + AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, + AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, + AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, + AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, + AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, + AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, +} audio_terminal_input_type_t; + +/// 2.3 - Audio Class-Output Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, + AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, + AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, + AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, + AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, + AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, + AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, + AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, +} audio_terminal_output_type_t; + +/// Rest is yet to be implemented + +/// Additional Audio Device Class Codes - Source: Audio Data Formats + +/// A.1 - Audio Class-Format Type Codes UAC2 +typedef enum +{ + AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, + AUDIO_FORMAT_TYPE_I = 0x01, + AUDIO_FORMAT_TYPE_II = 0x02, + AUDIO_FORMAT_TYPE_III = 0x03, + AUDIO_FORMAT_TYPE_IV = 0x04, + AUDIO_EXT_FORMAT_TYPE_I = 0x81, + AUDIO_EXT_FORMAT_TYPE_II = 0x82, + AUDIO_EXT_FORMAT_TYPE_III = 0x83, +} audio_format_type_t; + +/// A.2.1 - Audio Class-Audio Data Format Type I UAC2 +typedef enum +{ + AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), + AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), + AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), + AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), + AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = (uint32_t) (1 << 31), +} audio_data_format_type_I_t; + +/// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification + +/// Isochronous End Point Attributes +typedef enum +{ + TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, + TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, + TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, + TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point + TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point +} tusb_iso_ep_attribute_t; + /// Audio Class-Control Values UAC2 typedef enum { @@ -138,13 +282,6 @@ typedef enum AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, } audio_cs_as_interface_control_pos_t; -/// Audio Class-Specific EP Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_EP_SUBTYPE_DESCRIPTOR_UNDEFINED = 0x00, - AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, -} audio_cs_ep_subtype_t; - /// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 typedef enum { @@ -198,26 +335,6 @@ typedef enum AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, } audio_clock_multiplier_control_pos_t; -/// Audio Class-Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, - AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, - AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, -} audio_terminal_type_t; - -/// Audio Class-Input Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, - AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, - AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, - AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, - AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, - AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, - AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, -} audio_terminal_input_type_t; - /// Audio Class-Input Terminal Controls UAC2 typedef enum { @@ -229,19 +346,6 @@ typedef enum AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, } audio_terminal_input_control_pos_t; -/// Audio Class-Output Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, - AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, - AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, - AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, - AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, - AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, - AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, - AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, -} audio_terminal_output_type_t; - /// Audio Class-Output Terminal Controls UAC2 typedef enum { @@ -272,29 +376,6 @@ typedef enum AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, } audio_feature_unit_control_pos_t; -/// Audio Class-Format Type Codes UAC2 -typedef enum -{ - AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, - AUDIO_FORMAT_TYPE_I = 0x01, - AUDIO_FORMAT_TYPE_II = 0x02, - AUDIO_FORMAT_TYPE_III = 0x03, - AUDIO_FORMAT_TYPE_IV = 0x04, - AUDIO_EXT_FORMAT_TYPE_I = 0x81, - AUDIO_EXT_FORMAT_TYPE_II = 0x82, - AUDIO_EXT_FORMAT_TYPE_III = 0x83, -} audio_format_type_t; - -/// Audio Class-Audio Data Format Type I UAC2 -typedef enum -{ - AUDIO_DATA_FORMAT_TYPE_I_PCM = 0x00000000, - AUDIO_DATA_FORMAT_TYPE_I_PCM8 = 0x00000001, - AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = 0x00000002, - AUDIO_DATA_FORMAT_TYPE_I_ALAW = 0x00000003, - AUDIO_DATA_FORMAT_TYPE_I_MULAW = 0x00000004, -} audio_data_format_type_I_t; - /// Audio Class-Audio Channel Configuration UAC2 typedef enum { @@ -490,6 +571,85 @@ typedef struct TU_ATTR_PACKED uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. } audio_desc_cs_as_iso_data_ep_t; +//// 5.2.3 Control Request Parameter Block Layout + +// 5.2.3.1 1-byte Control CUR Parameter Block +typedef struct TU_ATTR_PACKED +{ + int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control +} audio_control_cur_1_t; + +// 5.2.3.2 2-byte Control CUR Parameter Block +typedef struct TU_ATTR_PACKED +{ + int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control +} audio_control_cur_2_t; + +// 5.2.3.3 4-byte Control CUR Parameter Block +typedef struct TU_ATTR_PACKED +{ + int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control +} audio_control_cur_4_t; + +// 5.2.3.1 1-byte Control RANGE Parameter Block +//#define audio_control_range_1_n_t(numSubRanges) \ +// struct TU_ATTR_PACKED { \ +// uint16_t wNumSubRanges = numSubRanges; \ +// struct TU_ATTR_PACKED { \ +// int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ +// int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ +// uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ +// } setting[numSubRanges] ; \ +// } + +typedef struct TU_ATTR_PACKED { + uint16_t wNumSubRanges; + struct TU_ATTR_PACKED { + int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } setting[] ; +} audio_control_range_1_t; + +// 5.2.3.2 2-byte Control RANGE Parameter Block +//#define audio_control_range_2_n_t(numSubRanges) \ +// struct TU_ATTR_PACKED { \ +// uint16_t wNumSubRanges = numSubRanges; \ +// struct TU_ATTR_PACKED { \ +// int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ +// int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ +// uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ +// } setting[numSubRanges] ; \ +// } + +typedef struct TU_ATTR_PACKED { + uint16_t wNumSubRanges; + struct TU_ATTR_PACKED { + int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } setting[] ; +} audio_control_range_2_t; + +// 5.2.3.3 4-byte Control RANGE Parameter Block +//#define audio_control_range_4_n_t(numSubRanges) \ +// struct TU_ATTR_PACKED { \ +// uint16_t wNumSubRanges = numSubRanges; \ +// struct TU_ATTR_PACKED { \ +// int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ +// int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ +// uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ +// } setting[numSubRanges] ; \ +// } + +typedef struct TU_ATTR_PACKED { + uint16_t wNumSubRanges; + struct TU_ATTR_PACKED { + int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } setting[] ; +} audio_control_range_4_t; /** @} */ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 1c9e0494e..67c94837a 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -152,6 +152,9 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID); +static bool audiod_verify_itf_exists(uint8_t itf); +static bool audiod_verify_ep_exists(uint8_t ep); bool tud_audio_n_mounted(uint8_t itf) { @@ -638,7 +641,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); // Verify version is correct - this check can be omitted - TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); + TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed @@ -666,7 +669,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) // Notify caller we read complete descriptor -// (*p_length) += tud_audio_desc_lengths[i]; + // (*p_length) += tud_audio_desc_lengths[i]; // TODO: Find a way to find end of current audio function and avoid necessity of tud_audio_desc_lengths - since now max_length is available we could do this surely somehow uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor @@ -675,8 +678,6 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) { - (void) rhport; - #if CFG_TUD_AUDIO_N_AS_INT > 0 uint8_t const itf = tu_u16_low(p_request->wIndex); @@ -690,6 +691,7 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * return true; #else + (void) rhport; (void) p_request; return false; #endif @@ -805,21 +807,85 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Check for nothing found - we can rely on this since EP descriptors are never the last descriptors, there are always also class specific EP descriptors following! TU_VERIFY(p_desc < p_desc_end); - // Conduct audio driver function specific stuff - - // HERE DO WHAT YOU HAVE TO DO - E.G. START ADC OR SO - //#error Implementation specific setInterface code required here! + // Invoke callback + if (tud_audio_set_itf_cb) + { + if (!tud_audio_set_itf_cb(rhport, p_request)) + { + return false; + } + } // Save current alternative interface setting _audiod_itf[idxDriver].altSetting[idxItf] = alt; + tud_control_status(rhport, p_request); + return true; } +// Invoked when class request DATA stage is finished. +// return false to stall control EP (e.g Host send non-sense DATA) bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) { - (void) rhport; - (void) p_request; + // Handle audio class specific set requests + if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) + { + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present - This check may be omitted if we trust the host not to send rubbish + if (entityID != 0) + { + // Invoke callback + if (tud_audio_set_req_entity_cb && tud_audio_set_req_entity_cb(rhport, p_request)) + { + tud_control_status(rhport, p_request); + } + else + { + return false; // In case no callback function is present or request can not be conducted we stall it + } + } + else + { + // Invoke callback + if (tud_audio_set_req_itf_cb && tud_audio_set_req_itf_cb(rhport, p_request)) + { + tud_control_status(rhport, p_request); + } + else + { + return false; // In case no callback function is present or request can not be conducted we stall it + } + } + + break; + + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + // Invoke callback + if (tud_audio_set_req_ep_cb && tud_audio_set_req_ep_cb(rhport, p_request)) + { + tud_control_status(rhport, p_request); + } + else + { + return false; // In case no callback function is present or request can not be conducted we stall it + } + + break; + + // Unknown/Unsupported recipient + default: TU_BREAKPOINT(); return false; + } + } return true; } @@ -829,17 +895,103 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req { (void) rhport; - switch (p_request->bRequest) + // Handle standard requests - standard set requests usually have no data stage so we also handle set requests here + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) + { + switch (p_request->bRequest) + { + case TUSB_REQ_GET_INTERFACE: + return audiod_get_interface(rhport, p_request); + + case TUSB_REQ_SET_INTERFACE: + return audiod_set_interface(rhport, p_request); + + // Unknown/Unsupported request + default: TU_BREAKPOINT(); return false; + } + } + + // Handle class requests + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) { - case TUSB_REQ_GET_INTERFACE: - return audiod_get_interface(rhport, p_request); + // Conduct checks which depend on the recipient + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present - This check may be omitted if we trust the host not to send rubbish + if (entityID != 0) + { + TU_VERIFY(audiod_verify_entity_exists(itf, entityID)); + + // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished + if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; + + // Invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (tud_audio_get_req_entity_cb) + { + return tud_audio_get_req_entity_cb(rhport, p_request); + } + else + { + TU_LOG2(" No entity get request callback available!\r\n"); + } + } + else + { + TU_VERIFY(audiod_verify_itf_exists(itf)); + + // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished + if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; + + // Invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (tud_audio_get_req_itf_cb) + { + return tud_audio_get_req_itf_cb(rhport, p_request); + } + else + { + TU_LOG2(" No interface get request callback available!\r\n"); + } + } + + break; + + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + + uint8_t ep = TU_U16_LOW(p_request->wIndex); - case TUSB_REQ_SET_INTERFACE: - return audiod_set_interface(rhport, p_request); + // Verify if EP is present - This check may be omitted if we trust the host not to send rubbish + TU_VERIFY(audiod_verify_ep_exists(ep)); - default: + // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished + if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; + + if (tud_audio_get_req_ep_cb) + { + return tud_audio_get_req_ep_cb(rhport, p_request); + } + else + { + TU_LOG2(" No EP get request callback available!\r\n"); + } + + break; + + // Unknown/Unsupported recipient + default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; + } + + // Host expects an answer - in case no callback function is present we stall the request return false; } + + // There went something wrong + TU_BREAKPOINT(); + return false; } bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) @@ -936,19 +1088,22 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 } +// This helper function finds for a given interface number the index of the attached driver interface, the index of the interface in the audio function +// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and +// finally a pointer to the std. AS interface, where the pointer always points to the start i.e. alternate interface zero. static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) { // Loop over audio driver interfaces uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) { - if (!_audiod_itf[i].p_desc) + if (_audiod_itf[i].p_desc) { // Get pointer at end uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; // Advance past AC descriptors - uint8_t const * p_desc = tu_desc_next(_audiod_itf[i].p_desc); + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; uint8_t tmp = 0; @@ -973,6 +1128,83 @@ static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t return false; } +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID) +{ + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + // Look for the correct driver by checking if the unique standard AC interface number fits + if (_audiod_itf[i].p_desc && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) + { + // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); // Points to CS AC descriptor + uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; + p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor + + while (p_desc < p_desc_end) + { + if (p_desc[3] == entityID) // Entity IDs are always at offset 3 + { + return true; + } + p_desc = tu_desc_next(p_desc); + } + } + } + return false; +} + +static bool audiod_verify_itf_exists(uint8_t itf) +{ + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (_audiod_itf[i].p_desc) + { + // Get pointer at beginning and end + uint8_t const *p_desc = _audiod_itf[i].p_desc; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + while (p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) + { + return true; + } + p_desc = tu_desc_next(p_desc); + } + } + } + return false; +} + +static bool audiod_verify_ep_exists(uint8_t ep) +{ + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (_audiod_itf[i].p_desc) + { + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + // Advance past AC descriptors - EP we look for are streaming EPs + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); + p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; + + while (p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) + { + return true; + } + p_desc = tu_desc_next(p_desc); + } + } + } + return false; +} + #endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO // OLD diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 3e1fa7a92..95b361acd 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -229,6 +229,27 @@ bool tud_audio_fb_done_cb(uint8_t rhport); TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); #endif +// Invoked when audio set interface request received +TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific set request received for an EP +TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific set request received for an interface +TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific set request received for an entity +TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific get request received for an EP +TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific get request received for an interface +TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// Invoked when audio class specific get request received for an entity +TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); + //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index 39ad7639e..fa0be803c 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -322,12 +322,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Standard Interface Association Descriptor (IAD) */ #define TUD_AUDIO_DESC_IAD_LEN 8 #define TUD_AUDIO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ - TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_PROTOCOL_V2, _stridx + TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx /* Standard AC Interface Descriptor(4.7.1) */ #define TUD_AUDIO_DESC_STD_AC_LEN 9 #define TUD_AUDIO_DESC_STD_AC(_itfnum, _nEPs, _stridx) /* _nEPs is 0 or 1 */\ - TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx + TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_INT_PROTOCOL_CODE_V2, _stridx /* Class-Specific AC Interface Header Descriptor(4.7.2) */ #define TUD_AUDIO_DESC_CS_AC_LEN 9 @@ -360,7 +360,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Standard AS Interface Descriptor(4.9.1) */ #define TUD_AUDIO_DESC_STD_AS_INT_LEN 9 #define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ - TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, _stridx + TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_INT_PROTOCOL_CODE_V2, _stridx /* Class-Specific AS Interface Descriptor(4.9.2) */ #define TUD_AUDIO_DESC_CS_AS_INT_LEN 16 @@ -431,43 +431,6 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) -// Length of template descriptor (132 bytes) -//#define TUD_AUDIO_MIC_DESC_LEN (8 + 9 + 9 + 8 + 17 + 12 + 14 + 9 + 9 + 16 + 6 + 7 + 8) -//#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 -// -// // AUDIO simple descriptor (UAC2) for 1 microphone input -// // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source -// #define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ -// /* Standard Interface Association Descriptor (IAD) */\ -// 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 0x02, TUSB_CLASS_AUDIO, 0x00, AUDIO_PROTOCOL_V2, 0x00,\ -// /* Standard AC Interface Descriptor(4.7.1) */\ -// 9, TUSB_DESC_INTERFACE, _itfnum, 0x00, 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V2, _stridx,\ -// /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ -// 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0200), AUDIO_FUNC_MICROPHONE, U16_TO_U8S_LE(9+8+17+12+6+(1+1)*4), AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS,\ -// /* Clock Source Descriptor(4.7.2.1) */\ -// 8, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, 0x04, AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), 0x00, \ -// /* Input Terminal Descriptor(4.7.2.4) */\ -// 17, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, 0x01, U16_TO_U8S_LE(AUDIO_TERM_TYPE_IN_GENERIC_MIC), 0x00, 0x04, 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00, U16_TO_U8S_LE(AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), 0x00, \ -// /* Output Terminal Descriptor(4.7.2.5) */\ -// 12, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, 0x03, U16_TO_U8S_LE(AUDIO_TERM_TYPE_USB_STREAMING), 0x00, 0x02, 0x04, U16_TO_U8S_LE(0x0000), 0x00, \ -// /* Feature Unit Descriptor(4.7.2.8) */\ -// 6+(1+1)*4, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, 0x02, 0x01, U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), U32_TO_U8S_LE(AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), 0x00, \ -// /* Standard AS Interface Descriptor(4.9.1) */\ -// /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ -// 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x00, /* number of EPs */ 0x00, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ -// /* Standard AS Interface Descriptor(4.9.1) */\ -// /* Interface 1, Alternate 1 - alternate interface for data streaming */\ -// 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), /* alternate setting */ 0x01, /* number of EPs */ 0x01, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_PROTOCOL_V2, 0x00,\ -// /* Class-Specific AS Interface Descriptor(4.9.2) */\ -// 16, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, 0x03, AUDIO_CTRL_NONE, AUDIO_FORMAT_TYPE_I, U32_TO_U8S_LE(AUDIO_DATA_FORMAT_TYPE_I_PCM), 0x01, U32_TO_U8S_LE(AUDIO_CHANNEL_CONFIG_NON_PREDEFINED), 0x00,\ -// /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ -// 6, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _nBytesPerSample, _nBitsUsedPerSample,\ -// /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ -// 7, TUSB_DESC_ENDPOINT, _epin, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), U16_TO_U8S_LE(_epsize), (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01,\ -// /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ -// 8, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, U16_TO_U8S_LE(0x0000) - - //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) #define TUD_USBTMC_APP_SUBCLASS 0x03u diff --git a/src/tusb_option.h b/src/tusb_option.h index 0a227483f..cc91b1863 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -163,7 +163,7 @@ // Debug enable to print out error message #ifndef CFG_TUSB_DEBUG - #define CFG_TUSB_DEBUG 0 + #define CFG_TUSB_DEBUG 2 #endif // place data in accessible RAM for usb controller @@ -199,6 +199,10 @@ #define CFG_TUD_HID 0 #endif +#ifndef CFG_TUD_AUDIO + #define CFG_TUD_AUDIO 0 +#endif + #ifndef CFG_TUD_MIDI #define CFG_TUD_MIDI 0 #endif -- cgit v1.3.1 From 7baeea7a000a7d8f8d0bb2c966d4c2c409205a09 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Jul 2020 18:28:19 +0700 Subject: update actual link speed for spresense --- src/portable/sony/cxd56/dcd_cxd56.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index bcf94dc21..9269903a5 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -134,7 +134,8 @@ static void _dcd_disconnect(FAR struct usbdevclass_driver_s *driver, FAR struct { (void) driver; - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + tusb_speed_t speed = (dev->speed == 3) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL; + dcd_event_bus_reset(0, speed, true); DEV_CONNECT(dev); } -- cgit v1.3.1 From 881025afdcdc3e8954163f8cc7337caa8455f594 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 Jul 2020 23:01:39 +0700 Subject: add new name warning to cdc and midi (skip msc, hid warning for now) --- src/class/cdc/cdc_device.h | 5 +++++ src/class/hid/hid_device.h | 2 +- src/class/midi/midi_device.h | 8 +++++++- src/class/msc/msc_device.h | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 2d3312b21..9d257bbe9 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -34,6 +34,11 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ +#if !defined(CFG_TUD_CDC_EP_BUFSIZE) && defined(CFG_TUD_CDC_EPSIZE) + #warning CFG_TUD_CDC_EPSIZE is renamed to CFG_TUD_CDC_EP_BUFSIZE, please update to use the new name + #define CFG_TUD_CDC_EP_BUFSIZE CFG_TUD_CDC_EPSIZE +#endif + #ifndef CFG_TUD_CDC_EP_BUFSIZE #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index ad26ab369..f7ad38bab 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -41,7 +41,7 @@ #if !defined(CFG_TUD_HID_EP_BUFSIZE) & defined(CFG_TUD_HID_BUFSIZE) // TODO warn user to use new name later on - // #warning CFG_TUD_HID_BUFSIZE is renamed to CFG_TUD_HID_EP_BUFSIZE + // #warning CFG_TUD_HID_BUFSIZE is renamed to CFG_TUD_HID_EP_BUFSIZE, please update to use the new name #define CFG_TUD_HID_EP_BUFSIZE CFG_TUD_HID_BUFSIZE #endif diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 8f60d264a..1828a21a3 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -36,7 +36,13 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUD_MIDI_EPSIZE + +#if !defined(CFG_TUD_MIDI_EP_BUFSIZE) && defined(CFG_TUD_MIDI_EPSIZE) + #warning CFG_TUD_MIDI_EPSIZE is renamed to CFG_TUD_MIDI_EP_BUFSIZE, please update to use the new name + #define CFG_TUD_MIDI_EP_BUFSIZE CFG_TUD_MIDI_EPSIZE +#endif + +#ifndef CFG_TUD_MIDI_EP_BUFSIZE #define CFG_TUD_MIDI_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 995491ec4..3aa93ffd7 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -41,7 +41,7 @@ #if !defined(CFG_TUD_MSC_EP_BUFSIZE) & defined(CFG_TUD_MSC_BUFSIZE) // TODO warn user to use new name later on - // #warning CFG_TUD_MSC_BUFSIZE is renamed to CFG_TUD_MSC_EP_BUFSIZE + // #warning CFG_TUD_MSC_BUFSIZE is renamed to CFG_TUD_MSC_EP_BUFSIZE, please update to use the new name #define CFG_TUD_MSC_EP_BUFSIZE CFG_TUD_MSC_BUFSIZE #endif -- cgit v1.3.1 From 47bcedc0b4744d3554f385906414005b511e9ae4 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 18 Jul 2020 19:27:00 +0200 Subject: Add A.17.4 - Terminal Control Selectors --- src/class/audio/audio.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index f1784a006..301a26b2e 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -162,6 +162,19 @@ typedef enum AUDIO_CLK_SRC_CTRL_CLK_VALID = 0x02, } audio_clock_src_control_selector_t; +/// A.17.4 - Terminal Control Selectors +typedef enum +{ + AUDIO_TERMINAL_CTRL_UNDEF = 0x00, + AUDIO_TERMINAL_CTRL_COPY_PROTECT = 0x01, + AUDIO_TERMINAL_CTRL_CONNECTOR = 0x02, + AUDIO_TERMINAL_CTRL_OVERLOAD = 0x03, + AUDIO_TERMINAL_CTRL_CLUSTER = 0x04, + AUDIO_TERMINAL_CTRL_UNDERFLOW = 0x05, + AUDIO_TERMINAL_CTRL_OVERFLOW = 0x06, + AUDIO_TERMINAL_CTRL_LATENCY = 0x07, +} audio_terminal_control_selector_t; + /// A.17.7 - Feature Unit Control Selectors typedef enum { -- cgit v1.3.1 From 077e881c92c0704c53ede854f50701c3ba6dd921 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 19 Jul 2020 11:53:35 +0200 Subject: Implement all missing A.17 control selectors --- src/class/audio/audio.h | 253 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 241 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 301a26b2e..011f5381b 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -157,24 +157,58 @@ typedef enum /// A.17.1 - Clock Source Control Selectors typedef enum { - AUDIO_CLK_SRC_CTRL_UNDEF = 0x00, - AUDIO_CLK_SRC_CTRL_SAM_FREQ = 0x01, - AUDIO_CLK_SRC_CTRL_CLK_VALID = 0x02, + AUDIO_CS_CTRL_UNDEF = 0x00, + AUDIO_CS_CTRL_SAM_FREQ = 0x01, + AUDIO_CS_CTRL_CLK_VALID = 0x02, } audio_clock_src_control_selector_t; +/// A.17.2 - Clock Selector Control Selectors +typedef enum +{ + AUDIO_CX_CTRL_UNDEF = 0x00, + AUDIO_CX_CTRL_CONTROL = 0x01, +} audio_clock_sel_control_selector_t; + +/// A.17.3 - Clock Multiplier Control Selectors +typedef enum +{ + AUDIO_CM_CTRL_UNDEF = 0x00, + AUDIO_CM_CTRL_NUMERATOR_CONTROL = 0x01, + AUDIO_CM_CTRL_DENOMINATOR_CONTROL = 0x02, +} audio_clock_mul_control_selector_t; + /// A.17.4 - Terminal Control Selectors typedef enum { - AUDIO_TERMINAL_CTRL_UNDEF = 0x00, - AUDIO_TERMINAL_CTRL_COPY_PROTECT = 0x01, - AUDIO_TERMINAL_CTRL_CONNECTOR = 0x02, - AUDIO_TERMINAL_CTRL_OVERLOAD = 0x03, - AUDIO_TERMINAL_CTRL_CLUSTER = 0x04, - AUDIO_TERMINAL_CTRL_UNDERFLOW = 0x05, - AUDIO_TERMINAL_CTRL_OVERFLOW = 0x06, - AUDIO_TERMINAL_CTRL_LATENCY = 0x07, + AUDIO_TE_CTRL_UNDEF = 0x00, + AUDIO_TE_CTRL_COPY_PROTECT = 0x01, + AUDIO_TE_CTRL_CONNECTOR = 0x02, + AUDIO_TE_CTRL_OVERLOAD = 0x03, + AUDIO_TE_CTRL_CLUSTER = 0x04, + AUDIO_TE_CTRL_UNDERFLOW = 0x05, + AUDIO_TE_CTRL_OVERFLOW = 0x06, + AUDIO_TE_CTRL_LATENCY = 0x07, } audio_terminal_control_selector_t; +/// A.17.5 - Mixer Control Selectors +typedef enum +{ + AUDIO_MU_CTRL_UNDEF = 0x00, + AUDIO_MU_CTRL_MIXER = 0x01, + AUDIO_MU_CTRL_CLUSTER = 0x02, + AUDIO_MU_CTRL_UNDERFLOW = 0x03, + AUDIO_MU_CTRL_OVERFLOW = 0x04, + AUDIO_MU_CTRL_LATENCY = 0x05, +} audio_mixer_control_selector_t; + +/// A.17.6 - Selector Control Selectors +typedef enum +{ + AUDIO_SU_CTRL_UNDEF = 0x00, + AUDIO_SU_CTRL_SELECTOR = 0x01, + AUDIO_SU_CTRL_LATENCY = 0x02, +} audio_sel_control_selector_t; + /// A.17.7 - Feature Unit Control Selectors typedef enum { @@ -197,7 +231,202 @@ typedef enum AUDIO_FU_CTRL_LATENCY = 0x10, } audio_feature_unit_control_selector_t; -// Rest is yet to be implemented! +/// A.17.8 Effect Unit Control Selectors + +/// A.17.8.1 Parametric Equalizer Section Effect Unit Control Selectors +typedef enum +{ + AUDIO_PE_CTRL_UNDEF = 0x00, + AUDIO_PE_CTRL_ENABLE = 0x01, + AUDIO_PE_CTRL_CENTERFREQ = 0x02, + AUDIO_PE_CTRL_QFACTOR = 0x03, + AUDIO_PE_CTRL_GAIN = 0x04, + AUDIO_PE_CTRL_UNDERFLOW = 0x05, + AUDIO_PE_CTRL_OVERFLOW = 0x06, + AUDIO_PE_CTRL_LATENCY = 0x07, +} audio_parametric_equalizer_control_selector_t; + +/// A.17.8.2 Reverberation Effect Unit Control Selectors +typedef enum +{ + AUDIO_RV_CTRL_UNDEF = 0x00, + AUDIO_RV_CTRL_ENABLE = 0x01, + AUDIO_RV_CTRL_TYPE = 0x02, + AUDIO_RV_CTRL_LEVEL = 0x03, + AUDIO_RV_CTRL_TIME = 0x04, + AUDIO_RV_CTRL_FEEDBACK = 0x05, + AUDIO_RV_CTRL_PREDELAY = 0x06, + AUDIO_RV_CTRL_DENSITY = 0x07, + AUDIO_RV_CTRL_HIFREQ_ROLLOFF = 0x08, + AUDIO_RV_CTRL_UNDERFLOW = 0x09, + AUDIO_RV_CTRL_OVERFLOW = 0x0A, + AUDIO_RV_CTRL_LATENCY = 0x0B, +} audio_reverberation_effect_control_selector_t; + +/// A.17.8.3 Modulation Delay Effect Unit Control Selectors +typedef enum +{ + AUDIO_MD_CTRL_UNDEF = 0x00, + AUDIO_MD_CTRL_ENABLE = 0x01, + AUDIO_MD_CTRL_BALANCE = 0x02, + AUDIO_MD_CTRL_RATE = 0x03, + AUDIO_MD_CTRL_DEPTH = 0x04, + AUDIO_MD_CTRL_TIME = 0x05, + AUDIO_MD_CTRL_FEEDBACK = 0x06, + AUDIO_MD_CTRL_UNDERFLOW = 0x07, + AUDIO_MD_CTRL_OVERFLOW = 0x08, + AUDIO_MD_CTRL_LATENCY = 0x09, +} audio_modulation_delay_control_selector_t; + +/// A.17.8.4 Dynamic Range Compressor Effect Unit Control Selectors +typedef enum +{ + AUDIO_DR_CTRL_UNDEF = 0x00, + AUDIO_DR_CTRL_ENABLE = 0x01, + AUDIO_DR_CTRL_COMPRESSION_RATE = 0x02, + AUDIO_DR_CTRL_MAXAMPL = 0x03, + AUDIO_DR_CTRL_THRESHOLD = 0x04, + AUDIO_DR_CTRL_ATTACK_TIME = 0x05, + AUDIO_DR_CTRL_RELEASE_TIME = 0x06, + AUDIO_DR_CTRL_UNDERFLOW = 0x07, + AUDIO_DR_CTRL_OVERFLOW = 0x08, + AUDIO_DR_CTRL_LATENCY = 0x09, +} audio_dynamic_range_compression_control_selector_t; + +/// A.17.9 Processing Unit Control Selectors + +/// A.17.9.1 Up/Down-mix Processing Unit Control Selectors +typedef enum +{ + AUDIO_UD_CTRL_UNDEF = 0x00, + AUDIO_UD_CTRL_ENABLE = 0x01, + AUDIO_UD_CTRL_MODE_SELECT = 0x02, + AUDIO_UD_CTRL_CLUSTER = 0x03, + AUDIO_UD_CTRL_UNDERFLOW = 0x04, + AUDIO_UD_CTRL_OVERFLOW = 0x05, + AUDIO_UD_CTRL_LATENCY = 0x06, +} audio_up_down_mix_control_selector_t; + +/// A.17.9.2 Dolby Prologic ™ Processing Unit Control Selectors +typedef enum +{ + AUDIO_DP_CTRL_UNDEF = 0x00, + AUDIO_DP_CTRL_ENABLE = 0x01, + AUDIO_DP_CTRL_MODE_SELECT = 0x02, + AUDIO_DP_CTRL_CLUSTER = 0x03, + AUDIO_DP_CTRL_UNDERFLOW = 0x04, + AUDIO_DP_CTRL_OVERFLOW = 0x05, + AUDIO_DP_CTRL_LATENCY = 0x06, +} audio_dolby_prologic_control_selector_t; + +/// A.17.9.3 Stereo Extender Processing Unit Control Selectors +typedef enum +{ + AUDIO_ST_EXT_CTRL_UNDEF = 0x00, + AUDIO_ST_EXT_CTRL_ENABLE = 0x01, + AUDIO_ST_EXT_CTRL_WIDTH = 0x02, + AUDIO_ST_EXT_CTRL_UNDERFLOW = 0x03, + AUDIO_ST_EXT_CTRL_OVERFLOW = 0x04, + AUDIO_ST_EXT_CTRL_LATENCY = 0x05, +} audio_stereo_extender_control_selector_t; + +/// A.17.10 Extension Unit Control Selectors +typedef enum +{ + AUDIO_XU_CTRL_UNDEF = 0x00, + AUDIO_XU_CTRL_ENABLE = 0x01, + AUDIO_XU_CTRL_CLUSTER = 0x02, + AUDIO_XU_CTRL_UNDERFLOW = 0x03, + AUDIO_XU_CTRL_OVERFLOW = 0x04, + AUDIO_XU_CTRL_LATENCY = 0x05, +} audio_extension_unit_control_selector_t; + +/// A.17.11 AudioStreaming Interface Control Selectors +typedef enum +{ + AUDIO_AS_CTRL_UNDEF = 0x00, + AUDIO_AS_CTRL_ACT_ALT_SETTING = 0x01, + AUDIO_AS_CTRL_VAL_ALT_SETTINGS = 0x02, + AUDIO_AS_CTRL_AUDIO_DATA_FORMAT = 0x03, +} audio_audiostreaming_interface_control_selector_t; + +/// A.17.12 Encoder Control Selectors +typedef enum +{ + AUDIO_EN_CTRL_UNDEF = 0x00, + AUDIO_EN_CTRL_BIT_RATE = 0x01, + AUDIO_EN_CTRL_QUALITY = 0x02, + AUDIO_EN_CTRL_VBR = 0x03, + AUDIO_EN_CTRL_TYPE = 0x04, + AUDIO_EN_CTRL_UNDERFLOW = 0x05, + AUDIO_EN_CTRL_OVERFLOW = 0x06, + AUDIO_EN_CTRL_ENCODER_ERROR = 0x07, + AUDIO_EN_CTRL_PARAM1 = 0x08, + AUDIO_EN_CTRL_PARAM2 = 0x09, + AUDIO_EN_CTRL_PARAM3 = 0x0A, + AUDIO_EN_CTRL_PARAM4 = 0x0B, + AUDIO_EN_CTRL_PARAM5 = 0x0C, + AUDIO_EN_CTRL_PARAM6 = 0x0D, + AUDIO_EN_CTRL_PARAM7 = 0x0E, + AUDIO_EN_CTRL_PARAM8 = 0x0F, +} audio_encoder_control_selector_t; + +/// A.17.13 Decoder Control Selectors + +/// A.17.13.1 MPEG Decoder Control Selectors +typedef enum +{ + AUDIO_MPD_CTRL_UNDEF = 0x00, + AUDIO_MPD_CTRL_DUAL_CHANNEL = 0x01, + AUDIO_MPD_CTRL_SECOND_STEREO = 0x02, + AUDIO_MPD_CTRL_MULTILINGUAL = 0x03, + AUDIO_MPD_CTRL_DYN_RANGE = 0x04, + AUDIO_MPD_CTRL_SCALING = 0x05, + AUDIO_MPD_CTRL_HILO_SCALING = 0x06, + AUDIO_MPD_CTRL_UNDERFLOW = 0x07, + AUDIO_MPD_CTRL_OVERFLOW = 0x08, + AUDIO_MPD_CTRL_DECODER_ERROR = 0x09, +} audio_MPEG_decoder_control_selector_t; + +/// A.17.13.2 AC-3 Decoder Control Selectors +typedef enum +{ + AUDIO_AD_CTRL_UNDEF = 0x00, + AUDIO_AD_CTRL_MODE = 0x01, + AUDIO_AD_CTRL_DYN_RANGE = 0x02, + AUDIO_AD_CTRL_SCALING = 0x03, + AUDIO_AD_CTRL_HILO_SCALING = 0x04, + AUDIO_AD_CTRL_UNDERFLOW = 0x05, + AUDIO_AD_CTRL_OVERFLOW = 0x06, + AUDIO_AD_CTRL_DECODER_ERROR = 0x07, +} audio_AC3_decoder_control_selector_t; + +/// A.17.13.3 WMA Decoder Control Selectors +typedef enum +{ + AUDIO_WD_CTRL_UNDEF = 0x00, + AUDIO_WD_CTRL_UNDERFLOW = 0x01, + AUDIO_WD_CTRL_OVERFLOW = 0x02, + AUDIO_WD_CTRL_DECODER_ERROR = 0x03, +} audio_WMA_decoder_control_selector_t; + +/// A.17.13.4 DTS Decoder Control Selectors +typedef enum +{ + AUDIO_DD_CTRL_UNDEF = 0x00, + AUDIO_DD_CTRL_UNDERFLOW = 0x01, + AUDIO_DD_CTRL_OVERFLOW = 0x02, + AUDIO_DD_CTRL_DECODER_ERROR = 0x03, +} audio_DTS_decoder_control_selector_t; + +/// A.17.14 Endpoint Control Selectors +typedef enum +{ + AUDIO_EP_CTRL_UNDEF = 0x00, + AUDIO_EP_CTRL_PITCH = 0x01, + AUDIO_EP_CTRL_DATA_OVERRUN = 0x02, + AUDIO_EP_CTRL_DATA_UNDERRUN = 0x03, +} audio_EP_control_selector_t; /// Terminal Types -- cgit v1.3.1 From 5cd654838ba590ab49b637ead744cc0bae671946 Mon Sep 17 00:00:00 2001 From: Chang Feng Date: Sun, 19 Jul 2020 19:13:17 +0800 Subject: Remove 0xEE index string if statement & change TU_ASSERT to TU_VERIFY Signed-off-by: Chang Feng --- src/device/usbd.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index b607f5939..afd46b8ce 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -886,20 +886,11 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_LOG2(" String[%u]\r\n", desc_index); // String Descriptor always uses the desc set from user - if ( desc_index == 0xEE ) - { - // The 0xEE index string is a Microsoft OS Descriptors. - // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - return false; - } - else - { - uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex); - TU_ASSERT(desc_str); + uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex); + TU_VERIFY(desc_str); - // first byte of descriptor is its size - return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]); - } + // first byte of descriptor is its size + return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]); break; case TUSB_DESC_DEVICE_QUALIFIER: -- cgit v1.3.1 From 3822a6a385a99c88e1fb9f6293be9d2a84556a25 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Sun, 19 Jul 2020 23:55:35 +0300 Subject: FreeRTOS: Yield from ISR to notify the USB task If we do not yeld in ISR when we write to queue/give semaphore, the scheduler will not know of the change and will not check the queue untill the next OS tick. This change causes the task to be called immediately and makes communication many times faster. --- src/osal/osal_freertos.h | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 42ea1fd19..416065eeb 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -32,6 +32,7 @@ #include "semphr.h" #include "queue.h" #include "task.h" +#include "tusb_option.h" #ifdef __cplusplus extern "C" { @@ -58,7 +59,19 @@ static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semde static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { - return in_isr ? xSemaphoreGiveFromISR(sem_hdl, NULL) : xSemaphoreGive(sem_hdl); + if(!in_isr){ + return xSemaphoreGive(sem_hdl) != 0; + } + BaseType_t xHigherPriorityTaskWoken; + BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken); +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 + if (xHigherPriorityTaskWoken) { + portYIELD_FROM_ISR(); + } +#else + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +#endif + return res != 0; } static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) @@ -125,7 +138,19 @@ static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) { - return in_isr ? xQueueSendToBackFromISR(qhdl, data, NULL) : xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER); + if(!in_isr){ + return xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER) != 0; + } + BaseType_t xHigherPriorityTaskWoken; + BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken); +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 + if (xHigherPriorityTaskWoken) { + portYIELD_FROM_ISR(); + } +#else + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +#endif + return res != 0; } static inline bool osal_queue_empty(osal_queue_t qhdl) -- cgit v1.3.1 From fdb156a3bb1eb4bc223dbca1dd287c7eff7a8e7c Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 20 Jul 2020 20:18:45 +0200 Subject: Implement control EP0 buffer and get rid of CFG_TUD_AUDIO_USE_TX_FIFO --- src/class/audio/audio_device.c | 78 +++++++++++++++++++++++------------------- src/class/audio/audio_device.h | 45 +++++++++++------------- 2 files changed, 62 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 67c94837a..7e7fef19f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -73,18 +73,22 @@ typedef struct uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; #endif /*------------- From this point, data is not cleared by bus reset -------------*/ + + // Buffer for control requests + CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_AUDIO_CTRL_BUF_SIZE]; + // FIFO -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; - CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_FIFO_SIZE]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; #endif #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; - CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_FIFO_SIZE]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; #endif @@ -119,19 +123,21 @@ typedef struct } audiod_interface_t; -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_USE_TX_FIFO -#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, tx_ff) -#elif CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO -#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, rx_ff) -#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, int_ctr_ff) -#elif CFG_TUD_AUDIO_EPSIZE_OUT -#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epout_buf) -#elif CFG_TUD_AUDIO_EPSIZE_IN -#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epin_buf) -#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ep_int_ctr_buf) -#endif +#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ctrl_buf) + +//#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE +//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, tx_ff) +//#elif CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE +//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, rx_ff) +//#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, int_ctr_ff) +//#elif CFG_TUD_AUDIO_EPSIZE_OUT +//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epout_buf) +//#elif CFG_TUD_AUDIO_EPSIZE_IN +//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epin_buf) +//#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ep_int_ctr_buf) +//#endif //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION @@ -195,7 +201,7 @@ bool tud_audio_n_mounted(uint8_t itf) // READ API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId) { @@ -237,7 +243,7 @@ void tud_audio_int_ctr_n_read_flush (uint8_t itf) #endif // This function is called once something is received by USB and is responsible for decoding received stream into audio channels. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_USE_RX_FIFO = 0. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_FIFO_SIZE = 0. #if CFG_TUD_AUDIO_EPSIZE_OUT @@ -256,7 +262,7 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* { case AUDIO_DATA_FORMAT_TYPE_I_PCM: -#if CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_RX_FIFO_SIZE TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); #else #error YOUR DECODING AND BUFFERING IS REQUIRED HERE! @@ -283,8 +289,8 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* #endif //CFG_TUD_AUDIO_EPSIZE_OUT -// The following functions are used in case CFG_TUD_AUDIO_USE_RX_FIFO == 1 -#if CFG_TUD_AUDIO_USE_RX_FIFO +// The following functions are used in case CFG_TUD_AUDIO_RX_FIFO_SIZE != 0 +#if CFG_TUD_AUDIO_RX_FIFO_SIZE static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize) { (void) rhport; @@ -320,7 +326,7 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a } } } } -#endif //CFG_TUD_AUDIO_USE_RX_FIFO +#endif //CFG_TUD_AUDIO_RX_FIFO_SIZE #if CFG_TUD_AUDIO_EPSIZE_OUT @@ -342,7 +348,7 @@ TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_ // WRITE API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) { audiod_interface_t* audio = &_audiod_itf[itf]; @@ -370,7 +376,7 @@ uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_USE_TX_FIFO = 0. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_FIFO_SIZE = 0. #if CFG_TUD_AUDIO_EPSIZE_IN static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) { @@ -387,7 +393,7 @@ static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t { case AUDIO_DATA_FORMAT_TYPE_I_PCM: -#if CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_TX_FIFO_SIZE TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); #else #error YOUR ENCODING AND BUFFERING IS REQUIRED HERE! @@ -414,7 +420,7 @@ static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t #endif //CFG_TUD_AUDIO_EPSIZE_IN -#if CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_TX_FIFO_SIZE static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) { // We encode directly into IN EP's buffer - abort if previous transfer not complete @@ -478,7 +484,7 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a return true; } -#endif //CFG_TUD_AUDIO_USE_TX_FIFO +#endif //CFG_TUD_AUDIO_TX_FIFO_SIZE // This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent @@ -580,20 +586,20 @@ void audiod_init(void) audiod_interface_t* audio = &_audiod_itf[i]; // Initialize TX FIFOs if required -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { - tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_BUFSIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true); + tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); #endif } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { - tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_BUFSIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true); + tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); #endif @@ -619,14 +625,14 @@ void audiod_reset(uint8_t rhport) tu_memclr(audio, ITF_MEM_RESET_SIZE); uint8_t cnt; -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { tu_fifo_clear(&audio->tx_ff[cnt]); } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { tu_fifo_clear(&audio->rx_ff[cnt]); @@ -1376,7 +1382,7 @@ static bool audiod_verify_ep_exists(uint8_t ep) // //#if CFG_TUD_AUDIO_FORMAT_TYPE_I_TX == AUDIO_DATA_FORMAT_TYPE_I_PCM // -//#if CFG_TUD_AUDIO_USE_TX_FIFO +//#if CFG_TUD_AUDIO_TX_FIFO_SIZE // TU_VERIFY(audio_tx_done_type_I_pcm_cb(rhport, audio, n_bytes_copied)); //#else //#error YOUR ENCODING AND SENDING IS REQUIRED HERE! @@ -1407,7 +1413,7 @@ static bool audiod_verify_ep_exists(uint8_t ep) // //#if CFG_TUD_AUDIO_FORMAT_TYPE_I_RX == AUDIO_DATA_FORMAT_TYPE_I_PCM // -//#if CFG_TUD_AUDIO_USE_RX_FIFO +//#if CFG_TUD_AUDIO_RX_FIFO_SIZE // TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); //#else //#error YOUR DECODING AND BUFFERING IS REQUIRED HERE! diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 95b361acd..cc757d451 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -43,16 +43,23 @@ #define CFG_TUD_AUDIO_N_AS_INT 0 #endif -// Use internal FIFOs - In this case, audio.c implements FIFOs for RX and TX (whatever required) and implements encoding and decoding (parameterized by the defines below). +// Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors +#ifndef CFG_TUD_AUDIO_CTRL_BUF_SIZE +#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 +#endif + +// Use of TX/RX FIFOs - If sizes are not zero, audio.c implements FIFOs for RX and TX (whatever defined). // For RX: the input stream gets decoded into its corresponding channels, where for each channel a FIFO is setup to hold its data -> see: audio_rx_done_cb(). // For TX: the output stream is composed from CFG_TUD_AUDIO_N_CHANNELS_TX channels, where for each channel a FIFO is defined. -// If you disable this you need to fill in desired code into audio_rx_done_cb() and Y on your own, however, this allows for optimizations in byte processing. -#ifndef CFG_TUD_AUDIO_USE_RX_FIFO -#define CFG_TUD_AUDIO_USE_RX_FIFO 0 +// Further, it implements encoding and decoding of the individual channels (parameterized by the defines below). +// If you don't use the FIFOs you need to handle encoding and decoding on your own in audio_rx_done_cb() and Y. This, however, allows for optimizations. + +#ifndef CFG_TUD_AUDIO_TX_FIFO_SIZE +#define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel #endif -#ifndef CFG_TUD_AUDIO_USE_TX_FIFO -#define CFG_TUD_AUDIO_USE_TX_FIFO 0 +#ifndef CFG_TUD_AUDIO_RX_FIFO_SIZE +#define CFG_TUD_AUDIO_RX_FIFO_SIZE 0 // Buffer size per channel #endif // End point sizes - Limits: Full Speed <= 1023, High Speed <= 1024 @@ -60,22 +67,10 @@ #define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX #endif -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 -#ifndef CFG_TUD_AUDIO_TX_BUFSIZE -#define CFG_TUD_AUDIO_TX_BUFSIZE CFG_TUD_AUDIO_EPSIZE_IN // Buffer size per channel -#endif -#endif - #ifndef CFG_TUD_AUDIO_EPSIZE_OUT #define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 -#ifndef CFG_TUD_AUDIO_RX_BUFSIZE -#define CFG_TUD_AUDIO_RX_BUFSIZE CFG_TUD_AUDIO_EPSIZE_OUT // Buffer size per channel -#endif -#endif - #ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP #define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback #endif @@ -169,13 +164,13 @@ extern "C" { //--------------------------------------------------------------------+ bool tud_audio_n_mounted (uint8_t itf); -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE uint16_t tud_audio_n_available (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); #endif @@ -192,13 +187,13 @@ uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16 inline bool tud_audio_mounted (void); -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE inline uint16_t tud_audio_available (void); inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); inline void tud_audio_read_flush (void); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); #endif @@ -259,14 +254,14 @@ inline bool tud_audio_mounted(void) return tud_audio_n_mounted(0); } -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used { return tud_audio_n_write(0, channelId, buffer, bufsize); } -#endif // CFG_TUD_AUDIO_EPSIZE_IN > 0 && CFG_TUD_AUDIO_USE_TX_FIFO +#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_USE_RX_FIFO +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE inline uint16_t tud_audio_available(uint8_t channelId) { return tud_audio_n_available(0, channelId); -- cgit v1.3.1 From 141db1278aabd9a5d508450752fd5df79759747c Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 20 Jul 2020 20:24:05 +0200 Subject: Make definition of CFG_TUD_AUDIO_CTRL_BUF_SIZE mandatory --- src/class/audio/audio_device.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index cc757d451..8494281c4 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -45,7 +45,7 @@ // Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors #ifndef CFG_TUD_AUDIO_CTRL_BUF_SIZE -#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 +#error You must define an audio class control request buffer size! #endif // Use of TX/RX FIFOs - If sizes are not zero, audio.c implements FIFOs for RX and TX (whatever defined). @@ -79,7 +79,7 @@ #define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN #ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE #define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) #endif -- cgit v1.3.1 From dfca92d29b8f984ebe5f4752154fd8187ec24120 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 21 Jul 2020 21:06:10 +0700 Subject: follow up to pr468 --- src/osal/osal_freertos.h | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 416065eeb..004bd1b6b 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -32,7 +32,6 @@ #include "semphr.h" #include "queue.h" #include "task.h" -#include "tusb_option.h" #ifdef __cplusplus extern "C" { @@ -59,19 +58,23 @@ static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semde static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { - if(!in_isr){ + if ( !in_isr ) + { return xSemaphoreGive(sem_hdl) != 0; } - BaseType_t xHigherPriorityTaskWoken; - BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken); + else + { + BaseType_t xHigherPriorityTaskWoken; + BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken); + #if CFG_TUSB_MCU == OPT_MCU_ESP32S2 - if (xHigherPriorityTaskWoken) { - portYIELD_FROM_ISR(); - } + if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); #else - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); #endif - return res != 0; + + return res != 0; + } } static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) @@ -138,19 +141,23 @@ static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) { - if(!in_isr){ + if ( !in_isr ) + { return xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER) != 0; } - BaseType_t xHigherPriorityTaskWoken; - BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken); + else + { + BaseType_t xHigherPriorityTaskWoken; + BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken); + #if CFG_TUSB_MCU == OPT_MCU_ESP32S2 - if (xHigherPriorityTaskWoken) { - portYIELD_FROM_ISR(); - } + if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); #else - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); #endif - return res != 0; + + return res != 0; + } } static inline bool osal_queue_empty(osal_queue_t qhdl) -- cgit v1.3.1 From 0407cfe16c7b9736da2ff36c69232e7c3f470864 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 23 Jul 2020 01:39:15 +0700 Subject: fix samd21 race condition with setup packet reproduced with Adafruit_TinyUSB_ArduinoCore port commit 11d669b4d2a40eb2fc5e51b2a9707a6de9d42363 and SAMD BSP 1.6.1 --- examples/make.mk | 54 ++++++++++++++++------------------ hw/bsp/feather_m0_express/board.mk | 10 +++++-- hw/bsp/feather_m4_express/board.mk | 10 +++++-- hw/bsp/itsybitsy_m0/board.mk | 10 +++++-- hw/bsp/itsybitsy_m4/board.mk | 10 +++++-- hw/bsp/metro_m0_express/board.mk | 10 +++++-- hw/bsp/metro_m4_express/board.mk | 10 +++++-- src/portable/microchip/samd/dcd_samd.c | 2 ++ 8 files changed, 76 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/examples/make.mk b/examples/make.mk index 2ea50753b..b7917987e 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -46,31 +46,32 @@ SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/hw/bsp/$(BOARD)/*.c)) # Compiler Flags CFLAGS += \ - -fdata-sections \ - -ffunction-sections \ - -fsingle-precision-constant \ - -fno-strict-aliasing \ - -Wdouble-promotion \ - -Wstrict-prototypes \ - -Wall \ - -Wextra \ - -Werror \ - -Wfatal-errors \ - -Werror-implicit-function-declaration \ - -Wfloat-equal \ - -Wundef \ - -Wshadow \ - -Wwrite-strings \ - -Wsign-compare \ - -Wmissing-format-attribute \ - -Wunreachable-code \ - -Wcast-align - + -ggdb \ + -fdata-sections \ + -ffunction-sections \ + -fsingle-precision-constant \ + -fno-strict-aliasing \ + -Wdouble-promotion \ + -Wstrict-prototypes \ + -Wall \ + -Wextra \ + -Werror \ + -Wfatal-errors \ + -Werror-implicit-function-declaration \ + -Wfloat-equal \ + -Wundef \ + -Wshadow \ + -Wwrite-strings \ + -Wsign-compare \ + -Wmissing-format-attribute \ + -Wunreachable-code \ + -Wcast-align + # Debugging/Optimization ifeq ($(DEBUG), 1) - CFLAGS += -Og -ggdb + CFLAGS += -Og else - CFLAGS += -Os + CFLAGS += -Os endif # Log level is mapped to TUSB DEBUG option @@ -80,14 +81,11 @@ endif # Logger: default is uart, can be set to rtt or swo ifeq ($(LOGGER),rtt) - RTT_SRC = lib/SEGGER_RTT - - CFLAGS += -DLOGGER_RTT -DSEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL + RTT_SRC = lib/SEGGER_RTT + CFLAGS += -DLOGGER_RTT -DSEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL INC += $(TOP)/$(RTT_SRC)/RTT SRC_C += $(RTT_SRC)/RTT/SEGGER_RTT_printf.c SRC_C += $(RTT_SRC)/RTT/SEGGER_RTT.c - else ifeq ($(LOGGER),swo) - CFLAGS += -DLOGGER_SWO - + CFLAGS += -DLOGGER_SWO endif diff --git a/hw/bsp/feather_m0_express/board.mk b/hw/bsp/feather_m0_express/board.mk index d762c4eca..7b6891e03 100644 --- a/hw/bsp/feather_m0_express/board.mk +++ b/hw/bsp/feather_m0_express/board.mk @@ -41,5 +41,11 @@ FREERTOS_PORT = ARM_CM0 JLINK_DEVICE = ATSAMD21G18 JLINK_IF = swd -# flash using jlink -flash: flash-jlink +# flash using bossac at least version 1.8 +# can be found in arduino15/packages/arduino/tools/bossac/ +# Add it to your PATH or change BOSSAC variable to match your installation +BOSSAC = bossac + +flash: $(BUILD)/$(BOARD)-firmware.bin + @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) + $(BOSSAC) --port=$(SERIAL) -U -i --offset=0x2000 -e -w $^ -R diff --git a/hw/bsp/feather_m4_express/board.mk b/hw/bsp/feather_m4_express/board.mk index 49c2d7f2f..34c98597c 100644 --- a/hw/bsp/feather_m4_express/board.mk +++ b/hw/bsp/feather_m4_express/board.mk @@ -44,5 +44,11 @@ FREERTOS_PORT = ARM_CM4F JLINK_DEVICE = ATSAMD51J19 JLINK_IF = swd -# flash using jlink -flash: flash-jlink +# flash using bossac at least version 1.8 +# can be found in arduino15/packages/arduino/tools/bossac/ +# Add it to your PATH or change BOSSAC variable to match your installation +BOSSAC = bossac + +flash: $(BUILD)/$(BOARD)-firmware.bin + @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) + $(BOSSAC) --port=$(SERIAL) -U -i --offset=0x4000 -e -w $^ -R diff --git a/hw/bsp/itsybitsy_m0/board.mk b/hw/bsp/itsybitsy_m0/board.mk index d762c4eca..7b6891e03 100644 --- a/hw/bsp/itsybitsy_m0/board.mk +++ b/hw/bsp/itsybitsy_m0/board.mk @@ -41,5 +41,11 @@ FREERTOS_PORT = ARM_CM0 JLINK_DEVICE = ATSAMD21G18 JLINK_IF = swd -# flash using jlink -flash: flash-jlink +# flash using bossac at least version 1.8 +# can be found in arduino15/packages/arduino/tools/bossac/ +# Add it to your PATH or change BOSSAC variable to match your installation +BOSSAC = bossac + +flash: $(BUILD)/$(BOARD)-firmware.bin + @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) + $(BOSSAC) --port=$(SERIAL) -U -i --offset=0x2000 -e -w $^ -R diff --git a/hw/bsp/itsybitsy_m4/board.mk b/hw/bsp/itsybitsy_m4/board.mk index 49c2d7f2f..34c98597c 100644 --- a/hw/bsp/itsybitsy_m4/board.mk +++ b/hw/bsp/itsybitsy_m4/board.mk @@ -44,5 +44,11 @@ FREERTOS_PORT = ARM_CM4F JLINK_DEVICE = ATSAMD51J19 JLINK_IF = swd -# flash using jlink -flash: flash-jlink +# flash using bossac at least version 1.8 +# can be found in arduino15/packages/arduino/tools/bossac/ +# Add it to your PATH or change BOSSAC variable to match your installation +BOSSAC = bossac + +flash: $(BUILD)/$(BOARD)-firmware.bin + @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) + $(BOSSAC) --port=$(SERIAL) -U -i --offset=0x4000 -e -w $^ -R diff --git a/hw/bsp/metro_m0_express/board.mk b/hw/bsp/metro_m0_express/board.mk index d762c4eca..7b6891e03 100644 --- a/hw/bsp/metro_m0_express/board.mk +++ b/hw/bsp/metro_m0_express/board.mk @@ -41,5 +41,11 @@ FREERTOS_PORT = ARM_CM0 JLINK_DEVICE = ATSAMD21G18 JLINK_IF = swd -# flash using jlink -flash: flash-jlink +# flash using bossac at least version 1.8 +# can be found in arduino15/packages/arduino/tools/bossac/ +# Add it to your PATH or change BOSSAC variable to match your installation +BOSSAC = bossac + +flash: $(BUILD)/$(BOARD)-firmware.bin + @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) + $(BOSSAC) --port=$(SERIAL) -U -i --offset=0x2000 -e -w $^ -R diff --git a/hw/bsp/metro_m4_express/board.mk b/hw/bsp/metro_m4_express/board.mk index 49c2d7f2f..34c98597c 100644 --- a/hw/bsp/metro_m4_express/board.mk +++ b/hw/bsp/metro_m4_express/board.mk @@ -44,5 +44,11 @@ FREERTOS_PORT = ARM_CM4F JLINK_DEVICE = ATSAMD51J19 JLINK_IF = swd -# flash using jlink -flash: flash-jlink +# flash using bossac at least version 1.8 +# can be found in arduino15/packages/arduino/tools/bossac/ +# Add it to your PATH or change BOSSAC variable to match your installation +BOSSAC = bossac + +flash: $(BUILD)/$(BOARD)-firmware.bin + @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) + $(BOSSAC) --port=$(SERIAL) -U -i --offset=0x4000 -e -w $^ -R diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 45bff2511..d0cc8560a 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -43,6 +43,8 @@ static inline void prepare_setup(void) { // Only make sure the EP0 OUT buffer is ready sram_registers[0][0].ADDR.reg = (uint32_t) _setup_packet; + sram_registers[0][0].PCKSIZE.bit.MULTI_PACKET_SIZE = sizeof(_setup_packet); + sram_registers[0][0].PCKSIZE.bit.BYTE_COUNT = 0; } // Setup the control endpoint 0. -- cgit v1.3.1 From 503c15217edad86426db4792364b88b35ec04d31 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 23 Jul 2020 09:20:45 +0700 Subject: example to call tud_init() after freeRTOS kernel is started add note for usb init when using with RTOS --- examples/device/cdc_msc_freertos/src/main.c | 5 ++++- examples/device/hid_composite_freertos/src/main.c | 5 ++++- src/device/usbd.h | 2 ++ src/host/usbh.h | 3 +++ src/tusb.h | 2 ++ 5 files changed, 15 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index a847f4915..1371b84c3 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -83,7 +83,6 @@ void cdc_task(void* params); int main(void) { board_init(); - tusb_init(); // soft timer for blinky blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); @@ -116,6 +115,10 @@ void usb_device_task(void* param) { (void) param; + // This should be called after scheduler/kernel is started. + // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tusb_init(); + // RTOS forever loop while (1) { diff --git a/examples/device/hid_composite_freertos/src/main.c b/examples/device/hid_composite_freertos/src/main.c index 8a8570d60..de065ee64 100644 --- a/examples/device/hid_composite_freertos/src/main.c +++ b/examples/device/hid_composite_freertos/src/main.c @@ -79,7 +79,6 @@ void hid_task(void* params); int main(void) { board_init(); - tusb_init(); // soft timer for blinky blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); @@ -112,6 +111,10 @@ void usb_device_task(void* param) { (void) param; + // This should be called after scheduler/kernel is started. + // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tusb_init(); + // RTOS forever loop while (1) { diff --git a/src/device/usbd.h b/src/device/usbd.h index d9facf719..098e94075 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -42,6 +42,8 @@ //--------------------------------------------------------------------+ // Init device stack +// Note: when using with RTOS, this should be called after scheduler/kernel is started. +// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. bool tud_init (void); // Task function should be called in main/rtos loop diff --git a/src/host/usbh.h b/src/host/usbh.h index 42a2bd095..fe39a19f4 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -91,6 +91,9 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // CLASS-USBH & INTERNAL API //--------------------------------------------------------------------+ + +// Note: when using with RTOS, this should be called after scheduler/kernel is started. +// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. bool usbh_init(void); bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); diff --git a/src/tusb.h b/src/tusb.h index defbc54fb..c252a5789 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -109,6 +109,8 @@ * @{ */ // Initialize device/host stack +// Note: when using with RTOS, this should be called after scheduler/kernel is started. +// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. bool tusb_init(void); // Check if stack is initialized -- cgit v1.3.1 From d91843bcd21262658b43480240e5dfc2b7d7bd20 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 25 Jul 2020 11:18:50 +0200 Subject: Get and set requests work --- src/class/audio/audio.h | 311 +++++++++++++++++++++-------------------- src/class/audio/audio_device.c | 201 +++++++++++++++++--------- src/class/audio/audio_device.h | 14 +- 3 files changed, 309 insertions(+), 217 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 011f5381b..36f9f211c 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -652,165 +652,172 @@ typedef enum AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, } audio_channel_config_t; +/// AUDIO Channel Cluster Descriptor (4.1) +typedef struct TU_ATTR_PACKED { + uint8_t bNrChannels; ///< Number of channels currently connected. + audio_channel_config_t bmChannelConfig; ///< Bitmap according to 'audio_channel_config_t' with a 1 set if channel is connected and 0 else. In case channels are non-predefined ignore them here (see UAC2 specification 4.1 Audio Channel Cluster Descriptor. + uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first inserted channel with a non-predefined spatial location. +} audio_desc_channel_cluster_t; + /// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor in bytes: 9. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. - uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). - uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. - uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. - uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. + uint8_t bLength ; ///< Size of this descriptor in bytes: 9. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. + uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). + uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. + uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. + uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. } audio_desc_cs_ac_interface_t; /// AUDIO Clock Source Descriptor (4.7.2.1) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. - uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. - uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. + uint8_t bLength ; ///< Size of this descriptor in bytes: 8. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. + uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. + uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. } audio_desc_clock_source_t; /// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. - uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. - uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. + uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. + uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. } audio_desc_clock_selector_t; /// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins #define audio_desc_clock_selector_n_t(source_num) \ - struct TU_ATTR_PACKED { \ + struct TU_ATTR_PACKED { \ uint8_t bLength ; \ uint8_t bDescriptorType ; \ uint8_t bDescriptorSubType ; \ uint8_t bClockID ; \ uint8_t bNrInPins ; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID ; \ - } sourceID[source_num] ; \ - uint8_t bmControls ; \ - uint8_t iClockSource ; \ - } + struct TU_ATTR_PACKED { \ + uint8_t baSourceID ; \ + } sourceID[source_num] ; \ + uint8_t bmControls ; \ + uint8_t iClockSource ; \ +} /// AUDIO Clock Multiplier Descriptor (4.7.2.3) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. - uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. + uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. } audio_desc_clock_multiplier_t; /// AUDIO Input Terminal Descriptor(4.7.2.4) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. - uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. - uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. - uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. + uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. + uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. + uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. } audio_desc_input_terminal_t; /// AUDIO Output Terminal Descriptor(4.7.2.5) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. - uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. - uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. - uint16_t bmControls ; ///< See: audio_terminal_output_type_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. + uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. + uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. + uint16_t bmControls ; ///< See: audio_terminal_output_type_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. } audio_desc_output_terminal_t; /// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. - uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. - struct TU_ATTR_PACKED { - uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. - } controls[2] ; - uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. + uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. + struct TU_ATTR_PACKED { + uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. + } controls[2] ; + uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. } audio_desc_feature_unit_t; /// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels #define audio_desc_feature_unit_n_t(ch_num) \ - struct TU_ATTR_PACKED { \ + struct TU_ATTR_PACKED { \ uint8_t bLength ; /* 6+(ch_num+1)*4 */\ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bUnitID ; \ - uint8_t bSourceID ; \ - struct TU_ATTR_PACKED { \ - uint32_t bmaControls ; \ - } controls[ch_num+1] ; \ - uint8_t iTerminal ; \ - } + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bUnitID ; \ + uint8_t bSourceID ; \ + struct TU_ATTR_PACKED { \ + uint32_t bmaControls ; \ + } controls[ch_num+1] ; \ + uint8_t iTerminal ; \ +} /// AUDIO Class-Specific AS Interface Descriptor(4.9.2) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. - uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. - uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. - uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. - uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. - uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. + uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. + uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. + uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. + uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. + uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. } audio_desc_cs_as_interface_t; /// AUDIO Type I Format Type Descriptor(2.3.1.6 - Audio Formats) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. - uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. - uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. + uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. + uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. } audio_desc_type_I_format_t; /// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. - uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. - uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. - uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. - uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. + uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. + uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. + uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. + uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. + uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. } audio_desc_cs_as_iso_data_ep_t; //// 5.2.3 Control Request Parameter Block Layout @@ -818,87 +825,91 @@ typedef struct TU_ATTR_PACKED // 5.2.3.1 1-byte Control CUR Parameter Block typedef struct TU_ATTR_PACKED { - int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control + int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control } audio_control_cur_1_t; // 5.2.3.2 2-byte Control CUR Parameter Block typedef struct TU_ATTR_PACKED { - int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control + int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control } audio_control_cur_2_t; // 5.2.3.3 4-byte Control CUR Parameter Block typedef struct TU_ATTR_PACKED { - int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control + int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control } audio_control_cur_4_t; +// Use the following ONLY for RECEIVED data - compiler does not know how many subranges are defined! Use the one below for predefined lengths - or if you know what you are doing do what you like // 5.2.3.1 1-byte Control RANGE Parameter Block -//#define audio_control_range_1_n_t(numSubRanges) \ -// struct TU_ATTR_PACKED { \ -// uint16_t wNumSubRanges = numSubRanges; \ -// struct TU_ATTR_PACKED { \ -// int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ -// int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ -// uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ -// } setting[numSubRanges] ; \ -// } - typedef struct TU_ATTR_PACKED { uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } setting[] ; + struct TU_ATTR_PACKED { + int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; } audio_control_range_1_t; // 5.2.3.2 2-byte Control RANGE Parameter Block -//#define audio_control_range_2_n_t(numSubRanges) \ -// struct TU_ATTR_PACKED { \ -// uint16_t wNumSubRanges = numSubRanges; \ -// struct TU_ATTR_PACKED { \ -// int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ -// int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ -// uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ -// } setting[numSubRanges] ; \ -// } - typedef struct TU_ATTR_PACKED { uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } setting[] ; + struct TU_ATTR_PACKED { + int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; } audio_control_range_2_t; // 5.2.3.3 4-byte Control RANGE Parameter Block -//#define audio_control_range_4_n_t(numSubRanges) \ -// struct TU_ATTR_PACKED { \ -// uint16_t wNumSubRanges = numSubRanges; \ -// struct TU_ATTR_PACKED { \ -// int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ -// int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ -// uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ -// } setting[numSubRanges] ; \ -// } - typedef struct TU_ATTR_PACKED { uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } setting[] ; + struct TU_ATTR_PACKED { + int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; } audio_control_range_4_t; -/** @} */ +// 5.2.3.1 1-byte Control RANGE Parameter Block +#define audio_control_range_1_n_t(numSubRanges) \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges = numSubRanges; \ + struct TU_ATTR_PACKED { \ + int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges] ; \ +} + + // 5.2.3.2 2-byte Control RANGE Parameter Block +#define audio_control_range_2_n_t(numSubRanges) \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges = numSubRanges; \ + struct TU_ATTR_PACKED { \ + int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges] ; \ + } + + // 5.2.3.3 4-byte Control RANGE Parameter Block +#define audio_control_range_4_n_t(numSubRanges) \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges = numSubRanges; \ + struct TU_ATTR_PACKED { \ + int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges] ; \ + } + + /** @} */ #ifdef __cplusplus -} + } #endif #endif -/** @} */ + /** @} */ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 7e7fef19f..5f57c5e4a 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -157,10 +157,10 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); -static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID); -static bool audiod_verify_itf_exists(uint8_t itf); -static bool audiod_verify_ep_exists(uint8_t ep); +static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver); +static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver); +static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); bool tud_audio_n_mounted(uint8_t itf) { @@ -691,7 +691,7 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * uint8_t idxDriver, idxItf; uint8_t const *dummy; - TU_VERIFY(audiod_get_interface_index(itf, &idxDriver, &idxItf, &dummy)); + TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].altSetting[idxItf], 1)); return true; @@ -724,7 +724,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Find index of audio streaming interface and index of interface uint8_t idxDriver, idxItf; uint8_t const *p_desc; - TU_VERIFY(audiod_get_interface_index(itf, &idxDriver, &idxItf, &p_desc)); + TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) #if CFG_TUD_AUDIO_EPSIZE_IN > 0 @@ -837,6 +837,8 @@ bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_re // Handle audio class specific set requests if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) { + uint8_t idxDriver; + switch (p_request->bmRequestType_bit.recipient) { case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label @@ -844,28 +846,35 @@ bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_re uint8_t itf = TU_U16_LOW(p_request->wIndex); uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - // Verify if entity is present - This check may be omitted if we trust the host not to send rubbish if (entityID != 0) { - // Invoke callback - if (tud_audio_set_req_entity_cb && tud_audio_set_req_entity_cb(rhport, p_request)) + if (tud_audio_set_req_entity_cb) { - tud_control_status(rhport, p_request); + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); } else { + TU_LOG2(" No entity set request callback available!\r\n"); return false; // In case no callback function is present or request can not be conducted we stall it } } else { - // Invoke callback - if (tud_audio_set_req_itf_cb && tud_audio_set_req_itf_cb(rhport, p_request)) + if (tud_audio_set_req_itf_cb) { - tud_control_status(rhport, p_request); + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); } else { + TU_LOG2(" No interface set request callback available!\r\n"); return false; // In case no callback function is present or request can not be conducted we stall it } } @@ -876,18 +885,20 @@ bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ep = TU_U16_LOW(p_request->wIndex); - // Invoke callback - if (tud_audio_set_req_ep_cb && tud_audio_set_req_ep_cb(rhport, p_request)) + if (tud_audio_set_req_ep_cb) { - tud_control_status(rhport, p_request); + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); } else { + TU_LOG2(" No EP set request callback available!\r\n"); return false; // In case no callback function is present or request can not be conducted we stall it } - break; - // Unknown/Unsupported recipient default: TU_BREAKPOINT(); return false; } @@ -920,82 +931,89 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req // Handle class requests if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) { + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t idxDriver; + // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) { case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - uint8_t itf = TU_U16_LOW(p_request->wIndex); uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - // Verify if entity is present - This check may be omitted if we trust the host not to send rubbish + // Verify if entity is present if (entityID != 0) { - TU_VERIFY(audiod_verify_entity_exists(itf, entityID)); - - // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished - if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); - // Invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (tud_audio_get_req_entity_cb) + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - return tud_audio_get_req_entity_cb(rhport, p_request); - } - else - { - TU_LOG2(" No entity get request callback available!\r\n"); + if (tud_audio_get_req_entity_cb) + { + return tud_audio_get_req_entity_cb(rhport, p_request); + } + else + { + TU_LOG2(" No entity get request callback available!\r\n"); + return false; // Stall + } } } else { - TU_VERIFY(audiod_verify_itf_exists(itf)); - - // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished - if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); - // Invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (tud_audio_get_req_itf_cb) + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - return tud_audio_get_req_itf_cb(rhport, p_request); - } - else - { - TU_LOG2(" No interface get request callback available!\r\n"); + if (tud_audio_get_req_itf_cb) + { + return tud_audio_get_req_itf_cb(rhport, p_request); + } + else + { + TU_LOG2(" No interface get request callback available!\r\n"); + return false; // Stall + } } } - break; case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label uint8_t ep = TU_U16_LOW(p_request->wIndex); - // Verify if EP is present - This check may be omitted if we trust the host not to send rubbish - TU_VERIFY(audiod_verify_ep_exists(ep)); + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); - // If request is a set request we return true here and handle the rest later in audiod_control_complete() once the data stage was finished - if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return true; - - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - TU_LOG2(" No EP get request callback available!\r\n"); + if (tud_audio_get_req_ep_cb) + { + return tud_audio_get_req_ep_cb(rhport, p_request); + } + else + { + TU_LOG2(" No EP get request callback available!\r\n"); + return false; // Stall + } } - break; // Unknown/Unsupported recipient default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; } - // Host expects an answer - in case no callback function is present we stall the request - return false; + // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished + TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf, CFG_TUD_AUDIO_CTRL_BUF_SIZE)); + return true; } - // There went something wrong + // There went something wrong - unsupported control request type TU_BREAKPOINT(); return false; } @@ -1094,10 +1112,61 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 } -// This helper function finds for a given interface number the index of the attached driver interface, the index of the interface in the audio function +bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len) +{ + // Handles only sending of data not receiving + if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; + + // Get corresponding driver index + uint8_t idxDriver; + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + // Conduct checks which depend on the recipient + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present + if (entityID != 0) + { + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + } + else + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + } + break; + + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + break; + + // Unknown/Unsupported recipient + default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; + } + + // Crop length + if (len > CFG_TUD_AUDIO_CTRL_BUF_SIZE) len = CFG_TUD_AUDIO_CTRL_BUF_SIZE; + + // Copy into buffer + memcpy((void *)_audiod_itf[idxDriver].ctrl_buf, data, (size_t)len); + + // Schedule transmit + return tud_control_xfer(rhport, p_request, (void*)_audiod_itf[idxDriver].ctrl_buf, len); +} + +// This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function // (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and -// finally a pointer to the std. AS interface, where the pointer always points to the start i.e. alternate interface zero. -static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) +// finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. +static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) { // Loop over audio driver interfaces uint8_t i; @@ -1134,7 +1203,8 @@ static bool audiod_get_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t return false; } -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID) +// Verify an entity with the given ID exists and returns also the corresponding driver index +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -1151,6 +1221,7 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID) { if (p_desc[3] == entityID) // Entity IDs are always at offset 3 { + *idxDriver = i; return true; } p_desc = tu_desc_next(p_desc); @@ -1160,7 +1231,7 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID) return false; } -static bool audiod_verify_itf_exists(uint8_t itf) +static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -1175,6 +1246,7 @@ static bool audiod_verify_itf_exists(uint8_t itf) { if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) { + *idxDriver = i; return true; } p_desc = tu_desc_next(p_desc); @@ -1184,7 +1256,7 @@ static bool audiod_verify_itf_exists(uint8_t itf) return false; } -static bool audiod_verify_ep_exists(uint8_t ep) +static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -1202,6 +1274,7 @@ static bool audiod_verify_ep_exists(uint8_t ep) { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) { + *idxDriver = i; return true; } p_desc = tu_desc_next(p_desc); diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 8494281c4..9766eb5f9 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -204,6 +204,14 @@ inline void tud_audio_int_ctr_read_flush (void); inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); #endif +// Buffer control EP data and schedule a transmit +// This function is intended to be used if you do not have a persistent buffer or memory location available (e.g. non-local variables) and need to answer onto a +// get request. This function buffers your answer request frame into the control buffer of the corresponding audio driver and schedules a transmit for sending it. +// Since transmission is triggered via interrupts, a persistent memory location is required onto which the buffer pointer in pointing. If you already have such +// available you may directly use 'tud_control_xfer(...)'. In this case data does not need to be copied into an additional buffer and you save some time. +// If the request's wLength is zero, a status packet is sent instead. +bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len); + //--------------------------------------------------------------------+ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ @@ -228,13 +236,13 @@ TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_c TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); // Invoked when audio class specific set request received for an EP -TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); +TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); // Invoked when audio class specific set request received for an interface -TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); +TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); // Invoked when audio class specific set request received for an entity -TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); +TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); // Invoked when audio class specific get request received for an EP TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); -- cgit v1.3.1 From 1269bb440a62120108ebe9a6d5436b88b28b4de3 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 25 Jul 2020 14:31:25 +0200 Subject: Fix structure definition audio_control_range_X_n_t --- src/class/audio/audio.h | 10 +++++----- src/class/audio/audio_device.c | 22 ++++++++++++---------- 2 files changed, 17 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 36f9f211c..8f2c0d214 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -874,7 +874,7 @@ typedef struct TU_ATTR_PACKED { // 5.2.3.1 1-byte Control RANGE Parameter Block #define audio_control_range_1_n_t(numSubRanges) \ struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges = numSubRanges; \ + uint16_t wNumSubRanges; \ struct TU_ATTR_PACKED { \ int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ @@ -884,8 +884,8 @@ typedef struct TU_ATTR_PACKED { // 5.2.3.2 2-byte Control RANGE Parameter Block #define audio_control_range_2_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges = numSubRanges; \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ struct TU_ATTR_PACKED { \ int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ @@ -895,8 +895,8 @@ typedef struct TU_ATTR_PACKED { // 5.2.3.3 4-byte Control RANGE Parameter Block #define audio_control_range_4_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges = numSubRanges; \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ struct TU_ATTR_PACKED { \ int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 5f57c5e4a..b5fbf70f3 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -694,6 +694,8 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].altSetting[idxItf], 1)); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].altSetting[idxItf]); + return true; #else @@ -709,9 +711,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Here we need to do the following: - // 1. Find the audio driver interface which was assigned to the given interface which is to be set + // 1. Find the audio driver assigned to the given interface to be set // Since one audio driver interface has to be able to cover an unknown number of interfaces (AC, AS + its alternate settings), the best memory efficient way to solve this is to always search through the descriptors. - // The audio driver interface is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching + // The audio driver is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching // 2. Close EPs which are currently open // To do so it is not necessary to know the current active alternate interface since we already save the current EP addresses - we simply close them @@ -721,6 +723,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const itf = tu_u16_low(p_request->wIndex); uint8_t const alt = tu_u16_low(p_request->wValue); + TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); + // Find index of audio streaming interface and index of interface uint8_t idxDriver, idxItf; uint8_t const *p_desc; @@ -768,7 +772,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) { - TU_ASSERT(dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); +// TU_ASSERT(dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); + TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *)p_desc)); uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; #if CFG_TUD_AUDIO_EPSIZE_IN > 0 @@ -813,18 +818,15 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Check for nothing found - we can rely on this since EP descriptors are never the last descriptors, there are always also class specific EP descriptors following! TU_VERIFY(p_desc < p_desc_end); + // Save current alternative interface setting + _audiod_itf[idxDriver].altSetting[idxItf] = alt; + // Invoke callback if (tud_audio_set_itf_cb) { - if (!tud_audio_set_itf_cb(rhport, p_request)) - { - return false; - } + if (!tud_audio_set_itf_cb(rhport, p_request)) return false; } - // Save current alternative interface setting - _audiod_itf[idxDriver].altSetting[idxItf] = alt; - tud_control_status(rhport, p_request); return true; -- cgit v1.3.1 From 5e3f90cd6eabbeb664d523184338d7f4df46cef4 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 26 Jul 2020 19:21:30 +0200 Subject: add 'set_EP0_max_pkt_size(...)' and fix EP0 size to 64 bytes after reset --- src/portable/st/synopsys/dcd_synopsys.c | 97 ++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 7eb63e52f..5bfb6789c 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -206,11 +206,10 @@ static void bus_reset(uint8_t rhport) // are enabled at least "2 x (Largest-EPsize/4) + 1" are recommended. Maybe provide a macro for application to // overwrite this. -#if TUD_OPT_HIGH_SPEED - _allocated_fifo_words = 271 + 2*EP_MAX; -#else - _allocated_fifo_words = 47 + 2*EP_MAX; -#endif + // We rework this here and initialize the FIFOs here only for the USB reset case. The rest is done once a + // configuration was set from the host. For this initialization phase we use 64 bytes as FIFO size. + + _allocated_fifo_words = 16 + 2 + 10; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) usb_otg->GRXFSIZ = _allocated_fifo_words; @@ -219,15 +218,98 @@ static void bus_reset(uint8_t rhport) _allocated_fifo_words += 16; - // TU_LOG2_INT(_allocated_fifo_words); - // Fixed control EP0 size to 64 bytes in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; + // Set SETUP packet count to 3 out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + +//#if TUD_OPT_HIGH_SPEED +// _allocated_fifo_words = 271 + 2*EP_MAX; +//#else +// _allocated_fifo_words = 47 + 2*EP_MAX; +//#endif +// +// usb_otg->GRXFSIZ = _allocated_fifo_words; +// +// // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) +// usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; +// +// _allocated_fifo_words += 16; +// +// // TU_LOG2_INT(_allocated_fifo_words); +// +// // Fixed control EP0 size to 64 bytes +//// in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); +//// xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; +// +// // Set SETUP packet count to 3 +// out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); +// +// usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; +} + +// Required after new configuration received in case EP0 max packet size has changed +static bool set_EP0_max_pkt_size(uint8_t maxPktSize) +{ + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + + uint32_t enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; + + // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL. + switch (enum_spd) + { + case 0x00: // High speed - always 64 byte + if (maxPktSize == 64) + { + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; + return true; + } + + return false; // Only 64 bytes are valid + + case 0x03: // Full speed + switch (maxPktSize) + { + case 8: + in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 8; + break; + + case 16: + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + in_ep[0].DIEPCTL |= (0x02 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 16; + break; + + case 32: + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + in_ep[0].DIEPCTL |= (0x01 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 32; + break; + + case 64: + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; + break; + + default: + return false; // Other sizes are not valid + } + + return true; + + default: // Low speed - always 8 bytes + in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = 8; + xfer_status[0][TUSB_DIR_IN].max_size = 8; + return true; + } } // Set turn-around timeout according to link speed @@ -939,6 +1021,7 @@ void dcd_int_handler(uint8_t rhport) tusb_speed_t const speed = get_speed(rhport); set_turnaround(usb_otg, speed); + dcd_event_bus_reset(rhport, speed, true); } -- cgit v1.3.1 From 01903a4a6d0eb8a7260029133cc94a62d969092e Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 27 Jul 2020 21:03:20 +0200 Subject: Implement dynamic reallocation of RX and TX fifos for EP0. Tested with EP0 size 8/16/32/64. --- src/device/dcd.h | 4 + src/device/usbd.c | 17 +++-- src/portable/st/synopsys/dcd_synopsys.c | 126 +++++++++++++++++++------------- 3 files changed, 91 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index a4635346b..ff05f26cc 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -115,6 +115,10 @@ void dcd_connect(uint8_t rhport) TU_ATTR_WEAK; // Disconnect by disabling internal pull-up resistor on D+/D- void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; +// Invoked when a set configuration request was received +// Helper to allow for dynamic EP buffer allocation according to configuration descriptor +TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg); + //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index 20d4925d2..2164eb3f5 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -46,7 +46,6 @@ typedef struct { volatile uint8_t connected : 1; volatile uint8_t addressed : 1; - volatile uint8_t configured : 1; volatile uint8_t suspended : 1; uint8_t remote_wakeup_en : 1; // enable/disable by host @@ -54,6 +53,7 @@ typedef struct uint8_t self_powered : 1; // configuration descriptor's attribute }; + volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) uint8_t speed; uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) @@ -314,7 +314,7 @@ tusb_speed_t tud_speed_get(void) bool tud_mounted(void) { - return _usbd_dev.configured; + return _usbd_dev.cfg_num ? 1 : 0; } bool tud_suspended(void) @@ -583,8 +583,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const case TUSB_REQ_GET_CONFIGURATION: { - uint8_t cfgnum = _usbd_dev.configured ? 1 : 0; - tud_control_xfer(rhport, p_request, &cfgnum, 1); + uint8_t cfg_num = _usbd_dev.cfg_num; + tud_control_xfer(rhport, p_request, &cfg_num, 1); } break; @@ -592,9 +592,9 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const { uint8_t const cfg_num = (uint8_t) p_request->wValue; - if ( !_usbd_dev.configured && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); + if ( !_usbd_dev.cfg_num && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); - _usbd_dev.configured = cfg_num ? 1 : 0; + _usbd_dev.cfg_num = cfg_num; tud_control_status(rhport, p_request); } @@ -746,6 +746,9 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); // index is cfg_num-1 TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION); + // Allow for dynamic allocation of EP buffer for current configuration - only one configuration may be active according to USB specification + if (dcd_alloc_mem_for_conf) TU_ASSERT(dcd_alloc_mem_for_conf(rhport, desc_cfg)); + // Parse configuration descriptor _usbd_dev.remote_wakeup_support = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP) ? 1 : 0; _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED) ? 1 : 0; @@ -951,7 +954,7 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) case DCD_EVENT_UNPLUGGED: _usbd_dev.connected = 0; _usbd_dev.addressed = 0; - _usbd_dev.configured = 0; + _usbd_dev.cfg_num = 0; _usbd_dev.suspended = 0; osal_queue_send(_usbd_q, event, in_isr); break; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 5bfb6789c..75e6097fd 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -156,7 +156,7 @@ static void bus_reset(uint8_t rhport) USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); +// USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); tu_memclr(xfer_status, sizeof(xfer_status)); @@ -209,24 +209,24 @@ static void bus_reset(uint8_t rhport) // We rework this here and initialize the FIFOs here only for the USB reset case. The rest is done once a // configuration was set from the host. For this initialization phase we use 64 bytes as FIFO size. - _allocated_fifo_words = 16 + 2 + 10; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) + // Found by trial: 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6 - not quite sure where 1 + 6 comes from but this works for 8/16/32/64 EP0 size + _allocated_fifo_words = 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) + +// _allocated_fifo_words = 47 + 2*EP_MAX; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) usb_otg->GRXFSIZ = _allocated_fifo_words; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; + usb_otg->DIEPTXF0_HNPTXFSIZ = (CFG_TUD_ENDPOINT0_SIZE/4 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - _allocated_fifo_words += 16; - - // Fixed control EP0 size to 64 bytes - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; + _allocated_fifo_words += CFG_TUD_ENDPOINT0_SIZE/4; // Set SETUP packet count to 3 out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + //#if TUD_OPT_HIGH_SPEED // _allocated_fifo_words = 271 + 2*EP_MAX; //#else @@ -243,8 +243,8 @@ static void bus_reset(uint8_t rhport) // // TU_LOG2_INT(_allocated_fifo_words); // // // Fixed control EP0 size to 64 bytes -//// in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); -//// xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; +// in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); +// xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; // // // Set SETUP packet count to 3 // out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); @@ -253,7 +253,7 @@ static void bus_reset(uint8_t rhport) } // Required after new configuration received in case EP0 max packet size has changed -static bool set_EP0_max_pkt_size(uint8_t maxPktSize) +static void set_EP0_max_pkt_size() { USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); @@ -264,51 +264,34 @@ static bool set_EP0_max_pkt_size(uint8_t maxPktSize) switch (enum_spd) { case 0x00: // High speed - always 64 byte - if (maxPktSize == 64) - { - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; - return true; - } - - return false; // Only 64 bytes are valid + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; + break; case 0x03: // Full speed - switch (maxPktSize) - { - case 8: - in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 8; - break; - - case 16: - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - in_ep[0].DIEPCTL |= (0x02 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 16; - break; - - case 32: - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - in_ep[0].DIEPCTL |= (0x01 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 32; - break; - - case 64: - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; - break; - - default: - return false; // Other sizes are not valid - } - - return true; +#if CFG_TUD_ENDPOINT0_SIZE == 64 + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; +#elif CFG_TUD_ENDPOINT0_SIZE == 32 + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + in_ep[0].DIEPCTL |= (0x01 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 32; +#elif CFG_TUD_ENDPOINT0_SIZE == 16 + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + in_ep[0].DIEPCTL |= (0x02 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 16; +#elif CFG_TUD_ENDPOINT0_SIZE == 8 + in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 8; +#else +# error CFG_TUD_ENDPOINT0_SIZE MUST be 8, 16, 32, or 64! +#endif + break; default: // Low speed - always 8 bytes in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); xfer_status[0][TUSB_DIR_OUT].max_size = 8; xfer_status[0][TUSB_DIR_IN].max_size = 8; - return true; } } @@ -1022,6 +1005,8 @@ void dcd_int_handler(uint8_t rhport) set_turnaround(usb_otg, speed); + set_EP0_max_pkt_size(); + dcd_event_bus_reset(rhport, speed, true); } @@ -1086,4 +1071,47 @@ void dcd_int_handler(uint8_t rhport) } } +TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg) +{ + (void) rhport; + + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + +// for(uint8_t n = 0; n < EP_MAX; n++) { +// out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; +// } + + out_ep[0].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; + + // Deactivate Interrupts? + dev->DAINTMSK &= ~((1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos)); + dev->DOEPMSK &= ~(USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM); + dev->DIEPMSK &= ~(USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM); + + // usb_otg->GINTMSK &= ~(USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT); + + // Reconfigure RX buffer and EP0 TX buffer + _allocated_fifo_words = 47 + 2*EP_MAX; + + usb_otg->GRXFSIZ = _allocated_fifo_words; + + // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) + usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; + + _allocated_fifo_words += 16; + +// usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + + // Enable interrupts + dev->DAINTMSK |= (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); + dev->DOEPMSK |= USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; + dev->DIEPMSK |= USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM; + + // USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + + return true; +} + #endif -- cgit v1.3.1 From 6976e642176cf76be9cc1bd2ef1a137a0e71e078 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 28 Jul 2020 14:36:15 +0700 Subject: fix msp430 gcc 9.2.0 warning in #465 --- .github/workflows/build.yml | 8 +++++--- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 3 +-- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 51ec0e606..2ad274928 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,10 +41,12 @@ jobs: uses: actions/cache@v1 with: path: /tmp/dl/ - # Increment serial number at end when updating downloads - key: msp430-${{ runner.os }}-0 + # Increment gcc version number at end when updating downloads + key: msp430-${{ runner.os }}-9.2.0.50 - name: Install Toolchains + env: + MSP430GCC_URL: http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2 run: | # ARM & RISC-V GCC from xpack npm install --global xpm @@ -55,7 +57,7 @@ jobs: # TI MSP430 GCC mkdir -p /tmp/dl/ - [ -f "/tmp/dl/msp430-gcc.tar.bz2" ] || wget --progress=dot:mega http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/8_3_0_0/exports/msp430-gcc-8.3.0.16_linux64.tar.bz2 -O /tmp/dl/msp430-gcc.tar.bz2 + [ -f "/tmp/dl/msp430-gcc.tar.bz2" ] || wget --progress=dot:mega $MSP430GCC_URL -O /tmp/dl/msp430-gcc.tar.bz2 tar -C $HOME -xaf /tmp/dl/msp430-gcc.tar.bz2 echo "::add-path::`echo $HOME/msp430-gcc-*_linux64/bin`" diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 8672050f0..93ba99543 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -70,8 +70,7 @@ typedef enum SIZXY = 7 } ep_regs_index_t; -#define EP_REGS(epnum, dir) &USBOEPCNF_1 + 64*dir + 8*(epnum - 1) - +#define EP_REGS(epnum, dir) ((ep_regs_t) ((uintptr_t)&USBOEPCNF_1 + 64*dir + 8*(epnum - 1))) static void bus_reset(void) { -- cgit v1.3.1 From a1a390a7883b35bbc00a85e52d1e2f76a18ebcbd Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 28 Jul 2020 10:54:23 +0300 Subject: Update dcd_esp32s2.c --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 21bad327a..5be1c82e5 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -54,6 +54,9 @@ // FIFO size in bytes #define EP_FIFO_SIZE 1024 +// Max number of IN EP FIFOs +#define EP_FIFO_NUM 5 + typedef struct { uint8_t *buffer; uint16_t total_len; @@ -71,17 +74,12 @@ static uint32_t _setup_packet[2]; #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] static xfer_ctl_t xfer_status[EP_MAX][2]; -// Max number of IN EP FIFOs -#define USB_FIFO_NUM 5 - // Keep count of how many FIFOs are in use -static uint8_t dcd_allocated_fifos = 1; //FIFO0 is always in use +static uint8_t _allocated_fifos = 1; //FIFO0 is always in use // Will either return an unused FIFO number, or 0 if all are used. -static uint8_t dcd_get_free_fifo(){ - if (dcd_allocated_fifos < USB_FIFO_NUM) { - return dcd_allocated_fifos++; - } +static uint8_t get_free_fifo(){ + if (_allocated_fifos < EP_FIFO_NUM) return _allocated_fifos++; return 0; } @@ -285,7 +283,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) // - Offset: GRXFSIZ + 16 + Size*(epnum-1) // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". - uint8_t fifo_num = dcd_get_free_fifo(); + uint8_t fifo_num = get_free_fifo(); TU_ASSERT(fifo_num != 0); in_ep[epnum].diepctl &= ~(USB_D_TXFNUM1_M | USB_D_EPTYPE1_M | USB_DI_SETD0PID1 | USB_D_MPS1_M); @@ -300,7 +298,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) // Both TXFD and TXSA are in unit of 32-bit words. // IN FIFO 0 was configured during enumeration, hence the "+ 16". uint16_t const allocated_size = (USB0.grxfsiz & 0x0000ffff) + 16; - uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (USB_FIFO_NUM-1); + uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_FIFO_NUM-1); uint32_t const fifo_offset = allocated_size + fifo_size*(fifo_num-1); // DIEPTXF starts at FIFO #1. @@ -673,7 +671,7 @@ static void _dcd_int_handler(void* arg) ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); USB0.gintsts = USB_USBRST_M; // FIFOs will be reassigned when the endpoints are reopen - dcd_allocated_fifos = 1; + _allocated_fifos = 1; bus_reset(); } @@ -702,8 +700,6 @@ static void _dcd_int_handler(void* arg) if (otg_int & USB_SESENDDET_M) { dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); - // FIFOs will be reassigned when the endpoints are reopen - dcd_allocated_fifos = 1; } USB0.gotgint = otg_int; -- cgit v1.3.1 From 5af08e2ffc47c6a0c90f678edd04ca57480a1747 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 29 Jul 2020 16:59:07 +0700 Subject: fix strict prototype --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index b4d869517..755e06701 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -78,7 +78,8 @@ static xfer_ctl_t xfer_status[EP_MAX][2]; static uint8_t _allocated_fifos = 1; //FIFO0 is always in use // Will either return an unused FIFO number, or 0 if all are used. -static uint8_t get_free_fifo(){ +static uint8_t get_free_fifo(void) +{ if (_allocated_fifos < EP_FIFO_NUM) return _allocated_fifos++; return 0; } -- cgit v1.3.1 From 10a8ef7614b1f154576c6b3cdd14f15d1b18a443 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 29 Jul 2020 17:04:47 +0700 Subject: fix nested extern declaration of 'SystemCoreClock' [-Werror=nested-externs] --- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 7eb63e52f..03c33c598 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -231,6 +231,7 @@ static void bus_reset(uint8_t rhport) } // Set turn-around timeout according to link speed +extern uint32_t SystemCoreClock; static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, tusb_speed_t speed) { usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; @@ -243,7 +244,6 @@ static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, tusb_speed_t speed) else { // Turnaround timeout depends on the MCU clock - extern uint32_t SystemCoreClock; uint32_t turnaround; if ( SystemCoreClock >= 32000000U ) -- cgit v1.3.1 From c3b0389f10188e016c0cd0bb74638ecfb0eae8ea Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 31 Jul 2020 15:48:28 +0200 Subject: Fix synopsys size check for ISO endpoint Constraint was incorrect for ISO endpoint as stated in TODO. --- src/portable/st/synopsys/dcd_synopsys.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 03c33c598..f4430f582 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -514,8 +514,14 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) TU_ASSERT(epnum < EP_MAX); - // TODO ISO endpoint can be up to 1024 bytes - TU_ASSERT(desc_edpt->wMaxPacketSize.size <= (get_speed(rhport) == TUSB_SPEED_HIGH ? 512 : 64)); + if (desc_edpt->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) + { + TU_ASSERT(desc_edpt->wMaxPacketSize.size <= (get_speed(rhport) == TUSB_SPEED_HIGH ? 1024 : 1023)); + } + else + { + TU_ASSERT(desc_edpt->wMaxPacketSize.size <= (get_speed(rhport) == TUSB_SPEED_HIGH ? 512 : 64)); + } xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = desc_edpt->wMaxPacketSize.size; -- cgit v1.3.1 From 9bf2b3336610044dfb0187311797c5324eeec0ea Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 1 Aug 2020 12:02:59 +0700 Subject: correct isr context for nrf DCD_EVENT_UNPLUGGED also rename debug lookup to prevent conflict --- src/class/msc/msc_device.c | 6 +++--- src/common/tusb_common.h | 10 +++++----- src/portable/nordic/nrf5x/dcd_nrf5x.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 692fd2441..9b79b68a7 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -105,7 +105,7 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= 2 -static lookup_entry_t const _msc_scsi_cmd_lookup[] = +static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = { { .key = SCSI_CMD_TEST_UNIT_READY , .data = "Test Unit Ready" }, { .key = SCSI_CMD_INQUIRY , .data = "Inquiry" }, @@ -120,7 +120,7 @@ static lookup_entry_t const _msc_scsi_cmd_lookup[] = { .key = SCSI_CMD_WRITE_10 , .data = "Write10" } }; -static lookup_table_t const _msc_scsi_cmd_table = +static tu_lookup_table_t const _msc_scsi_cmd_table = { .count = TU_ARRAY_SIZE(_msc_scsi_cmd_lookup), .items = _msc_scsi_cmd_lookup @@ -418,7 +418,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_ASSERT( event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE ); - TU_LOG2(" SCSI Command: %s\r\n", lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); + TU_LOG2(" SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); // TU_LOG2_MEM(p_cbw, xferred_bytes, 2); p_csw->signature = MSC_CSW_SIGNATURE; diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 1dba6c914..d95c0ffc4 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -251,16 +251,16 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize) typedef struct { uint32_t key; - char const * data; -}lookup_entry_t; + const char* data; +} tu_lookup_entry_t; typedef struct { uint16_t count; - lookup_entry_t const* items; -} lookup_table_t; + tu_lookup_entry_t const* items; +} tu_lookup_table_t; -static inline char const* lookup_find(lookup_table_t const* p_table, uint32_t key) +static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) { for(uint16_t i=0; icount; i++) { diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 7ca32c4f6..fdf56b6ca 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -829,7 +829,7 @@ void tusb_hal_nrf_power_event (uint32_t event) hfclk_disable(); - dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) ? true : false); } break; -- cgit v1.3.1 From acde49ccc97466f603dc7face7ab70ea10d38ee3 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 1 Aug 2020 20:14:58 +0700 Subject: enable pull-up in dcd_init() instead of usbd --- docs/porting.md | 2 +- src/device/usbd.c | 1 - src/portable/dialog/da146xx/dcd_da146xx.c | 4 ++-- src/portable/espressif/esp32s2/dcd_esp32s2.c | 4 ++-- src/portable/microchip/samg/dcd_samg.c | 3 +-- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 2 ++ src/portable/nxp/transdimension/dcd_transdimension.c | 3 ++- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 4 ++-- src/portable/st/synopsys/dcd_synopsys.c | 2 ++ src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 3 +++ test/test/device/msc/test_msc_device.c | 1 - test/test/device/usbd/test_usbd.c | 1 - 12 files changed, 17 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/docs/porting.md b/docs/porting.md index 473768450..d3c688a81 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -62,7 +62,7 @@ All of the code for the low-level device API is in `src/portable//USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk; tusb_vbus_changed((CRG_TOP->ANA_STATUS_REG & CRG_TOP_ANA_STATUS_REG_VBUS_AVAILABLE_Msk) != 0); + + dcd_connect(rhport); } void dcd_int_enable(uint8_t rhport) diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 755e06701..58d92e728 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -165,8 +165,6 @@ static void enum_done_processing(void) *------------------------------------------------------------------*/ void dcd_init(uint8_t rhport) { - (void)rhport; - ESP_LOGV(TAG, "DCD init - Start"); // A. Disconnect @@ -204,6 +202,8 @@ void dcd_init(uint8_t rhport) USB_ENUMDONEMSK_M | USB_RESETDETMSK_M | USB_DISCONNINTMSK_M; // host most only + + dcd_connect(rhport); } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 4a8ed53f3..2b64df50b 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -154,9 +154,8 @@ static void bus_reset(void) // Initialize controller to device mode void dcd_init (uint8_t rhport) { - (void) rhport; - tu_memclr(_dcd_xfer, sizeof(_dcd_xfer)); + dcd_connect(rhport); } // Enable device interrupt diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index f7a59a808..39c5e6638 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -181,6 +181,8 @@ 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); + dcd_connect(rhport); + // Clear pending IRQ NVIC_ClearPendingIRQ(USB_IRQn); } diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 46751cf5d..755e7635e 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -345,7 +345,8 @@ void dcd_init(uint8_t rhport) dcd_reg->USBSTS = dcd_reg->USBSTS; 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 &= ~0x00FF0000; // Interrupt Threshold Interval = 0 + dcd_reg->USBCMD |= USBCMD_RUN_STOP; // Connect } void dcd_int_enable(uint8_t rhport) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index da184abe7..32179874e 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -205,7 +205,6 @@ static inline void reg16_clear_bits(__IO uint16_t *reg, uint16_t mask) { void dcd_init (uint8_t rhport) { - (void)rhport; /* Clocks should already be enabled */ /* Use __HAL_RCC_USB_CLK_ENABLE(); to enable the clocks before calling this function */ @@ -244,7 +243,8 @@ void dcd_init (uint8_t rhport) USB->CNTR |= USB_CNTR_RESETM | (USE_SOF ? USB_CNTR_SOFM : 0) | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; dcd_handle_bus_reset(); - // Data-line pull-up is left disconnected. + // Enable pull-up if supported + if ( dcd_connect ) dcd_connect(rhport); } // Define only on MCU with internal pull-up. BSP can define on MCU without internal PU. diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index f4430f582..a284c0384 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -453,6 +453,8 @@ void dcd_init (uint8_t rhport) // Enable global interrupt usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; + + dcd_connect(rhport); } void dcd_int_enable (uint8_t rhport) diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 8672050f0..b6951efef 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -134,6 +134,9 @@ void dcd_init (uint8_t rhport) // Enable reset and wait for it before continuing. USBIE |= RSTRIE; + // Enable pullup. + USBCNF |= PUR_EN; + USBKEYPID = 0; } diff --git a/test/test/device/msc/test_msc_device.c b/test/test/device/msc/test_msc_device.c index 0382fb327..a01ef153a 100644 --- a/test/test/device/msc/test_msc_device.c +++ b/test/test/device/msc/test_msc_device.c @@ -199,7 +199,6 @@ void setUp(void) if ( !tusb_inited() ) { dcd_init_Expect(rhport); - dcd_connect_Expect(rhport); tusb_init(); } diff --git a/test/test/device/usbd/test_usbd.c b/test/test/device/usbd/test_usbd.c index 1bb32c1e5..06372b2e4 100644 --- a/test/test/device/usbd/test_usbd.c +++ b/test/test/device/usbd/test_usbd.c @@ -127,7 +127,6 @@ void setUp(void) { mscd_init_Expect(); dcd_init_Expect(rhport); - dcd_connect_Expect(rhport); tusb_init(); } } -- cgit v1.3.1 From c557bf7b2e35482e8743eebfca7b5ff28b0b6d86 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 3 Aug 2020 19:48:05 +0200 Subject: Implement dynamic FIFO RAM allocation according to configuration desc. --- src/portable/st/synopsys/dcd_synopsys.c | 231 +++++++++++++++++++++++++++----- 1 file changed, 196 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 75e6097fd..133a3736a 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -137,6 +137,15 @@ typedef struct { uint16_t max_size; } xfer_ctl_t; +// EP size and transfer type report +typedef struct TU_ATTR_PACKED { + // The following format may look complicated but it is the most elegant way of addressing the required fields: EP number, EP direction, and EP transfer type. + // The codes assigned to those fields, according to the USB specification, can be neatly used as indices. + uint16_t ep_size[EP_MAX][2]; ///< dim 1: EP number, dim 2: EP direction denoted by TUSB_DIR_OUT (= 0) and TUSB_DIR_IN (= 1) + bool ep_transfer_type[EP_MAX][2][4]; ///< dim 1: EP number, dim 2: EP direction, dim 3: transfer type, where 0 = Control, 1 = Isochronous, 2 = Bulk, and 3 = Interrupt + ///< I know very well that EP0 can only be used as control EP and we waste space here but for the sake of simplicity we accept that. It is used in a non-persistent way anyway! +} ep_sz_tt_report_t; + typedef volatile uint32_t * usb_fifo_t; xfer_ctl_t xfer_status[EP_MAX][2]; @@ -569,7 +578,7 @@ void dcd_disconnect(uint8_t rhport) bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { - USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); +// USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); @@ -579,8 +588,14 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) TU_ASSERT(epnum < EP_MAX); - // TODO ISO endpoint can be up to 1024 bytes - TU_ASSERT(desc_edpt->wMaxPacketSize.size <= (get_speed(rhport) == TUSB_SPEED_HIGH ? 512 : 64)); + if (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS) + { + TU_ASSERT(desc_edpt->wMaxPacketSize.size <= (get_speed(rhport) == TUSB_SPEED_HIGH ? 512 : 64)); + } + else + { + TU_ASSERT(desc_edpt->wMaxPacketSize.size <= (get_speed(rhport) == TUSB_SPEED_HIGH ? 1024 : 1023)); + } xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = desc_edpt->wMaxPacketSize.size; @@ -595,6 +610,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) } else { + // FIFO allocation done in dcd_alloc_mem_for_conf() + // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture // @@ -620,29 +637,29 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // - Interrupt is EPSize // - Bulk/ISO is max(EPSize, remaining-fifo / non-opened-EPIN) - uint16_t const fifo_remaining = EP_FIFO_SIZE/4 - _allocated_fifo_words; - uint16_t fifo_size = desc_edpt->wMaxPacketSize.size / 4; - - if ( desc_edpt->bmAttributes.xfer != TUSB_XFER_INTERRUPT ) - { - uint8_t opened = 0; - for(uint8_t i = 0; i < EP_MAX; i++) - { - if ( (i != epnum) && (xfer_status[i][TUSB_DIR_IN].max_size > 0) ) opened++; - } - - // EP Size or equally divided of remaining whichever is larger - fifo_size = tu_max16(fifo_size, fifo_remaining / (EP_MAX - opened)); - } - - // FIFO overflows, we probably need a better allocating scheme - TU_ASSERT(fifo_size <= fifo_remaining); - - // DIEPTXF starts at FIFO #1. - // Both TXFD and TXSA are in unit of 32-bit words. - usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; - - _allocated_fifo_words += fifo_size; +// uint16_t const fifo_remaining = EP_FIFO_SIZE/4 - _allocated_fifo_words; +// uint16_t fifo_size = desc_edpt->wMaxPacketSize.size / 4; +// +// if ( desc_edpt->bmAttributes.xfer != TUSB_XFER_INTERRUPT ) +// { +// uint8_t opened = 0; +// for(uint8_t i = 0; i < EP_MAX; i++) +// { +// if ( (i != epnum) && (xfer_status[i][TUSB_DIR_IN].max_size > 0) ) opened++; +// } +// +// // EP Size or equally divided of remaining whichever is larger +// fifo_size = tu_max16(fifo_size, fifo_remaining / (EP_MAX - opened)); +// } +// +// // FIFO overflows, we probably need a better allocating scheme +// TU_ASSERT(fifo_size <= fifo_remaining); +// +// // DIEPTXF starts at FIFO #1. +// // Both TXFD and TXSA are in unit of 32-bit words. +// usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; +// +// _allocated_fifo_words += fifo_size; in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) | @@ -1071,6 +1088,53 @@ void dcd_int_handler(uint8_t rhport) } } +// Helper function which parses through the current configuration descriptors to find the biggest EPs in size. +static bool get_ep_size_report(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg, ep_sz_tt_report_t * p_report) +{ + (void) rhport; + +// tu_memclr(p_report, sizeof(ep_sz_tt_report_t)); // This does not initialize the first two entries ... i do not know why! + + // EP0 sizes and usages are fixed + p_report->ep_size[0][TUSB_DIR_OUT] = p_report->ep_size[0][TUSB_DIR_IN] = CFG_TUD_ENDPOINT0_SIZE; + p_report->ep_transfer_type[0][TUSB_DIR_OUT][TUSB_XFER_CONTROL] = p_report->ep_transfer_type[0][TUSB_DIR_IN][TUSB_XFER_CONTROL] = true; + + // Parse interface descriptor + uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); + uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + desc_cfg->wTotalLength; + + uint8_t addr; + + while( p_desc < desc_end ) + { + if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) + { + + addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; + + // Verify values - this checks may be omitted in case we trust the descriptors to be okay + TU_VERIFY(tu_edpt_number(addr) < EP_MAX); + TU_VERIFY(tu_edpt_dir(addr) <= TUSB_DIR_IN); + TU_VERIFY(((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer <= TUSB_XFER_INTERRUPT); + + p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)] = tu_max16(p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)], ((tusb_desc_endpoint_t const*) p_desc)->wMaxPacketSize.size); + p_report->ep_transfer_type[tu_edpt_number(addr)][tu_edpt_dir(addr)][((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer] = true; + } + p_desc = tu_desc_next(p_desc); // Proceed + } + return true; +} + +// Setup FIFO buffers at configuration time. +// The idea is to use this information such that the FIFOs need to be configured only once +// at configuration time and no more later. This makes it easy in case you want to close and open EPs for different +// purposes at any time (without taking care of other active EPs). You also avoid the nasty need of defragmenting +// the TX buffers, which is likely to happen. +// Certainly, this function does not allow for the highest possible flexibility as it only works in the worst case +// (all biggest EPs can be active at the same time). However, this should not be a problem for almost all applications. + +// Spare space is assigned equally divided to bulk and interrupt EPs. +// Pure isochronous EPs do not get any spare space as it does not make any sense. TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg) { (void) rhport; @@ -1079,9 +1143,9 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); -// for(uint8_t n = 0; n < EP_MAX; n++) { -// out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; -// } + // for(uint8_t n = 0; n < EP_MAX; n++) { + // out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; + // } out_ep[0].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; @@ -1092,17 +1156,112 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration // usb_otg->GINTMSK &= ~(USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT); - // Reconfigure RX buffer and EP0 TX buffer - _allocated_fifo_words = 47 + 2*EP_MAX; + // Determine maximum required spaces for individual EPs and what kind of usage (control, bulk, etc.) they are used for + ep_sz_tt_report_t report = {0}; // dim 1: EP number, dim 2: EP direction, dim 3: transfer type + TU_VERIFY(get_ep_size_report(rhport, desc_cfg, &report)); + + // With that information, set the following up: + // The RX buffer size (as it is a shared buffer here) is set to the sum of the two biggest out EPs plus all the required extra words used for setup packets etc. + // This should work well for all kinds of applications + + // Determine number of used out EPs of current configuration and size of two biggest out EPs + uint8_t nUsedOutEPs = 0, cnt_ep, cnt_tt; + bool tmp; + uint16_t sz[2] = {0, 0}; + + for (cnt_ep = 0; cnt_ep < EP_MAX; cnt_ep++) + { + tmp = false; + for (cnt_tt = 0; cnt_tt <= TUSB_XFER_INTERRUPT; cnt_tt++) + { + tmp |= report.ep_transfer_type[cnt_ep][TUSB_DIR_OUT][cnt_tt]; + } + nUsedOutEPs += tmp; + + if (sz[0] < report.ep_size[cnt_ep][TUSB_DIR_OUT]) + { + sz[1] = sz[0]; + sz[0] = report.ep_size[cnt_ep][TUSB_DIR_OUT]; + } + } + + // For configuration use the approach as explained in bus_reset() + _allocated_fifo_words = 15 + 2*nUsedOutEPs + (sz[0] / 4) + (sz[0] % 4 > 0 ? 1 : 0) + (sz[1] / 4) + (sz[1] % 4 > 0 ? 1 : 0) + 2; // again, i do not really know why we need + 2 but otherwise it does not work usb_otg->GRXFSIZ = _allocated_fifo_words; - // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; + // Control IN uses FIFO 0 with report.ep_size[0][TUSB_DIR_IN] bytes ( report.ep_size[0][TUSB_DIR_IN]/4 32-bit word ) + usb_otg->DIEPTXF0_HNPTXFSIZ = (report.ep_size[0][TUSB_DIR_IN]/4 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - _allocated_fifo_words += 16; + _allocated_fifo_words += report.ep_size[0][TUSB_DIR_IN]/4; // Since EP0 size MUST be a power of two we do not need to take care of remainders -// usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + // For configuration of remaining in EPs use the approach as explained in dcd_edpt_open() except that: + // - ISO EPs only get EP size as FIFO size. More makes no sense since within one frame precisely EP size bytes are transfered and not more. + // Furthermore, double buffering is not possible (for this silicon) since once FIFO was written to and transmit bit was set you are + // not allowed to write to the FIFO any more until transmit was done. So you can not send something and buffer the next frame in the + // meantime into the buffer. TODO: check for high speed and uC types which can do this! + // - Interrupt EPs only get EP size as FIFO size + // - Bulk and control (other than EP0 - this is possible) get spare space equally divided - those profit the most from extra space + + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO MAX | + // --------------- + // | ... | + // --------------- y + x + w + GRXFSIZ + // | IN FIFO 2 | + // --------------- x + w + GRXFSIZ + // | IN FIFO 1 | + // --------------- w + GRXFSIZ + // | IN FIFO 0 | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // In FIFO is allocated by following rules: + // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". + // - Offset: allocated so far + // - Size - as described above + + // Determine required numbers + // Remaining space available in bytes + uint16_t const fifo_remaining = EP_FIFO_SIZE/4 - _allocated_fifo_words; + + // Required space by EPs in words, number of bulk and control EPs + uint16_t ep_sz_total = 0; + uint8_t nbc = 0; + // EP0 is already taken care of so exclude that here + for (cnt_ep = 1; cnt_ep < EP_MAX; cnt_ep++) + { + ep_sz_total += report.ep_size[cnt_ep][TUSB_DIR_IN] / 4 + (report.ep_size[cnt_ep][TUSB_DIR_IN] % 4 > 0 ? 1 : 0); // Since we need full words take care of remainders! + nbc += (report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] | report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]); + } + + if (ep_sz_total > fifo_remaining) + { + // Too less space available to apply this allocation scheme - return false and set a flag such that a different approach may be used TODO: introduce flag + return false; + } + + uint16_t extra_space = nbc > 0 ? fifo_remaining / nbc : 0; // If no bulk or control EPs are used we just leave the rest of the memory unused + uint16_t fifo_size; + + // Setup FIFOs + for (cnt_ep = 1; cnt_ep < EP_MAX; cnt_ep++) + { + // If EP is used + if (report.ep_size[cnt_ep][TUSB_DIR_IN] > 0) + { + fifo_size = report.ep_size[cnt_ep][TUSB_DIR_IN] / 4 + (report.ep_size[cnt_ep][TUSB_DIR_IN] % 4 > 0 ? 1 : 0) + ((report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] || report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]) ? extra_space : 0); + usb_otg->DIEPTXF[cnt_ep - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; + _allocated_fifo_words += fifo_size; + } + } + + // usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; // Enable interrupts dev->DAINTMSK |= (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); @@ -1111,6 +1270,8 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration // USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + out_ep[0].DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + return true; } -- cgit v1.3.1 From 7d9efd06979f6cdde2a4093f0c26e8100312c92c Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 4 Aug 2020 14:18:12 +0700 Subject: manually submit unplugged event for nrf dcd_disconnect() --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index fdf56b6ca..cd35f2e5b 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -271,6 +271,10 @@ void dcd_disconnect(uint8_t rhport) { (void) rhport; NRF_USBD->USBPULLUP = 0; + + // Disable Pull-up does not trigger Power USB Removed, in fact it have no + // impact on the USB Power status at all -> need to submit unplugged event to the stack. + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, false); } // connect by enabling internal pull-up resistor on D+/D- @@ -693,6 +697,8 @@ void tusb_hal_nrf_power_event (uint32_t event) switch ( event ) { case USB_EVT_DETECTED: + TU_LOG2("Power USB Detect\r\n"); + if ( !NRF_USBD->ENABLE ) { /* Prepare for READY event receiving */ @@ -743,6 +749,12 @@ void tusb_hal_nrf_power_event (uint32_t event) break; case USB_EVT_READY: + TU_LOG2("Power USB Ready\r\n"); + + // Skip if pull-up is enabled and HCLK is already running. + // Application probably call this more than necessary. + if ( NRF_USBD->USBPULLUP && hfclk_running() ) break; + /* Waiting for USBD peripheral enabled */ while ( !(USBD_EVENTCAUSE_READY_Msk & NRF_USBD->EVENTCAUSE) ) { } @@ -810,6 +822,7 @@ void tusb_hal_nrf_power_event (uint32_t event) break; case USB_EVT_REMOVED: + TU_LOG2("Power USB Removed\r\n"); if ( NRF_USBD->ENABLE ) { // Abort all transfers -- cgit v1.3.1 From e9aa36a6e8991335d72666058f9c135c3331d238 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 31 Jul 2020 16:04:10 +0200 Subject: Fix synopsys odd/even frame bit for IN ISO endpoints For ISO endpoint driver has to specify when data is to be transmitted (odd or even frame). Currently code was not updating this bit resulting in data being sent every other frame. If interval was 1ms full data packed was sent every 2ms, and ZLP was sent in between. --- src/portable/st/synopsys/dcd_synopsys.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 03c33c598..283fefd01 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -365,6 +365,13 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c ((total_bytes << USB_OTG_DIEPTSIZ_XFRSIZ_Pos) & USB_OTG_DIEPTSIZ_XFRSIZ_Msk); in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; + // For ISO endpoint set correct odd/even bit for next frame. + if ((in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPTYP) == USB_OTG_DIEPCTL_EPTYP_0) + { + // Take odd/even bit from frame counter. + uint32_t const odd_frame_now = (dev->DSTS & (1u << USB_OTG_DSTS_FNSOF_Pos)); + in_ep[epnum].DIEPCTL |= (odd_frame_now ? USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Msk : USB_OTG_DIEPCTL_SODDFRM_Msk); + } // Enable fifo empty interrupt only if there are something to put in the fifo. if(total_bytes != 0) { dev->DIEPEMPMSK |= (1 << epnum); -- cgit v1.3.1 From 01b9b77d3b94ed83931d6a51c1b357f03f188e76 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Aug 2020 14:47:32 +0700 Subject: allow application driver to overwrite built-in one - position application driver before built-in - remove dcd.h from public include. --- src/class/msc/msc_device.c | 1 + src/class/usbtmc/usbtmc_device.c | 1 - src/device/usbd.c | 47 +++++++++++++++++++++++----------------- src/device/usbd.h | 16 +++----------- 4 files changed, 31 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 9b79b68a7..f3f2e536e 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -31,6 +31,7 @@ #include "common/tusb_common.h" #include "msc_device.h" #include "device/usbd_pvt.h" +#include "device/dcd.h" // for faking dcd_event_xfer_complete //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index a3ff76079..bc5f23f42 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -80,7 +80,6 @@ #include #include "usbtmc.h" #include "usbtmc_device.h" -#include "device/dcd.h" #include "device/usbd.h" #include "osal/osal.h" diff --git a/src/device/usbd.c b/src/device/usbd.c index 7fc7189a5..6b91048b6 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -203,30 +203,30 @@ static usbd_class_driver_t const _usbd_driver[] = #endif }; -enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; +enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; // Additional class drivers implemented by application static usbd_class_driver_t const * _app_driver = NULL; static uint8_t _app_driver_count = 0; -// virtually joins built-in and application drivers together -// All drivers = built-in + application +// virtually joins built-in and application drivers together. +// Application is positioned first to allow overwriting built-in ones. static inline usbd_class_driver_t const * get_driver(uint8_t drvid) { - // Built-in drivers - if (drvid < USBD_CLASS_DRIVER_COUNT) return &_usbd_driver[drvid]; - - // App drivers + // Application drivers if ( usbd_app_driver_get_cb ) { - drvid -= USBD_CLASS_DRIVER_COUNT; if ( drvid < _app_driver_count ) return &_app_driver[drvid]; + drvid -= _app_driver_count; } + // Built-in drivers + if (drvid < BUILTIN_DRIVER_COUNT) return &_usbd_driver[drvid]; + return NULL; } -#define TOTAL_DRIVER_COUNT (USBD_CLASS_DRIVER_COUNT+_app_driver_count) +#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) //--------------------------------------------------------------------+ // DCD Event @@ -245,6 +245,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const static bool process_set_config(uint8_t rhport, uint8_t cfg_num); static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); +// from usbd_control.c void usbd_control_reset(void); void usbd_control_set_request(tusb_control_request_t const *request); void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ); @@ -252,7 +253,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, //--------------------------------------------------------------------+ -// Debugging +// Debug //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= 2 static char const* const _usbd_event_str[DCD_EVENT_COUNT] = @@ -327,6 +328,20 @@ bool tud_remote_wakeup(void) return true; } +bool tud_disconnect(void) +{ + TU_VERIFY(dcd_disconnect); + dcd_disconnect(TUD_OPT_RHPORT); + return true; +} + +bool tud_connect(void) +{ + TU_VERIFY(dcd_connect); + dcd_connect(TUD_OPT_RHPORT); + return true; +} + //--------------------------------------------------------------------+ // USBD Task //--------------------------------------------------------------------+ @@ -593,7 +608,6 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const uint8_t const cfg_num = (uint8_t) p_request->wValue; if ( !_usbd_dev.configured && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) ); - _usbd_dev.configured = cfg_num ? 1 : 0; tud_control_status(rhport, p_request); @@ -688,18 +702,12 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const break; case TUSB_REQ_CLEAR_FEATURE: - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) - { - usbd_edpt_clear_stall(rhport, ep_addr); - } + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) usbd_edpt_clear_stall(rhport, ep_addr); tud_control_status(rhport, p_request); break; case TUSB_REQ_SET_FEATURE: - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) - { - usbd_edpt_stall(rhport, ep_addr); - } + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) usbd_edpt_stall(rhport, ep_addr); tud_control_status(rhport, p_request); break; @@ -773,7 +781,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { usbd_class_driver_t const *driver = get_driver(drv_id); - uint16_t const drv_len = driver->open(rhport, desc_itf, remaining_len); if ( drv_len > 0 ) diff --git a/src/device/usbd.h b/src/device/usbd.h index 098e94075..5338be157 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -35,7 +35,6 @@ #endif #include "common/tusb_common.h" -#include "dcd.h" //--------------------------------------------------------------------+ // Application API @@ -53,6 +52,7 @@ void tud_task (void); bool tud_task_event_ready(void); // Interrupt handler, name alias to DCD +extern void dcd_int_handler(uint8_t rhport); #define tud_int_handler dcd_int_handler // Get current bus speed @@ -75,21 +75,11 @@ bool tud_remote_wakeup(void); // Enable pull-up resistor on D+ D- // Return false on unsupported MCUs -static inline bool tud_disconnect(void) -{ - TU_VERIFY(dcd_disconnect); - dcd_disconnect(TUD_OPT_RHPORT); - return true; -} +bool tud_disconnect(void); // Disable pull-up resistor on D+ D- // Return false on unsupported MCUs -static inline bool tud_connect(void) -{ - TU_VERIFY(dcd_connect); - dcd_connect(TUD_OPT_RHPORT); - return true; -} +bool tud_connect(void); // Carry out Data and Status stage of control transfer // - If len = 0, it is equivalent to sending status only -- cgit v1.3.1 From a9d362185b5985062ce3f1a618a67938d9c9d5f7 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Aug 2020 15:06:19 +0700 Subject: update note for app driver list mustbe accesible at all time. --- src/device/usbd_pvt.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index e430a81d9..a5d223329 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -54,6 +54,7 @@ typedef struct // Invoked when initializing device stack to get additional class drivers. // Can optionally implemented by application to extend/overwrite class driver support. +// Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; //--------------------------------------------------------------------+ -- cgit v1.3.1 From 61e96e97cb078a8ae52a2bef107ebefd540603a4 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 Aug 2020 22:09:16 +0700 Subject: use usbd_edpt_open in bth driver --- src/class/bth/bth_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index 04011bcdb..252e20e37 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -121,7 +121,7 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(dcd_edpt_open(rhport, desc_ep), 0); + TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); _btd_itf.ep_ev = desc_ep->bEndpointAddress; // Open endpoint pair -- cgit v1.3.1 From 88c5e2a37ffee3d82107076642b64227cd66dc17 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 12 Aug 2020 10:18:11 +0200 Subject: Fix synopsys fifo flush during stall Wrong FIFO was flushed in dcd_edpt_stall(). (epnum - 1) should only be used when accessing DIEPTXF registers. For DIEPCTL and GRSTCTL epnum is correct index. --- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 3c349582f..aaf586ed0 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -667,7 +667,7 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) } // Flush the FIFO, and wait until we have confirmed it cleared. - usb_otg->GRSTCTL |= ((epnum - 1) << USB_OTG_GRSTCTL_TXFNUM_Pos); + usb_otg->GRSTCTL |= (epnum << USB_OTG_GRSTCTL_TXFNUM_Pos); usb_otg->GRSTCTL |= USB_OTG_GRSTCTL_TXFFLSH; while((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH_Msk) != 0); } else { -- cgit v1.3.1 From e8d50a3c57c0665cb254d3a88e3e18f9c31ad045 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 14 Aug 2020 14:29:35 +0200 Subject: Add dcd_edpt_close() to synopsys Endpoint close was implemented only in one driver so far. This function is needed for interfaces with several alternate settings. The way FIFO is allocated in dcd_edpt_open() allows to correctly close only one IN endpoint (the one that was opened last). --- src/portable/st/synopsys/dcd_synopsys.c | 38 +++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index aaf586ed0..cc7181c3d 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -637,9 +637,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -// TODO: The logic for STALLing and disabling an endpoint is very similar -// (send STALL versus NAK handshakes back). Refactor into resuable function. -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) +static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall) { (void) rhport; @@ -654,14 +652,14 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) if(dir == TUSB_DIR_IN) { // Only disable currently enabled non-control endpoint if ( (epnum == 0) || !(in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPENA) ){ - in_ep[epnum].DIEPCTL |= (USB_OTG_DIEPCTL_SNAK | USB_OTG_DIEPCTL_STALL); + in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SNAK | (stall ? USB_OTG_DIEPCTL_STALL : 0); } else { // Stop transmitting packets and NAK IN xfers. in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SNAK; while((in_ep[epnum].DIEPINT & USB_OTG_DIEPINT_INEPNE) == 0); // Disable the endpoint. - in_ep[epnum].DIEPCTL |= (USB_OTG_DIEPCTL_STALL | USB_OTG_DIEPCTL_EPDIS); + in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPDIS | (stall ? USB_OTG_DIEPCTL_STALL : 0); while((in_ep[epnum].DIEPINT & USB_OTG_DIEPINT_EPDISD_Msk) == 0); in_ep[epnum].DIEPINT = USB_OTG_DIEPINT_EPDISD; } @@ -673,7 +671,7 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) } else { // Only disable currently enabled non-control endpoint if ( (epnum == 0) || !(out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPENA) ){ - out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_STALL; + out_ep[epnum].DOEPCTL |= stall ? USB_OTG_DOEPCTL_STALL : 0; } else { // Asserting GONAK is required to STALL an OUT endpoint. // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt @@ -683,7 +681,7 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) while((usb_otg->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF_Msk) == 0); // Ditto here- disable the endpoint. - out_ep[epnum].DOEPCTL |= (USB_OTG_DOEPCTL_STALL | USB_OTG_DOEPCTL_EPDIS); + out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPDIS | (stall ? USB_OTG_DOEPCTL_STALL : 0); while((out_ep[epnum].DOEPINT & USB_OTG_DOEPINT_EPDISD_Msk) == 0); out_ep[epnum].DOEPINT = USB_OTG_DOEPINT_EPDISD; @@ -693,6 +691,32 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) } } +/** + * Close an endpoint. + */ +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) +{ + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + dcd_edpt_disable(rhport, ep_addr, false); + if (dir == TUSB_DIR_IN) + { + uint16_t const fifo_size = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXFD_Msk) >> USB_OTG_DIEPTXF_INEPTXFD_Pos; + uint16_t const fifo_start = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXSA_Msk) >> USB_OTG_DIEPTXF_INEPTXSA_Pos; + // For now only endpoint that has FIFO at the end of FIFO memory can be closed without fuss. + TU_ASSERT(fifo_start + fifo_size == _allocated_fifo_words,); + _allocated_fifo_words -= fifo_size; + } +} + +void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) +{ + dcd_edpt_disable(rhport, ep_addr, true); +} + void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; -- cgit v1.3.1 From 444e4d282137953e6834360a9fb866331d21d954 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 16 Aug 2020 13:48:25 +0200 Subject: Add EP close. Fix bug in set_interface within audio. --- src/class/audio/audio_device.c | 1545 ++++++++++++++++--------------- src/portable/st/synopsys/dcd_synopsys.c | 37 + 2 files changed, 812 insertions(+), 770 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index b5fbf70f3..2e3625825 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -48,77 +48,77 @@ //--------------------------------------------------------------------+ typedef struct { - uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function + uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function #if CFG_TUD_AUDIO_EPSIZE_IN - uint8_t ep_in; // Outgoing (out of uC) audio data EP. - uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) + uint8_t ep_in; // Outgoing (out of uC) audio data EP. + uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif #if CFG_TUD_AUDIO_EPSIZE_OUT - uint8_t ep_out; // Incoming (into uC) audio data EP. - uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) + uint8_t ep_out; // Incoming (into uC) audio data EP. + uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint8_t ep_fb; // Feedback EP. + uint8_t ep_fb; // Feedback EP. #endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - uint8_t ep_int_ctr; // Audio control interrupt EP. + uint8_t ep_int_ctr; // Audio control interrupt EP. #endif #if CFG_TUD_AUDIO_N_AS_INT - uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; + uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! #endif - /*------------- From this point, data is not cleared by bus reset -------------*/ + /*------------- From this point, data is not cleared by bus reset -------------*/ - // Buffer for control requests - CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_AUDIO_CTRL_BUF_SIZE]; + // Buffer for control requests + CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_AUDIO_CTRL_BUF_SIZE]; - // FIFO + // FIFO #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; - CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_FIFO_SIZE]; + tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; + CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; + osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; #endif #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; - CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_FIFO_SIZE]; + tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; + CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; + osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; #endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - tu_fifo_t int_ctr_ff; - CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; + tu_fifo_t int_ctr_ff; + CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t int_ctr_ff_mutex; + osal_mutex_def_t int_ctr_ff_mutex; #endif #endif - // Endpoint Transfer buffers + // Endpoint Transfer buffers #if CFG_TUD_AUDIO_EPSIZE_OUT - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) - // TODO: required? - //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // uint16_t fb_val; // Feedback value for asynchronous mode! - //#endif + // TODO: required? + //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // uint16_t fb_val; // Feedback value for asynchronous mode! + //#endif #endif #if CFG_TUD_AUDIO_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN]; + CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN]; #endif } audiod_interface_t; @@ -164,37 +164,37 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); bool tud_audio_n_mounted(uint8_t itf) { - audiod_interface_t* audio = &_audiod_itf[itf]; + audiod_interface_t* audio = &_audiod_itf[itf]; #if CFG_TUD_AUDIO_EPSIZE_OUT - if (audio->ep_out == 0) - { - return false; - } + if (audio->ep_out == 0) + { + return false; + } #endif #if CFG_TUD_AUDIO_EPSIZE_IN - if (audio->ep_in == 0) - { - return false; - } + if (audio->ep_in == 0) + { + return false; + } #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - if (audio->ep_int_ctr == 0) - { - return false; - } + if (audio->ep_int_ctr == 0) + { + return false; + } #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (audio->ep_fb == 0) - { - return false; - } + if (audio->ep_fb == 0) + { + return false; + } #endif - return true; + return true; } //--------------------------------------------------------------------+ @@ -205,20 +205,20 @@ bool tud_audio_n_mounted(uint8_t itf) uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + return tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); } uint16_t tud_audio_n_read(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); } void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); } #endif @@ -227,17 +227,17 @@ void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId) uint16_t tud_audio_int_ctr_n_available(uint8_t itf) { - return tu_fifo_count(&_audiod_itf[itf].int_ctr_ff); + return tu_fifo_count(&_audiod_itf[itf].int_ctr_ff); } uint16_t tud_audio_int_ctr_n_read(uint8_t itf, void* buffer, uint16_t bufsize) { - return tu_fifo_read_n(&_audiod_itf[itf].int_ctr_ff, buffer, bufsize); + return tu_fifo_read_n(&_audiod_itf[itf].int_ctr_ff, buffer, bufsize); } void tud_audio_int_ctr_n_read_flush (uint8_t itf) { - tu_fifo_clear(&_audiod_itf[itf].int_ctr_ff); + tu_fifo_clear(&_audiod_itf[itf].int_ctr_ff); } #endif @@ -249,42 +249,42 @@ void tud_audio_int_ctr_n_read_flush (uint8_t itf) static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) { - switch (CFG_TUD_AUDIO_FORMAT_TYPE_RX) - { - case AUDIO_FORMAT_TYPE_UNDEFINED: - // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! - asm("nop"); - break; + switch (CFG_TUD_AUDIO_FORMAT_TYPE_RX) + { + case AUDIO_FORMAT_TYPE_UNDEFINED: + // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! + asm("nop"); + break; - case AUDIO_FORMAT_TYPE_I: + case AUDIO_FORMAT_TYPE_I: - switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) - { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: + switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) + { + case AUDIO_DATA_FORMAT_TYPE_I_PCM: #if CFG_TUD_AUDIO_RX_FIFO_SIZE - TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); + TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); #else #error YOUR DECODING AND BUFFERING IS REQUIRED HERE! #endif - break; - - default: - // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! - asm("nop"); - break; - } - break; - - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! - asm("nop"); - break; - } - - // Call a weak callback here - a possibility for user to get informed RX was completed - TTU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); - return true; + break; + + default: + // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! + asm("nop"); + break; + } + break; + + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! + asm("nop"); + break; + } + + // Call a weak callback here - a possibility for user to get informed RX was completed + TTU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); + return true; } #endif //CFG_TUD_AUDIO_EPSIZE_OUT @@ -293,38 +293,38 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* #if CFG_TUD_AUDIO_RX_FIFO_SIZE static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize) { - (void) rhport; + (void) rhport; - // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel - if (bufsize % CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX*CFG_TUD_AUDIO_N_CHANNELS_RX != 0) { - return false; - } + // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel + if (bufsize % CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX*CFG_TUD_AUDIO_N_CHANNELS_RX != 0) { + return false; + } - uint8_t chId = 0; - uint16_t cnt; + uint8_t chId = 0; + uint16_t cnt; #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 - uint8_t sample = 0; + uint8_t sample = 0; #elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 2 - uint16_t sample = 0; + uint16_t sample = 0; #else - uint32_t sample = 0; + uint32_t sample = 0; #endif - for(cnt = 0; cnt < bufsize; cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) - { - // Let alignment problems be handled by memcpy - memcpy(&sample, &buffer[cnt], CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX); - if(tu_fifo_write_n(&audio->rx_ff[chId++], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE) != CFG_TUD_AUDIO_RX_ITEMSIZE) - { - // Buffer overflow - return false; - } - - if (chId == CFG_TUD_AUDIO_N_CHANNELS_RX) - { - chId = 0; - } - } + for(cnt = 0; cnt < bufsize; cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) + { + // Let alignment problems be handled by memcpy + memcpy(&sample, &buffer[cnt], CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX); + if(tu_fifo_write_n(&audio->rx_ff[chId++], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE) != CFG_TUD_AUDIO_RX_ITEMSIZE) + { + // Buffer overflow + return false; + } + + if (chId == CFG_TUD_AUDIO_N_CHANNELS_RX) + { + chId = 0; + } + } } } #endif //CFG_TUD_AUDIO_RX_FIFO_SIZE @@ -332,15 +332,15 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a #if CFG_TUD_AUDIO_EPSIZE_OUT TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize) { - (void) rhport; - (void) buffer; - (void) bufsize; + (void) rhport; + (void) buffer; + (void) bufsize; - /* NOTE: This function should not be modified, when the callback is needed, + /* NOTE: This function should not be modified, when the callback is needed, the tud_audio_rx_done_cb could be implemented in the user file - */ + */ - return true; + return true; } #endif @@ -351,12 +351,12 @@ TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_ #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) { - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) { - return 0; - } + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->p_desc == NULL) { + return 0; + } - return tu_fifo_write_n(&audio->tx_ff[channelId], buffer, bufsize); + return tu_fifo_write_n(&audio->tx_ff[channelId], buffer, bufsize); } #endif @@ -364,12 +364,12 @@ uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, uint8_t const* buffer uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t bufsize) { - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->itf_num == 0) { - return 0; - } + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->itf_num == 0) { + return 0; + } - return tu_fifo_write_n(&audio->int_ctr_ff, buffer, bufsize); + return tu_fifo_write_n(&audio->int_ctr_ff, buffer, bufsize); } #endif @@ -380,42 +380,42 @@ uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t #if CFG_TUD_AUDIO_EPSIZE_IN static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) { - switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) - { - case AUDIO_FORMAT_TYPE_UNDEFINED: - // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! - asm("nop"); - break; + switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) + { + case AUDIO_FORMAT_TYPE_UNDEFINED: + // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! + asm("nop"); + break; - case AUDIO_FORMAT_TYPE_I: + case AUDIO_FORMAT_TYPE_I: - switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_TX) - { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: + switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_TX) + { + case AUDIO_DATA_FORMAT_TYPE_I_PCM: #if CFG_TUD_AUDIO_TX_FIFO_SIZE - TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); + TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); #else #error YOUR ENCODING AND BUFFERING IS REQUIRED HERE! #endif - break; - - default: - // YOUR ENCODING AND SENDING IS REQUIRED HERE! - asm("nop"); - break; - } - break; - - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! - asm("nop"); - break; - } - - // Call a weak callback here - a possibility for user to get informed TX was completed - TU_VERIFY(tud_audio_tx_done_cb(rhport, n_bytes_copied)); - return true; + break; + + default: + // YOUR ENCODING AND SENDING IS REQUIRED HERE! + asm("nop"); + break; + } + break; + + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! + asm("nop"); + break; + } + + // Call a weak callback here - a possibility for user to get informed TX was completed + TU_VERIFY(tud_audio_tx_done_cb(rhport, n_bytes_copied)); + return true; } #endif //CFG_TUD_AUDIO_EPSIZE_IN @@ -423,65 +423,65 @@ static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t #if CFG_TUD_AUDIO_TX_FIFO_SIZE static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) { - // We encode directly into IN EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); - - // Determine amount of samples - uint16_t nSamplesPerChannelToSend = 0xFFFF; - uint8_t cntChannel; - - for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) - { - if (audio->tx_ff[cntChannel].count < nSamplesPerChannelToSend) - { - nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count; - } - } - - // Check if there is enough - if (nSamplesPerChannelToSend == 0) - { - *n_bytes_copied = 0; - return true; - } - - // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - if (nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX > CFG_TUD_AUDIO_EPSIZE_IN) - { - nSamplesPerChannelToSend = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - } - - // Encode - uint16_t cntSample; - uint8_t * pBuff = audio->epin_buf; + // We encode directly into IN EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); + + // Determine amount of samples + uint16_t nSamplesPerChannelToSend = 0xFFFF; + uint8_t cntChannel; + + for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + { + if (audio->tx_ff[cntChannel].count < nSamplesPerChannelToSend) + { + nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count; + } + } + + // Check if there is enough + if (nSamplesPerChannelToSend == 0) + { + *n_bytes_copied = 0; + return true; + } + + // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! + if (nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX > CFG_TUD_AUDIO_EPSIZE_IN) + { + nSamplesPerChannelToSend = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + } + + // Encode + uint16_t cntSample; + uint8_t * pBuff = audio->epin_buf; #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 - uint8_t sample; + uint8_t sample; #elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 - uint16_t sample; + uint16_t sample; #else - uint32_t sample; + uint32_t sample; #endif - // TODO: Big endianess handling - for (cntSample = 0; cntSample < nSamplesPerChannelToSend; cntSample++) - { - for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) - { - // Get sample from buffer - tu_fifo_read(&audio->tx_ff[cntChannel], &sample); - - // Put it into EP's buffer - Let alignment problems be handled by memcpy - memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); - - // Advance pointer - pBuff += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - } - } - - // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX)); - *n_bytes_copied = nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - return true; + // TODO: Big endianess handling + for (cntSample = 0; cntSample < nSamplesPerChannelToSend; cntSample++) + { + for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + { + // Get sample from buffer + tu_fifo_read(&audio->tx_ff[cntChannel], &sample); + + // Put it into EP's buffer - Let alignment problems be handled by memcpy + memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); + + // Advance pointer + pBuff += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + } + } + + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX)); + *n_bytes_copied = nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + return true; } #endif //CFG_TUD_AUDIO_TX_FIFO_SIZE @@ -491,14 +491,14 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) { - (void) rhport; - (void) audio; + (void) rhport; + (void) audio; - // Here we need to return the feedback value + // Here we need to return the feedback value #error RETURN YOUR FEEDBACK VALUE HERE! - TU_VERIFY(tud_audio_fb_done_cb(rhport)); - return 0; + TU_VERIFY(tud_audio_fb_done_cb(rhport)); + return 0; } #endif @@ -508,23 +508,23 @@ static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN static bool audio_int_ctr_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) { - // We write directly into the EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_int_ctr)); + // We write directly into the EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_int_ctr)); - // TODO: Big endianess handling - uint16_t cnt = tu_fifo_read_n(audio->int_ctr_ff, audio->ep_int_ctr_buf, CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN); + // TODO: Big endianess handling + uint16_t cnt = tu_fifo_read_n(audio->int_ctr_ff, audio->ep_int_ctr_buf, CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN); - if (cnt > 0) - { - // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_int_ctr, audio->ep_int_ctr_buf, cnt)); - } + if (cnt > 0) + { + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_int_ctr, audio->ep_int_ctr_buf, cnt)); + } - *n_bytes_copied = cnt; + *n_bytes_copied = cnt; - TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, n_bytes_copied)); + TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, n_bytes_copied)); - return true; + return true; } #endif @@ -534,41 +534,41 @@ static bool audio_int_ctr_done_cb(uint8_t rhport, audiod_interface_t* audio, uin #if CFG_TUD_AUDIO_EPSIZE_IN TU_ATTR_WEAK bool tud_audio_tx_done_cb(uint8_t rhport, uint16_t * n_bytes_copied) { - (void) rhport; - (void) n_bytes_copied; + (void) rhport; + (void) n_bytes_copied; - /* NOTE: This function should not be modified, when the callback is needed, + /* NOTE: This function should not be modified, when the callback is needed, the tud_audio_tx_done_cb could be implemented in the user file - */ + */ - return true; + return true; } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport) { - (void) rhport; + (void) rhport; - /* NOTE: This function should not be modified, when the callback is needed, + /* NOTE: This function should not be modified, when the callback is needed, the tud_audio_fb_done_cb could be implemented in the user file - */ + */ - return true; + return true; } #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_copied) { - (void) rhport; - (void) n_bytes_copied; + (void) rhport; + (void) n_bytes_copied; - /* NOTE: This function should not be modified, when the callback is needed, + /* NOTE: This function should not be modified, when the callback is needed, the tud_audio_int_ctr_done_cb could be implemented in the user file - */ + */ - return true; + return true; } #endif @@ -578,591 +578,596 @@ TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_c //--------------------------------------------------------------------+ void audiod_init(void) { - uint8_t cnt; - tu_memclr(_audiod_itf, sizeof(_audiod_itf)); + uint8_t cnt; + tu_memclr(_audiod_itf, sizeof(_audiod_itf)); - for(uint8_t i=0; itx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true); + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + { + tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); + tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); #endif - } + } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) - { - tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true); + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + { + tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); + tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); #endif - } + } #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 - tu_fifo_config(&audio->int_ctr_ff, &audio->int_ctr_ff_buf, CFG_TUD_AUDIO_INT_CTR_BUFSIZE, 1, true); + tu_fifo_config(&audio->int_ctr_ff, &audio->int_ctr_ff_buf, CFG_TUD_AUDIO_INT_CTR_BUFSIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->int_ctr_ff, osal_mutex_create(&audio->int_ctr_ff_mutex)); + tu_fifo_config_mutex(&audio->int_ctr_ff, osal_mutex_create(&audio->int_ctr_ff_mutex)); #endif #endif - } + } } void audiod_reset(uint8_t rhport) { - (void) rhport; + (void) rhport; - for(uint8_t i=0; itx_ff[cnt]); - } + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + { + tu_fifo_clear(&audio->tx_ff[cnt]); + } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) - { - tu_fifo_clear(&audio->rx_ff[cnt]); - } + for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + { + tu_fifo_clear(&audio->rx_ff[cnt]); + } #endif - } + } } uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { - TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); - - // Verify version is correct - this check can be omitted - TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); - - // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted - if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed - { - TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); - } - - // Alternate setting MUST be zero - this check can be omitted - TU_VERIFY(itf_desc->bAlternateSetting == 0); - - // Find available audio driver interface - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) - { - if (!_audiod_itf[i].p_desc) - { - _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one - break; - } - } - - // Verify we found a free one - TU_ASSERT( i < CFG_TUD_AUDIO ); - - // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - - // Notify caller we read complete descriptor - // (*p_length) += tud_audio_desc_lengths[i]; - // TODO: Find a way to find end of current audio function and avoid necessity of tud_audio_desc_lengths - since now max_length is available we could do this surely somehow - uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor - - return drv_len; + TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); + + // Verify version is correct - this check can be omitted + TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); + + // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted + if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed + { + TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); + } + + // Alternate setting MUST be zero - this check can be omitted + TU_VERIFY(itf_desc->bAlternateSetting == 0); + + // Find available audio driver interface + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (!_audiod_itf[i].p_desc) + { + _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one + break; + } + } + + // Verify we found a free one + TU_ASSERT( i < CFG_TUD_AUDIO ); + + // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) + + // Notify caller we read complete descriptor + // (*p_length) += tud_audio_desc_lengths[i]; + // TODO: Find a way to find end of current audio function and avoid necessity of tud_audio_desc_lengths - since now max_length is available we could do this surely somehow + uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor + + return drv_len; } static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) { #if CFG_TUD_AUDIO_N_AS_INT > 0 - uint8_t const itf = tu_u16_low(p_request->wIndex); + uint8_t const itf = tu_u16_low(p_request->wIndex); - // Find index of audio streaming interface - uint8_t idxDriver, idxItf; - uint8_t const *dummy; + // Find index of audio streaming interface + uint8_t idxDriver, idxItf; + uint8_t const *dummy; - TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].altSetting[idxItf], 1)); + TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].altSetting[idxItf], 1)); - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].altSetting[idxItf]); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].altSetting[idxItf]); - return true; + return true; #else - (void) rhport; - (void) p_request; - return false; + (void) rhport; + (void) p_request; + return false; #endif } static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request) { - (void) rhport; + (void) rhport; - // Here we need to do the following: + // Here we need to do the following: - // 1. Find the audio driver assigned to the given interface to be set - // Since one audio driver interface has to be able to cover an unknown number of interfaces (AC, AS + its alternate settings), the best memory efficient way to solve this is to always search through the descriptors. - // The audio driver is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching + // 1. Find the audio driver assigned to the given interface to be set + // Since one audio driver interface has to be able to cover an unknown number of interfaces (AC, AS + its alternate settings), the best memory efficient way to solve this is to always search through the descriptors. + // The audio driver is mapped to an audio function by a reference pointer to the corresponding AC interface of this audio function which serves as a starting point for searching - // 2. Close EPs which are currently open - // To do so it is not necessary to know the current active alternate interface since we already save the current EP addresses - we simply close them + // 2. Close EPs which are currently open + // To do so it is not necessary to know the current active alternate interface since we already save the current EP addresses - we simply close them - // 3. Open new EP + // 3. Open new EP - uint8_t const itf = tu_u16_low(p_request->wIndex); - uint8_t const alt = tu_u16_low(p_request->wValue); + uint8_t const itf = tu_u16_low(p_request->wIndex); + uint8_t const alt = tu_u16_low(p_request->wValue); - TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); + TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); - // Find index of audio streaming interface and index of interface - uint8_t idxDriver, idxItf; - uint8_t const *p_desc; - TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); + // Find index of audio streaming interface and index of interface + uint8_t idxDriver, idxItf; + uint8_t const *p_desc; + TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); - // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) + // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) #if CFG_TUD_AUDIO_EPSIZE_IN > 0 - if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) - { - _audiod_itf[idxDriver].ep_in_as_intf_num = 0; - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); - _audiod_itf[idxDriver].ep_in = 0; // Necessary? - } + if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) + { + _audiod_itf[idxDriver].ep_in_as_intf_num = 0; + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); + _audiod_itf[idxDriver].ep_in = 0; // Necessary? + } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT - if (_audiod_itf[idxDriver].ep_out_as_intf_num == itf) - { - _audiod_itf[idxDriver].ep_out_as_intf_num = 0; - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_out); - _audiod_itf[idxDriver].ep_out = 0; // Necessary? + if (_audiod_itf[idxDriver].ep_out_as_intf_num == itf) + { + _audiod_itf[idxDriver].ep_out_as_intf_num = 0; + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_out); + _audiod_itf[idxDriver].ep_out = 0; // Necessary? - // Close corresponding feedback EP + // Close corresponding feedback EP #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_fb); - _audiod_itf[idxDriver].ep_fb = 0; // Necessary? + usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_fb); + _audiod_itf[idxDriver].ep_fb = 0; // Necessary? #endif - } + } #endif - // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface - // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[idxDriver].p_desc + tud_audio_desc_lengths[idxDriver]; - - // p_desc starts at required interface with alternate setting zero - while (p_desc < p_desc_end) + // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[idxDriver].p_desc + tud_audio_desc_lengths[idxDriver]; + + // p_desc starts at required interface with alternate setting zero + while (p_desc < p_desc_end) + { + // Find correct interface + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) + { + // From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary + uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints; + while (foundEPs < nEps && p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) { - // Find correct interface - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) - { - // Open EPs - uint8_t foundEPs = 0; - while (foundEPs < ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints && p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) - { -// TU_ASSERT(dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false); - TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *)p_desc)); - uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *)p_desc)); + uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; #if CFG_TUD_AUDIO_EPSIZE_IN > 0 - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP - { - _audiod_itf[idxDriver].ep_in = ep_addr; - } + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP + { + _audiod_itf[idxDriver].ep_in = ep_addr; + _audiod_itf[idxDriver].ep_in_as_intf_num = itf; + } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT - if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary - { - // Save address - _audiod_itf[idxDriver].ep_out = ep_addr; + if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary + { + // Save address + _audiod_itf[idxDriver].ep_out = ep_addr; + _audiod_itf[idxDriver].ep_out_as_intf_num = itf; - // Prepare for incoming data - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); - } + // Prepare for incoming data + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback - { - _audiod_itf[idxDriver].ep_fb = ep_addr; - } + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback + { + _audiod_itf[idxDriver].ep_fb = ep_addr; + } #endif #endif - foundEPs += 1; - } - p_desc = tu_desc_next(p_desc); - } + foundEPs += 1; + } + p_desc = tu_desc_next(p_desc); + } - // We are done - abort loop - break; - } + TU_VERIFY(foundEPs == nEps); - // Increase index, bytes read, and pointer - p_desc = tu_desc_next(p_desc); - } + // We are done - abort loop + break; + } - // Check for nothing found - we can rely on this since EP descriptors are never the last descriptors, there are always also class specific EP descriptors following! - TU_VERIFY(p_desc < p_desc_end); + // Moving forward + p_desc = tu_desc_next(p_desc); + } - // Save current alternative interface setting - _audiod_itf[idxDriver].altSetting[idxItf] = alt; +// // Check for nothing found - we can rely on this since EP descriptors are never the last descriptors, there are always also class specific EP descriptors following! +// TU_VERIFY(p_desc < p_desc_end); - // Invoke callback - if (tud_audio_set_itf_cb) - { - if (!tud_audio_set_itf_cb(rhport, p_request)) return false; - } + // Save current alternative interface setting + _audiod_itf[idxDriver].altSetting[idxItf] = alt; + + // Invoke callback + if (tud_audio_set_itf_cb) + { + if (!tud_audio_set_itf_cb(rhport, p_request)) return false; + } + + // Start sending or receiving? - tud_control_status(rhport, p_request); + tud_control_status(rhport, p_request); - return true; + return true; } // Invoked when class request DATA stage is finished. // return false to stall control EP (e.g Host send non-sense DATA) bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) { - // Handle audio class specific set requests - if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) + // Handle audio class specific set requests + if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) + { + uint8_t idxDriver; + + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + if (entityID != 0) + { + if (tud_audio_set_req_entity_cb) { - uint8_t idxDriver; - - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - if (entityID != 0) - { - if (tud_audio_set_req_entity_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); - - // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); - } - else - { - TU_LOG2(" No entity set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - else - { - if (tud_audio_set_req_itf_cb) - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); - - // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); - } - else - { - TU_LOG2(" No interface set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - } - - break; - - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - if (tud_audio_set_req_ep_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); - - // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); - } - else - { - TU_LOG2(" No EP set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - - // Unknown/Unsupported recipient - default: TU_BREAKPOINT(); return false; - } + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + } + else + { + TU_LOG2(" No entity set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } + } + else + { + if (tud_audio_set_req_itf_cb) + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); } - return true; + else + { + TU_LOG2(" No interface set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } + } + + break; + + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + if (tud_audio_set_req_ep_cb) + { + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + } + else + { + TU_LOG2(" No EP set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } + + // Unknown/Unsupported recipient + default: TU_BREAKPOINT(); return false; + } + } + return true; } // Handle class control request // return false to stall control endpoint (e.g unsupported request) bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) { - (void) rhport; - - // Handle standard requests - standard set requests usually have no data stage so we also handle set requests here - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) + (void) rhport; + + // Handle standard requests - standard set requests usually have no data stage so we also handle set requests here + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) + { + switch (p_request->bRequest) + { + case TUSB_REQ_GET_INTERFACE: + return audiod_get_interface(rhport, p_request); + + case TUSB_REQ_SET_INTERFACE: + return audiod_set_interface(rhport, p_request); + + // Unknown/Unsupported request + default: TU_BREAKPOINT(); return false; + } + } + + // Handle class requests + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) + { + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t idxDriver; + + // Conduct checks which depend on the recipient + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present + if (entityID != 0) + { + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + if (tud_audio_get_req_entity_cb) + { + return tud_audio_get_req_entity_cb(rhport, p_request); + } + else + { + TU_LOG2(" No entity get request callback available!\r\n"); + return false; // Stall + } + } + } + else + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - switch (p_request->bRequest) - { - case TUSB_REQ_GET_INTERFACE: - return audiod_get_interface(rhport, p_request); + if (tud_audio_get_req_itf_cb) + { + return tud_audio_get_req_itf_cb(rhport, p_request); + } + else + { + TU_LOG2(" No interface get request callback available!\r\n"); + return false; // Stall + } + } + } + break; - case TUSB_REQ_SET_INTERFACE: - return audiod_set_interface(rhport, p_request); + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - // Unknown/Unsupported request - default: TU_BREAKPOINT(); return false; - } - } + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); - // Handle class requests - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + if (tud_audio_get_req_ep_cb) + { + return tud_audio_get_req_ep_cb(rhport, p_request); + } + else { - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t idxDriver; - - // Conduct checks which depend on the recipient - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) - { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_entity_cb) - { - return tud_audio_get_req_entity_cb(rhport, p_request); - } - else - { - TU_LOG2(" No entity get request callback available!\r\n"); - return false; // Stall - } - } - } - else - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_itf_cb) - { - return tud_audio_get_req_itf_cb(rhport, p_request); - } - else - { - TU_LOG2(" No interface get request callback available!\r\n"); - return false; // Stall - } - } - } - break; - - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else - { - TU_LOG2(" No EP get request callback available!\r\n"); - return false; // Stall - } - } - break; - - // Unknown/Unsupported recipient - default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; - } - - // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf, CFG_TUD_AUDIO_CTRL_BUF_SIZE)); - return true; + TU_LOG2(" No EP get request callback available!\r\n"); + return false; // Stall } + } + break; - // There went something wrong - unsupported control request type - TU_BREAKPOINT(); - return false; + // Unknown/Unsupported recipient + default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; + } + + // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished + TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf, CFG_TUD_AUDIO_CTRL_BUF_SIZE)); + return true; + } + + // There went something wrong - unsupported control request type + TU_BREAKPOINT(); + return false; } bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - (void) result; + (void) result; - // Search for interface belonging to given end point address and proceed as required - uint8_t idxDriver; - for (idxDriver = 0; idxDriver < CFG_TUD_AUDIO; idxDriver++) - { + // Search for interface belonging to given end point address and proceed as required + uint8_t idxDriver; + for (idxDriver = 0; idxDriver < CFG_TUD_AUDIO; idxDriver++) + { #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - // Data transmission of control interrupt finished - if (_audiod_itf[idxDriver].ep_int_ctr == ep_addr) - { - // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) - // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? - // In case of an erroneous transmission a retransmission is conducted - this is taken care of by PHY ??? - - // Load new data - uint16 *n_bytes_copied; - TU_VERIFY(audio_int_ctr_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); - - if (*n_bytes_copied == 0 && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN))) - { - // There is no data left to send, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); - } - } + // Data transmission of control interrupt finished + if (_audiod_itf[idxDriver].ep_int_ctr == ep_addr) + { + // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) + // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? + // In case of an erroneous transmission a retransmission is conducted - this is taken care of by PHY ??? + + // Load new data + uint16 *n_bytes_copied; + TU_VERIFY(audio_int_ctr_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); + + if (*n_bytes_copied == 0 && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN))) + { + // There is no data left to send, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + } #endif #if CFG_TUD_AUDIO_EPSIZE_IN - // Data transmission of audio packet finished - if (_audiod_itf[idxDriver].ep_in == ep_addr) - { - // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." - // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." - // This can only be solved reliably if we load a ZLP after every IN transmission since we can not say if the host requests samples earlier than we declared! Once all samples are collected we overwrite the loaded ZLP. - - // Check if there is data to load into EPs buffer - if not load it with ZLP - // Be aware - we as a device are not able to know if the host polls for data with a faster rate as we stated this in the descriptors. Therefore we always have to put something into the EPs buffer. However, once we did that, there is no way of aborting this or replacing what we put into the buffer before! - // This is the only place where we can fill something into the EPs buffer! - - // Load new data - uint16_t *n_bytes_copied = NULL; - TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); - - if (*n_bytes_copied == 0) - { - // Load with ZLP - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); - } - - return true; - } + // Data transmission of audio packet finished + if (_audiod_itf[idxDriver].ep_in == ep_addr) + { + // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." + // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." + // This can only be solved reliably if we load a ZLP after every IN transmission since we can not say if the host requests samples earlier than we declared! Once all samples are collected we overwrite the loaded ZLP. + + // Check if there is data to load into EPs buffer - if not load it with ZLP + // Be aware - we as a device are not able to know if the host polls for data with a faster rate as we stated this in the descriptors. Therefore we always have to put something into the EPs buffer. However, once we did that, there is no way of aborting this or replacing what we put into the buffer before! + // This is the only place where we can fill something into the EPs buffer! + + // Load new data + uint16_t *n_bytes_copied = NULL; + TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); + + if (*n_bytes_copied == 0) + { + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + + return true; + } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT - // New audio packet received - if (_audiod_itf[idxDriver].ep_out == ep_addr) - { - // Save into buffer - do whatever has to be done - TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].epout_buf, xferred_bytes)); + // New audio packet received + if (_audiod_itf[idxDriver].ep_out == ep_addr) + { + // Save into buffer - do whatever has to be done + TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].epout_buf, xferred_bytes)); - // prepare for next transmission - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + // prepare for next transmission + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); - return true; - } + return true; + } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Transmission of feedback EP finished - if (_audiod_itf[idxDriver].ep_fb == ep_addr) - { - if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver])) - { - // Load with ZLP - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); - } - - return true; - } + // Transmission of feedback EP finished + if (_audiod_itf[idxDriver].ep_fb == ep_addr) + { + if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver])) + { + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } + + return true; + } #endif #endif - } + } - return false; + return false; } bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len) { - // Handles only sending of data not receiving - if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; + // Handles only sending of data not receiving + if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; - // Get corresponding driver index - uint8_t idxDriver; - uint8_t itf = TU_U16_LOW(p_request->wIndex); + // Get corresponding driver index + uint8_t idxDriver; + uint8_t itf = TU_U16_LOW(p_request->wIndex); - // Conduct checks which depend on the recipient - switch (p_request->bmRequestType_bit.recipient) - { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + // Conduct checks which depend on the recipient + switch (p_request->bmRequestType_bit.recipient) + { + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - // Verify if entity is present - if (entityID != 0) - { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); - } - else - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); - } - break; + // Verify if entity is present + if (entityID != 0) + { + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + } + else + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + } + break; - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - uint8_t ep = TU_U16_LOW(p_request->wIndex); + uint8_t ep = TU_U16_LOW(p_request->wIndex); - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); - break; + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + break; - // Unknown/Unsupported recipient - default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; - } + // Unknown/Unsupported recipient + default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; + } - // Crop length - if (len > CFG_TUD_AUDIO_CTRL_BUF_SIZE) len = CFG_TUD_AUDIO_CTRL_BUF_SIZE; + // Crop length + if (len > CFG_TUD_AUDIO_CTRL_BUF_SIZE) len = CFG_TUD_AUDIO_CTRL_BUF_SIZE; - // Copy into buffer - memcpy((void *)_audiod_itf[idxDriver].ctrl_buf, data, (size_t)len); + // Copy into buffer + memcpy((void *)_audiod_itf[idxDriver].ctrl_buf, data, (size_t)len); - // Schedule transmit - return tud_control_xfer(rhport, p_request, (void*)_audiod_itf[idxDriver].ctrl_buf, len); + // Schedule transmit + return tud_control_xfer(rhport, p_request, (void*)_audiod_itf[idxDriver].ctrl_buf, len); } // This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function @@ -1170,120 +1175,120 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req // finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) { - // Loop over audio driver interfaces - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) + // Loop over audio driver interfaces + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (_audiod_itf[i].p_desc) + { + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + // Advance past AC descriptors + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); + p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; + + uint8_t tmp = 0; + while (p_desc < p_desc_end) + { + // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) { - if (_audiod_itf[i].p_desc) - { - // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; - - // Advance past AC descriptors - uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - - uint8_t tmp = 0; - while (p_desc < p_desc_end) - { - // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) - { - *idxItf = tmp; - *idxDriver = i; - *pp_desc_int = p_desc; - return true; - } - - // Increase index, bytes read, and pointer - tmp++; - p_desc = tu_desc_next(p_desc); - } - } + *idxItf = tmp; + *idxDriver = i; + *pp_desc_int = p_desc; + return true; } - return false; + // Increase index, bytes read, and pointer + tmp++; + p_desc = tu_desc_next(p_desc); + } + } + } + + return false; } // Verify an entity with the given ID exists and returns also the corresponding driver index static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver) { - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + // Look for the correct driver by checking if the unique standard AC interface number fits + if (_audiod_itf[i].p_desc && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) + { + // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); // Points to CS AC descriptor + uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; + p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor + + while (p_desc < p_desc_end) + { + if (p_desc[3] == entityID) // Entity IDs are always at offset 3 { - // Look for the correct driver by checking if the unique standard AC interface number fits - if (_audiod_itf[i].p_desc && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) - { - // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between - uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); // Points to CS AC descriptor - uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; - p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor - - while (p_desc < p_desc_end) - { - if (p_desc[3] == entityID) // Entity IDs are always at offset 3 - { - *idxDriver = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } + *idxDriver = i; + return true; } - return false; + p_desc = tu_desc_next(p_desc); + } + } + } + return false; } static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) { - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (_audiod_itf[i].p_desc) + { + // Get pointer at beginning and end + uint8_t const *p_desc = _audiod_itf[i].p_desc; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + while (p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) { - if (_audiod_itf[i].p_desc) - { - // Get pointer at beginning and end - uint8_t const *p_desc = _audiod_itf[i].p_desc; - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; - - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) - { - *idxDriver = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } + *idxDriver = i; + return true; } - return false; + p_desc = tu_desc_next(p_desc); + } + } + } + return false; } static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) { - uint8_t i; - for (i = 0; i < CFG_TUD_AUDIO; i++) + uint8_t i; + for (i = 0; i < CFG_TUD_AUDIO; i++) + { + if (_audiod_itf[i].p_desc) + { + // Get pointer at end + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + + // Advance past AC descriptors - EP we look for are streaming EPs + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); + p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; + + while (p_desc < p_desc_end) + { + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) { - if (_audiod_itf[i].p_desc) - { - // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; - - // Advance past AC descriptors - EP we look for are streaming EPs - uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - - while (p_desc < p_desc_end) - { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) - { - *idxDriver = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } + *idxDriver = i; + return true; } - return false; + p_desc = tu_desc_next(p_desc); + } + } + } + return false; } #endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 133a3736a..68c30c4b5 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -673,6 +673,43 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } +/** + * Close an EP. + * + * Currently, we only deactivate the EPs and do not fully disable them - this might not be necessary! + * + */ +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); + + USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + + if(dir == TUSB_DIR_IN) + { + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + + // Disable interrupt for this EP + dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); + + // Clear USB active EP + in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_USBAEP; + } + else + { + USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); + + // Disable interrupt for this EP + dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum));; + + // Clear USB active EP bit + out_ep[epnum].DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP; + + } +} + bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); -- cgit v1.3.1 From c14f68e2c1db7ce82fb8e05d40d8b0b9a83aced6 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 19 Aug 2020 21:07:43 +0200 Subject: Commit before sharing. Setup a test example - UNTESTED! Missing: Start transmitting audio data in set_interface. --- examples/device/audio_test/Makefile | 12 + examples/device/audio_test/src/main.c | 367 +++++ examples/device/audio_test/src/tusb_config.h | 112 ++ examples/device/audio_test/src/usb_descriptors.c | 167 +++ src/class/audio/audio.h | 1627 +++++++++++----------- src/class/audio/audio_device.c | 90 +- src/class/audio/audio_device.h | 9 +- src/portable/st/synopsys/dcd_synopsys.c | 1 + 8 files changed, 1503 insertions(+), 882 deletions(-) create mode 100644 examples/device/audio_test/Makefile create mode 100644 examples/device/audio_test/src/main.c create mode 100644 examples/device/audio_test/src/tusb_config.h create mode 100644 examples/device/audio_test/src/usb_descriptors.c (limited to 'src') diff --git a/examples/device/audio_test/Makefile b/examples/device/audio_test/Makefile new file mode 100644 index 000000000..5a455078e --- /dev/null +++ b/examples/device/audio_test/Makefile @@ -0,0 +1,12 @@ +include ../../../tools/top.mk +include ../../make.mk + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +include ../../rules.mk diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c new file mode 100644 index 000000000..e55c64c7c --- /dev/null +++ b/examples/device/audio_test/src/main.c @@ -0,0 +1,367 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Reinhard Panhuber + * + * 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. + * + */ + +#include +#include +#include + +#include "bsp/board.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ + +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +// Audio controls +// Current states +bool mute[CFG_TUD_AUDIO_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint16_t volume[CFG_TUD_AUDIO_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint32_t sampFreq; +uint8_t clkValid; + +// Range states +audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_N_CHANNELS_TX+1]; // Volume range state +audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state + +void led_blinking_task(void); +void audio_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + tusb_init(); + + // Init values + sampFreq = 44100; + clkValid = 1; + + sampleFreqRng.wNumSubRanges = 1; + sampleFreqRng.subrange[0].bMin = 44100; + sampleFreqRng.subrange[0].bMax = 44100; + sampleFreqRng.subrange[0].bRes = 0; + + while (1) + { + tud_task(); // tinyusb device task + led_blinking_task(); + audio_task(); + } + + + return 0; +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + blink_interval_ms = BLINK_NOT_MOUNTED; +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) +{ + (void) remote_wakeup_en; + blink_interval_ms = BLINK_SUSPENDED; +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +//--------------------------------------------------------------------+ +// AUDIO Task +//--------------------------------------------------------------------+ + +void audio_task(void) +{ + // Yet to be filled - e.g. put meas data into TX FIFOs etc. + asm("nop"); +} + +//--------------------------------------------------------------------+ +// Application Callback API Implementations +//--------------------------------------------------------------------+ + +// Invoked when audio class specific set request received for an EP +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + return false; // Yet not implemented +} + +// Invoked when audio class specific set request received for an interface +bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + return false; // Yet not implemented +} + +// Invoked when audio class specific set request received for an entity +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // If request is for our feature unit + if (entityID == 2) + { + switch (ctrlSel) + { + case AUDIO_FU_CTRL_MUTE: + // Request uses format layout 1 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); + + mute[channelNum] = ((audio_control_cur_1_t *)pBuff)->bCur; + + TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); + + return true; + + case AUDIO_FU_CTRL_VOLUME: + // Request uses format layout 2 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); + + volume[channelNum] = ((audio_control_cur_2_t *)pBuff)->bCur; + + TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); + + return true; + + // Unknown/Unsupported control + default: TU_BREAKPOINT(); return false; + } + } + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an EP +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + // return tud_control_xfer(rhport, p_request, &tmp, 1); + + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an interface +bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an entity +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + // uint8_t itf = TU_U16_LOW(p_request->wIndex); // Since we have only one audio function implemented, we do not need the itf value + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Input terminal (Microphone input) + if (entityID == 1) + { + switch (ctrlSel) + { + case AUDIO_TE_CTRL_CONNECTOR:; + // The terminal connector control only has a get request with only the CUR attribute. + + audio_desc_channel_cluster_t ret; + + // Those are dummy values for now + ret.bNrChannels = 1; + ret.bmChannelConfig = 0; + ret.iChannelNames = 0; + + TU_LOG2(" Get terminal connector\r\n"); + + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*)&ret, sizeof(ret)); + + // Unknown/Unsupported control selector + default: TU_BREAKPOINT(); return false; + } + } + + // Feature unit + if (entityID == 2) + { + switch (ctrlSel) + { + case AUDIO_FU_CTRL_MUTE: + // Audio control mute cur parameter block consists of only one byte - we thus can send it right away + // There does not exist a range parameter block for mute + TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); + + case AUDIO_FU_CTRL_VOLUME: + + switch (p_request->bRequest) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); + + // Copy values - only for testing - better is version below + audio_control_range_2_n_t(1) ret; + + ret.wNumSubRanges = 1; + ret.subrange[0].bMin = -90; // -90 dB + ret.subrange[0].bMax = 90; // +90 dB + ret.subrange[0].bRes = 1; // 1 dB steps + + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*)&ret, sizeof(ret)); + + // Unknown/Unsupported control + default: TU_BREAKPOINT(); return false; + } + + // Unknown/Unsupported control + default: TU_BREAKPOINT(); return false; + } + } + + // Clock Source unit + if (entityID == 4) + { + switch (ctrlSel) + { + case AUDIO_CS_CTRL_SAM_FREQ: + + // channelNum is always zero in this case + + switch (p_request->bRequest) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Sample Freq.\r\n"); + return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Sample Freq. range\r\n"); + return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); + + // Unknown/Unsupported control + default: TU_BREAKPOINT(); return false; + } + + case AUDIO_CS_CTRL_CLK_VALID: + // Only cur attribute exists for this request + TU_LOG2(" Get Sample Freq. valid\r\n"); + return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); + + // Unknown/Unsupported control + default: TU_BREAKPOINT(); return false; + } + } + + TU_LOG2(" Unsupported entity: %d\r\n", entityID); + return false; // Yet not implemented +} + +//--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +void led_blinking_task(void) +{ + static uint32_t start_ms = 0; + static bool led_state = false; + + // Blink every interval ms + if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h new file mode 100644 index 000000000..6cd6882bc --- /dev/null +++ b/examples/device/audio_test/src/tusb_config.h @@ -0,0 +1,112 @@ +/* + * 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 _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU +#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 +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#else +#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 +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_HID 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_AUDIO 1 +#define CFG_TUD_VENDOR 0 + +//-------------------------------------------------------------------- +// AUDIO CLASS DRIVER CONFIGURATION +//-------------------------------------------------------------------- + +// Audio format type +#define CFG_TUD_AUDIO_USE_TX_FIFO 1 +#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_I +#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED + +// Audio format type I specifications +#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM +#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 3 + +// EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) +#define CFG_TUD_AUDIO_EPSIZE_IN 45*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX*CFG_TUD_AUDIO_N_CHANNELS_TX // 45 Samples (44.1 kHz) x 3 Bytes/Sample x 1 Channels +#define CFG_TUD_AUDIO_TX_FIFO_SIZE 45*4 // 45 Samples (44.1 kHz) x 4 Bytes/Sample (1 word) + +// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) +#define CFG_TUD_AUDIO_N_AS_INT 1 + +// Size of control request buffer +#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_test/src/usb_descriptors.c b/examples/device/audio_test/src/usb_descriptors.c new file mode 100644 index 000000000..0b4f9b62c --- /dev/null +++ b/examples/device/audio_test/src/usb_descriptors.c @@ -0,0 +1,167 @@ +/* + * 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. + * + */ + +#include "tusb.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] AUDIO | 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) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ +enum +{ + ITF_NUM_AUDIO_CONTROL = 0, + ITF_NUM_AUDIO_STREAMING, + ITF_NUM_TOTAL +}; + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_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 ... +#define EPNUM_AUDIO 0x03 +#else +#define EPNUM_AUDIO 0x01 +#endif + +// These variables are required by the audio driver in audio_device.c + +// List of audio descriptor lengths which is required by audio driver - you need as many entries as CFG_TUD_AUDIO - unfortunately this is not possible to determine otherwise +const uint16_t tud_audio_desc_lengths[] = {TUD_AUDIO_MIC_DESC_LEN}; + +// TAKE CARE - THE NUMBER OF AUDIO STREAMING INTERFACES PER AUDIO FUNCTION MUST NOT EXCEED CFG_TUD_AUDIO_N_AS_INT - IF IT DOES INCREASE CFG_TUD_AUDIO_N_AS_INT IN tusb_config.h! + +uint8_t const desc_configuration[] = +{ + // 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), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_AUDIO_MIC_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ 3, /*_nBitsUsedPerSample*/ 24, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ 45*3) +}; + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// 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; +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "PaniRCorp", // 1: Manufacturer + "MicNode", // 2: Product + "123456", // 3: Serials, should use chip ID + "UAC2", // 4: Audio Interface +}; + +static uint16_t _desc_str[32]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void) langid; + + uint8_t chr_count; + + if ( index == 0) + { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + }else + { + // Convert ASCII string into UTF-16 + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + if ( chr_count > 31 ) chr_count = 31; + + for(uint8_t i=0; i 0 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP { + // Save address _audiod_itf[idxDriver].ep_in = ep_addr; _audiod_itf[idxDriver].ep_in_as_intf_num = itf; + + // HERE WE WOULD NEED TO SCHEDULE OUR FIRST TRANSMIT, HOWEVER, WE ALSO WOULD FIRST NEED TO ENABLE SAMPLING AT ALL - HOW TO HANDLE THIS? + // Invoke callback - fill something in the FIFO here for now + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + + uint16_t n_bytes_copied; + TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); } #endif @@ -791,6 +759,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * _audiod_itf[idxDriver].ep_out = ep_addr; _audiod_itf[idxDriver].ep_out_as_intf_num = itf; + // Invoke callback + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + // Prepare for incoming data TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); } @@ -799,6 +770,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback { _audiod_itf[idxDriver].ep_fb = ep_addr; + + // Invoke callback + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); } #endif @@ -818,20 +792,6 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_desc = tu_desc_next(p_desc); } -// // Check for nothing found - we can rely on this since EP descriptors are never the last descriptors, there are always also class specific EP descriptors following! -// TU_VERIFY(p_desc < p_desc_end); - - // Save current alternative interface setting - _audiod_itf[idxDriver].altSetting[idxItf] = alt; - - // Invoke callback - if (tud_audio_set_itf_cb) - { - if (!tud_audio_set_itf_cb(rhport, p_request)) return false; - } - - // Start sending or receiving? - tud_control_status(rhport, p_request); return true; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 9766eb5f9..b745ceb09 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -1,7 +1,8 @@ /* * The MIT License (MIT) * - * Copyright (c) 2020 Ha Thach (tinyusb.org) and Reinhard Panhuber + * Copyright (c) 2020 Ha Thach (tinyusb.org) + * Copyright (c) 2020 Reinhard Panhuber * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -217,15 +218,15 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_EPSIZE_IN -bool tud_audio_tx_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); +TU_ATTR_WEAK bool tud_audio_tx_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); #endif #if CFG_TUD_AUDIO_EPSIZE_OUT -bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize); +TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize); #endif #if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -bool tud_audio_fb_done_cb(uint8_t rhport); +TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 2d42dd43b..c188bb485 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -4,6 +4,7 @@ * Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries * Copyright (c) 2019 Ha Thach (tinyusb.org) * Copyright (c) 2020 Jan Duempelmann + * Copyright (c) 2020 Reinhard Panhuber * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal -- cgit v1.3.1 From 15b063beb287785b2bf84d00361000036afaba2c Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Thu, 20 Aug 2020 02:20:01 -0700 Subject: Smarter CDC TX refill logic --- src/class/cdc/cdc_device.c | 10 ++++++---- src/class/cdc/cdc_device.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index d8be48688..da9e94133 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -416,7 +416,12 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Though maybe the baudrate is not really important !!! if ( ep_addr == p_cdc->ep_in ) { - if ( 0 == tud_cdc_n_write_flush(itf) ) + uint32_t flushed = tud_cdc_n_write_flush(itf); + + // invoke transmit callback to possibly refill tx fifo + if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); + + if ( 0 == flushed && tu_fifo_empty(&p_cdc->tx_ff) ) { // There is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero @@ -425,9 +430,6 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); } } - - // invoke transmit callback to possibly refill tx fifo - if ( tud_cdc_tx_cb && !tu_fifo_full(&p_cdc->tx_ff) ) tud_cdc_tx_cb(itf); } // nothing to do with notif endpoint for now diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 13b59416b..7e9e8ca21 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -129,7 +129,7 @@ TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); // Invoked when space becomes available in TX buffer -TU_ATTR_WEAK void tud_cdc_tx_cb(uint8_t itf); +TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf); // Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); -- cgit v1.3.1 From 72183c7bb44ff117d9abac7b6e9c373c0945fb0b Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Thu, 20 Aug 2020 09:59:23 -0700 Subject: Slight optimization for cdc tx refill --- src/class/cdc/cdc_device.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index da9e94133..513fe203b 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -416,12 +416,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Though maybe the baudrate is not really important !!! if ( ep_addr == p_cdc->ep_in ) { - uint32_t flushed = tud_cdc_n_write_flush(itf); - // invoke transmit callback to possibly refill tx fifo if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); - if ( 0 == flushed && tu_fifo_empty(&p_cdc->tx_ff) ) + if ( 0 == tud_cdc_n_write_flush(itf) ) { // There is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero -- cgit v1.3.1 From 37be0ca73238a40a2387c2e2566ae39f5cae6e08 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 20 Aug 2020 20:09:44 +0200 Subject: Fix formatting, get rid of all tabs. --- src/class/audio/audio.h | 1584 +++++++++++++++---------------- src/class/audio/audio_device.c | 660 ++++--------- src/class/audio/audio_device.h | 88 +- src/portable/st/synopsys/dcd_synopsys.c | 103 +- 4 files changed, 1093 insertions(+), 1342 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 1afacf0c4..5e64549ed 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -39,748 +39,748 @@ extern "C" { #endif - /// Audio Device Class Codes - - /// A.2 - Audio Function Subclass Codes - typedef enum - { - AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, - } audio_function_subclass_type_t; - - /// A.3 - Audio Function Protocol Codes - typedef enum - { - AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00, - AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 - } audio_function_protocol_code_t; - - /// A.5 - Audio Interface Subclass Codes - typedef enum - { - AUDIO_SUBCLASS_UNDEFINED = 0x00, - AUDIO_SUBCLASS_CONTROL , ///< Audio Control - AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming - AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming - } audio_subclass_type_t; - - /// A.6 - Audio Interface Protocol Codes - typedef enum - { - AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, - AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 - } audio_interface_protocol_code_t; - - /// A.7 - Audio Function Category Codes - typedef enum - { - AUDIO_FUNC_UNDEF = 0x00, - AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, - AUDIO_FUNC_HOME_THEATER = 0x02, - AUDIO_FUNC_MICROPHONE = 0x03, - AUDIO_FUNC_HEADSET = 0x04, - AUDIO_FUNC_TELEPHONE = 0x05, - AUDIO_FUNC_CONVERTER = 0x06, - AUDIO_FUNC_SOUND_RECODER = 0x07, - AUDIO_FUNC_IO_BOX = 0x08, - AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, - AUDIO_FUNC_PRO_AUDIO = 0x0A, - AUDIO_FUNC_AUDIO_VIDEO = 0x0B, - AUDIO_FUNC_CONTROL_PANEL = 0x0C, - AUDIO_FUNC_OTHER = 0xFF, - } audio_function_code_t; - - /// A.9 - Audio Class-Specific AC Interface Descriptor Subtypes UAC2 - typedef enum - { - AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, - AUDIO_CS_AC_INTERFACE_HEADER = 0x01, - AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, - AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, - AUDIO_CS_AC_INTERFACE_MIXER_UNIT = 0x04, - AUDIO_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, - AUDIO_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, - AUDIO_CS_AC_INTERFACE_EFFECT_UNIT = 0x07, - AUDIO_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08, - AUDIO_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09, - AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A, - AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B, - AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C, - AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, - } audio_cs_ac_interface_subtype_t; - - /// A.10 - Audio Class-Specific AS Interface Descriptor Subtypes UAC2 - typedef enum - { - AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, - AUDIO_CS_AS_INTERFACE_AS_GENERAL = 0x01, - AUDIO_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, - AUDIO_CS_AS_INTERFACE_ENCODER = 0x03, - AUDIO_CS_AS_INTERFACE_DECODER = 0x04, - } audio_cs_as_interface_subtype_t; - - /// A.11 - Effect Unit Effect Types - typedef enum - { - AUDIO_EFFECT_TYPE_UNDEF = 0x00, - AUDIO_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01, - AUDIO_EFFECT_TYPE_REVERBERATION = 0x02, - AUDIO_EFFECT_TYPE_MOD_DELAY = 0x03, - AUDIO_EFFECT_TYPE_DYN_RANGE_COMP = 0x04, - } audio_effect_unit_effect_type_t; - - /// A.12 - Processing Unit Process Types - typedef enum - { - AUDIO_PROCESS_TYPE_UNDEF = 0x00, - AUDIO_PROCESS_TYPE_UP_DOWN_MIX = 0x01, - AUDIO_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02, - AUDIO_PROCESS_TYPE_STEREO_EXTENDER = 0x03, - } audio_processing_unit_process_type_t; - - /// A.13 - Audio Class-Specific EP Descriptor Subtypes UAC2 - typedef enum - { - AUDIO_CS_EP_SUBTYPE_UNDEF = 0x00, - AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, - } audio_cs_ep_subtype_t; - - /// A.14 - Audio Class-Specific Request Codes - typedef enum - { - AUDIO_CS_REQ_UNDEF = 0x00, - AUDIO_CS_REQ_CUR = 0x01, - AUDIO_CS_REQ_RANGE = 0x02, - AUDIO_CS_REQ_MEM = 0x03, - } audio_cs_req_t; - - /// A.17 - Control Selector Codes - - /// A.17.1 - Clock Source Control Selectors - typedef enum - { - AUDIO_CS_CTRL_UNDEF = 0x00, - AUDIO_CS_CTRL_SAM_FREQ = 0x01, - AUDIO_CS_CTRL_CLK_VALID = 0x02, - } audio_clock_src_control_selector_t; - - /// A.17.2 - Clock Selector Control Selectors - typedef enum - { - AUDIO_CX_CTRL_UNDEF = 0x00, - AUDIO_CX_CTRL_CONTROL = 0x01, - } audio_clock_sel_control_selector_t; - - /// A.17.3 - Clock Multiplier Control Selectors - typedef enum - { - AUDIO_CM_CTRL_UNDEF = 0x00, - AUDIO_CM_CTRL_NUMERATOR_CONTROL = 0x01, - AUDIO_CM_CTRL_DENOMINATOR_CONTROL = 0x02, - } audio_clock_mul_control_selector_t; - - /// A.17.4 - Terminal Control Selectors - typedef enum - { - AUDIO_TE_CTRL_UNDEF = 0x00, - AUDIO_TE_CTRL_COPY_PROTECT = 0x01, - AUDIO_TE_CTRL_CONNECTOR = 0x02, - AUDIO_TE_CTRL_OVERLOAD = 0x03, - AUDIO_TE_CTRL_CLUSTER = 0x04, - AUDIO_TE_CTRL_UNDERFLOW = 0x05, - AUDIO_TE_CTRL_OVERFLOW = 0x06, - AUDIO_TE_CTRL_LATENCY = 0x07, - } audio_terminal_control_selector_t; - - /// A.17.5 - Mixer Control Selectors - typedef enum - { - AUDIO_MU_CTRL_UNDEF = 0x00, - AUDIO_MU_CTRL_MIXER = 0x01, - AUDIO_MU_CTRL_CLUSTER = 0x02, - AUDIO_MU_CTRL_UNDERFLOW = 0x03, - AUDIO_MU_CTRL_OVERFLOW = 0x04, - AUDIO_MU_CTRL_LATENCY = 0x05, - } audio_mixer_control_selector_t; - - /// A.17.6 - Selector Control Selectors - typedef enum - { - AUDIO_SU_CTRL_UNDEF = 0x00, - AUDIO_SU_CTRL_SELECTOR = 0x01, - AUDIO_SU_CTRL_LATENCY = 0x02, - } audio_sel_control_selector_t; - - /// A.17.7 - Feature Unit Control Selectors - typedef enum - { - AUDIO_FU_CTRL_UNDEF = 0x00, - AUDIO_FU_CTRL_MUTE = 0x01, - AUDIO_FU_CTRL_VOLUME = 0x02, - AUDIO_FU_CTRL_BASS = 0x03, - AUDIO_FU_CTRL_MID = 0x04, - AUDIO_FU_CTRL_TREBLE = 0x05, - AUDIO_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, - AUDIO_FU_CTRL_AGC = 0x07, - AUDIO_FU_CTRL_DELAY = 0x08, - AUDIO_FU_CTRL_BASS_BOOST = 0x09, - AUDIO_FU_CTRL_LOUDNESS = 0x0A, - AUDIO_FU_CTRL_INPUT_GAIN = 0x0B, - AUDIO_FU_CTRL_GAIN_PAD = 0x0C, - AUDIO_FU_CTRL_INVERTER = 0x0D, - AUDIO_FU_CTRL_UNDERFLOW = 0x0E, - AUDIO_FU_CTRL_OVERVLOW = 0x0F, - AUDIO_FU_CTRL_LATENCY = 0x10, - } audio_feature_unit_control_selector_t; - - /// A.17.8 Effect Unit Control Selectors - - /// A.17.8.1 Parametric Equalizer Section Effect Unit Control Selectors - typedef enum - { - AUDIO_PE_CTRL_UNDEF = 0x00, - AUDIO_PE_CTRL_ENABLE = 0x01, - AUDIO_PE_CTRL_CENTERFREQ = 0x02, - AUDIO_PE_CTRL_QFACTOR = 0x03, - AUDIO_PE_CTRL_GAIN = 0x04, - AUDIO_PE_CTRL_UNDERFLOW = 0x05, - AUDIO_PE_CTRL_OVERFLOW = 0x06, - AUDIO_PE_CTRL_LATENCY = 0x07, - } audio_parametric_equalizer_control_selector_t; - - /// A.17.8.2 Reverberation Effect Unit Control Selectors - typedef enum - { - AUDIO_RV_CTRL_UNDEF = 0x00, - AUDIO_RV_CTRL_ENABLE = 0x01, - AUDIO_RV_CTRL_TYPE = 0x02, - AUDIO_RV_CTRL_LEVEL = 0x03, - AUDIO_RV_CTRL_TIME = 0x04, - AUDIO_RV_CTRL_FEEDBACK = 0x05, - AUDIO_RV_CTRL_PREDELAY = 0x06, - AUDIO_RV_CTRL_DENSITY = 0x07, - AUDIO_RV_CTRL_HIFREQ_ROLLOFF = 0x08, - AUDIO_RV_CTRL_UNDERFLOW = 0x09, - AUDIO_RV_CTRL_OVERFLOW = 0x0A, - AUDIO_RV_CTRL_LATENCY = 0x0B, - } audio_reverberation_effect_control_selector_t; - - /// A.17.8.3 Modulation Delay Effect Unit Control Selectors - typedef enum - { - AUDIO_MD_CTRL_UNDEF = 0x00, - AUDIO_MD_CTRL_ENABLE = 0x01, - AUDIO_MD_CTRL_BALANCE = 0x02, - AUDIO_MD_CTRL_RATE = 0x03, - AUDIO_MD_CTRL_DEPTH = 0x04, - AUDIO_MD_CTRL_TIME = 0x05, - AUDIO_MD_CTRL_FEEDBACK = 0x06, - AUDIO_MD_CTRL_UNDERFLOW = 0x07, - AUDIO_MD_CTRL_OVERFLOW = 0x08, - AUDIO_MD_CTRL_LATENCY = 0x09, - } audio_modulation_delay_control_selector_t; - - /// A.17.8.4 Dynamic Range Compressor Effect Unit Control Selectors - typedef enum - { - AUDIO_DR_CTRL_UNDEF = 0x00, - AUDIO_DR_CTRL_ENABLE = 0x01, - AUDIO_DR_CTRL_COMPRESSION_RATE = 0x02, - AUDIO_DR_CTRL_MAXAMPL = 0x03, - AUDIO_DR_CTRL_THRESHOLD = 0x04, - AUDIO_DR_CTRL_ATTACK_TIME = 0x05, - AUDIO_DR_CTRL_RELEASE_TIME = 0x06, - AUDIO_DR_CTRL_UNDERFLOW = 0x07, - AUDIO_DR_CTRL_OVERFLOW = 0x08, - AUDIO_DR_CTRL_LATENCY = 0x09, - } audio_dynamic_range_compression_control_selector_t; - - /// A.17.9 Processing Unit Control Selectors - - /// A.17.9.1 Up/Down-mix Processing Unit Control Selectors - typedef enum - { - AUDIO_UD_CTRL_UNDEF = 0x00, - AUDIO_UD_CTRL_ENABLE = 0x01, - AUDIO_UD_CTRL_MODE_SELECT = 0x02, - AUDIO_UD_CTRL_CLUSTER = 0x03, - AUDIO_UD_CTRL_UNDERFLOW = 0x04, - AUDIO_UD_CTRL_OVERFLOW = 0x05, - AUDIO_UD_CTRL_LATENCY = 0x06, - } audio_up_down_mix_control_selector_t; - - /// A.17.9.2 Dolby Prologic ™ Processing Unit Control Selectors - typedef enum - { - AUDIO_DP_CTRL_UNDEF = 0x00, - AUDIO_DP_CTRL_ENABLE = 0x01, - AUDIO_DP_CTRL_MODE_SELECT = 0x02, - AUDIO_DP_CTRL_CLUSTER = 0x03, - AUDIO_DP_CTRL_UNDERFLOW = 0x04, - AUDIO_DP_CTRL_OVERFLOW = 0x05, - AUDIO_DP_CTRL_LATENCY = 0x06, - } audio_dolby_prologic_control_selector_t; - - /// A.17.9.3 Stereo Extender Processing Unit Control Selectors - typedef enum - { - AUDIO_ST_EXT_CTRL_UNDEF = 0x00, - AUDIO_ST_EXT_CTRL_ENABLE = 0x01, - AUDIO_ST_EXT_CTRL_WIDTH = 0x02, - AUDIO_ST_EXT_CTRL_UNDERFLOW = 0x03, - AUDIO_ST_EXT_CTRL_OVERFLOW = 0x04, - AUDIO_ST_EXT_CTRL_LATENCY = 0x05, - } audio_stereo_extender_control_selector_t; - - /// A.17.10 Extension Unit Control Selectors - typedef enum - { - AUDIO_XU_CTRL_UNDEF = 0x00, - AUDIO_XU_CTRL_ENABLE = 0x01, - AUDIO_XU_CTRL_CLUSTER = 0x02, - AUDIO_XU_CTRL_UNDERFLOW = 0x03, - AUDIO_XU_CTRL_OVERFLOW = 0x04, - AUDIO_XU_CTRL_LATENCY = 0x05, - } audio_extension_unit_control_selector_t; - - /// A.17.11 AudioStreaming Interface Control Selectors - typedef enum - { - AUDIO_AS_CTRL_UNDEF = 0x00, - AUDIO_AS_CTRL_ACT_ALT_SETTING = 0x01, - AUDIO_AS_CTRL_VAL_ALT_SETTINGS = 0x02, - AUDIO_AS_CTRL_AUDIO_DATA_FORMAT = 0x03, - } audio_audiostreaming_interface_control_selector_t; - - /// A.17.12 Encoder Control Selectors - typedef enum - { - AUDIO_EN_CTRL_UNDEF = 0x00, - AUDIO_EN_CTRL_BIT_RATE = 0x01, - AUDIO_EN_CTRL_QUALITY = 0x02, - AUDIO_EN_CTRL_VBR = 0x03, - AUDIO_EN_CTRL_TYPE = 0x04, - AUDIO_EN_CTRL_UNDERFLOW = 0x05, - AUDIO_EN_CTRL_OVERFLOW = 0x06, - AUDIO_EN_CTRL_ENCODER_ERROR = 0x07, - AUDIO_EN_CTRL_PARAM1 = 0x08, - AUDIO_EN_CTRL_PARAM2 = 0x09, - AUDIO_EN_CTRL_PARAM3 = 0x0A, - AUDIO_EN_CTRL_PARAM4 = 0x0B, - AUDIO_EN_CTRL_PARAM5 = 0x0C, - AUDIO_EN_CTRL_PARAM6 = 0x0D, - AUDIO_EN_CTRL_PARAM7 = 0x0E, - AUDIO_EN_CTRL_PARAM8 = 0x0F, - } audio_encoder_control_selector_t; - - /// A.17.13 Decoder Control Selectors - - /// A.17.13.1 MPEG Decoder Control Selectors - typedef enum - { - AUDIO_MPD_CTRL_UNDEF = 0x00, - AUDIO_MPD_CTRL_DUAL_CHANNEL = 0x01, - AUDIO_MPD_CTRL_SECOND_STEREO = 0x02, - AUDIO_MPD_CTRL_MULTILINGUAL = 0x03, - AUDIO_MPD_CTRL_DYN_RANGE = 0x04, - AUDIO_MPD_CTRL_SCALING = 0x05, - AUDIO_MPD_CTRL_HILO_SCALING = 0x06, - AUDIO_MPD_CTRL_UNDERFLOW = 0x07, - AUDIO_MPD_CTRL_OVERFLOW = 0x08, - AUDIO_MPD_CTRL_DECODER_ERROR = 0x09, - } audio_MPEG_decoder_control_selector_t; - - /// A.17.13.2 AC-3 Decoder Control Selectors - typedef enum - { - AUDIO_AD_CTRL_UNDEF = 0x00, - AUDIO_AD_CTRL_MODE = 0x01, - AUDIO_AD_CTRL_DYN_RANGE = 0x02, - AUDIO_AD_CTRL_SCALING = 0x03, - AUDIO_AD_CTRL_HILO_SCALING = 0x04, - AUDIO_AD_CTRL_UNDERFLOW = 0x05, - AUDIO_AD_CTRL_OVERFLOW = 0x06, - AUDIO_AD_CTRL_DECODER_ERROR = 0x07, - } audio_AC3_decoder_control_selector_t; - - /// A.17.13.3 WMA Decoder Control Selectors - typedef enum - { - AUDIO_WD_CTRL_UNDEF = 0x00, - AUDIO_WD_CTRL_UNDERFLOW = 0x01, - AUDIO_WD_CTRL_OVERFLOW = 0x02, - AUDIO_WD_CTRL_DECODER_ERROR = 0x03, - } audio_WMA_decoder_control_selector_t; - - /// A.17.13.4 DTS Decoder Control Selectors - typedef enum - { - AUDIO_DD_CTRL_UNDEF = 0x00, - AUDIO_DD_CTRL_UNDERFLOW = 0x01, - AUDIO_DD_CTRL_OVERFLOW = 0x02, - AUDIO_DD_CTRL_DECODER_ERROR = 0x03, - } audio_DTS_decoder_control_selector_t; - - /// A.17.14 Endpoint Control Selectors - typedef enum - { - AUDIO_EP_CTRL_UNDEF = 0x00, - AUDIO_EP_CTRL_PITCH = 0x01, - AUDIO_EP_CTRL_DATA_OVERRUN = 0x02, - AUDIO_EP_CTRL_DATA_UNDERRUN = 0x03, - } audio_EP_control_selector_t; - - /// Terminal Types - - /// 2.1 - Audio Class-Terminal Types UAC2 - typedef enum - { - AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, - AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, - AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, - } audio_terminal_type_t; - - /// 2.2 - Audio Class-Input Terminal Types UAC2 - typedef enum - { - AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, - AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, - AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, - AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, - AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, - AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, - AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, - } audio_terminal_input_type_t; - - /// 2.3 - Audio Class-Output Terminal Types UAC2 - typedef enum - { - AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, - AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, - AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, - AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, - AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, - AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, - AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, - AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, - } audio_terminal_output_type_t; - - /// Rest is yet to be implemented - - /// Additional Audio Device Class Codes - Source: Audio Data Formats - - /// A.1 - Audio Class-Format Type Codes UAC2 - typedef enum - { - AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, - AUDIO_FORMAT_TYPE_I = 0x01, - AUDIO_FORMAT_TYPE_II = 0x02, - AUDIO_FORMAT_TYPE_III = 0x03, - AUDIO_FORMAT_TYPE_IV = 0x04, - AUDIO_EXT_FORMAT_TYPE_I = 0x81, - AUDIO_EXT_FORMAT_TYPE_II = 0x82, - AUDIO_EXT_FORMAT_TYPE_III = 0x83, - } audio_format_type_t; - - /// A.2.1 - Audio Class-Audio Data Format Type I UAC2 - typedef enum - { - AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), - AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), - AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), - AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), - AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = (uint32_t) (1 << 31), - } audio_data_format_type_I_t; - - /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification - - /// Isochronous End Point Attributes - typedef enum - { - TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, - TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, - TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, - TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point - TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point - } tusb_iso_ep_attribute_t; - - /// Audio Class-Control Values UAC2 - typedef enum - { - AUDIO_CTRL_NONE = 0x00, ///< No Host access - AUDIO_CTRL_R = 0x01, ///< Host read access only - AUDIO_CTRL_RW = 0x03, ///< Host read write access - } audio_control_t; - - /// Audio Class-Specific AC Interface Descriptor Controls UAC2 - typedef enum - { - AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0, - } audio_cs_ac_interface_control_pos_t; - - /// Audio Class-Specific AS Interface Descriptor Controls UAC2 - typedef enum - { - AUDIO_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0, - AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, - } audio_cs_as_interface_control_pos_t; - - /// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 - typedef enum - { - AUDIO_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, - AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, - } audio_cs_as_iso_data_ep_attribute_t; - - /// Audio Class-Specific AS Isochronous Data EP Controls UAC2 - typedef enum - { - AUDIO_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0, - AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2, - AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4, - } audio_cs_as_iso_data_ep_control_pos_t; - - /// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC2 - typedef enum - { - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, - } audio_cs_as_iso_data_ep_lock_delay_unit_t; - - /// Audio Class-Clock Source Attributes UAC2 - typedef enum - { - AUDIO_CLOCK_SOURCE_ATT_EXT_CLK = 0x00, - AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01, - AUDIO_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02, - AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03, - AUDIO_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04, - } audio_clock_source_attribute_t; - - /// Audio Class-Clock Source Controls UAC2 - typedef enum - { - AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0, - AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2, - } audio_clock_source_control_pos_t; - - /// Audio Class-Clock Selector Controls UAC2 - typedef enum - { - AUDIO_CLOCK_SELECTOR_CTRL_POS = 0, - } audio_clock_selector_control_pos_t; - - /// Audio Class-Clock Multiplier Controls UAC2 - typedef enum - { - AUDIO_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0, - AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, - } audio_clock_multiplier_control_pos_t; - - /// Audio Class-Input Terminal Controls UAC2 - typedef enum - { - AUDIO_IN_TERM_CTRL_CPY_PROT_POS = 0, - AUDIO_IN_TERM_CTRL_CONNECTOR_POS = 2, - AUDIO_IN_TERM_CTRL_OVERLOAD_POS = 4, - AUDIO_IN_TERM_CTRL_CLUSTER_POS = 6, - AUDIO_IN_TERM_CTRL_UNDERFLOW_POS = 8, - AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, - } audio_terminal_input_control_pos_t; - - /// Audio Class-Output Terminal Controls UAC2 - typedef enum - { - AUDIO_OUT_TERM_CTRL_CPY_PROT_POS = 0, - AUDIO_OUT_TERM_CTRL_CONNECTOR_POS = 2, - AUDIO_OUT_TERM_CTRL_OVERLOAD_POS = 4, - AUDIO_OUT_TERM_CTRL_UNDERFLOW_POS = 6, - AUDIO_OUT_TERM_CTRL_OVERFLOW_POS = 8, - } audio_terminal_output_control_pos_t; - - /// Audio Class-Feature Unit Controls UAC2 - typedef enum - { - AUDIO_FEATURE_UNIT_CTRL_MUTE_POS = 0, - AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS = 2, - AUDIO_FEATURE_UNIT_CTRL_BASS_POS = 4, - AUDIO_FEATURE_UNIT_CTRL_MID_POS = 6, - AUDIO_FEATURE_UNIT_CTRL_TREBLE_POS = 8, - AUDIO_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10, - AUDIO_FEATURE_UNIT_CTRL_AGC_POS = 12, - AUDIO_FEATURE_UNIT_CTRL_DELAY_POS = 14, - AUDIO_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16, - AUDIO_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18, - AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20, - AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22, - AUDIO_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24, - AUDIO_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26, - AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, - } audio_feature_unit_control_pos_t; - - /// Audio Class-Audio Channel Configuration UAC2 - typedef enum - { - AUDIO_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000, - AUDIO_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001, - AUDIO_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002, - AUDIO_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004, - AUDIO_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008, - AUDIO_CHANNEL_CONFIG_BACK_LEFT = 0x00000010, - AUDIO_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020, - AUDIO_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040, - AUDIO_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080, - AUDIO_CHANNEL_CONFIG_BACK_CENTER = 0x00000100, - AUDIO_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200, - AUDIO_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400, - AUDIO_CHANNEL_CONFIG_TOP_CENTER = 0x00000800, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000, - AUDIO_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000, - AUDIO_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000, - AUDIO_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000, - AUDIO_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000, - AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, - AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, - AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, - AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, - } audio_channel_config_t; - - /// AUDIO Channel Cluster Descriptor (4.1) - typedef struct TU_ATTR_PACKED { - uint8_t bNrChannels; ///< Number of channels currently connected. - audio_channel_config_t bmChannelConfig; ///< Bitmap according to 'audio_channel_config_t' with a 1 set if channel is connected and 0 else. In case channels are non-predefined ignore them here (see UAC2 specification 4.1 Audio Channel Cluster Descriptor. - uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first inserted channel with a non-predefined spatial location. - } audio_desc_channel_cluster_t; - - /// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) - typedef struct TU_ATTR_PACKED - { - uint8_t bLength ; ///< Size of this descriptor in bytes: 9. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. - uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). - uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. - uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. - uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. - } audio_desc_cs_ac_interface_t; - - /// AUDIO Clock Source Descriptor (4.7.2.1) - typedef struct TU_ATTR_PACKED - { - uint8_t bLength ; ///< Size of this descriptor in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. - uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. - uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. - } audio_desc_clock_source_t; - - /// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin - typedef struct TU_ATTR_PACKED - { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. - uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. - uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. - } audio_desc_clock_selector_t; - - /// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins +/// Audio Device Class Codes + +/// A.2 - Audio Function Subclass Codes +typedef enum +{ + AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, +} audio_function_subclass_type_t; + +/// A.3 - Audio Function Protocol Codes +typedef enum +{ + AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +} audio_function_protocol_code_t; + +/// A.5 - Audio Interface Subclass Codes +typedef enum +{ + AUDIO_SUBCLASS_UNDEFINED = 0x00, + AUDIO_SUBCLASS_CONTROL , ///< Audio Control + AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming + AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming +} audio_subclass_type_t; + +/// A.6 - Audio Interface Protocol Codes +typedef enum +{ + AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +} audio_interface_protocol_code_t; + +/// A.7 - Audio Function Category Codes +typedef enum +{ + AUDIO_FUNC_UNDEF = 0x00, + AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, + AUDIO_FUNC_HOME_THEATER = 0x02, + AUDIO_FUNC_MICROPHONE = 0x03, + AUDIO_FUNC_HEADSET = 0x04, + AUDIO_FUNC_TELEPHONE = 0x05, + AUDIO_FUNC_CONVERTER = 0x06, + AUDIO_FUNC_SOUND_RECODER = 0x07, + AUDIO_FUNC_IO_BOX = 0x08, + AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, + AUDIO_FUNC_PRO_AUDIO = 0x0A, + AUDIO_FUNC_AUDIO_VIDEO = 0x0B, + AUDIO_FUNC_CONTROL_PANEL = 0x0C, + AUDIO_FUNC_OTHER = 0xFF, +} audio_function_code_t; + +/// A.9 - Audio Class-Specific AC Interface Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, + AUDIO_CS_AC_INTERFACE_HEADER = 0x01, + AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, + AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, + AUDIO_CS_AC_INTERFACE_MIXER_UNIT = 0x04, + AUDIO_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, + AUDIO_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, + AUDIO_CS_AC_INTERFACE_EFFECT_UNIT = 0x07, + AUDIO_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08, + AUDIO_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09, + AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A, + AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B, + AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C, + AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, +} audio_cs_ac_interface_subtype_t; + +/// A.10 - Audio Class-Specific AS Interface Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, + AUDIO_CS_AS_INTERFACE_AS_GENERAL = 0x01, + AUDIO_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, + AUDIO_CS_AS_INTERFACE_ENCODER = 0x03, + AUDIO_CS_AS_INTERFACE_DECODER = 0x04, +} audio_cs_as_interface_subtype_t; + +/// A.11 - Effect Unit Effect Types +typedef enum +{ + AUDIO_EFFECT_TYPE_UNDEF = 0x00, + AUDIO_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01, + AUDIO_EFFECT_TYPE_REVERBERATION = 0x02, + AUDIO_EFFECT_TYPE_MOD_DELAY = 0x03, + AUDIO_EFFECT_TYPE_DYN_RANGE_COMP = 0x04, +} audio_effect_unit_effect_type_t; + +/// A.12 - Processing Unit Process Types +typedef enum +{ + AUDIO_PROCESS_TYPE_UNDEF = 0x00, + AUDIO_PROCESS_TYPE_UP_DOWN_MIX = 0x01, + AUDIO_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02, + AUDIO_PROCESS_TYPE_STEREO_EXTENDER = 0x03, +} audio_processing_unit_process_type_t; + +/// A.13 - Audio Class-Specific EP Descriptor Subtypes UAC2 +typedef enum +{ + AUDIO_CS_EP_SUBTYPE_UNDEF = 0x00, + AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, +} audio_cs_ep_subtype_t; + +/// A.14 - Audio Class-Specific Request Codes +typedef enum +{ + AUDIO_CS_REQ_UNDEF = 0x00, + AUDIO_CS_REQ_CUR = 0x01, + AUDIO_CS_REQ_RANGE = 0x02, + AUDIO_CS_REQ_MEM = 0x03, +} audio_cs_req_t; + +/// A.17 - Control Selector Codes + +/// A.17.1 - Clock Source Control Selectors +typedef enum +{ + AUDIO_CS_CTRL_UNDEF = 0x00, + AUDIO_CS_CTRL_SAM_FREQ = 0x01, + AUDIO_CS_CTRL_CLK_VALID = 0x02, +} audio_clock_src_control_selector_t; + +/// A.17.2 - Clock Selector Control Selectors +typedef enum +{ + AUDIO_CX_CTRL_UNDEF = 0x00, + AUDIO_CX_CTRL_CONTROL = 0x01, +} audio_clock_sel_control_selector_t; + +/// A.17.3 - Clock Multiplier Control Selectors +typedef enum +{ + AUDIO_CM_CTRL_UNDEF = 0x00, + AUDIO_CM_CTRL_NUMERATOR_CONTROL = 0x01, + AUDIO_CM_CTRL_DENOMINATOR_CONTROL = 0x02, +} audio_clock_mul_control_selector_t; + +/// A.17.4 - Terminal Control Selectors +typedef enum +{ + AUDIO_TE_CTRL_UNDEF = 0x00, + AUDIO_TE_CTRL_COPY_PROTECT = 0x01, + AUDIO_TE_CTRL_CONNECTOR = 0x02, + AUDIO_TE_CTRL_OVERLOAD = 0x03, + AUDIO_TE_CTRL_CLUSTER = 0x04, + AUDIO_TE_CTRL_UNDERFLOW = 0x05, + AUDIO_TE_CTRL_OVERFLOW = 0x06, + AUDIO_TE_CTRL_LATENCY = 0x07, +} audio_terminal_control_selector_t; + +/// A.17.5 - Mixer Control Selectors +typedef enum +{ + AUDIO_MU_CTRL_UNDEF = 0x00, + AUDIO_MU_CTRL_MIXER = 0x01, + AUDIO_MU_CTRL_CLUSTER = 0x02, + AUDIO_MU_CTRL_UNDERFLOW = 0x03, + AUDIO_MU_CTRL_OVERFLOW = 0x04, + AUDIO_MU_CTRL_LATENCY = 0x05, +} audio_mixer_control_selector_t; + +/// A.17.6 - Selector Control Selectors +typedef enum +{ + AUDIO_SU_CTRL_UNDEF = 0x00, + AUDIO_SU_CTRL_SELECTOR = 0x01, + AUDIO_SU_CTRL_LATENCY = 0x02, +} audio_sel_control_selector_t; + +/// A.17.7 - Feature Unit Control Selectors +typedef enum +{ + AUDIO_FU_CTRL_UNDEF = 0x00, + AUDIO_FU_CTRL_MUTE = 0x01, + AUDIO_FU_CTRL_VOLUME = 0x02, + AUDIO_FU_CTRL_BASS = 0x03, + AUDIO_FU_CTRL_MID = 0x04, + AUDIO_FU_CTRL_TREBLE = 0x05, + AUDIO_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, + AUDIO_FU_CTRL_AGC = 0x07, + AUDIO_FU_CTRL_DELAY = 0x08, + AUDIO_FU_CTRL_BASS_BOOST = 0x09, + AUDIO_FU_CTRL_LOUDNESS = 0x0A, + AUDIO_FU_CTRL_INPUT_GAIN = 0x0B, + AUDIO_FU_CTRL_GAIN_PAD = 0x0C, + AUDIO_FU_CTRL_INVERTER = 0x0D, + AUDIO_FU_CTRL_UNDERFLOW = 0x0E, + AUDIO_FU_CTRL_OVERVLOW = 0x0F, + AUDIO_FU_CTRL_LATENCY = 0x10, +} audio_feature_unit_control_selector_t; + +/// A.17.8 Effect Unit Control Selectors + +/// A.17.8.1 Parametric Equalizer Section Effect Unit Control Selectors +typedef enum +{ + AUDIO_PE_CTRL_UNDEF = 0x00, + AUDIO_PE_CTRL_ENABLE = 0x01, + AUDIO_PE_CTRL_CENTERFREQ = 0x02, + AUDIO_PE_CTRL_QFACTOR = 0x03, + AUDIO_PE_CTRL_GAIN = 0x04, + AUDIO_PE_CTRL_UNDERFLOW = 0x05, + AUDIO_PE_CTRL_OVERFLOW = 0x06, + AUDIO_PE_CTRL_LATENCY = 0x07, +} audio_parametric_equalizer_control_selector_t; + +/// A.17.8.2 Reverberation Effect Unit Control Selectors +typedef enum +{ + AUDIO_RV_CTRL_UNDEF = 0x00, + AUDIO_RV_CTRL_ENABLE = 0x01, + AUDIO_RV_CTRL_TYPE = 0x02, + AUDIO_RV_CTRL_LEVEL = 0x03, + AUDIO_RV_CTRL_TIME = 0x04, + AUDIO_RV_CTRL_FEEDBACK = 0x05, + AUDIO_RV_CTRL_PREDELAY = 0x06, + AUDIO_RV_CTRL_DENSITY = 0x07, + AUDIO_RV_CTRL_HIFREQ_ROLLOFF = 0x08, + AUDIO_RV_CTRL_UNDERFLOW = 0x09, + AUDIO_RV_CTRL_OVERFLOW = 0x0A, + AUDIO_RV_CTRL_LATENCY = 0x0B, +} audio_reverberation_effect_control_selector_t; + +/// A.17.8.3 Modulation Delay Effect Unit Control Selectors +typedef enum +{ + AUDIO_MD_CTRL_UNDEF = 0x00, + AUDIO_MD_CTRL_ENABLE = 0x01, + AUDIO_MD_CTRL_BALANCE = 0x02, + AUDIO_MD_CTRL_RATE = 0x03, + AUDIO_MD_CTRL_DEPTH = 0x04, + AUDIO_MD_CTRL_TIME = 0x05, + AUDIO_MD_CTRL_FEEDBACK = 0x06, + AUDIO_MD_CTRL_UNDERFLOW = 0x07, + AUDIO_MD_CTRL_OVERFLOW = 0x08, + AUDIO_MD_CTRL_LATENCY = 0x09, +} audio_modulation_delay_control_selector_t; + +/// A.17.8.4 Dynamic Range Compressor Effect Unit Control Selectors +typedef enum +{ + AUDIO_DR_CTRL_UNDEF = 0x00, + AUDIO_DR_CTRL_ENABLE = 0x01, + AUDIO_DR_CTRL_COMPRESSION_RATE = 0x02, + AUDIO_DR_CTRL_MAXAMPL = 0x03, + AUDIO_DR_CTRL_THRESHOLD = 0x04, + AUDIO_DR_CTRL_ATTACK_TIME = 0x05, + AUDIO_DR_CTRL_RELEASE_TIME = 0x06, + AUDIO_DR_CTRL_UNDERFLOW = 0x07, + AUDIO_DR_CTRL_OVERFLOW = 0x08, + AUDIO_DR_CTRL_LATENCY = 0x09, +} audio_dynamic_range_compression_control_selector_t; + +/// A.17.9 Processing Unit Control Selectors + +/// A.17.9.1 Up/Down-mix Processing Unit Control Selectors +typedef enum +{ + AUDIO_UD_CTRL_UNDEF = 0x00, + AUDIO_UD_CTRL_ENABLE = 0x01, + AUDIO_UD_CTRL_MODE_SELECT = 0x02, + AUDIO_UD_CTRL_CLUSTER = 0x03, + AUDIO_UD_CTRL_UNDERFLOW = 0x04, + AUDIO_UD_CTRL_OVERFLOW = 0x05, + AUDIO_UD_CTRL_LATENCY = 0x06, +} audio_up_down_mix_control_selector_t; + +/// A.17.9.2 Dolby Prologic ™ Processing Unit Control Selectors +typedef enum +{ + AUDIO_DP_CTRL_UNDEF = 0x00, + AUDIO_DP_CTRL_ENABLE = 0x01, + AUDIO_DP_CTRL_MODE_SELECT = 0x02, + AUDIO_DP_CTRL_CLUSTER = 0x03, + AUDIO_DP_CTRL_UNDERFLOW = 0x04, + AUDIO_DP_CTRL_OVERFLOW = 0x05, + AUDIO_DP_CTRL_LATENCY = 0x06, +} audio_dolby_prologic_control_selector_t; + +/// A.17.9.3 Stereo Extender Processing Unit Control Selectors +typedef enum +{ + AUDIO_ST_EXT_CTRL_UNDEF = 0x00, + AUDIO_ST_EXT_CTRL_ENABLE = 0x01, + AUDIO_ST_EXT_CTRL_WIDTH = 0x02, + AUDIO_ST_EXT_CTRL_UNDERFLOW = 0x03, + AUDIO_ST_EXT_CTRL_OVERFLOW = 0x04, + AUDIO_ST_EXT_CTRL_LATENCY = 0x05, +} audio_stereo_extender_control_selector_t; + +/// A.17.10 Extension Unit Control Selectors +typedef enum +{ + AUDIO_XU_CTRL_UNDEF = 0x00, + AUDIO_XU_CTRL_ENABLE = 0x01, + AUDIO_XU_CTRL_CLUSTER = 0x02, + AUDIO_XU_CTRL_UNDERFLOW = 0x03, + AUDIO_XU_CTRL_OVERFLOW = 0x04, + AUDIO_XU_CTRL_LATENCY = 0x05, +} audio_extension_unit_control_selector_t; + +/// A.17.11 AudioStreaming Interface Control Selectors +typedef enum +{ + AUDIO_AS_CTRL_UNDEF = 0x00, + AUDIO_AS_CTRL_ACT_ALT_SETTING = 0x01, + AUDIO_AS_CTRL_VAL_ALT_SETTINGS = 0x02, + AUDIO_AS_CTRL_AUDIO_DATA_FORMAT = 0x03, +} audio_audiostreaming_interface_control_selector_t; + +/// A.17.12 Encoder Control Selectors +typedef enum +{ + AUDIO_EN_CTRL_UNDEF = 0x00, + AUDIO_EN_CTRL_BIT_RATE = 0x01, + AUDIO_EN_CTRL_QUALITY = 0x02, + AUDIO_EN_CTRL_VBR = 0x03, + AUDIO_EN_CTRL_TYPE = 0x04, + AUDIO_EN_CTRL_UNDERFLOW = 0x05, + AUDIO_EN_CTRL_OVERFLOW = 0x06, + AUDIO_EN_CTRL_ENCODER_ERROR = 0x07, + AUDIO_EN_CTRL_PARAM1 = 0x08, + AUDIO_EN_CTRL_PARAM2 = 0x09, + AUDIO_EN_CTRL_PARAM3 = 0x0A, + AUDIO_EN_CTRL_PARAM4 = 0x0B, + AUDIO_EN_CTRL_PARAM5 = 0x0C, + AUDIO_EN_CTRL_PARAM6 = 0x0D, + AUDIO_EN_CTRL_PARAM7 = 0x0E, + AUDIO_EN_CTRL_PARAM8 = 0x0F, +} audio_encoder_control_selector_t; + +/// A.17.13 Decoder Control Selectors + +/// A.17.13.1 MPEG Decoder Control Selectors +typedef enum +{ + AUDIO_MPD_CTRL_UNDEF = 0x00, + AUDIO_MPD_CTRL_DUAL_CHANNEL = 0x01, + AUDIO_MPD_CTRL_SECOND_STEREO = 0x02, + AUDIO_MPD_CTRL_MULTILINGUAL = 0x03, + AUDIO_MPD_CTRL_DYN_RANGE = 0x04, + AUDIO_MPD_CTRL_SCALING = 0x05, + AUDIO_MPD_CTRL_HILO_SCALING = 0x06, + AUDIO_MPD_CTRL_UNDERFLOW = 0x07, + AUDIO_MPD_CTRL_OVERFLOW = 0x08, + AUDIO_MPD_CTRL_DECODER_ERROR = 0x09, +} audio_MPEG_decoder_control_selector_t; + +/// A.17.13.2 AC-3 Decoder Control Selectors +typedef enum +{ + AUDIO_AD_CTRL_UNDEF = 0x00, + AUDIO_AD_CTRL_MODE = 0x01, + AUDIO_AD_CTRL_DYN_RANGE = 0x02, + AUDIO_AD_CTRL_SCALING = 0x03, + AUDIO_AD_CTRL_HILO_SCALING = 0x04, + AUDIO_AD_CTRL_UNDERFLOW = 0x05, + AUDIO_AD_CTRL_OVERFLOW = 0x06, + AUDIO_AD_CTRL_DECODER_ERROR = 0x07, +} audio_AC3_decoder_control_selector_t; + +/// A.17.13.3 WMA Decoder Control Selectors +typedef enum +{ + AUDIO_WD_CTRL_UNDEF = 0x00, + AUDIO_WD_CTRL_UNDERFLOW = 0x01, + AUDIO_WD_CTRL_OVERFLOW = 0x02, + AUDIO_WD_CTRL_DECODER_ERROR = 0x03, +} audio_WMA_decoder_control_selector_t; + +/// A.17.13.4 DTS Decoder Control Selectors +typedef enum +{ + AUDIO_DD_CTRL_UNDEF = 0x00, + AUDIO_DD_CTRL_UNDERFLOW = 0x01, + AUDIO_DD_CTRL_OVERFLOW = 0x02, + AUDIO_DD_CTRL_DECODER_ERROR = 0x03, +} audio_DTS_decoder_control_selector_t; + +/// A.17.14 Endpoint Control Selectors +typedef enum +{ + AUDIO_EP_CTRL_UNDEF = 0x00, + AUDIO_EP_CTRL_PITCH = 0x01, + AUDIO_EP_CTRL_DATA_OVERRUN = 0x02, + AUDIO_EP_CTRL_DATA_UNDERRUN = 0x03, +} audio_EP_control_selector_t; + +/// Terminal Types + +/// 2.1 - Audio Class-Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, + AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, + AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, +} audio_terminal_type_t; + +/// 2.2 - Audio Class-Input Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, + AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, + AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, + AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, + AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, + AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, + AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, +} audio_terminal_input_type_t; + +/// 2.3 - Audio Class-Output Terminal Types UAC2 +typedef enum +{ + AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, + AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, + AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, + AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, + AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, + AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, + AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, + AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, +} audio_terminal_output_type_t; + +/// Rest is yet to be implemented + +/// Additional Audio Device Class Codes - Source: Audio Data Formats + +/// A.1 - Audio Class-Format Type Codes UAC2 +typedef enum +{ + AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, + AUDIO_FORMAT_TYPE_I = 0x01, + AUDIO_FORMAT_TYPE_II = 0x02, + AUDIO_FORMAT_TYPE_III = 0x03, + AUDIO_FORMAT_TYPE_IV = 0x04, + AUDIO_EXT_FORMAT_TYPE_I = 0x81, + AUDIO_EXT_FORMAT_TYPE_II = 0x82, + AUDIO_EXT_FORMAT_TYPE_III = 0x83, +} audio_format_type_t; + +/// A.2.1 - Audio Class-Audio Data Format Type I UAC2 +typedef enum +{ + AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), + AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), + AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), + AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), + AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = (uint32_t) (1 << 31), +} audio_data_format_type_I_t; + +/// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification + +/// Isochronous End Point Attributes +typedef enum +{ + TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, + TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, + TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, + TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point + TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point +} tusb_iso_ep_attribute_t; + +/// Audio Class-Control Values UAC2 +typedef enum +{ + AUDIO_CTRL_NONE = 0x00, ///< No Host access + AUDIO_CTRL_R = 0x01, ///< Host read access only + AUDIO_CTRL_RW = 0x03, ///< Host read write access +} audio_control_t; + +/// Audio Class-Specific AC Interface Descriptor Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0, +} audio_cs_ac_interface_control_pos_t; + +/// Audio Class-Specific AS Interface Descriptor Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0, + AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, +} audio_cs_as_interface_control_pos_t; + +/// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, + AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, +} audio_cs_as_iso_data_ep_attribute_t; + +/// Audio Class-Specific AS Isochronous Data EP Controls UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0, + AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2, + AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4, +} audio_cs_as_iso_data_ep_control_pos_t; + +/// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC2 +typedef enum +{ + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, + AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, +} audio_cs_as_iso_data_ep_lock_delay_unit_t; + +/// Audio Class-Clock Source Attributes UAC2 +typedef enum +{ + AUDIO_CLOCK_SOURCE_ATT_EXT_CLK = 0x00, + AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01, + AUDIO_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02, + AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03, + AUDIO_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04, +} audio_clock_source_attribute_t; + +/// Audio Class-Clock Source Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0, + AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2, +} audio_clock_source_control_pos_t; + +/// Audio Class-Clock Selector Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_SELECTOR_CTRL_POS = 0, +} audio_clock_selector_control_pos_t; + +/// Audio Class-Clock Multiplier Controls UAC2 +typedef enum +{ + AUDIO_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0, + AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, +} audio_clock_multiplier_control_pos_t; + +/// Audio Class-Input Terminal Controls UAC2 +typedef enum +{ + AUDIO_IN_TERM_CTRL_CPY_PROT_POS = 0, + AUDIO_IN_TERM_CTRL_CONNECTOR_POS = 2, + AUDIO_IN_TERM_CTRL_OVERLOAD_POS = 4, + AUDIO_IN_TERM_CTRL_CLUSTER_POS = 6, + AUDIO_IN_TERM_CTRL_UNDERFLOW_POS = 8, + AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, +} audio_terminal_input_control_pos_t; + +/// Audio Class-Output Terminal Controls UAC2 +typedef enum +{ + AUDIO_OUT_TERM_CTRL_CPY_PROT_POS = 0, + AUDIO_OUT_TERM_CTRL_CONNECTOR_POS = 2, + AUDIO_OUT_TERM_CTRL_OVERLOAD_POS = 4, + AUDIO_OUT_TERM_CTRL_UNDERFLOW_POS = 6, + AUDIO_OUT_TERM_CTRL_OVERFLOW_POS = 8, +} audio_terminal_output_control_pos_t; + +/// Audio Class-Feature Unit Controls UAC2 +typedef enum +{ + AUDIO_FEATURE_UNIT_CTRL_MUTE_POS = 0, + AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS = 2, + AUDIO_FEATURE_UNIT_CTRL_BASS_POS = 4, + AUDIO_FEATURE_UNIT_CTRL_MID_POS = 6, + AUDIO_FEATURE_UNIT_CTRL_TREBLE_POS = 8, + AUDIO_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10, + AUDIO_FEATURE_UNIT_CTRL_AGC_POS = 12, + AUDIO_FEATURE_UNIT_CTRL_DELAY_POS = 14, + AUDIO_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16, + AUDIO_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18, + AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20, + AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22, + AUDIO_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24, + AUDIO_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26, + AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, +} audio_feature_unit_control_pos_t; + +/// Audio Class-Audio Channel Configuration UAC2 +typedef enum +{ + AUDIO_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000, + AUDIO_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001, + AUDIO_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002, + AUDIO_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004, + AUDIO_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008, + AUDIO_CHANNEL_CONFIG_BACK_LEFT = 0x00000010, + AUDIO_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020, + AUDIO_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040, + AUDIO_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080, + AUDIO_CHANNEL_CONFIG_BACK_CENTER = 0x00000100, + AUDIO_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200, + AUDIO_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400, + AUDIO_CHANNEL_CONFIG_TOP_CENTER = 0x00000800, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000, + AUDIO_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000, + AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000, + AUDIO_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000, + AUDIO_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000, + AUDIO_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000, + AUDIO_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000, + AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, + AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, + AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, + AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, +} audio_channel_config_t; + +/// AUDIO Channel Cluster Descriptor (4.1) +typedef struct TU_ATTR_PACKED { + uint8_t bNrChannels; ///< Number of channels currently connected. + audio_channel_config_t bmChannelConfig; ///< Bitmap according to 'audio_channel_config_t' with a 1 set if channel is connected and 0 else. In case channels are non-predefined ignore them here (see UAC2 specification 4.1 Audio Channel Cluster Descriptor. + uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first inserted channel with a non-predefined spatial location. +} audio_desc_channel_cluster_t; + +/// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes: 9. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. + uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). + uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. + uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. + uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. +} audio_desc_cs_ac_interface_t; + +/// AUDIO Clock Source Descriptor (4.7.2.1) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes: 8. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. + uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. + uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. +} audio_desc_clock_source_t; + +/// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. + uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. + uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. +} audio_desc_clock_selector_t; + +/// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins #define audio_desc_clock_selector_n_t(source_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; \ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bClockID ; \ - uint8_t bNrInPins ; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID ; \ - } sourceID[source_num] ; \ - uint8_t bmControls ; \ - uint8_t iClockSource ; \ + struct TU_ATTR_PACKED { \ + uint8_t bLength ; \ + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bClockID ; \ + uint8_t bNrInPins ; \ + struct TU_ATTR_PACKED { \ + uint8_t baSourceID ; \ + } sourceID[source_num] ; \ + uint8_t bmControls ; \ + uint8_t iClockSource ; \ } - /// AUDIO Clock Multiplier Descriptor (4.7.2.3) - typedef struct TU_ATTR_PACKED - { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. - uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. - } audio_desc_clock_multiplier_t; - - /// AUDIO Input Terminal Descriptor(4.7.2.4) - typedef struct TU_ATTR_PACKED - { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. - uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. - uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. - uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. - } audio_desc_input_terminal_t; - - /// AUDIO Output Terminal Descriptor(4.7.2.5) - typedef struct TU_ATTR_PACKED - { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. - uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. - uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. - uint16_t bmControls ; ///< See: audio_terminal_output_type_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. - } audio_desc_output_terminal_t; - - /// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel - typedef struct TU_ATTR_PACKED - { - uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. - uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. - struct TU_ATTR_PACKED { - uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. - } controls[2] ; - uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. - } audio_desc_feature_unit_t; - - /// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels -#define audio_desc_feature_unit_n_t(ch_num) \ +/// AUDIO Clock Multiplier Descriptor (4.7.2.3) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. + uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. + uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. + uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. +} audio_desc_clock_multiplier_t; + +/// AUDIO Input Terminal Descriptor(4.7.2.4) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. + uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. + uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. + uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. +} audio_desc_input_terminal_t; + +/// AUDIO Output Terminal Descriptor(4.7.2.5) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. + uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. + uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. + uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. + uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. + uint16_t bmControls ; ///< See: audio_terminal_output_type_t. + uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. +} audio_desc_output_terminal_t; + +/// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. + uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. + uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. + uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. + struct TU_ATTR_PACKED { + uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. + } controls[2] ; + uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. +} audio_desc_feature_unit_t; + +/// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels +#define audio_desc_feature_unit_n_t(ch_num)\ struct TU_ATTR_PACKED { \ - uint8_t bLength ; /* 6+(ch_num+1)*4 */\ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bUnitID ; \ - uint8_t bSourceID ; \ - struct TU_ATTR_PACKED { \ - uint32_t bmaControls ; \ - } controls[ch_num+1] ; \ - uint8_t iTerminal ; \ + uint8_t bLength ; /* 6+(ch_num+1)*4 */\ + uint8_t bDescriptorType ; \ + uint8_t bDescriptorSubType ; \ + uint8_t bUnitID ; \ + uint8_t bSourceID ; \ + struct TU_ATTR_PACKED { \ + uint32_t bmaControls ; \ + } controls[ch_num+1] ; \ + uint8_t iTerminal ; \ } /// AUDIO Class-Specific AS Interface Descriptor(4.9.2) @@ -789,13 +789,13 @@ typedef struct TU_ATTR_PACKED uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. - uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. - uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. - uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. - uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. - uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. + uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. + uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. + uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. + uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. + uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. + uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. } audio_desc_cs_as_interface_t; /// AUDIO Type I Format Type Descriptor(2.3.1.6 - Audio Formats) @@ -804,9 +804,9 @@ typedef struct TU_ATTR_PACKED uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. - uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. - uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. + uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. + uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. + uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. } audio_desc_type_I_format_t; /// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) @@ -815,10 +815,10 @@ typedef struct TU_ATTR_PACKED uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. - uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. - uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. - uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. - uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. + uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. + uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. + uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. + uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. } audio_desc_cs_as_iso_data_ep_t; //// 5.2.3 Control Request Parameter Block Layout @@ -826,19 +826,19 @@ typedef struct TU_ATTR_PACKED // 5.2.3.1 1-byte Control CUR Parameter Block typedef struct TU_ATTR_PACKED { - int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control + int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control } audio_control_cur_1_t; // 5.2.3.2 2-byte Control CUR Parameter Block typedef struct TU_ATTR_PACKED { - int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control + int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control } audio_control_cur_2_t; // 5.2.3.3 4-byte Control CUR Parameter Block typedef struct TU_ATTR_PACKED { - int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control + int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control } audio_control_cur_4_t; // Use the following ONLY for RECEIVED data - compiler does not know how many subranges are defined! Use the one below for predefined lengths - or if you know what you are doing do what you like @@ -846,64 +846,64 @@ typedef struct TU_ATTR_PACKED typedef struct TU_ATTR_PACKED { uint16_t wNumSubRanges; struct TU_ATTR_PACKED { - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; + int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; } audio_control_range_1_t; // 5.2.3.2 2-byte Control RANGE Parameter Block typedef struct TU_ATTR_PACKED { uint16_t wNumSubRanges; struct TU_ATTR_PACKED { - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; + int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; } audio_control_range_2_t; // 5.2.3.3 4-byte Control RANGE Parameter Block typedef struct TU_ATTR_PACKED { uint16_t wNumSubRanges; struct TU_ATTR_PACKED { - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; + int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ + int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ + uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ + } subrange[] ; } audio_control_range_4_t; // 5.2.3.1 1-byte Control RANGE Parameter Block #define audio_control_range_1_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges] ; \ - } + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ + struct TU_ATTR_PACKED { \ + int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges] ; \ +} - // 5.2.3.2 2-byte Control RANGE Parameter Block + /// 5.2.3.2 2-byte Control RANGE Parameter Block #define audio_control_range_2_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges] ; \ - } + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ + struct TU_ATTR_PACKED { \ + int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges]; \ +} // 5.2.3.3 4-byte Control RANGE Parameter Block #define audio_control_range_4_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges] ; \ - } + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ + struct TU_ATTR_PACKED { \ + int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ + int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ + uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ + } subrange[numSubRanges]; \ +} /** @} */ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 129aed481..6fe5d6717 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -48,29 +48,29 @@ //--------------------------------------------------------------------+ typedef struct { - uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function + uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function #if CFG_TUD_AUDIO_EPSIZE_IN - uint8_t ep_in; // Outgoing (out of uC) audio data EP. - uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) + uint8_t ep_in; // Outgoing (out of uC) audio data EP. + uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif #if CFG_TUD_AUDIO_EPSIZE_OUT - uint8_t ep_out; // Incoming (into uC) audio data EP. - uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) + uint8_t ep_out; // Incoming (into uC) audio data EP. + uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint8_t ep_fb; // Feedback EP. + uint8_t ep_fb; // Feedback EP. #endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - uint8_t ep_int_ctr; // Audio control interrupt EP. + uint8_t ep_int_ctr; // Audio control interrupt EP. #endif #if CFG_TUD_AUDIO_N_AS_INT - uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! + uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! #endif /*------------- From this point, data is not cleared by bus reset -------------*/ @@ -104,17 +104,17 @@ typedef struct // Endpoint Transfer buffers #if CFG_TUD_AUDIO_EPSIZE_OUT - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) // TODO: required? //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // uint16_t fb_val; // Feedback value for asynchronous mode! + // uint16_t fb_val; // Feedback value for asynchronous mode! //#endif #endif #if CFG_TUD_AUDIO_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -125,20 +125,6 @@ typedef struct #define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ctrl_buf) -//#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, tx_ff) -//#elif CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, rx_ff) -//#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, int_ctr_ff) -//#elif CFG_TUD_AUDIO_EPSIZE_OUT -//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epout_buf) -//#elif CFG_TUD_AUDIO_EPSIZE_IN -//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, epin_buf) -//#elif CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -//#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ep_int_ctr_buf) -//#endif - //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -253,37 +239,41 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* { case AUDIO_FORMAT_TYPE_UNDEFINED: // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! - asm("nop"); + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); + TU_BREAKPOINT(); break; case AUDIO_FORMAT_TYPE_I: switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: + case AUDIO_DATA_FORMAT_TYPE_I_PCM: #if CFG_TUD_AUDIO_RX_FIFO_SIZE - TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); + TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); #else #error YOUR DECODING AND BUFFERING IS REQUIRED HERE! #endif - break; + break; - default: - // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! - asm("nop"); - break; + default: + // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_RX encoding not implemented!\r\n"); + TU_BREAKPOINT(); + break; } break; - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! - asm("nop"); - break; + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented!\r\n"); + TU_BREAKPOINT(); + break; } // Call a weak callback here - a possibility for user to get informed RX was completed - TTU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); + if (tud_audio_rx_done_cb) TU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); + return true; } @@ -325,25 +315,9 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a chId = 0; } } -} } +} } #endif //CFG_TUD_AUDIO_RX_FIFO_SIZE - -#if CFG_TUD_AUDIO_EPSIZE_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize) -{ - (void) rhport; - (void) buffer; - (void) bufsize; - - /* NOTE: This function should not be modified, when the callback is needed, - the tud_audio_rx_done_cb could be implemented in the user file - */ - - return true; -} -#endif - //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ @@ -392,28 +366,28 @@ static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_TX) { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: + case AUDIO_DATA_FORMAT_TYPE_I_PCM: #if CFG_TUD_AUDIO_TX_FIFO_SIZE - TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); + TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); #else #error YOUR ENCODING AND BUFFERING IS REQUIRED HERE! #endif - break; + break; - default: - // YOUR ENCODING AND SENDING IS REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); - TU_BREAKPOINT(); - break; + default: + // YOUR ENCODING AND SENDING IS REQUIRED HERE! + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); + TU_BREAKPOINT(); + break; } break; - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented!\r\n"); - TU_BREAKPOINT(); - break; + default: + // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! + TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented!\r\n"); + TU_BREAKPOINT(); + break; } // Call a weak callback here - a possibility for user to get informed TX was completed @@ -601,8 +575,8 @@ void audiod_reset(uint8_t rhport) uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { - TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); + TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); // Verify version is correct - this check can be omitted TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); @@ -622,7 +596,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin { if (!_audiod_itf[i].p_desc) { - _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one + _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one break; } } @@ -631,11 +605,8 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin TU_ASSERT( i < CFG_TUD_AUDIO ); // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - - // Notify caller we read complete descriptor - // (*p_length) += tud_audio_desc_lengths[i]; // TODO: Find a way to find end of current audio function and avoid necessity of tud_audio_desc_lengths - since now max_length is available we could do this surely somehow - uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor + uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor return drv_len; } @@ -694,7 +665,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { _audiod_itf[idxDriver].ep_in_as_intf_num = 0; usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); - _audiod_itf[idxDriver].ep_in = 0; // Necessary? + _audiod_itf[idxDriver].ep_in = 0; // Necessary? } #endif @@ -703,12 +674,12 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { _audiod_itf[idxDriver].ep_out_as_intf_num = 0; usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_out); - _audiod_itf[idxDriver].ep_out = 0; // Necessary? + _audiod_itf[idxDriver].ep_out = 0; // Necessary? // Close corresponding feedback EP #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_fb); - _audiod_itf[idxDriver].ep_fb = 0; // Necessary? + _audiod_itf[idxDriver].ep_fb = 0; // Necessary? #endif } #endif @@ -730,56 +701,56 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints; while (foundEPs < nEps && p_desc < p_desc_end) { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) - { - TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *)p_desc)); - uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) + { + TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *)p_desc)); + uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; #if CFG_TUD_AUDIO_EPSIZE_IN > 0 - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP - { - // Save address - _audiod_itf[idxDriver].ep_in = ep_addr; - _audiod_itf[idxDriver].ep_in_as_intf_num = itf; - - // HERE WE WOULD NEED TO SCHEDULE OUR FIRST TRANSMIT, HOWEVER, WE ALSO WOULD FIRST NEED TO ENABLE SAMPLING AT ALL - HOW TO HANDLE THIS? - // Invoke callback - fill something in the FIFO here for now - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - - uint16_t n_bytes_copied; - TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); - } + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP + { + // Save address + _audiod_itf[idxDriver].ep_in = ep_addr; + _audiod_itf[idxDriver].ep_in_as_intf_num = itf; + + // HERE WE WOULD NEED TO SCHEDULE OUR FIRST TRANSMIT, HOWEVER, WE ALSO WOULD FIRST NEED TO ENABLE SAMPLING AT ALL - HOW TO HANDLE THIS? + // Invoke callback - fill something in the FIFO here for now + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + + uint16_t n_bytes_copied; + TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); + } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT - if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary - { - // Save address - _audiod_itf[idxDriver].ep_out = ep_addr; - _audiod_itf[idxDriver].ep_out_as_intf_num = itf; + if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary + { + // Save address + _audiod_itf[idxDriver].ep_out = ep_addr; + _audiod_itf[idxDriver].ep_out_as_intf_num = itf; - // Invoke callback - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + // Invoke callback + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - // Prepare for incoming data - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); - } + // Prepare for incoming data + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback - { - _audiod_itf[idxDriver].ep_fb = ep_addr; + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback + { + _audiod_itf[idxDriver].ep_fb = ep_addr; - // Invoke callback - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - } + // Invoke callback + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + } #endif #endif - foundEPs += 1; - } - p_desc = tu_desc_next(p_desc); + foundEPs += 1; + } + p_desc = tu_desc_next(p_desc); } TU_VERIFY(foundEPs == nEps); @@ -808,62 +779,62 @@ bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_re switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label uint8_t itf = TU_U16_LOW(p_request->wIndex); uint8_t entityID = TU_U16_HIGH(p_request->wIndex); if (entityID != 0) { - if (tud_audio_set_req_entity_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); - - // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); - } - else - { - TU_LOG2(" No entity set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } + if (tud_audio_set_req_entity_cb) + { + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + } + else + { + TU_LOG2(" No entity set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } } else { - if (tud_audio_set_req_itf_cb) - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); - - // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); - } - else - { - TU_LOG2(" No interface set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } + if (tud_audio_set_req_itf_cb) + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + + // Invoke callback + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + } + else + { + TU_LOG2(" No interface set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } } break; - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label uint8_t ep = TU_U16_LOW(p_request->wIndex); if (tud_audio_set_req_ep_cb) { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); - // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + // Invoke callback + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); } else { - TU_LOG2(" No EP set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it + TU_LOG2(" No EP set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it } // Unknown/Unsupported recipient @@ -885,12 +856,12 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req switch (p_request->bRequest) { case TUSB_REQ_GET_INTERFACE: - return audiod_get_interface(rhport, p_request); + return audiod_get_interface(rhport, p_request); case TUSB_REQ_SET_INTERFACE: - return audiod_set_interface(rhport, p_request); + return audiod_set_interface(rhport, p_request); - // Unknown/Unsupported request + // Unknown/Unsupported request default: TU_BREAKPOINT(); return false; } } @@ -904,52 +875,52 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label uint8_t entityID = TU_U16_HIGH(p_request->wIndex); // Verify if entity is present if (entityID != 0) { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_entity_cb) - { - return tud_audio_get_req_entity_cb(rhport, p_request); - } - else - { - TU_LOG2(" No entity get request callback available!\r\n"); - return false; // Stall - } - } + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + if (tud_audio_get_req_entity_cb) + { + return tud_audio_get_req_entity_cb(rhport, p_request); + } + else + { + TU_LOG2(" No entity get request callback available!\r\n"); + return false; // Stall + } + } } else { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_itf_cb) - { - return tud_audio_get_req_itf_cb(rhport, p_request); - } - else - { - TU_LOG2(" No interface get request callback available!\r\n"); - return false; // Stall - } - } + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + if (tud_audio_get_req_itf_cb) + { + return tud_audio_get_req_itf_cb(rhport, p_request); + } + else + { + TU_LOG2(" No interface get request callback available!\r\n"); + return false; // Stall + } + } } break; - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label uint8_t ep = TU_U16_LOW(p_request->wIndex); @@ -959,15 +930,15 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else - { - TU_LOG2(" No EP get request callback available!\r\n"); - return false; // Stall - } + if (tud_audio_get_req_ep_cb) + { + return tud_audio_get_req_ep_cb(rhport, p_request); + } + else + { + TU_LOG2(" No EP get request callback available!\r\n"); + return false; // Stall + } } break; @@ -1009,9 +980,9 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 if (*n_bytes_copied == 0 && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN))) { - // There is no data left to send, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + // There is no data left to send, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); } } @@ -1036,8 +1007,8 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 if (*n_bytes_copied == 0) { - // Load with ZLP - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); } return true; @@ -1065,8 +1036,8 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 { if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver])) { - // Load with ZLP - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); } return true; @@ -1091,7 +1062,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label uint8_t entityID = TU_U16_HIGH(p_request->wIndex); @@ -1108,7 +1079,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req } break; - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label uint8_t ep = TU_U16_LOW(p_request->wIndex); @@ -1151,18 +1122,18 @@ static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8 uint8_t tmp = 0; while (p_desc < p_desc_end) { - // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) - { - *idxItf = tmp; - *idxDriver = i; - *pp_desc_int = p_desc; - return true; - } - - // Increase index, bytes read, and pointer - tmp++; - p_desc = tu_desc_next(p_desc); + // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + { + *idxItf = tmp; + *idxDriver = i; + *pp_desc_int = p_desc; + return true; + } + + // Increase index, bytes read, and pointer + tmp++; + p_desc = tu_desc_next(p_desc); } } } @@ -1180,18 +1151,18 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * if (_audiod_itf[i].p_desc && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) { // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between - uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); // Points to CS AC descriptor + uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); // Points to CS AC descriptor uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; - p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor + p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor while (p_desc < p_desc_end) { - if (p_desc[3] == entityID) // Entity IDs are always at offset 3 - { - *idxDriver = i; - return true; - } - p_desc = tu_desc_next(p_desc); + if (p_desc[3] == entityID) // Entity IDs are always at offset 3 + { + *idxDriver = i; + return true; + } + p_desc = tu_desc_next(p_desc); } } } @@ -1211,12 +1182,12 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) while (p_desc < p_desc_end) { - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) - { - *idxDriver = i; - return true; - } - p_desc = tu_desc_next(p_desc); + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) + { + *idxDriver = i; + return true; + } + p_desc = tu_desc_next(p_desc); } } } @@ -1239,12 +1210,12 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) while (p_desc < p_desc_end) { - if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) - { - *idxDriver = i; - return true; - } - p_desc = tu_desc_next(p_desc); + if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) + { + *idxDriver = i; + return true; + } + p_desc = tu_desc_next(p_desc); } } } @@ -1252,222 +1223,3 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) } #endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO - -// OLD -//// In order that this function works the following is mandatory: -// // - An IAD descriptor is required and has to be placed directly before the Standard AC Interface Descriptor (4.7.1) ALSO if no Audio Streaming interfaces are used! -// // - The Standard AC Interface Descriptor (4.7.1) has to be the first interface listed (required by UAC2 specification) -// // - The alternate interfaces of the Standard AS Interface Descriptor(4.9.1) must be listed in increasing order and alternate 0 must have zero EPs -// -// TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && -// AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); -// -// // Verify version is correct - this check can be omitted -// TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); -// -// // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted -// if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed -// { -// TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0); -// } -// -// // Alternate setting MUST be zero - this check can be omitted -// TU_VERIFY(itf_desc->bAlternateSetting == 0); -// -// // Since checks are successful we get the number of interfaces we have to process by exploiting the fact that an IAD descriptor has to be provided directly before this AC descriptor -// // We do not get this value delivered by the stack so we need to hack a little bit - the number of interfaces to be processed is listed in the IAD descriptor with an offset of exactly 5 -// uint8_t nItfs = *(((uint8_t const *) itf_desc) - 5) - 1; // -1 since we already process the (included) AC interface -// -// // Notify caller we have read Standard AC Interface Descriptor (4.7.1) -// (*p_length) = sizeof(tusb_desc_interface_t); -// -// // Go to next descriptor which has to be a Class-Specific AC Interface Header Descriptor(4.7.2) - always present -// audio_desc_cs_ac_interface_t const * p_desc_cs_ac = (audio_desc_cs_ac_interface_t const *) tu_desc_next ( (uint8_t const *) itf_desc ); -// -// // Verify its the correct descriptor - this check can be omitted -// TU_VERIFY(p_desc_cs_ac->bDescriptorType == TUSB_DESC_CS_INTERFACE -// && p_desc_cs_ac->bDescriptorSubType == AUDIO_CS_AC_INTERFACE_HEADER -// && p_desc_cs_ac->bcdADC == 0x0200); -// -// // We do not check the Audio Function Category Codes -// -// // We do not check all the following Clock Source, Unit and Terminal descriptors -// -// // We do not check the latency control -// -// // We jump over all the following descriptor to the next following interface (which should be a Standard AS Interface Descriptor(4.9.1) if nItfs > 0) -// (*p_length) += p_desc_cs_ac->wTotalLength; // Notify caller of read bytes -// itf_desc = (tusb_desc_interface_t const * )(((uint8_t const *)p_desc_cs_ac ) + p_desc_cs_ac->wTotalLength); // Move pointer -// -// // From this point on we have nItfs packs of audio streaming interfaces (consisting of multiple descriptors always starting with a Standard AS Interface Descriptor(4.9.1)) -// -// uint8_t cnt; -// uint8_t nEPs; -// audio_format_type_t formatType; -// uint8_t intNum; -// uint8_t altInt; -// -// for (cnt = 0; cnt < nItfs; cnt++) -// { -// -// // Here starts an unknown number of alternate interfaces - the art here is to find the end of this interface pack. We do not have the total number of descriptor bytes available (not provided by tinyUSB stack for .open() function) so we try to find the end of this interface pack by deducing it from the order and content of the descriptor pack -// while(1) -// { -// // At first this should be a Standard AS Interface Descriptor(4.9.1) - this check can be omitted -// TU_VERIFY(itf_desc->bDescriptorType == TUSB_DESC_INTERFACE && -// itf_desc->bInterfaceClass == TUSB_CLASS_AUDIO && -// itf_desc->bInterfaceSubClass == AUDIO_SUBCLASS_STREAMING && -// itf_desc->bInterfaceProtocol == AUDIO_PROTOCOL_V2); -// -// // Remember number of EPs this interface has - required for later -// nEPs = itf_desc->bNumEndpoints; -// intNum = itf_desc->bInterfaceNumber; -// altInt = itf_desc->bAlternateSetting; -// -// // Notify caller we have read bytes -// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); -// -// // Advance pointer -// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); -// -// // It is possible now that the following interface is again a Standard AS Interface Descriptor(4.9.1) (in case the related terminal has more than zero EPs at all and this is the following alternative interface > 0 - the alternative (that this is not a Standard AS Interface Descriptor(4.9.1) but a Class-Specific AS Interface Descriptor(4.9.2)) could be in case the related terminal has no EPs at all e.g. SPDIF connector -// if (tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_INTERFACE) -// { -// // It is not possible, that a Standard AS Interface Descriptor(4.9.1) ends without a Class-Specific AS Interface Descriptor(4.9.2) -// // hence the next interface has to be an alternative interface with regard to the one we started above - continue -// continue; -// } -// -// // Second, this interface has to be a Class-Specific AS Interface Descriptor(4.9.2) - this check can be omitted -// TU_VERIFY(tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_CS_INTERFACE && -// ((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_AS_GENERAL); -// -// // Remember format type of this interface - required for later -// formatType = ((audio_desc_cs_as_interface_t *) itf_desc)->bFormatType; -// -// // Notify caller we have read bytes -// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); -// -// // Advance pointer -// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); -// -// // Every Class-Specific AS Interface Descriptor(4.9.2) defines a format type and thus a format type descriptor e.g. Type I Format Type Descriptor(2.3.1.6 - Audio Formats) should follow - only if the format type is undefined no format type descriptor follows -// if (formatType != AUDIO_FORMAT_TYPE_UNDEFINED) -// { -// // We do not need any information from this descriptor - we simply advance -// // Notify caller we have read bytes -// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); -// -// // Advance pointer -// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); -// } -// -// // Now there might be an encoder/decoder interface - i found no clue if this interface is mandatory (although examples found by google never use this descriptor) or if there is any way to determine if this descriptor is reliably present or not. Problem here: Since we need to find the end of this interface pack and we do not have the total amount of descriptor bytes available here (not given by the tinyUSB stack for the .open() function), we have to make a speculative check if the following is an encoder/decoder interface or not. -// // It could be possible that we ready over the total length of all descriptor bytes here - we simply hope that the combination of descriptor length, type, and sub type does not occur randomly in memory here. The only way to make this check waterproof is to know how many bytes we can read at all but this would be an information we need to be given by tinyUSB! -// if (tu_desc_len((uint8_t const *) itf_desc) == 21 && tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_CS_INTERFACE && (((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_ENCODER || ((audio_desc_cs_as_interface_t *) itf_desc)->bDescriptorSubType == AUDIO_CS_AS_INTERFACE_DECODER)) -// { -// // We do not need any information from this descriptor - we simply advance -// // Notify caller we have read bytes -// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); -// -// // Advance pointer -// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); -// } -// -// // Here may be some EP descriptors -// for (uint8_t cntEP = 0; cntEP < nEPs; cntEP++) -// { -// // This check can be omitted -// TU_VERIFY(tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_ENDPOINT); -// -// // Here we can find information about our EPs address etc. but in the initialization process we do not set anything, we have to wait for the host to send a setInterface request where the EPs etc. are set up according -// -// // Notify caller we have read bytes -// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); -// -// // If the usage type is something else than feedback there is a Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) following up -// if (((tusb_desc_endpoint_t *) itf_desc)->bmAttributes.usage != 0x10) -// { -// // Advance pointer -// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); -// -// // We do not need any information from this descriptor - we simply advance -// // Notify caller we have read bytes -// (*p_length) += tu_desc_len((uint8_t const *) itf_desc); -// -// } -// -// // Advance pointer -// itf_desc = (tusb_desc_interface_t const * )(tu_desc_next((uint8_t const *)itf_desc)); -// } -// -// // Okay we processed a complete pack - now we have to make a speculative check if the next interface is an alternate interface belonging to the ones processed before - since it is speculative we check a lot to reduce the chances we go wrong and hope for the best -// if (!(tu_desc_len((uint8_t const *) itf_desc) == 9 && tu_desc_type((uint8_t const *) itf_desc) == TUSB_DESC_INTERFACE && itf_desc->bInterfaceNumber == intNum && itf_desc->bAlternateSetting == altInt + 1)) -// { -// // The current interface is not a consecutive alternate interface to the one processed above -// break; -// } -// } -// -// } - - -// Here follow the encoding steps - -//#if CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_UNDEFINED -// -//#error Individual encoding procedure required! -// -//#elif CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I -// -//#if CFG_TUD_AUDIO_FORMAT_TYPE_I_TX == AUDIO_DATA_FORMAT_TYPE_I_PCM -// -//#if CFG_TUD_AUDIO_TX_FIFO_SIZE -// TU_VERIFY(audio_tx_done_type_I_pcm_cb(rhport, audio, n_bytes_copied)); -//#else -//#error YOUR ENCODING AND SENDING IS REQUIRED HERE! -//#endif -// -//#else -//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX not implemented! -//#endif -// -//#else -//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! -//#endif -// -// // Call a weak callback here - a possibility for user to get informed TX was completed -// TU_VERIFY(tud_audio_tx_done_cb(rhport, n_bytes_copied)); -// return true; - -//#if CFG_TUD_AUDIO_EPSIZE_OUT -//static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) { -// -// // Here follow the decoding steps -// -//#if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_UNDEFINED -// -//#error Individual decoding procedure required! -// -//#elif CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I -// -//#if CFG_TUD_AUDIO_FORMAT_TYPE_I_RX == AUDIO_DATA_FORMAT_TYPE_I_PCM -// -//#if CFG_TUD_AUDIO_RX_FIFO_SIZE -// TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); -//#else -//#error YOUR DECODING AND BUFFERING IS REQUIRED HERE! -//#endif -// -//#else -//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_RX not implemented! -//#endif -// -//#else -//#error Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! -//#endif -// -// TU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); -// return true; -//} -//#endif diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index b745ceb09..c23cf72c2 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -41,7 +41,7 @@ // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just waste a few bytes) #ifndef CFG_TUD_AUDIO_N_AS_INT -#define CFG_TUD_AUDIO_N_AS_INT 0 +#define CFG_TUD_AUDIO_N_AS_INT 0 #endif // Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors @@ -56,51 +56,51 @@ // If you don't use the FIFOs you need to handle encoding and decoding on your own in audio_rx_done_cb() and Y. This, however, allows for optimizations. #ifndef CFG_TUD_AUDIO_TX_FIFO_SIZE -#define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel +#define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel #endif #ifndef CFG_TUD_AUDIO_RX_FIFO_SIZE -#define CFG_TUD_AUDIO_RX_FIFO_SIZE 0 // Buffer size per channel +#define CFG_TUD_AUDIO_RX_FIFO_SIZE 0 // Buffer size per channel #endif // End point sizes - Limits: Full Speed <= 1023, High Speed <= 1024 #ifndef CFG_TUD_AUDIO_EPSIZE_IN -#define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX +#define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX #endif #ifndef CFG_TUD_AUDIO_EPSIZE_OUT -#define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX +#define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX #endif #ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback #endif #ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control +#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN #ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE -#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) #endif #endif #ifndef CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 +#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 #endif #ifndef CFG_TUD_AUDIO_N_CHANNELS_RX -#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 +#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 #endif // Audio data format types #ifndef CFG_TUD_AUDIO_FORMAT_TYPE_TX -#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, an encoding function has to be implemented in audio_device.c +#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, an encoding function has to be implemented in audio_device.c #endif #ifndef CFG_TUD_AUDIO_FORMAT_TYPE_RX -#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, a decoding function has to be implemented in audio_device.c +#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, a decoding function has to be implemented in audio_device.c #endif // Audio data format type I specifications @@ -108,11 +108,11 @@ // Type definitions - for possible formats see: audio_data_format_type_I_t and further in UAC2 specifications. #ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_TX -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM +#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM #endif -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 #endif #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 @@ -128,11 +128,11 @@ #if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I #ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_RX -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM +#define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM #endif -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 #endif #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 @@ -148,7 +148,7 @@ //static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); // Supported types of this driver: -// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL +// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL #ifdef __cplusplus extern "C" { @@ -172,26 +172,26 @@ void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); #endif #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE -uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); +uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -uint16_t tud_audio_int_ctr_n_available (uint8_t itf); -uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); -void tud_audio_int_ctr_n_read_flush (uint8_t itf); -uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t bufsize); +uint16_t tud_audio_int_ctr_n_available (uint8_t itf); +uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); +void tud_audio_int_ctr_n_read_flush (uint8_t itf); +uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t bufsize); #endif //--------------------------------------------------------------------+ // Application API (Interface0) //--------------------------------------------------------------------+ -inline bool tud_audio_mounted (void); +inline bool tud_audio_mounted (void); #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE -inline uint16_t tud_audio_available (void); -inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); -inline void tud_audio_read_flush (void); +inline uint16_t tud_audio_available (void); +inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); +inline void tud_audio_read_flush (void); #endif #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE @@ -199,10 +199,10 @@ inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -inline uint32_t tud_audio_int_ctr_available (void); -inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize); -inline void tud_audio_int_ctr_read_flush (void); -inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); +inline uint32_t tud_audio_int_ctr_available (void); +inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize); +inline void tud_audio_int_ctr_read_flush (void); +inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); #endif // Buffer control EP data and schedule a transmit @@ -260,52 +260,52 @@ TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_reque inline bool tud_audio_mounted(void) { - return tud_audio_n_mounted(0); + return tud_audio_n_mounted(0); } #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE -inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used +inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used { - return tud_audio_n_write(0, channelId, buffer, bufsize); + return tud_audio_n_write(0, channelId, buffer, bufsize); } -#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE +#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE inline uint16_t tud_audio_available(uint8_t channelId) { - return tud_audio_n_available(0, channelId); + return tud_audio_n_available(0, channelId); } inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize) { - return tud_audio_n_read(0, channelId, buffer, bufsize); + return tud_audio_n_read(0, channelId, buffer, bufsize); } inline void tud_audio_read_flush(uint8_t channelId) { - tud_audio_n_read_flush(0, channelId); + tud_audio_n_read_flush(0, channelId); } #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 inline uint16_t tud_audio_int_ctr_available(void) { - return tud_audio_int_ctr_n_available(0); + return tud_audio_int_ctr_n_available(0); } inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize) { - return tud_audio_int_ctr_n_read(0, buffer, bufsize); + return tud_audio_int_ctr_n_read(0, buffer, bufsize); } inline void tud_audio_int_ctr_read_flush(void) { - return tud_audio_int_ctr_n_read_flush(0); + return tud_audio_int_ctr_n_read_flush(0); } inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) { - return tud_audio_int_ctr_n_write(0, buffer, bufsize); + return tud_audio_int_ctr_n_write(0, buffer, bufsize); } #endif @@ -314,7 +314,7 @@ inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) //--------------------------------------------------------------------+ void audiod_init (void); void audiod_reset (uint8_t rhport); -uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool audiod_control_request (uint8_t rhport, tusb_control_request_t const * request); bool audiod_control_complete (uint8_t rhport, tusb_control_request_t const * request); bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index c188bb485..56d606717 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -142,9 +142,9 @@ typedef struct { typedef struct TU_ATTR_PACKED { // The following format may look complicated but it is the most elegant way of addressing the required fields: EP number, EP direction, and EP transfer type. // The codes assigned to those fields, according to the USB specification, can be neatly used as indices. - uint16_t ep_size[EP_MAX][2]; ///< dim 1: EP number, dim 2: EP direction denoted by TUSB_DIR_OUT (= 0) and TUSB_DIR_IN (= 1) - bool ep_transfer_type[EP_MAX][2][4]; ///< dim 1: EP number, dim 2: EP direction, dim 3: transfer type, where 0 = Control, 1 = Isochronous, 2 = Bulk, and 3 = Interrupt - ///< I know very well that EP0 can only be used as control EP and we waste space here but for the sake of simplicity we accept that. It is used in a non-persistent way anyway! + uint16_t ep_size[EP_MAX][2]; ///< dim 1: EP number, dim 2: EP direction denoted by TUSB_DIR_OUT (= 0) and TUSB_DIR_IN (= 1) + bool ep_transfer_type[EP_MAX][2][4]; ///< dim 1: EP number, dim 2: EP direction, dim 3: transfer type, where 0 = Control, 1 = Isochronous, 2 = Bulk, and 3 = Interrupt + ///< I know very well that EP0 can only be used as control EP and we waste space here but for the sake of simplicity we accept that. It is used in a non-persistent way anyway! } ep_sz_tt_report_t; typedef volatile uint32_t * usb_fifo_t; @@ -166,7 +166,7 @@ static void bus_reset(uint8_t rhport) USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); -// USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + // USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); tu_memclr(xfer_status, sizeof(xfer_status)); @@ -220,9 +220,9 @@ static void bus_reset(uint8_t rhport) // configuration was set from the host. For this initialization phase we use 64 bytes as FIFO size. // Found by trial: 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6 - not quite sure where 1 + 6 comes from but this works for 8/16/32/64 EP0 size - _allocated_fifo_words = 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) + _allocated_fifo_words = 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) -// _allocated_fifo_words = 47 + 2*EP_MAX; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) + // _allocated_fifo_words = 47 + 2*EP_MAX; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) usb_otg->GRXFSIZ = _allocated_fifo_words; @@ -237,29 +237,29 @@ static void bus_reset(uint8_t rhport) usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; -//#if TUD_OPT_HIGH_SPEED -// _allocated_fifo_words = 271 + 2*EP_MAX; -//#else -// _allocated_fifo_words = 47 + 2*EP_MAX; -//#endif -// -// usb_otg->GRXFSIZ = _allocated_fifo_words; -// -// // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) -// usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; -// -// _allocated_fifo_words += 16; -// -// // TU_LOG2_INT(_allocated_fifo_words); -// -// // Fixed control EP0 size to 64 bytes -// in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); -// xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; -// -// // Set SETUP packet count to 3 -// out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); -// -// usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + //#if TUD_OPT_HIGH_SPEED + // _allocated_fifo_words = 271 + 2*EP_MAX; + //#else + // _allocated_fifo_words = 47 + 2*EP_MAX; + //#endif + // + // usb_otg->GRXFSIZ = _allocated_fifo_words; + // + // // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) + // usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; + // + // _allocated_fifo_words += 16; + // + // // TU_LOG2_INT(_allocated_fifo_words); + // + // // Fixed control EP0 size to 64 bytes + // in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + // xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; + // + // // Set SETUP packet count to 3 + // out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); + // + // usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; } // Required after new configuration received in case EP0 max packet size has changed @@ -273,12 +273,12 @@ static void set_EP0_max_pkt_size() // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL. switch (enum_spd) { - case 0x00: // High speed - always 64 byte + case 0x00: // High speed - always 64 byte in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; break; - case 0x03: // Full speed + case 0x03: // Full speed #if CFG_TUD_ENDPOINT0_SIZE == 64 in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; @@ -298,7 +298,7 @@ static void set_EP0_max_pkt_size() #endif break; - default: // Low speed - always 8 bytes + default: // Low speed - always 8 bytes in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); xfer_status[0][TUSB_DIR_OUT].max_size = 8; xfer_status[0][TUSB_DIR_IN].max_size = 8; @@ -375,7 +375,6 @@ static void set_speed(uint8_t rhport, tusb_speed_t speed) dev->DCFG |= (bitvalue << USB_OTG_DCFG_DSPD_Pos); } - #if defined(USB_HS_PHYC) static bool USB_HS_PHYCInit(void) { @@ -1140,7 +1139,7 @@ static bool get_ep_size_report(uint8_t rhport, tusb_desc_configuration_t const * { (void) rhport; -// tu_memclr(p_report, sizeof(ep_sz_tt_report_t)); // This does not initialize the first two entries ... i do not know why! + // tu_memclr(p_report, sizeof(ep_sz_tt_report_t)); // This does not initialize the first two entries ... i do not know why! // EP0 sizes and usages are fixed p_report->ep_size[0][TUSB_DIR_OUT] = p_report->ep_size[0][TUSB_DIR_IN] = CFG_TUD_ENDPOINT0_SIZE; @@ -1153,22 +1152,22 @@ static bool get_ep_size_report(uint8_t rhport, tusb_desc_configuration_t const * uint8_t addr; while( p_desc < desc_end ) + { + if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { - if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) - { - addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; + addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - // Verify values - this checks may be omitted in case we trust the descriptors to be okay - TU_VERIFY(tu_edpt_number(addr) < EP_MAX); - TU_VERIFY(tu_edpt_dir(addr) <= TUSB_DIR_IN); - TU_VERIFY(((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer <= TUSB_XFER_INTERRUPT); + // Verify values - this checks may be omitted in case we trust the descriptors to be okay + TU_VERIFY(tu_edpt_number(addr) < EP_MAX); + TU_VERIFY(tu_edpt_dir(addr) <= TUSB_DIR_IN); + TU_VERIFY(((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer <= TUSB_XFER_INTERRUPT); - p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)] = tu_max16(p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)], ((tusb_desc_endpoint_t const*) p_desc)->wMaxPacketSize.size); - p_report->ep_transfer_type[tu_edpt_number(addr)][tu_edpt_dir(addr)][((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer] = true; - } - p_desc = tu_desc_next(p_desc); // Proceed + p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)] = tu_max16(p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)], ((tusb_desc_endpoint_t const*) p_desc)->wMaxPacketSize.size); + p_report->ep_transfer_type[tu_edpt_number(addr)][tu_edpt_dir(addr)][((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer] = true; } + p_desc = tu_desc_next(p_desc); // Proceed + } return true; } @@ -1201,10 +1200,10 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration dev->DOEPMSK &= ~(USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM); dev->DIEPMSK &= ~(USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM); - // usb_otg->GINTMSK &= ~(USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT); + // usb_otg->GINTMSK &= ~(USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT); // Determine maximum required spaces for individual EPs and what kind of usage (control, bulk, etc.) they are used for - ep_sz_tt_report_t report = {0}; // dim 1: EP number, dim 2: EP direction, dim 3: transfer type + ep_sz_tt_report_t report = {0}; // dim 1: EP number, dim 2: EP direction, dim 3: transfer type TU_VERIFY(get_ep_size_report(rhport, desc_cfg, &report)); // With that information, set the following up: @@ -1233,14 +1232,14 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration } // For configuration use the approach as explained in bus_reset() - _allocated_fifo_words = 15 + 2*nUsedOutEPs + (sz[0] / 4) + (sz[0] % 4 > 0 ? 1 : 0) + (sz[1] / 4) + (sz[1] % 4 > 0 ? 1 : 0) + 2; // again, i do not really know why we need + 2 but otherwise it does not work + _allocated_fifo_words = 15 + 2*nUsedOutEPs + (sz[0] / 4) + (sz[0] % 4 > 0 ? 1 : 0) + (sz[1] / 4) + (sz[1] % 4 > 0 ? 1 : 0) + 2; // again, i do not really know why we need + 2 but otherwise it does not work usb_otg->GRXFSIZ = _allocated_fifo_words; // Control IN uses FIFO 0 with report.ep_size[0][TUSB_DIR_IN] bytes ( report.ep_size[0][TUSB_DIR_IN]/4 32-bit word ) usb_otg->DIEPTXF0_HNPTXFSIZ = (report.ep_size[0][TUSB_DIR_IN]/4 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - _allocated_fifo_words += report.ep_size[0][TUSB_DIR_IN]/4; // Since EP0 size MUST be a power of two we do not need to take care of remainders + _allocated_fifo_words += report.ep_size[0][TUSB_DIR_IN]/4; // Since EP0 size MUST be a power of two we do not need to take care of remainders // For configuration of remaining in EPs use the approach as explained in dcd_edpt_open() except that: // - ISO EPs only get EP size as FIFO size. More makes no sense since within one frame precisely EP size bytes are transfered and not more. @@ -1283,7 +1282,7 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration // EP0 is already taken care of so exclude that here for (cnt_ep = 1; cnt_ep < EP_MAX; cnt_ep++) { - ep_sz_total += report.ep_size[cnt_ep][TUSB_DIR_IN] / 4 + (report.ep_size[cnt_ep][TUSB_DIR_IN] % 4 > 0 ? 1 : 0); // Since we need full words take care of remainders! + ep_sz_total += report.ep_size[cnt_ep][TUSB_DIR_IN] / 4 + (report.ep_size[cnt_ep][TUSB_DIR_IN] % 4 > 0 ? 1 : 0); // Since we need full words take care of remainders! nbc += (report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] | report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]); } @@ -1293,7 +1292,7 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration return false; } - uint16_t extra_space = nbc > 0 ? fifo_remaining / nbc : 0; // If no bulk or control EPs are used we just leave the rest of the memory unused + uint16_t extra_space = nbc > 0 ? fifo_remaining / nbc : 0; // If no bulk or control EPs are used we just leave the rest of the memory unused uint16_t fifo_size; // Setup FIFOs @@ -1315,7 +1314,7 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration dev->DOEPMSK |= USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; dev->DIEPMSK |= USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM; - // USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + // USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; out_ep[0].DOEPCTL |= USB_OTG_DOEPCTL_CNAK; -- cgit v1.3.1 From 9d3a9cf546580907d0e72fd6e36e23050bcab850 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 Aug 2020 18:46:19 +0700 Subject: add OPT_MCU_SAMD11 skip ci build for example that need more ROM/RAM could fit into SAMD11 --- examples/device/cdc_msc/.skip.MCU_SAMD11 | 0 examples/device/cdc_msc_freertos/.skip.MCU_SAMD11 | 0 examples/device/dynamic_configuration/.skip.MCU_SAMD11 | 0 examples/device/hid_composite_freertos/.skip.MCU_SAMD11 | 0 examples/device/msc_dual_lun/.skip.MCU_SAMD11 | 0 examples/device/net_lwip_webserver/.skip.MCU_SAMD11 | 0 hw/bsp/board_mcu.h | 2 +- hw/bsp/samd11_xplained/board.mk | 2 +- src/portable/microchip/samd/dcd_samd.c | 5 +++-- src/tusb_option.h | 3 ++- 10 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 examples/device/cdc_msc/.skip.MCU_SAMD11 create mode 100644 examples/device/cdc_msc_freertos/.skip.MCU_SAMD11 create mode 100644 examples/device/dynamic_configuration/.skip.MCU_SAMD11 create mode 100644 examples/device/hid_composite_freertos/.skip.MCU_SAMD11 create mode 100644 examples/device/msc_dual_lun/.skip.MCU_SAMD11 create mode 100644 examples/device/net_lwip_webserver/.skip.MCU_SAMD11 (limited to 'src') diff --git a/examples/device/cdc_msc/.skip.MCU_SAMD11 b/examples/device/cdc_msc/.skip.MCU_SAMD11 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/cdc_msc_freertos/.skip.MCU_SAMD11 b/examples/device/cdc_msc_freertos/.skip.MCU_SAMD11 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/dynamic_configuration/.skip.MCU_SAMD11 b/examples/device/dynamic_configuration/.skip.MCU_SAMD11 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/hid_composite_freertos/.skip.MCU_SAMD11 b/examples/device/hid_composite_freertos/.skip.MCU_SAMD11 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/msc_dual_lun/.skip.MCU_SAMD11 b/examples/device/msc_dual_lun/.skip.MCU_SAMD11 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/net_lwip_webserver/.skip.MCU_SAMD11 b/examples/device/net_lwip_webserver/.skip.MCU_SAMD11 new file mode 100644 index 000000000..e69de29bb diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index 15b31edfd..3382d465d 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -52,7 +52,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_NRF5X #include "nrf.h" -#elif CFG_TUSB_MCU == OPT_MCU_SAMD21 || CFG_TUSB_MCU == OPT_MCU_SAMD51 +#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || CFG_TUSB_MCU == OPT_MCU_SAMD51 #include "sam.h" #elif CFG_TUSB_MCU == OPT_MCU_SAMG diff --git a/hw/bsp/samd11_xplained/board.mk b/hw/bsp/samd11_xplained/board.mk index db0c62cf1..5b1a42157 100644 --- a/hw/bsp/samd11_xplained/board.mk +++ b/hw/bsp/samd11_xplained/board.mk @@ -9,7 +9,7 @@ CFLAGS += \ -D__SAMD11D14AM__ \ -DCONF_DFLL_OVERWRITE_CALIBRATION=0 \ -DOSC32K_OVERWRITE_CALIBRATION=0 \ - -DCFG_TUSB_MCU=OPT_MCU_SAMD21 \ + -DCFG_TUSB_MCU=OPT_MCU_SAMD11 \ -fshort-enums \ -Os diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index d0cc8560a..f1dca88a5 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -27,7 +27,8 @@ #include "tusb_option.h" #if TUSB_OPT_DEVICE_ENABLED && \ - (CFG_TUSB_MCU == OPT_MCU_SAMD21 || CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X) + (CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ + CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X) #include "sam.h" #include "device/dcd.h" @@ -113,7 +114,7 @@ void dcd_int_disable(uint8_t rhport) NVIC_DisableIRQ(USB_0_IRQn); } -#elif CFG_TUSB_MCU == OPT_MCU_SAMD21 +#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 void dcd_int_enable(uint8_t rhport) { diff --git a/src/tusb_option.h b/src/tusb_option.h index abf6450ca..7e486bff0 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -55,10 +55,11 @@ #define OPT_MCU_NRF5X 100 ///< Nordic nRF5x series // SAM +#define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 #define OPT_MCU_SAMD21 200 ///< MicroChip SAMD21 #define OPT_MCU_SAMD51 201 ///< MicroChip SAMD51 -#define OPT_MCU_SAMG 202 ///< MicroChip SAMDG series #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x +#define OPT_MCU_SAMG 202 ///< MicroChip SAMDG series // STM32 #define OPT_MCU_STM32F0 300 ///< ST STM32F0 -- cgit v1.3.1 From c61e9fb96def7b77b4001374b362141a29dcba5b Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 24 Aug 2020 09:01:03 +0200 Subject: audio_device: Fix descriptor limit calculation In several place p_desc_end calculation was not taking into account that starting pointer (_audiod_itf[idxDriver].p_desc) was pointing past interface association descriptor. It would result in accessing random memory. --- src/class/audio/audio_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 6fe5d6717..f8676d4b5 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -689,7 +689,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[idxDriver].p_desc + tud_audio_desc_lengths[idxDriver]; + uint8_t const *p_desc_end = _audiod_itf[idxDriver].p_desc + tud_audio_desc_lengths[idxDriver] - TUD_AUDIO_DESC_IAD_LEN; // p_desc starts at required interface with alternate setting zero while (p_desc < p_desc_end) @@ -1113,7 +1113,7 @@ static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8 if (_audiod_itf[i].p_desc) { // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // Advance past AC descriptors uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); @@ -1178,7 +1178,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) { // Get pointer at beginning and end uint8_t const *p_desc = _audiod_itf[i].p_desc; - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; while (p_desc < p_desc_end) { -- cgit v1.3.1 From a1b7e767af7c4916e9b004120715988268079d28 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 24 Aug 2020 14:31:46 +0700 Subject: improve midi - fix #436 tud_midi_rx_cb() not invoked - fix xfer_cb() not handle ep in - add ZLP if needed --- src/class/cdc/cdc_device.c | 7 +++--- src/class/cdc/cdc_device.h | 1 - src/class/midi/midi_device.c | 51 ++++++++++++++++++++++++++------------------ src/class/midi/midi_device.h | 2 +- 4 files changed, 35 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 94473d036..b4ebfc92e 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -164,7 +164,7 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) // skip if previous transfer not complete yet TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in), 0 ); - uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); + uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); if ( count ) { TU_VERIFY( tud_cdc_n_connected(itf), 0 ); // fifo is empty if not connected @@ -376,7 +376,6 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - (void) rhport; (void) result; uint8_t itf; @@ -393,6 +392,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Received new data if ( ep_addr == p_cdc->ep_out ) { + // TODO search for wanted char first for better performance for(uint32_t i=0; irx_ff, &p_cdc->epout_buf[i]); @@ -423,9 +423,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ { // There is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero + // FIXME CFG_TUD_CDC_EP_BUFSIZE is not Endpoint packet size if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, NULL, 0); + usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); } } } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index f9692e20f..145381c42 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -57,7 +57,6 @@ // CFG_TUD_CDC > 1 //--------------------------------------------------------------------+ - // Check if terminal is connected to this port bool tud_cdc_n_connected (uint8_t itf); diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index d4ed21c78..71a24cbcd 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -101,8 +101,7 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bu // Fill empty buffer if (midi->read_buffer_length == 0) { - if (!tud_midi_n_receive(itf, midi->read_buffer)) - return 0; + if (!tud_midi_n_receive(itf, midi->read_buffer)) return 0; uint8_t code_index = midi->read_buffer[0] & 0x0f; // We always copy over the first byte. @@ -119,8 +118,7 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bu } uint32_t n = midi->read_buffer_length - midi->read_target_length; - if (bufsize < n) - n = bufsize; + if (bufsize < n) n = bufsize; // Skip the header in the buffer memcpy(buffer, midi->read_buffer + 1 + midi->read_target_length, n); @@ -153,10 +151,8 @@ void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bu // WRITE API //--------------------------------------------------------------------+ -static bool maybe_transmit(midid_interface_t* midi, uint8_t itf_index) +static uint32_t write_flush(midid_interface_t* midi) { - (void) itf_index; - // skip if previous transfer not complete TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, midi->ep_in) ); @@ -165,7 +161,7 @@ static bool maybe_transmit(midid_interface_t* midi, uint8_t itf_index) { TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, midi->ep_in, midi->epin_buf, count) ); } - return true; + return count; } uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize) @@ -234,7 +230,8 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u } i++; } - maybe_transmit(midi, itf); + + write_flush(midi); return i; } @@ -250,7 +247,7 @@ bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]) return false; tu_fifo_write_n(&midi->tx_ff, packet, 4); - maybe_transmit(midi, itf); + write_flush(midi); return true; } @@ -389,27 +386,39 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 (void) result; uint8_t itf = 0; - midid_interface_t* p_midi = _midid_itf; + midid_interface_t* p_midi; - for ( ; ; itf++, p_midi++) + // Identify which interface to use + for (itf = 0; itf < CFG_TUD_MIDI; itf++) { - if (itf >= TU_ARRAY_SIZE(_midid_itf)) return false; - - if ( ep_addr == p_midi->ep_out ) break; + p_midi = &_midid_itf[itf]; + if ( ( ep_addr == p_midi->ep_out ) || ( ep_addr == p_midi->ep_in ) ) break; } + TU_ASSERT(itf < CFG_TUD_CDC); // receive new data if ( ep_addr == p_midi->ep_out ) { - midi_rx_done_cb(p_midi, p_midi->epout_buf, xferred_bytes); + tu_fifo_write_n(&p_midi->rx_ff, p_midi->epout_buf, xferred_bytes); + + // invoke receive callback if available + if (tud_midi_rx_cb) tud_midi_rx_cb(itf); // prepare for next - TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE), false ); - } else if ( ep_addr == p_midi->ep_in ) { - maybe_transmit(p_midi, itf); + TU_ASSERT(usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE), false); + } + else if ( ep_addr == p_midi->ep_in ) + { + if (0 == write_flush(p_midi)) + { + // There is no data left, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) ) + { + usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); + } + } } - - // nothing to do with in and notif endpoint return true; } diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 1828a21a3..b8fb55cc2 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -72,7 +72,7 @@ bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]); bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]); //--------------------------------------------------------------------+ -// Application API (Interface0) +// Application API (Single Interface) //--------------------------------------------------------------------+ static inline bool tud_midi_mounted (void); static inline uint32_t tud_midi_available (void); -- cgit v1.3.1 From 2d8787cdeb649f6b4e3c34ea2bd7015f0f120861 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 24 Aug 2020 15:29:34 +0700 Subject: fix typo --- src/class/midi/midi_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 71a24cbcd..376b3670a 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -385,7 +385,7 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 { (void) result; - uint8_t itf = 0; + uint8_t itf; midid_interface_t* p_midi; // Identify which interface to use @@ -394,7 +394,7 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 p_midi = &_midid_itf[itf]; if ( ( ep_addr == p_midi->ep_out ) || ( ep_addr == p_midi->ep_in ) ) break; } - TU_ASSERT(itf < CFG_TUD_CDC); + TU_ASSERT(itf < CFG_TUD_MIDI); // receive new data if ( ep_addr == p_midi->ep_out ) -- cgit v1.3.1 From a4c096be377dd57554a67db92dd3d3167475c142 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 25 Aug 2020 13:15:43 +0200 Subject: audio_device: Fix FIFO element size discrepancies Buffer for TX and RX FIFO was not taking into account size of element leading to out of bound access. audio_tx_done_type_I_pcm_ff_cb() reported copied bytes was not returning correct value number if channels was omitted in computation. Transfer size calculation uses simpler arithmetic. --- src/class/audio/audio_device.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index f8676d4b5..1f2660825 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -80,7 +80,7 @@ typedef struct // FIFO #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; - CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_FIFO_SIZE]; + CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_FIFO_SIZE * CFG_TUD_AUDIO_TX_ITEMSIZE]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; #endif @@ -88,7 +88,7 @@ typedef struct #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; - CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_FIFO_SIZE]; + CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_FIFO_SIZE * CFG_TUD_AUDIO_RX_ITEMSIZE]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; #endif @@ -404,10 +404,12 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples - uint16_t nSamplesPerChannelToSend = 0xFFFF; + uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]); + uint16_t nBytesToSend; uint8_t cntChannel; - for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { if (audio->tx_ff[cntChannel].count < nSamplesPerChannelToSend) { @@ -423,10 +425,8 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a } // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - if (nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX > CFG_TUD_AUDIO_EPSIZE_IN) - { - nSamplesPerChannelToSend = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - } + nSamplesPerChannelToSend = min(nSamplesPerChannelToSend, nEndpointSampleCapacity); + nBytesToSend = nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; // Encode uint16_t cntSample; @@ -456,8 +456,8 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a } // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX)); - *n_bytes_copied = nSamplesPerChannelToSend*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, nBytesToSend)); + *n_bytes_copied = nBytesToSend; return true; } -- cgit v1.3.1 From a3eff0c51a8b5ad58fa7111e770e3b5b3d959351 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 25 Aug 2020 14:30:02 +0200 Subject: audio_device: Fix NULL pointer access in audiod_xfer_cb b_bytes_copied was pointer with NULL value instead of plain variable. NULL pointer was passed to audio_tx_done_cb() and dereference as well. Now variable is not a pointer. --- src/class/audio/audio_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 1f2660825..cbb13afc9 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1002,10 +1002,10 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // This is the only place where we can fill something into the EPs buffer! // Load new data - uint16_t *n_bytes_copied = NULL; - TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); + uint16_t n_bytes_copied; + TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); - if (*n_bytes_copied == 0) + if (n_bytes_copied == 0) { // Load with ZLP return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); -- cgit v1.3.1 From b1f0d6f57eb14aec8c5d83bd54a70a56558d24e8 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 25 Aug 2020 14:41:50 +0200 Subject: audio_device: Change CFG_TUD_AUDIO_TX_BUFSIZE to CFG_TUD_AUDIO_TX_FIFO_SIZE CFG_TUD_AUDIO_TX_BUFSIZE seems to be used only in 3 preprocessor condition while in other places CFG_TUD_AUDIO_TX_FIFO_SIZE is used. --- src/class/audio/audio_device.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index c23cf72c2..41356c61a 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -171,7 +171,7 @@ uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, u void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); #endif @@ -194,7 +194,7 @@ inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); inline void tud_audio_read_flush (void); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); #endif @@ -263,12 +263,12 @@ inline bool tud_audio_mounted(void) return tud_audio_n_mounted(0); } -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used { return tud_audio_n_write(0, channelId, buffer, bufsize); } -#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_BUFSIZE +#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE inline uint16_t tud_audio_available(uint8_t channelId) -- cgit v1.3.1 From b9c9cfdbac66b38faacdff6b5b2629c332d328a9 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 29 Aug 2020 13:22:21 +0200 Subject: Change min to tu_min16. --- src/class/audio/audio_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index cbb13afc9..3be100890 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -425,7 +425,7 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a } // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - nSamplesPerChannelToSend = min(nSamplesPerChannelToSend, nEndpointSampleCapacity); + nSamplesPerChannelToSend = tu_min16(nSamplesPerChannelToSend, nEndpointSampleCapacity); nBytesToSend = nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; // Encode -- cgit v1.3.1 From 43c4b536356fdb9cb54a79f59fa0524cd14dc28c Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 29 Aug 2020 13:24:10 +0200 Subject: Fix CFG_TUD_AUDIO_RX_FIFO_SIZE defines. --- src/class/audio/audio_device.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 41356c61a..2f86168f5 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -165,7 +165,7 @@ extern "C" { //--------------------------------------------------------------------+ bool tud_audio_n_mounted (uint8_t itf); -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE uint16_t tud_audio_n_available (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); @@ -188,7 +188,7 @@ uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, inline bool tud_audio_mounted (void); -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE inline uint16_t tud_audio_available (void); inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); inline void tud_audio_read_flush (void); @@ -270,7 +270,7 @@ inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint1 } #endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_BUFSIZE +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE inline uint16_t tud_audio_available(uint8_t channelId) { return tud_audio_n_available(0, channelId); -- cgit v1.3.1 From 83bd21420375d42f3788b3d3abd5e20ae00cd5b2 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 29 Aug 2020 13:26:41 +0200 Subject: Fix comment. --- src/class/audio/audio_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 2f86168f5..f5830b3a1 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -53,7 +53,7 @@ // For RX: the input stream gets decoded into its corresponding channels, where for each channel a FIFO is setup to hold its data -> see: audio_rx_done_cb(). // For TX: the output stream is composed from CFG_TUD_AUDIO_N_CHANNELS_TX channels, where for each channel a FIFO is defined. // Further, it implements encoding and decoding of the individual channels (parameterized by the defines below). -// If you don't use the FIFOs you need to handle encoding and decoding on your own in audio_rx_done_cb() and Y. This, however, allows for optimizations. +// If you don't use the FIFOs you need to handle encoding and decoding on your own in audio_rx_done_cb() and audio_tx_done_cb(). This, however, allows for optimizations. #ifndef CFG_TUD_AUDIO_TX_FIFO_SIZE #define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel -- cgit v1.3.1 From 8f0693346cf4cba4ea9ea5755a7690b9ee4dc28f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 1 Sep 2020 11:26:16 +0200 Subject: Allow epin_buf to be written directly into in case no TX FIFOs are used. This is helpful if you have already encoded audio data and want an efficient way to send it. However, this approach is NOT THREADSAFE so far and works realiably ONLY IF tud_audio_n_write_ep_in_buffer() is NOT called form an interrupt! --- src/class/audio/audio_device.c | 120 ++++++++++++++++++++++++++++++++--------- src/class/audio/audio_device.h | 13 ++++- 2 files changed, 107 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 3be100890..19be2d6d1 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -52,6 +52,7 @@ typedef struct #if CFG_TUD_AUDIO_EPSIZE_IN uint8_t ep_in; // Outgoing (out of uC) audio data EP. + uint16_t epin_buf_cnt; // Count filling status of EP in buffer uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif @@ -104,11 +105,11 @@ typedef struct // Endpoint Transfer buffers #if CFG_TUD_AUDIO_EPSIZE_OUT - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) // TODO: required? //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // uint16_t fb_val; // Feedback value for asynchronous mode! + // uint16_t fb_val; // Feedback value for asynchronous mode! //#endif #endif @@ -137,7 +138,7 @@ static audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, #endif #if CFG_TUD_AUDIO_EPSIZE_IN -static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied); +static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio); #endif static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); @@ -322,38 +323,93 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a // WRITE API //--------------------------------------------------------------------+ +/** + * \brief Write data to EP in buffer + * + * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). + * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. + * + * \param[in] itf: Index of audio function interface + * \param[in] data: Pointer to data array to be copied from + * \param[in] len: # of array elements to copy + * \return Number of bytes actually written + */ +#if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE +uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) +{ + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->p_desc == NULL) { + return 0; + } + + // THIS IS A CRITICAL SECTION - audio->epin_buf_cnt MUST NOT BE MODIFIED FROM HERE - happens if audiod_tx_done_cb() is executed in between! + + // FOR SINGLE THREADED OPERATION: + // AS LONG AS THIS FUNCTION IS NOT EXECUTED WITHIN AN INTERRUPT ALL IS FINE! + + // Determine free space + uint16_t free = CFG_TUD_AUDIO_EPSIZE_IN - audio->epin_buf_cnt; + + // Clip length if needed + if (len > free) len = free; + + // Write data + memcpy((void *) &audio->epin_buf[audio->epin_buf_cnt], data, len); + + audio->epin_buf_cnt += len; + + // Return number of bytes written + return len; +} +#endif + #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) +uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { audiod_interface_t* audio = &_audiod_itf[itf]; if (audio->p_desc == NULL) { return 0; } - return tu_fifo_write_n(&audio->tx_ff[channelId], buffer, bufsize); + return tu_fifo_write_n(&audio->tx_ff[channelId], data, len); } #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 - uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t bufsize) { audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->itf_num == 0) { + if (audio->p_desc == NULL) { return 0; } return tu_fifo_write_n(&audio->int_ctr_ff, buffer, bufsize); } - #endif // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. // If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_FIFO_SIZE = 0. + +// n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. #if CFG_TUD_AUDIO_EPSIZE_IN -static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) { + uint8_t idxDriver, idxItf; + uint8_t const *dummy2; + + // If a callback is used determine current alternate setting of + if (tud_audio_tx_done_pre_load_cb || tud_audio_tx_done_post_load_cb) + { + // Find index of audio streaming interface and index of interface + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); + } + + // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or + // if no FIFOs are used the user may use this call back to load its data into the EP in buffer by use of tud_audio_n_write_ep_in_buffer(). + if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->altSetting[idxItf])); + +#if CFG_TUD_AUDIO_TX_FIFO_SIZE switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) { case AUDIO_FORMAT_TYPE_UNDEFINED: @@ -368,15 +424,12 @@ static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t { case AUDIO_DATA_FORMAT_TYPE_I_PCM: -#if CFG_TUD_AUDIO_TX_FIFO_SIZE - TU_VERIFY(audio_tx_done_type_I_pcm_ff_cb(rhport, audio, n_bytes_copied)); -#else -#error YOUR ENCODING AND BUFFERING IS REQUIRED HERE! -#endif + TU_VERIFY(audiod_tx_done_type_I_pcm_ff_cb(rhport, audio)); + break; default: - // YOUR ENCODING AND SENDING IS REQUIRED HERE! + // YOUR ENCODING IS REQUIRED HERE! TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); TU_BREAKPOINT(); break; @@ -389,16 +442,36 @@ static bool audio_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t TU_BREAKPOINT(); break; } +#endif + + // THIS IS A CRITICAL SECTION - audio->epin_buf_cnt MUST NOT BE MODIFIED FROM HERE - happens if tud_audio_n_write_ep_in_buffer() is executed in between! + + // THIS IS NOT SOLVED SO FAR! + + // FOR SINGLE THREADED OPERATION: + // THIS FUNCTION IS NOT EXECUTED WITHIN AN INTERRUPT SO IT DOES NOT INTERRUPT tud_audio_n_write_ep_in_buffer()! AS LONG AS tud_audio_n_write_ep_in_buffer() IS NOT EXECUTED WITHIN AN INTERRUPT ALL IS FINE! + + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, audio->epin_buf_cnt)); + + // Inform how many bytes were copied + *n_bytes_copied = audio->epin_buf_cnt; + + // Declare EP in buffer empty + audio->epin_buf_cnt = 0; + + // TO HERE + + // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame + if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, *n_bytes_copied, idxDriver, audio->ep_in, audio->altSetting[idxItf])); - // Call a weak callback here - a possibility for user to get informed TX was completed - if (tud_audio_tx_done_cb) TU_VERIFY(tud_audio_tx_done_cb(rhport, n_bytes_copied)); return true; } #endif //CFG_TUD_AUDIO_EPSIZE_IN #if CFG_TUD_AUDIO_TX_FIFO_SIZE -static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) { // We encode directly into IN EP's buffer - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); @@ -420,7 +493,7 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a // Check if there is enough if (nSamplesPerChannelToSend == 0) { - *n_bytes_copied = 0; + audio->epin_buf_cnt = 0; return true; } @@ -455,9 +528,8 @@ static bool audio_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a } } - // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, nBytesToSend)); - *n_bytes_copied = nBytesToSend; + audio->epin_buf_cnt = nBytesToSend; + return true; } @@ -718,7 +790,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); uint16_t n_bytes_copied; - TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); } #endif @@ -1003,7 +1075,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // Load new data uint16_t n_bytes_copied; - TU_VERIFY(audio_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); if (n_bytes_copied == 0) { diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index f5830b3a1..c5b8e3e15 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -59,6 +59,10 @@ #define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel #endif +#if CFG_TUD_AUDIO_TX_FIFO_SIZE && CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE +#error TX_FIFOs and TX_DMA_RINGBUFFER can not be used simultaneously! +#endif + #ifndef CFG_TUD_AUDIO_RX_FIFO_SIZE #define CFG_TUD_AUDIO_RX_FIFO_SIZE 0 // Buffer size per channel #endif @@ -171,8 +175,12 @@ uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, u void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); #endif +#if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE +uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) +#endif + #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); +uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 @@ -218,7 +226,8 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_EPSIZE_IN -TU_ATTR_WEAK bool tud_audio_tx_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); +TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_EPSIZE_OUT -- cgit v1.3.1 From 84425c50b3bb5c892bfab9d094cc3da6a9c04da5 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 1 Sep 2020 19:16:50 +0700 Subject: add more logging to host stack tested host with lpc4357, don't use fpu with lpc m4 since it seems to cause hardfault (stack does not make use of fpu anyway). --- hw/bsp/ea4357/board.mk | 6 ++---- hw/bsp/mcb1800/board.mk | 2 +- hw/bsp/ngx4330/board.mk | 2 -- src/class/msc/msc_host.c | 1 + src/host/usbh.c | 44 ++++++++++++++++++++++++++++++++++---------- src/host/usbh.h | 4 ++++ src/osal/osal.h | 4 ++-- 7 files changed, 44 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/hw/bsp/ea4357/board.mk b/hw/bsp/ea4357/board.mk index 2ee6b695c..c77ee4536 100644 --- a/hw/bsp/ea4357/board.mk +++ b/hw/bsp/ea4357/board.mk @@ -3,8 +3,6 @@ CFLAGS += \ -mthumb \ -mabi=aapcs \ -mcpu=cortex-m4 \ - -mfloat-abi=hard \ - -mfpu=fpv4-sp-d16 \ -nostdlib \ -D__USE_LPCOPEN \ -DCORE_M4 \ @@ -40,8 +38,8 @@ CHIP_FAMILY = transdimension FREERTOS_PORT = ARM_CM4F # For flash-jlink target -JLINK_DEVICE = LPC4357 -JLINK_IF = jtag +JLINK_DEVICE = LPC4357_M4 +JLINK_IF = swd # flash using jlink flash: flash-jlink diff --git a/hw/bsp/mcb1800/board.mk b/hw/bsp/mcb1800/board.mk index 7ff17dae3..e3f07d0d0 100644 --- a/hw/bsp/mcb1800/board.mk +++ b/hw/bsp/mcb1800/board.mk @@ -6,7 +6,7 @@ CFLAGS += \ -nostdlib \ -DCORE_M3 \ -D__USE_LPCOPEN \ - -DCFG_TUSB_MCU=OPT_MCU_LPC18XX \ + -DCFG_TUSB_MCU=OPT_MCU_LPC18XX # mcu driver cause following warnings CFLAGS += -Wno-error=unused-parameter -Wno-error=strict-prototypes diff --git a/hw/bsp/ngx4330/board.mk b/hw/bsp/ngx4330/board.mk index 97c24b40e..df9df63a1 100644 --- a/hw/bsp/ngx4330/board.mk +++ b/hw/bsp/ngx4330/board.mk @@ -3,8 +3,6 @@ CFLAGS += \ -mthumb \ -mabi=aapcs \ -mcpu=cortex-m4 \ - -mfloat-abi=hard \ - -mfpu=fpv4-sp-d16 \ -nostdlib \ -DCORE_M4 \ -DCFG_TUSB_MCU=OPT_MCU_LPC43XX \ diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 98c71eb70..3aa697b17 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -310,6 +310,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); //------------- Get Max Lun -------------// + TU_LOG2("MSC Get Max Lun\r\n"); tusb_control_request_t request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, .bRequest = MSC_REQ_GET_MAX_LUN, diff --git a/src/host/usbh.c b/src/host/usbh.c index 8536cec0a..c5f28cf0e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -42,10 +42,17 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + #define DRIVER_NAME(_name) .name = _name, +#else + #define DRIVER_NAME(_name) +#endif + static host_class_driver_t const usbh_class_drivers[] = { #if CFG_TUH_CDC { + DRIVER_NAME("CDC") .class_code = TUSB_CLASS_CDC, .init = cdch_init, .open = cdch_open, @@ -56,6 +63,7 @@ static host_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_MSC { + DRIVER_NAME("MSC") .class_code = TUSB_CLASS_MSC, .init = msch_init, .open = msch_open, @@ -66,6 +74,7 @@ static host_class_driver_t const usbh_class_drivers[] = #if HOST_CLASS_HID { + DRIVER_NAME("HID") .class_code = TUSB_CLASS_HID, .init = hidh_init, .open = hidh_open_subtask, @@ -76,6 +85,7 @@ static host_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_HUB { + DRIVER_NAME("HUB") .class_code = TUSB_CLASS_HUB, .init = hub_init, .open = hub_open, @@ -86,6 +96,7 @@ static host_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_VENDOR { + DRIVER_NAME("VENDOR") .class_code = TUSB_CLASS_VENDOR_SPECIFIC, .init = cush_init, .open = cush_open_subtask, @@ -131,7 +142,7 @@ static inline void osal_task_delay(uint32_t msec) { (void) msec; - uint32_t start = hcd_frame_number(TUH_OPT_RHPORT); + const uint32_t start = hcd_frame_number(TUH_OPT_RHPORT); while ( ( hcd_frame_number(TUH_OPT_RHPORT) - start ) < msec ) {} } @@ -162,7 +173,11 @@ bool usbh_init(void) } // Class drivers init - for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) usbh_class_drivers[drv_id].init(); + for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) + { + TU_LOG2("%s init\r\n", usbh_class_drivers[drv_id].name); + usbh_class_drivers[drv_id].init(); + } TU_ASSERT(hcd_init()); hcd_int_enable(TUH_OPT_RHPORT); @@ -269,6 +284,7 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t ev if (usbh_class_drivers[drv_id].isr) { + TU_LOG2("%s isr\r\n", usbh_class_drivers[drv_id].name); usbh_class_drivers[drv_id].isr(dev_addr, ep_addr, event, xferred_bytes); } else @@ -336,7 +352,11 @@ static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_ if (tuh_umount_cb) tuh_umount_cb(dev_addr); // Close class driver - for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) usbh_class_drivers[drv_id].close(dev_addr); + for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) + { + TU_LOG2("%s close\r\n", usbh_class_drivers[drv_id].name); + usbh_class_drivers[drv_id].close(dev_addr); + } memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping @@ -381,7 +401,7 @@ bool enum_task(hcd_event_t* event) { if( hcd_port_connect_status(dev0->rhport) ) { - TU_LOG2("Connect \r\n"); + TU_LOG2("Device connect \r\n"); // connection event osal_task_delay(POWER_STABLE_DELAY); // wait until device is stable. Increase this if the first 8 bytes is failed to get @@ -396,7 +416,7 @@ bool enum_task(hcd_event_t* event) } else { - TU_LOG2("Disconnect \r\n"); + TU_LOG2("Device disconnect \r\n"); // disconnection event usbh_device_unplugged(dev0->rhport, 0, 0); @@ -451,7 +471,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT_ERR( usbh_pipe_control_open(0, 8) ); //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// - TU_LOG2("Get 8 byte of Device Descriptor \r\n"); + TU_LOG2("Get 8 byte of Device Descriptor\r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, @@ -536,7 +556,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT(configure_selected <= new_dev->configure_count); // TODO notify application when invalid configuration //------------- Get 9 bytes of configuration descriptor -------------// - TU_LOG2("Get 9 bytes of Configuration Descriptor \r\n"); + TU_LOG2("Get 9 bytes of Configuration Descriptor\r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, @@ -550,7 +570,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT( CFG_TUSB_HOST_ENUM_BUFFER_SIZE >= ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength ); //------------- Get full configuration descriptor -------------// - TU_LOG2("Get full Configuration Descriptor \r\n"); + TU_LOG2("Get full Configuration Descriptor\r\n"); request.wLength = ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength; // full length TU_ASSERT( usbh_control_xfer( new_addr, &request, _usbh_ctrl_buf ) ); @@ -558,7 +578,7 @@ bool enum_task(hcd_event_t* event) new_dev->interface_count = ((tusb_desc_configuration_t*) _usbh_ctrl_buf)->bNumInterfaces; //------------- Set Configure -------------// - TU_LOG2("Set Configuration Descriptor \r\n"); + TU_LOG2("Set Configuration Descriptor\r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, .bRequest = TUSB_REQ_SET_CONFIGURATION, @@ -568,6 +588,7 @@ bool enum_task(hcd_event_t* event) }; TU_ASSERT(usbh_control_xfer( new_addr, &request, NULL )); + TU_LOG2("Device configured\r\n"); new_dev->state = TUSB_DEVICE_STATE_CONFIGURED; //------------- TODO Get String Descriptors -------------// @@ -575,6 +596,8 @@ bool enum_task(hcd_event_t* event) //------------- parse configuration & install drivers -------------// uint8_t const* p_desc = _usbh_ctrl_buf + sizeof(tusb_desc_configuration_t); + TU_LOG2_MEM(_usbh_ctrl_buf, ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength, 0); + // parse each interfaces while( p_desc < _usbh_ctrl_buf + ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength ) { @@ -584,7 +607,7 @@ bool enum_task(hcd_event_t* event) p_desc = tu_desc_next(p_desc); // skip the descriptor, increase by the descriptor's length }else { - tusb_desc_interface_t* desc_itf = (tusb_desc_interface_t*) p_desc; + tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; // Check if class is supported uint8_t drv_id; @@ -614,6 +637,7 @@ bool enum_task(hcd_event_t* event) { uint16_t itf_len = 0; + TU_LOG2("%s open\r\n", usbh_class_drivers[drv_id].name); TU_ASSERT( usbh_class_drivers[drv_id].open(new_dev->rhport, new_addr, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); p_desc += itf_len; diff --git a/src/host/usbh.h b/src/host/usbh.h index cc112d756..39e7a4e0d 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -52,6 +52,10 @@ typedef enum tusb_interface_status_{ } tusb_interface_status_t; typedef struct { + #if CFG_TUSB_DEBUG >= 2 + char const* name; + #endif + uint8_t class_code; void (* const init) (void); diff --git a/src/osal/osal.h b/src/osal/osal.h index c61f0c912..b5057ff4c 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -37,9 +37,9 @@ #include "common/tusb_common.h" // Return immediately -#define OSAL_TIMEOUT_NOTIMEOUT (0) +#define OSAL_TIMEOUT_NOTIMEOUT (0) // Default timeout -#define OSAL_TIMEOUT_NORMAL (10) +#define OSAL_TIMEOUT_NORMAL (10) // Wait forever #define OSAL_TIMEOUT_WAIT_FOREVER (UINT32_MAX) -- cgit v1.3.1 From c492aef4c7b4dd6ee7b24c30176a570ae6eae043 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Sep 2020 00:46:08 +0700 Subject: revert to use float-abi define __USE_CMSIS instead of __USE_LPCOPEN will have startup enable FPU on startup properly. Although it is only relevant to lpx43/40 series, change all to __USE_CMSIS for consistency --- hw/bsp/ea4088qs/board.mk | 4 ++-- hw/bsp/ea4357/board.mk | 4 +++- hw/bsp/lpcxpresso11u37/board.mk | 2 +- hw/bsp/lpcxpresso11u68/board.mk | 2 +- hw/bsp/lpcxpresso1347/board.mk | 2 +- hw/bsp/lpcxpresso1549/board.mk | 2 +- hw/bsp/lpcxpresso1769/board.mk | 2 +- hw/bsp/mbed1768/board.mk | 2 +- hw/bsp/mcb1800/board.mk | 2 +- hw/bsp/ngx4330/board.mk | 6 ++++-- src/host/usbh.c | 2 +- 11 files changed, 17 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/hw/bsp/ea4088qs/board.mk b/hw/bsp/ea4088qs/board.mk index 950aa484c..2a63d8af2 100644 --- a/hw/bsp/ea4088qs/board.mk +++ b/hw/bsp/ea4088qs/board.mk @@ -5,9 +5,9 @@ CFLAGS += \ -mcpu=cortex-m4 \ -nostdlib \ -DCORE_M4 \ - -DCFG_TUSB_MCU=OPT_MCU_LPC40XX \ + -D__USE_CMSIS \ -DCFG_TUSB_MEM_SECTION='__attribute__((section(".data.$$RAM2")))' \ - -D__USE_LPCOPEN + -DCFG_TUSB_MCU=OPT_MCU_LPC40XX # mcu driver cause following warnings CFLAGS += -Wno-error=strict-prototypes -Wno-error=unused-parameter diff --git a/hw/bsp/ea4357/board.mk b/hw/bsp/ea4357/board.mk index c77ee4536..44481118d 100644 --- a/hw/bsp/ea4357/board.mk +++ b/hw/bsp/ea4357/board.mk @@ -3,9 +3,11 @@ CFLAGS += \ -mthumb \ -mabi=aapcs \ -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ -nostdlib \ - -D__USE_LPCOPEN \ -DCORE_M4 \ + -D__USE_CMSIS \ -DCFG_TUSB_MCU=OPT_MCU_LPC43XX # mcu driver cause following warnings diff --git a/hw/bsp/lpcxpresso11u37/board.mk b/hw/bsp/lpcxpresso11u37/board.mk index d1c48a2e5..27019ff8b 100644 --- a/hw/bsp/lpcxpresso11u37/board.mk +++ b/hw/bsp/lpcxpresso11u37/board.mk @@ -5,7 +5,7 @@ CFLAGS += \ -mcpu=cortex-m0 \ -nostdlib \ -DCORE_M0 \ - -D__USE_LPCOPEN \ + -D__USE_CMSIS \ -DCFG_EXAMPLE_MSC_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_LPC11UXX \ -DCFG_TUSB_MEM_SECTION='__attribute__((section(".data.$$RAM2")))' \ diff --git a/hw/bsp/lpcxpresso11u68/board.mk b/hw/bsp/lpcxpresso11u68/board.mk index d9017ae1a..1c1660367 100644 --- a/hw/bsp/lpcxpresso11u68/board.mk +++ b/hw/bsp/lpcxpresso11u68/board.mk @@ -6,7 +6,7 @@ CFLAGS += \ -nostdlib \ -DCORE_M0PLUS \ -D__VTOR_PRESENT=0 \ - -D__USE_LPCOPEN \ + -D__USE_CMSIS \ -DCFG_TUSB_MCU=OPT_MCU_LPC11UXX \ -DCFG_TUSB_MEM_SECTION='__attribute__((section(".data.$$RAM3")))' \ -DCFG_TUSB_MEM_ALIGN='__attribute__((aligned(64)))' diff --git a/hw/bsp/lpcxpresso1347/board.mk b/hw/bsp/lpcxpresso1347/board.mk index 6dc3937f6..5befc3aee 100644 --- a/hw/bsp/lpcxpresso1347/board.mk +++ b/hw/bsp/lpcxpresso1347/board.mk @@ -5,7 +5,7 @@ CFLAGS += \ -mcpu=cortex-m3 \ -nostdlib \ -DCORE_M3 \ - -D__USE_LPCOPEN \ + -D__USE_CMSIS \ -DCFG_EXAMPLE_MSC_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_LPC13XX \ -DCFG_TUSB_MEM_SECTION='__attribute__((section(".data.$$RAM2")))' \ diff --git a/hw/bsp/lpcxpresso1549/board.mk b/hw/bsp/lpcxpresso1549/board.mk index 18325c5f7..c603e4b30 100644 --- a/hw/bsp/lpcxpresso1549/board.mk +++ b/hw/bsp/lpcxpresso1549/board.mk @@ -5,7 +5,7 @@ CFLAGS += \ -mcpu=cortex-m3 \ -nostdlib \ -DCORE_M3 \ - -D__USE_LPCOPEN \ + -D__USE_CMSIS \ -DCFG_EXAMPLE_MSC_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_LPC15XX \ -DCFG_TUSB_MEM_ALIGN='__attribute__((aligned(64)))' diff --git a/hw/bsp/lpcxpresso1769/board.mk b/hw/bsp/lpcxpresso1769/board.mk index a345e5a27..6886ef749 100644 --- a/hw/bsp/lpcxpresso1769/board.mk +++ b/hw/bsp/lpcxpresso1769/board.mk @@ -5,7 +5,7 @@ CFLAGS += \ -mcpu=cortex-m3 \ -nostdlib \ -DCORE_M3 \ - -D__USE_LPCOPEN \ + -D__USE_CMSIS \ -DCFG_TUSB_MCU=OPT_MCU_LPC175X_6X \ -DRTC_EV_SUPPORT=0 diff --git a/hw/bsp/mbed1768/board.mk b/hw/bsp/mbed1768/board.mk index 3bdc8a27a..5b23900ff 100644 --- a/hw/bsp/mbed1768/board.mk +++ b/hw/bsp/mbed1768/board.mk @@ -5,7 +5,7 @@ CFLAGS += \ -mcpu=cortex-m3 \ -nostdlib \ -DCORE_M3 \ - -D__USE_LPCOPEN \ + -D__USE_CMSIS \ -DCFG_TUSB_MCU=OPT_MCU_LPC175X_6X \ -DRTC_EV_SUPPORT=0 diff --git a/hw/bsp/mcb1800/board.mk b/hw/bsp/mcb1800/board.mk index e3f07d0d0..3d3bb2371 100644 --- a/hw/bsp/mcb1800/board.mk +++ b/hw/bsp/mcb1800/board.mk @@ -5,7 +5,7 @@ CFLAGS += \ -mcpu=cortex-m3 \ -nostdlib \ -DCORE_M3 \ - -D__USE_LPCOPEN \ + -D__USE_CMSIS \ -DCFG_TUSB_MCU=OPT_MCU_LPC18XX # mcu driver cause following warnings diff --git a/hw/bsp/ngx4330/board.mk b/hw/bsp/ngx4330/board.mk index df9df63a1..08a877229 100644 --- a/hw/bsp/ngx4330/board.mk +++ b/hw/bsp/ngx4330/board.mk @@ -3,10 +3,12 @@ CFLAGS += \ -mthumb \ -mabi=aapcs \ -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ -nostdlib \ -DCORE_M4 \ - -DCFG_TUSB_MCU=OPT_MCU_LPC43XX \ - -D__USE_LPCOPEN + -D__USE_CMSIS \ + -DCFG_TUSB_MCU=OPT_MCU_LPC43XX # mcu driver cause following warnings CFLAGS += -Wno-error=strict-prototypes -Wno-error=unused-parameter diff --git a/src/host/usbh.c b/src/host/usbh.c index c5f28cf0e..352450588 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -596,7 +596,7 @@ bool enum_task(hcd_event_t* event) //------------- parse configuration & install drivers -------------// uint8_t const* p_desc = _usbh_ctrl_buf + sizeof(tusb_desc_configuration_t); - TU_LOG2_MEM(_usbh_ctrl_buf, ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength, 0); + // TU_LOG2_MEM(_usbh_ctrl_buf, ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength, 0); // parse each interfaces while( p_desc < _usbh_ctrl_buf + ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength ) -- cgit v1.3.1 From 1d83ad0ebb6c263736b0dadec80c9406563a5199 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Sep 2020 13:12:09 +0700 Subject: rename tuh_isr/hcd_isr to tuh_int_handler/hcd_int_handler --- hw/bsp/ea4088qs/ea4088qs.c | 2 +- hw/bsp/ea4357/ea4357.c | 4 ++-- hw/bsp/lpcxpresso1769/lpcxpresso1769.c | 2 +- hw/bsp/mbed1768/mbed1768.c | 2 +- hw/bsp/mcb1800/mcb1800.c | 4 ++-- hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c | 2 +- hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c | 2 +- hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c | 2 +- hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c | 4 ++-- hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c | 4 ++-- hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c | 4 ++-- hw/bsp/ngx4330/ngx4330.c | 4 ++-- hw/bsp/teensy_40/teensy40.c | 4 ++-- src/device/dcd.h | 6 +++--- src/host/ehci/ehci.c | 2 +- src/host/hcd.h | 9 +++------ src/host/ohci/ohci.c | 2 +- src/host/usbh.h | 3 ++- 18 files changed, 30 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/hw/bsp/ea4088qs/ea4088qs.c b/hw/bsp/ea4088qs/ea4088qs.c index 00db1a299..df76bb92a 100644 --- a/hw/bsp/ea4088qs/ea4088qs.c +++ b/hw/bsp/ea4088qs/ea4088qs.c @@ -33,7 +33,7 @@ void USB_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/ea4357/ea4357.c b/hw/bsp/ea4357/ea4357.c index f41ba5ab9..69d2c3cc1 100644 --- a/hw/bsp/ea4357/ea4357.c +++ b/hw/bsp/ea4357/ea4357.c @@ -246,7 +246,7 @@ void board_init(void) void USB0_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE @@ -257,7 +257,7 @@ void USB0_IRQHandler(void) void USB1_IRQHandler(void) { #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST - tuh_isr(1); + tuh_int_handler(1); #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c index 5ec4fac23..0d5e98e9e 100644 --- a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c +++ b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c @@ -33,7 +33,7 @@ void USB_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mbed1768/mbed1768.c b/hw/bsp/mbed1768/mbed1768.c index 0dfd05c81..17004cfe0 100644 --- a/hw/bsp/mbed1768/mbed1768.c +++ b/hw/bsp/mbed1768/mbed1768.c @@ -147,7 +147,7 @@ void board_init(void) void USB_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mcb1800/mcb1800.c b/hw/bsp/mcb1800/mcb1800.c index b57385985..a17ac5c3b 100644 --- a/hw/bsp/mcb1800/mcb1800.c +++ b/hw/bsp/mcb1800/mcb1800.c @@ -33,7 +33,7 @@ void USB0_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE @@ -44,7 +44,7 @@ void USB0_IRQHandler(void) void USB1_IRQHandler(void) { #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST - tuh_isr(1); + tuh_int_handler(1); #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c b/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c index c682ace8d..1c4b1798c 100644 --- a/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c +++ b/hw/bsp/mimxrt1010_evk/mimxrt1010_evk.c @@ -121,7 +121,7 @@ void board_init(void) void USB_OTG1_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c b/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c index 214077a4a..2b1f3cc80 100644 --- a/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c +++ b/hw/bsp/mimxrt1015_evk/mimxrt1015_evk.c @@ -121,7 +121,7 @@ void board_init(void) void USB_OTG1_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c b/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c index f32ec5401..273f3a0c9 100644 --- a/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c +++ b/hw/bsp/mimxrt1020_evk/mimxrt1020_evk.c @@ -120,7 +120,7 @@ void board_init(void) void USB_OTG1_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c b/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c index be0ae3ea8..1042bcfe7 100644 --- a/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c +++ b/hw/bsp/mimxrt1050_evkb/mimxrt1050_evkb.c @@ -124,7 +124,7 @@ void board_init(void) void USB_OTG1_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE @@ -135,7 +135,7 @@ void USB_OTG1_IRQHandler(void) void USB_OTG2_IRQHandler(void) { #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST - tuh_isr(1); + tuh_int_handler(1); #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c index be0ae3ea8..1042bcfe7 100644 --- a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c +++ b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c @@ -124,7 +124,7 @@ void board_init(void) void USB_OTG1_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE @@ -135,7 +135,7 @@ void USB_OTG1_IRQHandler(void) void USB_OTG2_IRQHandler(void) { #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST - tuh_isr(1); + tuh_int_handler(1); #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c b/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c index be0ae3ea8..1042bcfe7 100644 --- a/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c +++ b/hw/bsp/mimxrt1064_evk/mimxrt1064_evk.c @@ -124,7 +124,7 @@ void board_init(void) void USB_OTG1_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE @@ -135,7 +135,7 @@ void USB_OTG1_IRQHandler(void) void USB_OTG2_IRQHandler(void) { #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST - tuh_isr(1); + tuh_int_handler(1); #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/ngx4330/ngx4330.c b/hw/bsp/ngx4330/ngx4330.c index b1908fc38..dda3bc092 100644 --- a/hw/bsp/ngx4330/ngx4330.c +++ b/hw/bsp/ngx4330/ngx4330.c @@ -231,7 +231,7 @@ void board_init(void) void USB0_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE @@ -242,7 +242,7 @@ void USB0_IRQHandler(void) void USB1_IRQHandler(void) { #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST - tuh_isr(1); + tuh_int_handler(1); #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE diff --git a/hw/bsp/teensy_40/teensy40.c b/hw/bsp/teensy_40/teensy40.c index f45a98ef3..30fdedd27 100644 --- a/hw/bsp/teensy_40/teensy40.c +++ b/hw/bsp/teensy_40/teensy40.c @@ -125,7 +125,7 @@ void board_init(void) void USB_OTG1_IRQHandler(void) { #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - tuh_isr(0); + tuh_int_handler(0); #endif #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE @@ -136,7 +136,7 @@ void USB_OTG1_IRQHandler(void) void USB_OTG2_IRQHandler(void) { #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST - tuh_isr(1); + tuh_int_handler(1); #endif #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE diff --git a/src/device/dcd.h b/src/device/dcd.h index a4635346b..776f782b8 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -87,9 +87,9 @@ typedef struct TU_ATTR_ALIGNED(4) //TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct"); -/*------------------------------------------------------------------*/ -/* Device API - *------------------------------------------------------------------*/ +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ // Initialize controller to device mode void dcd_init (uint8_t rhport); diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index e2ead7b08..295da4566 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -648,7 +648,7 @@ static void xfer_error_isr(uint8_t hostid) } //------------- Host Controller Driver's Interrupt Handler -------------// -void hcd_isr(uint8_t rhport) +void hcd_int_handler(uint8_t rhport) { ehci_registers_t* regs = ehci_data.regs; diff --git a/src/host/hcd.h b/src/host/hcd.h index f2ca0a1d6..24cc62501 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -84,10 +84,10 @@ enum { #endif //--------------------------------------------------------------------+ -// HCD API +// Controller & Port API //--------------------------------------------------------------------+ bool hcd_init(void); -void hcd_isr(uint8_t hostid); +void hcd_int_handler(uint8_t rhport); void hcd_int_enable (uint8_t rhport); void hcd_int_disable(uint8_t rhport); @@ -100,7 +100,6 @@ static inline uint32_t hcd_frame_number(uint8_t rhport) return hcd_uframe_number(rhport) >> 3; } -// PORT API /// return the current connect status of roothub port bool hcd_port_connect_status(uint8_t hostid); void hcd_port_reset(uint8_t hostid); @@ -144,9 +143,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes); // only queue, not transferring yet bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete); -#if 0 -tusb_error_t hcd_pipe_cancel(); -#endif +// tusb_error_t hcd_pipe_cancel(); #ifdef __cplusplus } diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 5ee5fe8c4..114f52e7d 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -606,7 +606,7 @@ static void done_queue_isr(uint8_t hostid) } } -void hcd_isr(uint8_t hostid) +void hcd_int_handler(uint8_t hostid) { uint32_t const int_en = OHCI_REG->interrupt_enable; uint32_t const int_status = OHCI_REG->interrupt_status & int_en; diff --git a/src/host/usbh.h b/src/host/usbh.h index 39e7a4e0d..27193d378 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -73,7 +73,8 @@ typedef struct { void tuh_task(void); // Interrupt handler, name alias to HCD -#define tuh_isr hcd_isr +extern void hcd_int_handler(uint8_t rhport); +#define tuh_int_handler hcd_int_handler tusb_device_state_t tuh_device_get_state (uint8_t dev_addr); static inline bool tuh_device_is_configured(uint8_t dev_addr) -- cgit v1.3.1 From ef651e073409bac1a9793d97bf5a25220913f32e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Sep 2020 17:07:29 +0700 Subject: fix #449 remove obsolete pipehandle from hid host --- examples/host/cdc_msc_hid/Makefile | 5 +-- src/class/hid/hid_host.c | 66 +++++++++++++++++++++----------------- src/class/hid/hid_host.h | 10 ++---- src/class/msc/msc_host.c | 6 ++-- src/class/msc/msc_host.h | 2 +- 5 files changed, 45 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index 29a323957..35de0a9a0 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -13,12 +13,13 @@ CFLAGS += -Wno-error=cast-align # TinyUSB Host Stack source SRC_C += \ + src/class/cdc/cdc_host.c \ + src/class/hid/hid_host.c \ + src/class/msc/msc_host.c \ src/host/usbh.c \ src/host/hub.c \ src/host/ehci/ehci.c \ src/host/ohci/ohci.c \ - src/class/cdc/cdc_host.c \ - src/class/msc/msc_host.c \ src/portable/nxp/lpc18_43/hcd_lpc18_43.c \ src/portable/nxp/lpc17_40/hcd_lpc17_40.c diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 8abb3cd22..ec5333917 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -35,35 +35,43 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +typedef struct { + uint8_t itf_numr; + uint8_t ep_in; + uint8_t ep_out; + + uint16_t report_size; +}hidh_interface_t; + //--------------------------------------------------------------------+ // HID Interface common functions //--------------------------------------------------------------------+ -static inline bool hidh_interface_open(uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *p_endpoint_desc, hidh_interface_info_t *p_hid) +static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *p_endpoint_desc, hidh_interface_t *p_hid) { - p_hid->pipe_hdl = usbh_edpt_open(dev_addr, p_endpoint_desc, TUSB_CLASS_HID); - p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor - p_hid->interface_number = interface_number; + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, p_endpoint_desc) ); - TU_ASSERT (pipehandle_is_valid(p_hid->pipe_hdl)); + p_hid->ep_in = p_endpoint_desc->bEndpointAddress; + p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor + p_hid->itf_numr = interface_number; return true; } -static inline void hidh_interface_close(hidh_interface_info_t *p_hid) +static inline void hidh_interface_close(hidh_interface_t *p_hid) { - tu_memclr(p_hid, sizeof(hidh_interface_info_t)); + tu_memclr(p_hid, sizeof(hidh_interface_t)); } // called from public API need to validate parameters -tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_info_t *p_hid) +tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_t *p_hid) { //------------- parameters validation -------------// // TODO change to use is configured function TU_ASSERT (TUSB_DEVICE_STATE_CONFIGURED == tuh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); TU_VERIFY (report, TUSB_ERROR_INVALID_PARA); - TU_ASSERT (!hcd_edpt_busy(p_hid->pipe_hdl), TUSB_ERROR_INTERFACE_IS_BUSY); + TU_ASSERT (!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); - TU_ASSERT_ERR( hcd_pipe_xfer(p_hid->pipe_hdl, report, p_hid->report_size, true) ) ; + TU_ASSERT_ERR( hcd_pipe_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size, true) ) ; return TUSB_ERROR_NONE; } @@ -85,12 +93,12 @@ uint8_t const hid_keycode_to_ascii_tbl[2][128] = }; #endif -static hidh_interface_info_t keyboardh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 +static hidh_interface_t keyboardh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- KEYBOARD PUBLIC API (parameter validation required) -------------// bool tuh_hid_keyboard_is_mounted(uint8_t dev_addr) { - return tuh_device_is_configured(dev_addr) && pipehandle_is_valid(keyboardh_data[dev_addr-1].pipe_hdl); + return tuh_device_is_configured(dev_addr) && (keyboardh_data[dev_addr-1].ep_in != 0); } tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* p_report) @@ -100,8 +108,7 @@ tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* p_report) bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) { - return tuh_hid_keyboard_is_mounted(dev_addr) && - hcd_edpt_busy( keyboardh_data[dev_addr-1].pipe_hdl ); + return tuh_hid_keyboard_is_mounted(dev_addr) && hcd_edpt_busy(dev_addr, keyboardh_data[dev_addr-1].ep_in); } #endif @@ -111,18 +118,17 @@ bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) //--------------------------------------------------------------------+ #if CFG_TUH_HID_MOUSE -static hidh_interface_info_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 +static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- Public API -------------// bool tuh_hid_mouse_is_mounted(uint8_t dev_addr) { - return tuh_device_is_configured(dev_addr) && pipehandle_is_valid(mouseh_data[dev_addr-1].pipe_hdl); + return tuh_device_is_configured(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); } bool tuh_hid_mouse_is_busy(uint8_t dev_addr) { - return tuh_hid_mouse_is_mounted(dev_addr) && - hcd_edpt_busy( mouseh_data[dev_addr-1].pipe_hdl ); + return tuh_hid_mouse_is_mounted(dev_addr) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); } tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) @@ -149,11 +155,11 @@ tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) void hidh_init(void) { #if CFG_TUH_HID_KEYBOARD - tu_memclr(&keyboardh_data, sizeof(hidh_interface_info_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(&keyboardh_data, sizeof(hidh_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); #endif #if CFG_TUH_HID_MOUSE - tu_memclr(&mouseh_data, sizeof(hidh_interface_info_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(&mouseh_data, sizeof(hidh_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); #endif #if CFG_TUSB_HOST_HID_GENERIC @@ -165,7 +171,7 @@ void hidh_init(void) CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256]; #endif -bool hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) +bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) { uint8_t const *p_desc = (uint8_t const *) p_interface_desc; @@ -208,7 +214,7 @@ bool hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interfac #if CFG_TUH_HID_KEYBOARD if ( HID_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol) { - TU_ASSERT( hidh_interface_open(dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) ); + TU_ASSERT( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) ); tuh_hid_keyboard_mounted_cb(dev_addr); } else #endif @@ -216,7 +222,7 @@ bool hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interfac #if CFG_TUH_HID_MOUSE if ( HID_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol) { - TU_ASSERT ( hidh_interface_open(dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) ); + TU_ASSERT ( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) ); tuh_hid_mouse_mounted_cb(dev_addr); } else #endif @@ -236,22 +242,22 @@ bool hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interfac return true; } -void hidh_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes) +void hidh_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO may need to use this para later #if CFG_TUH_HID_KEYBOARD - if ( pipehandle_is_equal(pipe_hdl, keyboardh_data[pipe_hdl.dev_addr-1].pipe_hdl) ) + if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) { - tuh_hid_keyboard_isr(pipe_hdl.dev_addr, event); + tuh_hid_keyboard_isr(dev_addr, event); return; } #endif #if CFG_TUH_HID_MOUSE - if ( pipehandle_is_equal(pipe_hdl, mouseh_data[pipe_hdl.dev_addr-1].pipe_hdl) ) + if ( ep_addr == mouseh_data[dev_addr-1].ep_in ) { - tuh_hid_mouse_isr(pipe_hdl.dev_addr, event); + tuh_hid_mouse_isr(dev_addr, event); return; } #endif @@ -264,7 +270,7 @@ void hidh_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_byte void hidh_close(uint8_t dev_addr) { #if CFG_TUH_HID_KEYBOARD - if ( pipehandle_is_valid( keyboardh_data[dev_addr-1].pipe_hdl ) ) + if ( keyboardh_data[dev_addr-1].ep_in != 0 ) { hidh_interface_close(&keyboardh_data[dev_addr-1]); tuh_hid_keyboard_unmounted_cb(dev_addr); @@ -272,7 +278,7 @@ void hidh_close(uint8_t dev_addr) #endif #if CFG_TUH_HID_MOUSE - if( pipehandle_is_valid( mouseh_data[dev_addr-1].pipe_hdl ) ) + if( mouseh_data[dev_addr-1].ep_in != 0 ) { hidh_interface_close(&mouseh_data[dev_addr-1]); tuh_hid_mouse_unmounted_cb( dev_addr ); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index a3b614cd7..2e7f52674 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -195,15 +195,9 @@ void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -typedef struct { - pipe_handle_t pipe_hdl; - uint16_t report_size; - uint8_t interface_number; -}hidh_interface_info_t; - void hidh_init(void); -bool hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); -void hidh_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes); +bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); +void hidh_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hidh_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 3aa697b17..539e98376 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -306,7 +306,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc); } - p_msc->itf_numr = itf_desc->bInterfaceNumber; + p_msc->itf_num = itf_desc->bInterfaceNumber; (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); //------------- Get Max Lun -------------// @@ -315,7 +315,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, .bRequest = MSC_REQ_GET_MAX_LUN, .wValue = 0, - .wIndex = p_msc->itf_numr, + .wIndex = p_msc->itf_num, .wLength = 1 }; // TODO STALL means zero @@ -328,7 +328,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, .bRequest = MSC_REQ_RESET, .wValue = 0, - .wIndex = p_msc->itf_numr, + .wIndex = p_msc->itf_num, .wLength = 0 }; TU_ASSERT( usbh_control_xfer( dev_addr, &request, NULL ) ); diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 76cf86853..959294adf 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -175,7 +175,7 @@ void tuh_msc_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes); //--------------------------------------------------------------------+ typedef struct { - uint8_t itf_numr; + uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; -- cgit v1.3.1 From d9eaa54e14775ebcf6a78cb84c354e69e57903d3 Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Thu, 3 Sep 2020 16:40:53 +0200 Subject: Remove connected check for write flushing --- src/class/cdc/cdc_device.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index b4ebfc92e..91799b2de 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -165,11 +165,7 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in), 0 ); uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); - if ( count ) - { - TU_VERIFY( tud_cdc_n_connected(itf), 0 ); // fifo is empty if not connected - TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); - } + if ( count ) TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); return count; } -- cgit v1.3.1 From fd6cf9010b522019a4434ebd02fb447b567e7131 Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Thu, 3 Sep 2020 17:03:13 +0200 Subject: Turn transmit fifo overwritable in no DTR mode --- src/class/cdc/cdc_device.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 91799b2de..6c0f5fc7a 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -197,7 +197,7 @@ void cdcd_init(void) // config fifo tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); - tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, false); + tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&p_cdc->rx_ff, osal_mutex_create(&p_cdc->rx_ff_mutex)); @@ -355,6 +355,9 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request p_cdc->line_state = (uint8_t) request->wValue; + // Disable fifo overwriting if DTR bit is set + p_cdc->tx_ff.overwritable = dtr ? false : true; + TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); tud_control_status(rhport, request); -- cgit v1.3.1 From 4071e490e259de5bf2891c9893ab7965b5be3d2e Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Thu, 3 Sep 2020 17:21:32 +0200 Subject: New function to modify fifo overwritability --- src/class/cdc/cdc_device.c | 2 +- src/common/tusb_fifo.c | 19 +++++++++++++++++++ src/common/tusb_fifo.h | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 6c0f5fc7a..6f71cb781 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -356,7 +356,7 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request p_cdc->line_state = (uint8_t) request->wValue; // Disable fifo overwriting if DTR bit is set - p_cdc->tx_ff.overwritable = dtr ? false : true; + tu_fifo_change_mode(&p_cdc->tx_ff, (dtr?false:true)); TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 6ab158cca..fdd8c3e35 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -319,3 +319,22 @@ bool tu_fifo_clear(tu_fifo_t *f) return true; } + +/******************************************************************************/ +/*! + @brief Change the fifo mode to overwritable or not overwritable + + @param[in] f + Pointer to the FIFO buffer to manipulate +*/ +/******************************************************************************/ +bool tu_fifo_change_mode(tu_fifo_t *f, bool overwritable) +{ + tu_fifo_lock(f); + + f->overwritable = overwritable; + + tu_fifo_unlock(f); + + return true; +} diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index fb0c896f3..7957d83af 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -76,6 +76,7 @@ typedef struct .overwritable = _overwritable, \ } +bool tu_fifo_change_mode(tu_fifo_t *f, bool overwritable); bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); -- cgit v1.3.1 From 338e96fa826b2e2bbb6fb489456202e9e4ec4fe2 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 3 Sep 2020 18:09:46 +0200 Subject: Remove tud_audio_n_write_ep_in_buffer() as long as ISO EPs are not RBs. --- src/class/audio/audio_device.c | 4 ++++ src/class/audio/audio_device.h | 2 ++ 2 files changed, 6 insertions(+) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 19be2d6d1..942933b5d 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -334,6 +334,8 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a * \param[in] len: # of array elements to copy * \return Number of bytes actually written */ + +/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers #if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) { @@ -363,6 +365,8 @@ uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t } #endif +*/ + #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index c5b8e3e15..11f444daa 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -175,9 +175,11 @@ uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, u void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); #endif +/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers #if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) #endif +*/ #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); -- cgit v1.3.1 From 35aee4a6af40c7c8befb5dfe81bbf7e26dc01ca8 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Sep 2020 23:57:51 +0700 Subject: more hid host work --- examples/host/cdc_msc_hid/src/main.c | 63 +++++++++++++++++++++++++++++++++--- src/class/hid/hid_host.c | 22 ++++--------- src/host/usbh.c | 2 +- 3 files changed, 65 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 9ec213090..8f61310d5 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -110,21 +110,74 @@ void cdc_task(void) // USB HID //--------------------------------------------------------------------+ #if CFG_TUH_HID_KEYBOARD -void hid_task(void) + +uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; + +// look up new key in previous keys +static inline bool find_key_in_report(hid_keyboard_report_t const *p_report, uint8_t keycode) +{ + for(uint8_t i=0; i<6; i++) + { + if (p_report->keycode[i] == keycode) return true; + } + + return false; +} + +static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) { + static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released + + //------------- example code ignore control (non-printable) key affects -------------// + for(uint8_t i=0; i<6; i++) + { + if ( p_new_report->keycode[i] ) + { + if ( find_key_in_report(&prev_report, p_new_report->keycode[i]) ) + { + // exist in previous report means the current key is holding + }else + { + // not existed in previous report means the current key is pressed + bool const is_shift = p_new_report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); + uint8_t ch = keycode2ascii[p_new_report->keycode[i]][is_shift ? 1 : 0]; + putchar(ch); + if ( ch == '\r' ) putchar('\n'); // added new line for enter key + } + } + // TODO example skips key released + } + + prev_report = *p_new_report; +} + +CFG_TUSB_MEM_SECTION static hid_keyboard_report_t usb_keyboard_report; +void hid_task(void) +{ + uint8_t const addr = 1; + if ( tuh_hid_keyboard_is_mounted(addr) ) + { + if ( !tuh_hid_keyboard_is_busy(addr) ) + { + process_kbd_report(&usb_keyboard_report); + tuh_hid_keyboard_get_report(addr, &usb_keyboard_report); + } + } } void tuh_hid_keyboard_mounted_cb(uint8_t dev_addr) { // application set-up - printf("\na Keyboard device (address %d) is mounted\n", dev_addr); + printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); + + tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); } void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr) { // application tear-down - printf("\na Keyboard device (address %d) is unmounted\n", dev_addr); + printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); } // invoked ISR context @@ -139,13 +192,13 @@ void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event) void tuh_hid_mouse_mounted_cb(uint8_t dev_addr) { // application set-up - printf("\na Mouse device (address %d) is mounted\n", dev_addr); + printf("A Mouse device (address %d) is mounted\r\n", dev_addr); } void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr) { // application tear-down - printf("\na Mouse device (address %d) is unmounted\n", dev_addr); + printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); } // invoked ISR context diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index ec5333917..d2d1c0397 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -67,11 +67,11 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int { //------------- parameters validation -------------// // TODO change to use is configured function - TU_ASSERT (TUSB_DEVICE_STATE_CONFIGURED == tuh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); - TU_VERIFY (report, TUSB_ERROR_INVALID_PARA); - TU_ASSERT (!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); + TU_ASSERT(TUSB_DEVICE_STATE_CONFIGURED == tuh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); + TU_VERIFY(report, TUSB_ERROR_INVALID_PARA); + TU_ASSERT(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); - TU_ASSERT_ERR( hcd_pipe_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size, true) ) ; + TU_ASSERT( hcd_pipe_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size, true) ) ; return TUSB_ERROR_NONE; } @@ -81,18 +81,6 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int //--------------------------------------------------------------------+ #if CFG_TUH_HID_KEYBOARD -#if 0 -#define EXPAND_KEYCODE_TO_ASCII(keycode, ascii, shift_modified) \ - [0][keycode] = ascii,\ - [1][keycode] = shift_modified,\ - -// TODO size of table should be a macro for application to check boundary -uint8_t const hid_keycode_to_ascii_tbl[2][128] = -{ - HID_KEYCODE_TABLE(EXPAND_KEYCODE_TO_ASCII) -}; -#endif - static hidh_interface_t keyboardh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- KEYBOARD PUBLIC API (parameter validation required) -------------// @@ -215,6 +203,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c if ( HID_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol) { TU_ASSERT( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) ); + TU_LOG2_HEX(keyboardh_data[dev_addr-1].ep_in); tuh_hid_keyboard_mounted_cb(dev_addr); } else #endif @@ -223,6 +212,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c if ( HID_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol) { TU_ASSERT ( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) ); + TU_LOG2_HEX(mouseh_data[dev_addr-1].ep_in); tuh_hid_mouse_mounted_cb(dev_addr); } else #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index 352450588..58550c93b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -284,7 +284,7 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t ev if (usbh_class_drivers[drv_id].isr) { - TU_LOG2("%s isr\r\n", usbh_class_drivers[drv_id].name); + //TU_LOG2("%s isr\r\n", usbh_class_drivers[drv_id].name); usbh_class_drivers[drv_id].isr(dev_addr, ep_addr, event, xferred_bytes); } else -- cgit v1.3.1 From a8e538efe7d11291e32e016fad5910ebaf9eac43 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Sep 2020 01:35:32 +0700 Subject: clean up --- src/class/hid/hid_host.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index d2d1c0397..378278cc3 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -36,7 +36,7 @@ //--------------------------------------------------------------------+ typedef struct { - uint8_t itf_numr; + uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; @@ -52,7 +52,7 @@ static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t p_hid->ep_in = p_endpoint_desc->bEndpointAddress; p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor - p_hid->itf_numr = interface_number; + p_hid->itf_num = interface_number; return true; } -- cgit v1.3.1 From 9cc22b635c5c4b9426b1530c3623b899dc652302 Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Fri, 4 Sep 2020 15:40:23 +0200 Subject: Add functionality to abort an ongoing transfer --- src/class/cdc/cdc_device.c | 10 ++++++++++ src/device/dcd.h | 3 +++ src/device/usbd.c | 27 +++++++++++++++++++++++++++ src/device/usbd_pvt.h | 3 +++ 4 files changed, 43 insertions(+) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 6f71cb781..56cc94abc 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -353,6 +353,16 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request bool const dtr = tu_bit_test(request->wValue, 0); bool const rts = tu_bit_test(request->wValue, 1); +#if CFG_TUD_CDC_CLEAR_AT_CONNECTION + // DTE connected event (if DTE supports DTR bit) + if ( dtr && !tu_bit_test(p_cdc->line_state, 0) ) + { + // Clear not transmitted data + usbd_edpt_xfer_abort(rhport, p_cdc->ep_in); + tu_fifo_clear(&p_cdc->tx_ff); + } +#endif + p_cdc->line_state = (uint8_t) request->wValue; // Disable fifo overwriting if DTR bit is set diff --git a/src/device/dcd.h b/src/device/dcd.h index a4635346b..ee41fefd0 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -133,6 +133,9 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Abort a ongoing transfer +TU_ATTR_WEAK bool dcd_edpt_xfer_abort(uint8_t rhport, uint8_t ep_addr); + // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index 6b91048b6..04ae31ce7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1100,6 +1100,33 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } +bool usbd_edpt_xfer_abort(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + TU_LOG2(" Abort XFER EP %02X ... ", ep_addr); + + // Abort API is optional for DCD + if ( dcd_edpt_xfer_abort ) + { + if ( dcd_edpt_xfer_abort(rhport, ep_addr) ) + { + _usbd_dev.ep_status[epnum][dir].busy = false; + TU_LOG2("OK\r\n"); + return true; + }else + { + TU_LOG2("failed\r\n"); + return false; + } + }else + { + TU_LOG2("no DCD support\r\n"); + return false; + } +} + bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) { (void) rhport; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index a5d223329..d87c07c01 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -70,6 +70,9 @@ 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); +// Abort a scheduled transfer +bool usbd_edpt_xfer_abort(uint8_t rhport, uint8_t ep_addr); + // Check if endpoint transferring is complete bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr); -- cgit v1.3.1 From 4d57b4ea336d0ba89b97b388aa02f15c2d947a2a Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 13:57:07 +0700 Subject: clean up --- src/device/usbd.h | 2 -- src/host/usbh.c | 12 ++++-------- src/host/usbh.h | 9 +++++---- src/tusb.c | 2 +- tools/build_esp32s.py | 16 ++++++++++------ 5 files changed, 20 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index 5338be157..bbdd1be99 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -41,8 +41,6 @@ //--------------------------------------------------------------------+ // Init device stack -// Note: when using with RTOS, this should be called after scheduler/kernel is started. -// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. bool tud_init (void); // Task function should be called in main/rtos loop diff --git a/src/host/usbh.c b/src/host/usbh.c index 58550c93b..b6df6bad8 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -116,7 +116,7 @@ enum { USBH_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) }; CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // Event queue -// role device/host is used by OS NONE for mutex (disable usb isr) only +// role device/host is used by OS NONE for mutex (disable usb isr) OSAL_QUEUE_DEF(OPT_MODE_HOST, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); static osal_queue_t _usbh_q; @@ -137,7 +137,6 @@ tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr) return (tusb_device_state_t) _usbh_devices[dev_addr].state; } - static inline void osal_task_delay(uint32_t msec) { (void) msec; @@ -149,7 +148,7 @@ static inline void osal_task_delay(uint32_t msec) //--------------------------------------------------------------------+ // CLASS-USBD API (don't require to verify parameters) //--------------------------------------------------------------------+ -bool usbh_init(void) +bool tuh_init(void) { tu_memclr(_usbh_devices, sizeof(usbh_device_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); @@ -385,13 +384,10 @@ bool enum_task(hcd_event_t* event) #endif }; - // for OSAL_NONE local variable won't retain value after blocking service sem_wait/queue_recv - static uint8_t configure_selected = 1; // TODO move - usbh_device_t* dev0 = &_usbh_devices[0]; tusb_control_request_t request; - dev0->rhport = event->rhport; // TODO refractor integrate to device_pool + dev0->rhport = event->rhport; // TODO refractor integrate to device_pool dev0->hub_addr = event->attach.hub_addr; dev0->hub_port = event->attach.hub_port; dev0->state = TUSB_DEVICE_STATE_UNPLUG; @@ -552,7 +548,7 @@ bool enum_task(hcd_event_t* event) new_dev->product_id = ((tusb_desc_device_t*) _usbh_ctrl_buf)->idProduct; new_dev->configure_count = ((tusb_desc_device_t*) _usbh_ctrl_buf)->bNumConfigurations; - configure_selected = get_configure_number_for_device((tusb_desc_device_t*) _usbh_ctrl_buf); + uint8_t const configure_selected = get_configure_number_for_device((tusb_desc_device_t*) _usbh_ctrl_buf); TU_ASSERT(configure_selected <= new_dev->configure_count); // TODO notify application when invalid configuration //------------- Get 9 bytes of configuration descriptor -------------// diff --git a/src/host/usbh.h b/src/host/usbh.h index 27193d378..1930dc20b 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -70,6 +70,11 @@ typedef struct { //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ + +// Init host stack +bool tuh_init(void); + +// Task function should be called in main/rtos loop void tuh_task(void); // Interrupt handler, name alias to HCD @@ -97,11 +102,7 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); // CLASS-USBH & INTERNAL API //--------------------------------------------------------------------+ -// Note: when using with RTOS, this should be called after scheduler/kernel is started. -// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. -bool usbh_init(void); bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); - bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); #ifdef __cplusplus diff --git a/src/tusb.c b/src/tusb.c index 1bc134dba..ae1bc47e3 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -43,7 +43,7 @@ bool tusb_init(void) if (_initialized) return true; #if TUSB_OPT_HOST_ENABLED - TU_ASSERT( usbh_init() ); // init host stack + TU_ASSERT( tuh_init() ); // init host stack #endif #if TUSB_OPT_DEVICE_ENABLED diff --git a/tools/build_esp32s.py b/tools/build_esp32s.py index 9600b6145..44364806b 100644 --- a/tools/build_esp32s.py +++ b/tools/build_esp32s.py @@ -4,6 +4,10 @@ import sys import subprocess import time +SUCCEEDED = "\033[32msucceeded\033[0m" +FAILED = "\033[31mfailed\033[0m" +SKIPPED = "\033[33mskipped\033[0m" + success_count = 0 fail_count = 0 skip_count = 0 @@ -11,7 +15,7 @@ exit_status = 0 total_time = time.monotonic() -build_format = '| {:23} | {:30} | {:9} | {:7} | {:6} | {:6} |' +build_format = '| {:23} | {:30} | {:18} | {:7} | {:6} | {:6} |' build_separator = '-' * 100 # 1st Argument is Example, build all examples if not existed @@ -58,7 +62,7 @@ def skip_example(example, board): return 0 print(build_separator) -print(build_format.format('Example', 'Board', 'Result', 'Time', 'Flash', 'SRAM')) +print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) print(build_separator) for example in all_examples: @@ -70,19 +74,19 @@ for example in all_examples: # Check if board is skipped if skip_example(example, board): - success = "\033[33mskipped\033[0m " + success = SKIPPED skip_count += 1 print(build_format.format(example, board, success, '-', flash_size, sram_size)) else: build_result = build_example(example, board) if build_result.returncode == 0: - success = "\033[32msucceeded\033[0m" + success = SUCCEEDED success_count += 1 (flash_size, sram_size) = build_size(example, board) else: exit_status = build_result.returncode - success = "\033[31mfailed\033[0m " + success = FAILED fail_count += 1 build_duration = time.monotonic() - start_time @@ -95,7 +99,7 @@ for example in all_examples: total_time = time.monotonic() - total_time print(build_separator) -print("Build Sumamary: {} \033[32msucceeded\033[0m, {} \033[31mfailed\033[0m, {} \033[33mskipped\033[0m and took {:.2f}s".format(success_count, fail_count, skip_count, total_time)) +print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) print(build_separator) sys.exit(exit_status) -- cgit v1.3.1 From f7cf8cdf27a016093df65c0de7167685e407d014 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 14:28:58 +0700 Subject: defer xfer_isr to xfer_cb --- src/class/cdc/cdc_host.c | 2 +- src/class/cdc/cdc_host.h | 2 +- src/class/hid/hid_host.c | 2 +- src/class/hid/hid_host.h | 2 +- src/class/msc/msc_host.c | 2 +- src/class/msc/msc_host.h | 2 +- src/host/hcd.h | 8 ++--- src/host/hub.c | 2 +- src/host/hub.h | 2 +- src/host/usbh.c | 88 +++++++++++++++++++++++++++++++----------------- src/host/usbh.h | 2 +- 11 files changed, 70 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index e62f47b72..23e342134 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -209,7 +209,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it return true; } -void cdch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +void cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) ep_addr; tuh_cdc_xfer_isr( dev_addr, event, 0, xferred_bytes ); diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 306420ce4..0e2820fef 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -113,7 +113,7 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i //--------------------------------------------------------------------+ void cdch_init(void); bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -void cdch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void cdch_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 378278cc3..e17bfc9e5 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -232,7 +232,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c return true; } -void hidh_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +void hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO may need to use this para later diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 2e7f52674..54542de55 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -197,7 +197,7 @@ void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); //--------------------------------------------------------------------+ void hidh_init(void); bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); -void hidh_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hidh_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 539e98376..b129d538f 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -383,7 +383,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it return true; } -void msch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +void msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { msch_interface_t* p_msc = &msch_data[dev_addr-1]; if ( ep_addr == p_msc->ep_in ) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 959294adf..3eb45e6fc 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -193,7 +193,7 @@ typedef struct void msch_init(void); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -void msch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void msch_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/host/hcd.h b/src/host/hcd.h index 24cc62501..da530421d 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -51,17 +51,17 @@ typedef struct { uint8_t rhport; uint8_t event_id; + uint8_t dev_addr; union { - struct - { + struct { uint8_t hub_addr; uint8_t hub_port; } attach, remove; - struct - { + // XFER_COMPLETE + struct { uint8_t ep_addr; uint8_t result; uint32_t len; diff --git a/src/host/hub.c b/src/host/hub.c index eb85dfa42..4fb28b72f 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -199,7 +199,7 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf // is the response of interrupt endpoint polling #include "usbh_hcd.h" // FIXME remove -void hub_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports (void) ep_addr; diff --git a/src/host/hub.h b/src/host/hub.h index 621356315..8f307190b 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -182,7 +182,7 @@ bool hub_status_pipe_queue(uint8_t dev_addr); //--------------------------------------------------------------------+ void hub_init(void); bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -void hub_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hub_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/host/usbh.c b/src/host/usbh.c index b6df6bad8..73a4fc9f3 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -56,7 +56,7 @@ static host_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_CDC, .init = cdch_init, .open = cdch_open, - .isr = cdch_isr, + .xfer_cb = cdch_xfer_cb, .close = cdch_close }, #endif @@ -67,7 +67,7 @@ static host_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_MSC, .init = msch_init, .open = msch_open, - .isr = msch_isr, + .xfer_cb = msch_xfer_cb, .close = msch_close }, #endif @@ -78,7 +78,7 @@ static host_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_HID, .init = hidh_init, .open = hidh_open_subtask, - .isr = hidh_isr, + .xfer_cb = hidh_xfer_cb, .close = hidh_close }, #endif @@ -89,7 +89,7 @@ static host_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_HUB, .init = hub_init, .open = hub_open, - .isr = hub_isr, + .xfer_cb = hub_xfer_cb, .close = hub_close }, #endif @@ -100,7 +100,7 @@ static host_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_VENDOR_SPECIFIC, .init = cush_init, .open = cush_open_subtask, - .isr = cush_isr, + .xfer_cb = cush_isr, .close = cush_close } #endif @@ -263,33 +263,46 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const } //--------------------------------------------------------------------+ -// USBH-HCD ISR/Callback API +// HCD Event Handler //--------------------------------------------------------------------+ + +void hcd_event_handler(hcd_event_t const* event, bool in_isr) +{ + switch (event->event_id) + { + default: + osal_queue_send(_usbh_q, event, in_isr); + break; + } +} + // interrupt caused by a TD (with IOC=1) in pipe of class class_code -void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint8_t result, uint32_t xferred_bytes) { usbh_device_t* dev = &_usbh_devices[ dev_addr ]; if (0 == tu_edpt_number(ep_addr)) { - dev->control.pipe_status = event; + dev->control.pipe_status = result; // usbh_devices[ pipe_hdl.dev_addr ].control.xferred_bytes = xferred_bytes; not yet neccessary osal_semaphore_post( dev->control.sem_hdl, true ); } else { - uint8_t drv_id = dev->ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)]; - TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); - - if (usbh_class_drivers[drv_id].isr) + hcd_event_t event = { - //TU_LOG2("%s isr\r\n", usbh_class_drivers[drv_id].name); - usbh_class_drivers[drv_id].isr(dev_addr, ep_addr, event, xferred_bytes); - } - else - { - TU_BREAKPOINT(); // something wrong, no one claims the isr's source - } + .rhport = 0, + .event_id = HCD_EVENT_XFER_COMPLETE, + .dev_addr = dev_addr, + .xfer_complete = + { + .ep_addr = ep_addr, + .result = result, + .len = xferred_bytes + } + }; + + hcd_event_handler(&event, true); } } @@ -307,16 +320,6 @@ void hcd_event_device_attach(uint8_t rhport) hcd_event_handler(&event, true); } -void hcd_event_handler(hcd_event_t const* event, bool in_isr) -{ - switch (event->event_id) - { - default: - osal_queue_send(_usbh_q, event, in_isr); - break; - } -} - void hcd_event_device_remove(uint8_t hostid) { hcd_event_t event = @@ -419,7 +422,7 @@ bool enum_task(hcd_event_t* event) return true; // restart task } } - #if CFG_TUH_HUB +#if CFG_TUH_HUB //------------- connected/disconnected via hub -------------// else { @@ -462,7 +465,7 @@ bool enum_task(hcd_event_t* event) hub_port_clear_feature_subtask(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE); } } - #endif +#endif // CFG_TUH_HUB TU_ASSERT_ERR( usbh_pipe_control_open(0, 8) ); @@ -684,6 +687,29 @@ void tuh_task(void) enum_task(&event); break; + case HCD_EVENT_XFER_COMPLETE: + { + usbh_device_t* dev = &_usbh_devices[event.dev_addr]; + uint8_t const ep_addr = event.xfer_complete.ep_addr; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); + + TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + + if ( 0 == epnum ) + { + // TODO control transfer + }else + { + uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; + TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); + + TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); + usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + } + } + break; + default: break; } } diff --git a/src/host/usbh.h b/src/host/usbh.h index 1930dc20b..56a5ce72f 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -60,7 +60,7 @@ typedef struct { void (* const init) (void); bool (* const open)(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); - void (* const isr) (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t len); + void (* const xfer_cb) (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t len); void (* const close) (uint8_t); } host_class_driver_t; //--------------------------------------------------------------------+ -- cgit v1.3.1 From 9531e47d10915b652c2c5cff9ef2956889639f93 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 14:59:07 +0700 Subject: update example to test with mouse --- examples/host/cdc_msc_hid/src/main.c | 97 ++++++++++++++++++++++++++++++------ src/class/hid/hid_host.c | 5 +- 2 files changed, 85 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 4200cc5e0..bbaac8644 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -111,6 +111,7 @@ void cdc_task(void) //--------------------------------------------------------------------+ #if CFG_TUH_HID_KEYBOARD +CFG_TUSB_MEM_SECTION static hid_keyboard_report_t usb_keyboard_report; uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; // look up new key in previous keys @@ -153,21 +154,6 @@ static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) prev_report = *p_new_report; } -CFG_TUSB_MEM_SECTION static hid_keyboard_report_t usb_keyboard_report; - -void hid_task(void) -{ - uint8_t const addr = 1; - if ( tuh_hid_keyboard_is_mounted(addr) ) - { - if ( !tuh_hid_keyboard_is_busy(addr) ) - { - process_kbd_report(&usb_keyboard_report); - tuh_hid_keyboard_get_report(addr, &usb_keyboard_report); - } - } -} - void tuh_hid_keyboard_mounted_cb(uint8_t dev_addr) { // application set-up @@ -192,6 +178,58 @@ void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event) #endif #if CFG_TUH_HID_MOUSE + +CFG_TUSB_MEM_SECTION static hid_mouse_report_t usb_mouse_report; + +void cursor_movement(int8_t x, int8_t y, int8_t wheel) +{ + //------------- X -------------// + if ( x < 0) + { + printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left + }else if ( x > 0) + { + printf(ANSI_CURSOR_FORWARD(%d), x); // move right + }else { } + + //------------- Y -------------// + if ( y < 0) + { + printf(ANSI_CURSOR_UP(%d), (-y)); // move up + }else if ( y > 0) + { + printf(ANSI_CURSOR_DOWN(%d), y); // move down + }else { } + + //------------- wheel -------------// + if (wheel < 0) + { + printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up + }else if (wheel > 0) + { + printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down + }else { } +} + +static inline void process_mouse_report(hid_mouse_report_t const * p_report) +{ + static hid_mouse_report_t prev_report = { 0 }; + + //------------- button state -------------// + uint8_t button_changed_mask = p_report->buttons ^ prev_report.buttons; + if ( button_changed_mask & p_report->buttons) + { + printf(" %c%c%c ", + p_report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', + p_report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', + p_report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); + } + + //------------- cursor movement -------------// + cursor_movement(p_report->x, p_report->y, p_report->wheel); +} + + void tuh_hid_mouse_mounted_cb(uint8_t dev_addr) { // application set-up @@ -212,6 +250,35 @@ void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event) } #endif + + +void hid_task(void) +{ + uint8_t const addr = 1; + +#if CFG_TUH_HID_KEYBOARD + if ( tuh_hid_keyboard_is_mounted(addr) ) + { + if ( !tuh_hid_keyboard_is_busy(addr) ) + { + process_kbd_report(&usb_keyboard_report); + tuh_hid_keyboard_get_report(addr, &usb_mouse_report); + } + } +#endif + +#if CFG_TUH_HID_MOUSE + if ( tuh_hid_mouse_is_mounted(addr) ) + { + if ( !tuh_hid_mouse_is_busy(addr) ) + { + process_mouse_report(&usb_mouse_report); + tuh_hid_mouse_get_report(addr, &usb_mouse_report); + } + } +#endif +} + //--------------------------------------------------------------------+ // tinyusb callbacks //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index e17bfc9e5..d9ed1f651 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -173,7 +173,8 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c tusb_desc_endpoint_t const * p_endpoint_desc = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint_desc->bDescriptorType, TUSB_ERROR_INVALID_PARA); - //------------- SET IDLE (0) request -------------// + // SET IDLE = 0 request + // Device can stall if not support this request tusb_control_request_t request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, .bRequest = HID_REQ_CONTROL_SET_IDLE, @@ -181,7 +182,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c .wIndex = p_interface_desc->bInterfaceNumber, .wLength = 0 }; - TU_ASSERT( usbh_control_xfer( dev_addr, &request, NULL ) ); + usbh_control_xfer( dev_addr, &request, NULL ); // TODO stall is valid #if 0 //------------- Get Report Descriptor TODO HID parser -------------// -- cgit v1.3.1 From d87f2a96914ef381045d80f35299a84a5118c57f Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 15:05:25 +0700 Subject: remove usbh control mutex --- src/host/usbh.c | 7 ------- src/host/usbh_hcd.h | 3 --- 2 files changed, 10 deletions(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index 73a4fc9f3..4c35e7d65 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -164,9 +164,6 @@ bool tuh_init(void) dev->control.sem_hdl = osal_semaphore_create(&dev->control.sem_def); TU_ASSERT(dev->control.sem_hdl != NULL); - dev->control.mutex_hdl = osal_mutex_create(&dev->control.mutex_def); - TU_ASSERT(dev->control.mutex_hdl != NULL); - memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping } @@ -190,8 +187,6 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8 usbh_device_t* dev = &_usbh_devices[dev_addr]; const uint8_t rhport = dev->rhport; - TU_ASSERT(osal_mutex_lock(dev->control.mutex_hdl, OSAL_TIMEOUT_NORMAL)); - dev->control.request = *request; dev->control.pipe_status = 0; @@ -210,8 +205,6 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8 hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); TU_VERIFY(osal_semaphore_wait(dev->control.sem_hdl, OSAL_TIMEOUT_NORMAL)); - osal_mutex_unlock(dev->control.mutex_hdl); - if ( XFER_RESULT_STALLED == dev->control.pipe_status ) return false; if ( XFER_RESULT_FAILED == dev->control.pipe_status ) return false; diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index 01be82851..019b9f037 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -69,9 +69,6 @@ typedef struct { osal_semaphore_def_t sem_def; osal_semaphore_t sem_hdl; // used to synchronize with HCD when control xfer complete - - osal_mutex_def_t mutex_def; - osal_mutex_t mutex_hdl; // used to exclusively occupy control pipe } control; uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) -- cgit v1.3.1 From bc09b6065fc2b90783a56ff66b84933353566b08 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 15:16:45 +0700 Subject: refactor extract parse_configuration_descriptor() --- src/host/usbh.c | 113 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 61 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index 4c35e7d65..67b6efbd1 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -366,6 +366,64 @@ static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_ //--------------------------------------------------------------------+ // ENUMERATION TASK //--------------------------------------------------------------------+ +static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) +{ + usbh_device_t* dev = &_usbh_devices[dev_addr]; + uint8_t const* p_desc = (uint8_t const*) desc_cfg; + p_desc = tu_desc_next(p_desc); + + TU_LOG2_MEM(desc_cfg, desc_cfg->wTotalLength, 0); + + // parse each interfaces + while( p_desc < _usbh_ctrl_buf + desc_cfg->wTotalLength ) + { + // skip until we see interface descriptor + if ( TUSB_DESC_INTERFACE != tu_desc_type(p_desc) ) + { + p_desc = tu_desc_next(p_desc); // skip the descriptor, increase by the descriptor's length + }else + { + tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; + + // Check if class is supported + uint8_t drv_id; + for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) + { + if ( usbh_class_drivers[drv_id].class_code == desc_itf->bInterfaceClass ) break; + } + + if( drv_id >= USBH_CLASS_DRIVER_COUNT ) + { + // skip unsupported class + p_desc = tu_desc_next(p_desc); + } + else + { + // Interface number must not be used already TODO alternate interface + TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff ); + dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; + + if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) + { + // TODO Attach hub to Hub is not currently supported + // skip this interface + p_desc = tu_desc_next(p_desc); + } + else + { + uint16_t itf_len = 0; + + TU_LOG2("%s open\r\n", usbh_class_drivers[drv_id].name); + TU_ASSERT( usbh_class_drivers[drv_id].open(dev->rhport, dev_addr, desc_itf, &itf_len) ); + TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); + p_desc += itf_len; + } + } + } + } + + return true; +} bool enum_task(hcd_event_t* event) { @@ -585,59 +643,10 @@ bool enum_task(hcd_event_t* event) //------------- TODO Get String Descriptors -------------// - //------------- parse configuration & install drivers -------------// - uint8_t const* p_desc = _usbh_ctrl_buf + sizeof(tusb_desc_configuration_t); - - // TU_LOG2_MEM(_usbh_ctrl_buf, ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength, 0); - - // parse each interfaces - while( p_desc < _usbh_ctrl_buf + ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength ) - { - // skip until we see interface descriptor - if ( TUSB_DESC_INTERFACE != tu_desc_type(p_desc) ) - { - p_desc = tu_desc_next(p_desc); // skip the descriptor, increase by the descriptor's length - }else - { - tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; - - // Check if class is supported - uint8_t drv_id; - for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) - { - if ( usbh_class_drivers[drv_id].class_code == desc_itf->bInterfaceClass ) break; - } - - if( drv_id >= USBH_CLASS_DRIVER_COUNT ) - { - // skip unsupported class - p_desc = tu_desc_next(p_desc); - } - else - { - // Interface number must not be used already TODO alternate interface - TU_ASSERT( new_dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff ); - new_dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; - - if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && new_dev->hub_addr != 0) - { - // TODO Attach hub to Hub is not currently supported - // skip this interface - p_desc = tu_desc_next(p_desc); - } - else - { - uint16_t itf_len = 0; - - TU_LOG2("%s open\r\n", usbh_class_drivers[drv_id].name); - TU_ASSERT( usbh_class_drivers[drv_id].open(new_dev->rhport, new_addr, desc_itf, &itf_len) ); - TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); - p_desc += itf_len; - } - } - } - } + // Parse configuration & set up drivers + parse_configuration_descriptor(new_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); + // Invoke callback if available if (tuh_mount_cb) tuh_mount_cb(new_addr); return true; -- cgit v1.3.1 From 90c8c14652ec81b34c9f2fa6ce69fa25d74a5bbf Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 15:19:01 +0700 Subject: clean up --- src/host/usbh.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index 67b6efbd1..da163f9e4 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -211,7 +211,7 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8 return true; } -tusb_error_t usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) +bool usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) { osal_semaphore_reset( _usbh_devices[dev_addr].control.sem_hdl ); //osal_mutex_reset( usbh_devices[dev_addr].control.mutex_hdl ); @@ -226,9 +226,7 @@ tusb_error_t usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) .bInterval = 0 }; - hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc); - - return TUSB_ERROR_NONE; + return hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc); } bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) @@ -518,7 +516,7 @@ bool enum_task(hcd_event_t* event) } #endif // CFG_TUH_HUB - TU_ASSERT_ERR( usbh_pipe_control_open(0, 8) ); + TU_ASSERT( usbh_pipe_control_open(0, 8) ); //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// TU_LOG2("Get 8 byte of Device Descriptor\r\n"); @@ -584,7 +582,7 @@ bool enum_task(hcd_event_t* event) dev0->state = TUSB_DEVICE_STATE_UNPLUG; // open control pipe for new address - TU_ASSERT_ERR ( usbh_pipe_control_open(new_addr, ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0 ) ); + TU_ASSERT ( usbh_pipe_control_open(new_addr, ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0 ) ); //------------- Get full device descriptor -------------// TU_LOG2("Get Device Descriptor \r\n"); -- cgit v1.3.1 From b8b95e84944b4c07cc9c9f4a7e4d53e6256b42f0 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 15:45:03 +0700 Subject: add in_isr to all hcd event functions --- src/device/dcd.h | 2 +- src/host/ehci/ehci.c | 8 ++++---- src/host/hcd.h | 30 ++++++++++++++++-------------- src/host/hub.c | 2 +- src/host/ohci/ohci.c | 6 +++--- src/host/usbh.c | 14 +++++++------- 6 files changed, 32 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index 776f782b8..a5c485f9e 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -140,7 +140,7 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); //--------------------------------------------------------------------+ -// Event API (Implemented by device stack) +// Event API (implemented by stack) //--------------------------------------------------------------------+ // Called by DCD to notify device stack diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 295da4566..c2d5ebf7b 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -489,10 +489,10 @@ static void port_connect_status_change_isr(uint8_t hostid) if (ehci_data.regs->portsc_bm.current_connect_status) { hcd_port_reset(hostid); - hcd_event_device_attach(hostid); + hcd_event_device_attach(hostid, true); }else // device unplugged { - hcd_event_device_remove(hostid); + hcd_event_device_remove(hostid, true); } } @@ -512,7 +512,7 @@ static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) { // end of request // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), XFER_RESULT_SUCCESS, p_qhd->total_xferred_bytes); + hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), p_qhd->total_xferred_bytes, XFER_RESULT_SUCCESS, true); p_qhd->total_xferred_bytes = 0; } } @@ -599,7 +599,7 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) } // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), error_event, p_qhd->total_xferred_bytes); + hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), p_qhd->total_xferred_bytes, error_event, true); p_qhd->total_xferred_bytes = 0; } diff --git a/src/host/hcd.h b/src/host/hcd.h index da530421d..eebf2c801 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -109,20 +109,6 @@ tusb_speed_t hcd_port_speed_get(uint8_t hostid); // HCD closes all opened endpoints belong to this device void hcd_device_close(uint8_t rhport, uint8_t dev_addr); -//--------------------------------------------------------------------+ -// Event function -//--------------------------------------------------------------------+ -void hcd_event_handler(hcd_event_t const* event, bool in_isr); - -// Helper to send device attach event -void hcd_event_device_attach(uint8_t rhport); - -// Helper to send device removal event -void hcd_event_device_remove(uint8_t rhport); - -// Helper to send USB transfer event -void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - //--------------------------------------------------------------------+ // Endpoints API //--------------------------------------------------------------------+ @@ -145,6 +131,22 @@ bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t // tusb_error_t hcd_pipe_cancel(); +//--------------------------------------------------------------------+ +// Event API (implemented by stack) +//--------------------------------------------------------------------+ + +// Called by HCD to notify stack +extern void hcd_event_handler(hcd_event_t const* event, bool in_isr); + +// Helper to send device attach event +extern void hcd_event_device_attach(uint8_t rhport, bool in_isr); + +// Helper to send device removal event +extern void hcd_event_device_remove(uint8_t rhport, bool in_isr); + +// Helper to send USB transfer event +extern void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr); + #ifdef __cplusplus } #endif diff --git a/src/host/hub.c b/src/host/hub.c index 4fb28b72f..f88056c92 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -223,7 +223,7 @@ void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_ event.attach.hub_port = port; hcd_event_handler(&event, true); - break; // handle one port at a time, next port if any will be handled in the next cycle + break; // TODO handle one port at a time, next port if any will be handled in the next cycle } } // NOTE: next status transfer is queued by usbh.c after handling this request diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 114f52e7d..87da374d5 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -599,7 +599,7 @@ static void done_queue_isr(uint8_t hostid) hcd_event_xfer_complete(p_ed->dev_addr, tu_edpt_addr(p_ed->ep_number, p_ed->pid == OHCI_PID_IN), - event, xferred_bytes); + xferred_bytes, event, true); } td_head = (ohci_td_item_t*) td_head->next; @@ -632,10 +632,10 @@ void hcd_int_handler(uint8_t hostid) { // TODO reset port immediately, without this controller will got 2-3 (debouncing connection status change) OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK; - hcd_event_device_attach(0); + hcd_event_device_attach(hostid, true); }else { - hcd_event_device_remove(0); + hcd_event_device_remove(hostid, true); } } diff --git a/src/host/usbh.c b/src/host/usbh.c index da163f9e4..6304b6b48 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -268,7 +268,7 @@ void hcd_event_handler(hcd_event_t const* event, bool in_isr) } // interrupt caused by a TD (with IOC=1) in pipe of class class_code -void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint8_t result, uint32_t xferred_bytes) +void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) { usbh_device_t* dev = &_usbh_devices[ dev_addr ]; @@ -276,7 +276,7 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint8_t result, { dev->control.pipe_status = result; // usbh_devices[ pipe_hdl.dev_addr ].control.xferred_bytes = xferred_bytes; not yet neccessary - osal_semaphore_post( dev->control.sem_hdl, true ); + osal_semaphore_post( dev->control.sem_hdl, true ); // FIXME post within ISR } else { @@ -293,11 +293,11 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint8_t result, } }; - hcd_event_handler(&event, true); + hcd_event_handler(&event, in_isr); } } -void hcd_event_device_attach(uint8_t rhport) +void hcd_event_device_attach(uint8_t rhport, bool in_isr) { hcd_event_t event = { @@ -308,10 +308,10 @@ void hcd_event_device_attach(uint8_t rhport) event.attach.hub_addr = 0; event.attach.hub_port = 0; - hcd_event_handler(&event, true); + hcd_event_handler(&event, in_isr); } -void hcd_event_device_remove(uint8_t hostid) +void hcd_event_device_remove(uint8_t hostid, bool in_isr) { hcd_event_t event = { @@ -322,7 +322,7 @@ void hcd_event_device_remove(uint8_t hostid) event.attach.hub_addr = 0; event.attach.hub_port = 0; - hcd_event_handler(&event, true); + hcd_event_handler(&event, in_isr); } -- cgit v1.3.1 From 7ffb6acc1625022d8a79c1d408b11240707136ca Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 17:16:46 +0700 Subject: more clean up --- src/host/usbh.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index 6304b6b48..2e1fed5e3 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -426,14 +426,8 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura bool enum_task(hcd_event_t* event) { enum { -#if 1 - // FIXME ohci LPC1769 xpresso + debugging to have 1st control xfer to work, some kind of timing or ohci driver issue !!! POWER_STABLE_DELAY = 100, - RESET_DELAY = 500 -#else - POWER_STABLE_DELAY = 500, - RESET_DELAY = 200, // USB specs say only 50ms but many devices require much longer -#endif + RESET_DELAY = 500, // 200 USB specs say only 50ms but many devices require much longer }; usbh_device_t* dev0 = &_usbh_devices[0]; @@ -534,14 +528,13 @@ bool enum_task(hcd_event_t* event) if (dev0->hub_addr == 0) { + TU_ASSERT(is_ok); + // connected directly to roothub - TU_ASSERT(is_ok); // TODO some slow device is observed to fail the very fist controller xfer, can try more times hcd_port_reset( dev0->rhport ); // reset port after 8 byte descriptor osal_task_delay(RESET_DELAY); -// hcd_port_reset_end(dev0->rhport); -// osal_task_delay(RESET_DELAY); } - #if CFG_TUH_HUB +#if CFG_TUH_HUB else { // connected via a hub @@ -555,7 +548,7 @@ bool enum_task(hcd_event_t* event) (void) hub_status_pipe_queue( dev0->hub_addr ); // done with hub, waiting for next data on status pipe } - #endif +#endif // CFG_TUH_HUB //------------- Set new address -------------// TU_LOG2("Set Address \r\n"); -- cgit v1.3.1 From 828f720207d4ded25ed533ea6c52da49c799b476 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 20:20:45 +0700 Subject: refactor hub class - separate connect/disconnect handling - hub work with full speed, but doesn't seem to work with Low speed device (with mcb1800) - need to update msc host after migrating from isr to xfer_cb (blocked at inquiry) --- examples/host/cdc_msc_hid/src/tusb_config.h | 2 +- src/host/ehci/ehci.c | 2 +- src/host/hcd.h | 3 +- src/host/hub.c | 110 +++++++++++++--------------- src/host/hub.h | 34 ++++----- src/host/usbh.c | 106 +++++++++++---------------- 6 files changed, 117 insertions(+), 140 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 6604623b1..d8cf993be 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -69,7 +69,7 @@ // CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUH_HUB 0 +#define CFG_TUH_HUB 1 #define CFG_TUH_CDC 1 #define CFG_TUH_HID_KEYBOARD 1 #define CFG_TUH_HID_MOUSE 1 diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index c2d5ebf7b..13e9b0edc 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -533,7 +533,7 @@ static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head) static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms) { - uint8_t max_loop = 0; + uint16_t max_loop = 0; uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1); ehci_link_t next_item = * get_period_head(hostid, interval_ms); diff --git a/src/host/hcd.h b/src/host/hcd.h index eebf2c801..ba3035300 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -55,10 +55,11 @@ typedef struct union { + // Attach, Remove struct { uint8_t hub_addr; uint8_t hub_port; - } attach, remove; + } connection; // XFER_COMPLETE struct { diff --git a/src/host/hub.c b/src/host/hub.c index f88056c92..db1ca0786 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -33,6 +33,8 @@ //--------------------------------------------------------------------+ #include "hub.h" +extern void osal_task_delay(uint32_t msec); // TODO remove + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -53,7 +55,7 @@ TU_ATTR_ALIGNED(4) CFG_TUSB_MEM_SECTION static uint8_t hub_enum_buffer[sizeof(de //--------------------------------------------------------------------+ // HUB //--------------------------------------------------------------------+ -bool hub_port_clear_feature_subtask(uint8_t hub_addr, uint8_t hub_port, uint8_t feature) +bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature) { TU_ASSERT(HUB_FEATURE_PORT_CONNECTION_CHANGE <= feature && feature <= HUB_FEATURE_PORT_RESET_CHANGE); @@ -65,33 +67,35 @@ bool hub_port_clear_feature_subtask(uint8_t hub_addr, uint8_t hub_port, uint8_t .wLength = 0 }; - //------------- Clear Port Feature request -------------// TU_ASSERT( usbh_control_xfer( hub_addr, &request, NULL ) ); + return true; +} - //------------- Get Port Status to check if feature is cleared -------------// - request = (tusb_control_request_t ) { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, - .bRequest = HUB_REQUEST_GET_STATUS, - .wValue = 0, - .wIndex = hub_port, - .wLength = 4 +bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, hub_port_status_response_t* resp) +{ + tusb_control_request_t request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_OTHER, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + + .bRequest = HUB_REQUEST_GET_STATUS, + .wValue = 0, + .wIndex = hub_port, + .wLength = 4 }; TU_ASSERT( usbh_control_xfer( hub_addr, &request, hub_enum_buffer ) ); - //------------- Check if feature is cleared -------------// - hub_port_status_response_t * p_port_status; - p_port_status = (hub_port_status_response_t *) hub_enum_buffer; - - TU_ASSERT( !tu_bit_test(p_port_status->status_change.value, feature-16) ); - + memcpy(resp, hub_enum_buffer, sizeof(hub_port_status_response_t)); return true; } -bool hub_port_reset_subtask(uint8_t hub_addr, uint8_t hub_port) +bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port) { - enum { RESET_DELAY = 200 }; // USB specs say only 50ms but many devices require much longer - //------------- Set Port Reset -------------// tusb_control_request_t request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, @@ -102,37 +106,9 @@ bool hub_port_reset_subtask(uint8_t hub_addr, uint8_t hub_port) }; TU_ASSERT( usbh_control_xfer( hub_addr, &request, NULL ) ); - - osal_task_delay(RESET_DELAY); // TODO Hub wait for Status Endpoint on Reset Change - - //------------- Get Port Status to check if port is enabled, powered and reset_change -------------// - request = (tusb_control_request_t ) { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, - .bRequest = HUB_REQUEST_GET_STATUS, - .wValue = 0, - .wIndex = hub_port, - .wLength = 4 - }; - - TU_ASSERT( usbh_control_xfer( hub_addr, &request, hub_enum_buffer ) ); - - hub_port_status_response_t * p_port_status; - p_port_status = (hub_port_status_response_t *) hub_enum_buffer; - - TU_ASSERT ( p_port_status->status_change.reset && p_port_status->status_current.connect_status && - p_port_status->status_current.port_power && p_port_status->status_current.port_enable); - return true; } -// can only get the speed RIGHT AFTER hub_port_reset_subtask call -tusb_speed_t hub_port_get_speed(void) -{ - hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer; - return (p_port_status->status_current.high_speed_device_attached) ? TUSB_SPEED_HIGH : - (p_port_status->status_current.low_speed_device_attached ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; -} - //--------------------------------------------------------------------+ // CLASS-USBH API (don't require to verify parameters) //--------------------------------------------------------------------+ @@ -199,31 +175,49 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf // is the response of interrupt endpoint polling #include "usbh_hcd.h" // FIXME remove -void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports (void) ep_addr; usbh_hub_t * p_hub = &hub_data[dev_addr-1]; - if ( event == XFER_RESULT_SUCCESS ) + if ( result == XFER_RESULT_SUCCESS ) { + TU_LOG2("Port Status Change = 0x%02X\r\n", p_hub->status_change); for (uint8_t port=1; port <= p_hub->port_number; port++) { // TODO HUB ignore bit0 hub_status_change if ( tu_bit_test(p_hub->status_change, port) ) { - hcd_event_t event = - { - .rhport = _usbh_devices[dev_addr].rhport, - .event_id = HCD_EVENT_DEVICE_ATTACH - }; - - event.attach.hub_addr = dev_addr; - event.attach.hub_port = port; + hub_port_status_response_t port_status; + hub_port_get_status(dev_addr, port, &port_status); - hcd_event_handler(&event, true); - break; // TODO handle one port at a time, next port if any will be handled in the next cycle + // Connection change + if (port_status.change.connection) + { + // Port is powered and enabled + //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); + + // Acknowledge Port Connection Change + hub_port_clear_feature(dev_addr, port, HUB_FEATURE_PORT_CONNECTION_CHANGE); + + // Reset port if attach event + if ( port_status.status.connection ) hub_port_reset(dev_addr, port); + + hcd_event_t event = + { + .rhport = _usbh_devices[dev_addr].rhport, + .event_id = port_status.status.connection ? HCD_EVENT_DEVICE_ATTACH : HCD_EVENT_DEVICE_REMOVE, + .connection = + { + .hub_addr = dev_addr, + .hub_port = port + } + }; + + hcd_event_handler(&event, true); + } } } // NOTE: next status transfer is queued by usbh.c after handling this request diff --git a/src/host/hub.h b/src/host/hub.h index 8f307190b..71dd39b8d 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -142,7 +142,7 @@ typedef struct { }; uint16_t value; - } status, status_change; + } status, change; } hub_status_response_t; TU_VERIFY_STATIC( sizeof(hub_status_response_t) == 4, "size is not correct"); @@ -151,30 +151,30 @@ TU_VERIFY_STATIC( sizeof(hub_status_response_t) == 4, "size is not correct"); typedef struct { union { struct TU_ATTR_PACKED { - uint16_t connect_status : 1; - uint16_t port_enable : 1; - uint16_t suspend : 1; - uint16_t over_current : 1; - uint16_t reset : 1; - - uint16_t : 3; - uint16_t port_power : 1; - uint16_t low_speed_device_attached : 1; - uint16_t high_speed_device_attached : 1; - uint16_t port_test_mode : 1; - uint16_t port_indicator_control : 1; + uint16_t connection : 1; + uint16_t port_enable : 1; + uint16_t suspend : 1; + uint16_t over_current : 1; + uint16_t reset : 1; + + uint16_t : 3; + uint16_t port_power : 1; + uint16_t low_speed : 1; + uint16_t high_speed : 1; + uint16_t port_test_mode : 1; + uint16_t port_indicator_control : 1; uint16_t : 0; }; uint16_t value; - } status_current, status_change; + } status, change; } hub_port_status_response_t; TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); -bool hub_port_reset_subtask(uint8_t hub_addr, uint8_t hub_port); -bool hub_port_clear_feature_subtask(uint8_t hub_addr, uint8_t hub_port, uint8_t feature); -tusb_speed_t hub_port_get_speed(void); +bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port); +bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, hub_port_status_response_t* resp); +bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature); bool hub_status_pipe_queue(uint8_t dev_addr); //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index 2e1fed5e3..fd0e9ee18 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -137,7 +137,7 @@ tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr) return (tusb_device_state_t) _usbh_devices[dev_addr].state; } -static inline void osal_task_delay(uint32_t msec) +void osal_task_delay(uint32_t msec) { (void) msec; @@ -305,8 +305,8 @@ void hcd_event_device_attach(uint8_t rhport, bool in_isr) .event_id = HCD_EVENT_DEVICE_ATTACH }; - event.attach.hub_addr = 0; - event.attach.hub_port = 0; + event.connection.hub_addr = 0; + event.connection.hub_port = 0; hcd_event_handler(&event, in_isr); } @@ -319,8 +319,8 @@ void hcd_event_device_remove(uint8_t hostid, bool in_isr) .event_id = HCD_EVENT_DEVICE_REMOVE }; - event.attach.hub_addr = 0; - event.attach.hub_port = 0; + event.connection.hub_addr = 0; + event.connection.hub_port = 0; hcd_event_handler(&event, in_isr); } @@ -434,78 +434,44 @@ bool enum_task(hcd_event_t* event) tusb_control_request_t request; dev0->rhport = event->rhport; // TODO refractor integrate to device_pool - dev0->hub_addr = event->attach.hub_addr; - dev0->hub_port = event->attach.hub_port; + dev0->hub_addr = event->connection.hub_addr; + dev0->hub_port = event->connection.hub_port; dev0->state = TUSB_DEVICE_STATE_UNPLUG; //------------- connected/disconnected directly with roothub -------------// if ( dev0->hub_addr == 0) { - if( hcd_port_connect_status(dev0->rhport) ) - { - TU_LOG2("Device connect \r\n"); - - // connection event - osal_task_delay(POWER_STABLE_DELAY); // wait until device is stable. Increase this if the first 8 bytes is failed to get - - // exit if device unplugged while delaying - if ( !hcd_port_connect_status(dev0->rhport) ) return true; + // wait until device is stable. Increase this if the first 8 bytes is failed to get + osal_task_delay(POWER_STABLE_DELAY); - hcd_port_reset( dev0->rhport ); // port must be reset to have correct speed operation - osal_task_delay(RESET_DELAY); + // device unplugged while delaying + if ( !hcd_port_connect_status(dev0->rhport) ) return true; - dev0->speed = hcd_port_speed_get( dev0->rhport ); - } - else - { - TU_LOG2("Device disconnect \r\n"); + hcd_port_reset( dev0->rhport ); // port must be reset to have correct speed operation + osal_task_delay(RESET_DELAY); - // disconnection event - usbh_device_unplugged(dev0->rhport, 0, 0); - return true; // restart task - } + dev0->speed = hcd_port_speed_get( dev0->rhport ); } #if CFG_TUH_HUB //------------- connected/disconnected via hub -------------// else { - //------------- Get Port Status -------------// - request = (tusb_control_request_t ) { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, - .bRequest = HUB_REQUEST_GET_STATUS, - .wValue = 0, - .wIndex = dev0->hub_port, - .wLength = 4 - }; - // TODO hub refractor - TU_VERIFY_HDLR( usbh_control_xfer( dev0->hub_addr, &request, _usbh_ctrl_buf ), hub_status_pipe_queue( dev0->hub_addr) ); + // TODO wait for PORT reset change instead + osal_task_delay(POWER_STABLE_DELAY); - // Acknowledge Port Connection Change - hub_port_clear_feature_subtask(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_CONNECTION_CHANGE); + hub_port_status_response_t port_status; + TU_VERIFY_HDLR( hub_port_get_status(dev0->hub_addr, dev0->hub_port, &port_status), hub_status_pipe_queue( dev0->hub_addr) ); - hub_port_status_response_t * p_port_status; - p_port_status = ((hub_port_status_response_t *) _usbh_ctrl_buf); + // device unplugged while delaying + if ( !port_status.status.connection ) return true; - if ( ! p_port_status->status_change.connect_status ) return true; // only handle connection change + dev0->speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : + (port_status.status.low_speed ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; - if ( ! p_port_status->status_current.connect_status ) + // Acknowledge Port Reset Change + if (port_status.change.reset) { - // Disconnection event - usbh_device_unplugged(dev0->rhport, dev0->hub_addr, dev0->hub_port); - - (void) hub_status_pipe_queue( dev0->hub_addr ); // done with hub, waiting for next data on status pipe - return true; // restart task - } - else - { - // Connection Event - TU_VERIFY_HDLR(hub_port_reset_subtask(dev0->hub_addr, dev0->hub_port), - hub_status_pipe_queue( dev0->hub_addr) ); // TODO hub refractor - - dev0->speed = hub_port_get_speed(); - - // Acknowledge Port Reset Change - hub_port_clear_feature_subtask(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE); + hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE); } } #endif // CFG_TUH_HUB @@ -540,10 +506,12 @@ bool enum_task(hcd_event_t* event) // connected via a hub TU_VERIFY_HDLR(is_ok, hub_status_pipe_queue( dev0->hub_addr) ); // TODO hub refractor - if ( hub_port_reset_subtask(dev0->hub_addr, dev0->hub_port) ) + if ( hub_port_reset(dev0->hub_addr, dev0->hub_port) ) { + osal_task_delay(RESET_DELAY); + // Acknowledge Port Reset Change if Reset Successful - hub_port_clear_feature_subtask(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE); + hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE); } (void) hub_status_pipe_queue( dev0->hub_addr ); // done with hub, waiting for next data on status pipe @@ -676,10 +644,24 @@ void tuh_task(void) switch (event.event_id) { case HCD_EVENT_DEVICE_ATTACH: - case HCD_EVENT_DEVICE_REMOVE: + TU_LOG2("USBH DEVICE ATTACH\r\n"); enum_task(&event); break; + case HCD_EVENT_DEVICE_REMOVE: + TU_LOG2("USBH DEVICE REMOVED\r\n"); + usbh_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port); + + #if CFG_TUH_HUB + // TODO remove + if ( event.connection.hub_addr != 0) + { + // done with hub, waiting for next data on status pipe + (void) hub_status_pipe_queue( event.connection.hub_addr ); + } + #endif + break; + case HCD_EVENT_XFER_COMPLETE: { usbh_device_t* dev = &_usbh_devices[event.dev_addr]; -- cgit v1.3.1 From 9a6d7c648e3f41529fad2e2af7e01dc5c56003ac Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 20:34:45 +0700 Subject: clean up enum task --- src/host/ehci/ehci.c | 3 +++ src/host/usbh.c | 33 ++++++++++----------------------- src/host/usbh.h | 2 +- src/host/usbh_hcd.h | 1 - 4 files changed, 14 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 13e9b0edc..3c02086c9 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -326,6 +326,9 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * // attach TD qhd->qtd_overlay.next.address = (uint32_t) qtd; + }else + { + // TODO implement later } return true; diff --git a/src/host/usbh.c b/src/host/usbh.c index fd0e9ee18..f669cac05 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -122,11 +122,8 @@ static osal_queue_t _usbh_q; CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _usbh_ctrl_buf[CFG_TUSB_HOST_ENUM_BUFFER_SIZE]; -//------------- Reporter Task Data -------------// - //------------- Helper Function Prototypes -------------// static inline uint8_t get_new_address(void); -static inline uint8_t get_configure_number_for_device(tusb_desc_device_t* dev_desc); //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) @@ -557,19 +554,22 @@ bool enum_task(hcd_event_t* event) TU_ASSERT(usbh_control_xfer(new_addr, &request, _usbh_ctrl_buf)); // update device info TODO alignment issue - new_dev->vendor_id = ((tusb_desc_device_t*) _usbh_ctrl_buf)->idVendor; - new_dev->product_id = ((tusb_desc_device_t*) _usbh_ctrl_buf)->idProduct; - new_dev->configure_count = ((tusb_desc_device_t*) _usbh_ctrl_buf)->bNumConfigurations; + tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; + + if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); + + new_dev->vendor_id = desc_device->idVendor; + new_dev->product_id = desc_device->idProduct; + TU_ASSERT(desc_device->bNumConfigurations > 0); - uint8_t const configure_selected = get_configure_number_for_device((tusb_desc_device_t*) _usbh_ctrl_buf); - TU_ASSERT(configure_selected <= new_dev->configure_count); // TODO notify application when invalid configuration + enum { CONFIG_NUM = 1 }; // default to use configuration 1 //------------- Get 9 bytes of configuration descriptor -------------// TU_LOG2("Get 9 bytes of Configuration Descriptor\r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = (TUSB_DESC_CONFIGURATION << 8) | (configure_selected - 1), + .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), .wIndex = 0, .wLength = 9 }; @@ -591,7 +591,7 @@ bool enum_task(hcd_event_t* event) request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, .bRequest = TUSB_REQ_SET_CONFIGURATION, - .wValue = configure_selected, + .wValue = CONFIG_NUM, .wIndex = 0, .wLength = 0 }; @@ -702,17 +702,4 @@ static inline uint8_t get_new_address(void) return CFG_TUSB_HOST_DEVICE_MAX+1; } -static inline uint8_t get_configure_number_for_device(tusb_desc_device_t* dev_desc) -{ - uint8_t config_num = 1; - - // invoke callback to ask user which configuration to select - if (tuh_device_attached_cb) - { - config_num = tu_min8(1, tuh_device_attached_cb(dev_desc) ); - } - - return config_num; -} - #endif diff --git a/src/host/usbh.h b/src/host/usbh.h index 56a5ce72f..1774666f1 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -90,7 +90,7 @@ static inline bool tuh_device_is_configured(uint8_t dev_addr) //--------------------------------------------------------------------+ // APPLICATION CALLBACK //--------------------------------------------------------------------+ -TU_ATTR_WEAK uint8_t tuh_device_attached_cb (tusb_desc_device_t const *p_desc_device); +TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); /** Callback invoked when device is mounted (configured) */ TU_ATTR_WEAK void tuh_mount_cb (uint8_t dev_addr); diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index 019b9f037..435af96bb 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -53,7 +53,6 @@ typedef struct { //------------- device descriptor -------------// uint16_t vendor_id; uint16_t product_id; - uint8_t configure_count; // bNumConfigurations alias //------------- configuration descriptor -------------// uint8_t interface_count; // bNumInterfaces alias -- cgit v1.3.1 From 15ad585e674f14e247aa7e5f42fb84f90f14be8b Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 6 Sep 2020 11:49:00 +0700 Subject: replacing hcd_pipe_xfer by usbh_edpt_xfer --- hw/bsp/ea4088qs/ea4088qs.c | 15 +++++++++++---- src/class/hid/hid_host.c | 2 +- src/host/ehci/ehci.c | 15 ++++++++++++++- src/host/hub.c | 4 ++-- src/host/ohci/ohci.c | 24 ++++++++++++++++++++++-- src/host/usbh.c | 6 ++++++ src/host/usbh.h | 2 ++ 7 files changed, 58 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/hw/bsp/ea4088qs/ea4088qs.c b/hw/bsp/ea4088qs/ea4088qs.c index f164526d7..b25f9101c 100644 --- a/hw/bsp/ea4088qs/ea4088qs.c +++ b/hw/bsp/ea4088qs/ea4088qs.c @@ -98,6 +98,11 @@ void SystemInit(void) Chip_IOCON_Init(LPC_IOCON); Chip_IOCON_SetPinMuxing(LPC_IOCON, pinmuxing, sizeof(pinmuxing) / sizeof(PINMUX_GRP_T)); + + /* CPU clock source starts with IRC */ + /* Enable PBOOST for CPU clock over 100MHz */ + Chip_SYSCTL_EnableBoost(); + Chip_SetupXtalClocking(); } @@ -130,13 +135,15 @@ void board_init(void) Chip_USB_Init(); enum { - USBCLK = 0x1B // Host + Device + OTG + AHB + USBCLK_DEVCIE = 0x12, // AHB + Device + USBCLK_HOST = 0x19 , // AHB + OTG + Host + USBCLK_ALL = 0x1B // Host + Device + OTG + AHB }; - LPC_USB->OTGClkCtrl = USBCLK; - while ( (LPC_USB->OTGClkSt & USBCLK) != USBCLK ) {} + LPC_USB->OTGClkCtrl = USBCLK_ALL; + while ( (LPC_USB->OTGClkSt & USBCLK_ALL) != USBCLK_ALL ) {} - // USB1 = host, USB2 = device + // set portfunc: USB1 = host, USB2 = device LPC_USB->StCtrl = 0x3; } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index d9ed1f651..5ea8cc7e9 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -71,7 +71,7 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int TU_VERIFY(report, TUSB_ERROR_INVALID_PARA); TU_ASSERT(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); - TU_ASSERT( hcd_pipe_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size, true) ) ; + TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size) ) ; return TUSB_ERROR_NONE; } diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 3c02086c9..23c8ea9ee 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -328,7 +328,20 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * qhd->qtd_overlay.next.address = (uint32_t) qtd; }else { - // TODO implement later + ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); + ehci_qtd_t *p_qtd = qtd_find_free(); + TU_ASSERT(p_qtd); + + qtd_init(p_qtd, buffer, buflen); + p_qtd->pid = p_qhd->pid; + + // Insert TD to QH + qtd_insert_to_qhd(p_qhd, p_qtd); + + p_qhd->p_qtd_list_tail->int_on_complete = 1; + + // attach head QTD to QHD start transferring + p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; } return true; diff --git a/src/host/hub.c b/src/host/hub.c index db1ca0786..abec20d06 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -167,8 +167,8 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf TU_ASSERT( usbh_control_xfer( dev_addr, &request, NULL ) ); } - //------------- Queue the initial Status endpoint transfer -------------// - TU_ASSERT( hcd_pipe_xfer(dev_addr, hub_data[dev_addr-1].ep_status, &hub_data[dev_addr-1].status_change, 1, true) ); + // Queue notification status endpoint + TU_ASSERT( usbh_edpt_xfer(dev_addr, hub_data[dev_addr-1].ep_status, &hub_data[dev_addr-1].status_change, 1) ); return true; } diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 87da374d5..d9bbfc8c6 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -306,6 +306,11 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet return true; } +// TODO move around +static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr); +static ohci_gtd_t * gtd_find_free(void); +static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd); + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { (void) rhport; @@ -329,6 +334,21 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * p_ed->td_head.address = (uint32_t) p_data; OHCI_REG->command_status_bit.control_list_filled = 1; + }else + { + ohci_ed_t * p_ed = ed_from_addr(dev_addr, ep_addr); + ohci_gtd_t* p_gtd = gtd_find_free(); + + TU_ASSERT(p_gtd); + + gtd_init(p_gtd, buffer, buflen); + p_gtd->index = p_ed-ohci_data.ed_pool; + p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + + td_insert_to_ed(p_ed, p_gtd); + + tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); + if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; } return true; @@ -337,7 +357,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * //--------------------------------------------------------------------+ // BULK/INT/ISO PIPE API //--------------------------------------------------------------------+ -static inline ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) +static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) { if ( tu_edpt_number(ep_addr) == 0 ) return &ohci_data.control[dev_addr].ed; @@ -355,7 +375,7 @@ static inline ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) return NULL; } -static inline ohci_ed_t * ed_find_free(void) +static ohci_ed_t * ed_find_free(void) { ohci_ed_t* ed_pool = ohci_data.ed_pool; diff --git a/src/host/usbh.c b/src/host/usbh.c index f669cac05..da35340ce 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -208,6 +208,12 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8 return true; } +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + usbh_device_t* dev = &_usbh_devices[dev_addr]; + return hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes); +} + bool usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) { osal_semaphore_reset( _usbh_devices[dev_addr].control.sem_hdl ); diff --git a/src/host/usbh.h b/src/host/usbh.h index 1774666f1..10e0c21be 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -105,6 +105,8 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + #ifdef __cplusplus } #endif -- cgit v1.3.1 From b3e81673c0582a07a764981604a560ee3d310ef9 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 6 Sep 2020 12:11:07 +0700 Subject: change xfer_cb return type from void to bool --- src/class/cdc/cdc_host.c | 3 ++- src/class/cdc/cdc_host.h | 2 +- src/class/hid/hid_host.c | 8 +++++--- src/class/hid/hid_host.h | 2 +- src/class/msc/msc_host.c | 6 +++++- src/class/msc/msc_host.h | 2 +- src/host/hub.c | 4 +++- src/host/hub.h | 2 +- src/host/usbh.c | 4 ++-- src/host/usbh.h | 7 +++++-- 10 files changed, 26 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 23e342134..ae1eef8a7 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -209,10 +209,11 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it return true; } -void cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) ep_addr; tuh_cdc_xfer_isr( dev_addr, event, 0, xferred_bytes ); + return true; } void cdch_close(uint8_t dev_addr) diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 0e2820fef..f28a0a713 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -113,7 +113,7 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i //--------------------------------------------------------------------+ void cdch_init(void); bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -void cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void cdch_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 5ea8cc7e9..6002ead3c 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -233,7 +233,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c return true; } -void hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO may need to use this para later @@ -241,7 +241,7 @@ void hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) { tuh_hid_keyboard_isr(dev_addr, event); - return; + return true; } #endif @@ -249,13 +249,15 @@ void hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 if ( ep_addr == mouseh_data[dev_addr-1].ep_in ) { tuh_hid_mouse_isr(dev_addr, event); - return; + return true; } #endif #if CFG_TUSB_HOST_HID_GENERIC #endif + + return true; } void hidh_close(uint8_t dev_addr) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 54542de55..324dad203 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -197,7 +197,7 @@ void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); //--------------------------------------------------------------------+ void hidh_init(void); bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); -void hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hidh_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index b129d538f..f47bbd163 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -336,6 +336,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it enum { SCSI_XFER_TIMEOUT = 2000 }; //------------- SCSI Inquiry -------------// + TU_LOG2("SCSI Inquiry\r\n"); tusbh_msc_inquiry(dev_addr, 0, msch_buffer); TU_ASSERT( osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT) ); @@ -343,6 +344,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it memcpy(p_msc->product_id, ((scsi_inquiry_resp_t*) msch_buffer)->product_id, 16); //------------- SCSI Read Capacity 10 -------------// + TU_LOG2("SCSI Read Capacity 10\r\n"); tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer); TU_ASSERT( osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT)); @@ -383,7 +385,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it return true; } -void msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { msch_interface_t* p_msc = &msch_data[dev_addr-1]; if ( ep_addr == p_msc->ep_in ) @@ -396,6 +398,8 @@ void msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 osal_semaphore_post(msch_sem_hdl, true); } } + + return true; } void msch_close(uint8_t dev_addr) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 3eb45e6fc..a32134215 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -193,7 +193,7 @@ typedef struct void msch_init(void); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -void msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void msch_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/host/hub.c b/src/host/hub.c index abec20d06..ed96713e2 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -175,7 +175,7 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf // is the response of interrupt endpoint polling #include "usbh_hcd.h" // FIXME remove -void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports (void) ep_addr; @@ -227,6 +227,8 @@ void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 // TODO [HUB] check if hub is still plugged before polling status endpoint since failed usually mean hub unplugged // TU_ASSERT ( hub_status_pipe_queue(dev_addr) ); } + + return true; } void hub_close(uint8_t dev_addr) diff --git a/src/host/hub.h b/src/host/hub.h index 71dd39b8d..f00f13de7 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -182,7 +182,7 @@ bool hub_status_pipe_queue(uint8_t dev_addr); //--------------------------------------------------------------------+ void hub_init(void); bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hub_close(uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/host/usbh.c b/src/host/usbh.c index da35340ce..a7f6397cd 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -48,7 +48,7 @@ #define DRIVER_NAME(_name) #endif -static host_class_driver_t const usbh_class_drivers[] = +static usbh_class_driver_t const usbh_class_drivers[] = { #if CFG_TUH_CDC { @@ -442,7 +442,7 @@ bool enum_task(hcd_event_t* event) dev0->state = TUSB_DEVICE_STATE_UNPLUG; //------------- connected/disconnected directly with roothub -------------// - if ( dev0->hub_addr == 0) + if (dev0->hub_addr == 0) { // wait until device is stable. Increase this if the first 8 bytes is failed to get osal_task_delay(POWER_STABLE_DELAY); diff --git a/src/host/usbh.h b/src/host/usbh.h index 10e0c21be..91afb90a3 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -60,9 +60,9 @@ typedef struct { void (* const init) (void); bool (* const open)(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); - void (* const xfer_cb) (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t len); + bool (* const xfer_cb) (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); void (* const close) (uint8_t); -} host_class_driver_t; +} usbh_class_driver_t; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -107,6 +107,9 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + +bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, uint8_t* buffer, uint16_t buflen); + #ifdef __cplusplus } #endif -- cgit v1.3.1 From 4e789b240deb0b124b65fd3a177674f562f0b3c1 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 6 Sep 2020 11:37:59 +0200 Subject: Start of sampling works. --- src/class/audio/audio_device.c | 15 ++++-- src/portable/st/synopsys/dcd_synopsys.c | 93 +++++++++++++++++---------------- 2 files changed, 59 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 942933b5d..ebb8434cd 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -780,8 +780,12 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) { TU_ASSERT(usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *)p_desc)); + uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + // We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! + usbd_edpt_clear_stall(rhport, ep_addr); + #if CFG_TUD_AUDIO_EPSIZE_IN > 0 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP { @@ -1081,11 +1085,12 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 uint16_t n_bytes_copied; TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); - if (n_bytes_copied == 0) - { - // Load with ZLP - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); - } + // Transmission of ZLP is done by audiod_tx_done_cb() +// if (n_bytes_copied == 0) +// { +// // Load with ZLP +// return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); +// } return true; } diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index d1f24916c..c1b087dac 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -682,42 +682,42 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } -/** - * Close an EP. - * - * Currently, we only deactivate the EPs and do not fully disable them - this might not be necessary! - * - */ -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); - - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - - if(dir == TUSB_DIR_IN) - { - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); - - // Disable interrupt for this EP - dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); - - // Clear USB active EP - in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_USBAEP; - } - else - { - USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); - - // Disable interrupt for this EP - dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum));; - - // Clear USB active EP bit - out_ep[epnum].DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP; - - } -} +///** +// * Close an EP. +// * +// * Currently, we only deactivate the EPs and do not fully disable them - this might not be necessary! +// * +// */ +//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); +// +// USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); +// +// if(dir == TUSB_DIR_IN) +// { +// USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); +// +// // Disable interrupt for this EP +// dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); +// +// // Clear USB active EP +// in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_USBAEP; +// } +// else +// { +// USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); +// +// // Disable interrupt for this EP +// dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum));; +// +// // Clear USB active EP bit +// out_ep[epnum].DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP; +// +// } +//} bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { @@ -815,14 +815,14 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) uint8_t const dir = tu_edpt_dir(ep_addr); dcd_edpt_disable(rhport, ep_addr, false); - if (dir == TUSB_DIR_IN) - { - uint16_t const fifo_size = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXFD_Msk) >> USB_OTG_DIEPTXF_INEPTXFD_Pos; - uint16_t const fifo_start = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXSA_Msk) >> USB_OTG_DIEPTXF_INEPTXSA_Pos; - // For now only endpoint that has FIFO at the end of FIFO memory can be closed without fuss. - TU_ASSERT(fifo_start + fifo_size == _allocated_fifo_words,); - _allocated_fifo_words -= fifo_size; - } +// if (dir == TUSB_DIR_IN) +// { +// uint16_t const fifo_size = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXFD_Msk) >> USB_OTG_DIEPTXF_INEPTXFD_Pos; +// uint16_t const fifo_start = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXSA_Msk) >> USB_OTG_DIEPTXF_INEPTXSA_Pos; +// // For now only endpoint that has FIFO at the end of FIFO memory can be closed without fuss. +// TU_ASSERT(fifo_start + fifo_size == _allocated_fifo_words,); +// _allocated_fifo_words -= fifo_size; +// } } void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) @@ -1156,6 +1156,11 @@ void dcd_int_handler(uint8_t rhport) // IEPINT bit read-only handle_epin_ints(rhport, dev, in_ep); } + + // Check for Incomplete isochronous IN transfer + if(int_status & USB_OTG_GINTSTS_IISOIXFR) { + TU_LOG2(" IISOIXFR!\r\n"); + } } // Helper function which parses through the current configuration descriptors to find the biggest EPs in size. -- cgit v1.3.1 From 66a10ec9c8042a48053b4af67a932f3cfe9470c2 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 7 Sep 2020 15:19:20 +0700 Subject: rework usbh control transfer use series of complete callback instead of blocking semaphore, which is more noOS friendly. still working with hid host --- examples/host/cdc_msc_hid/Makefile | 3 +- .../host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject | 1 + src/class/hid/hid_host.c | 22 +- src/common/tusb_types.h | 4 +- src/host/usbh.c | 299 ++++++++++++++++++--- src/host/usbh.h | 9 +- src/host/usbh_control.c | 135 ++++++++++ src/host/usbh_hcd.h | 11 +- 8 files changed, 435 insertions(+), 49 deletions(-) create mode 100644 src/host/usbh_control.c (limited to 'src') diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index 35de0a9a0..b49c4c75c 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -16,8 +16,9 @@ SRC_C += \ src/class/cdc/cdc_host.c \ src/class/hid/hid_host.c \ src/class/msc/msc_host.c \ - src/host/usbh.c \ src/host/hub.c \ + src/host/usbh.c \ + src/host/usbh_control.c \ src/host/ehci/ehci.c \ src/host/ohci/ohci.c \ src/portable/nxp/lpc18_43/hcd_lpc18_43.c \ diff --git a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject index 2b5538957..271076b5c 100644 --- a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject +++ b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject @@ -23,6 +23,7 @@ debug_target_connection="J-Link" gcc_entry_point="Reset_Handler" linker_memory_map_file="$(ProjectDir)/LPC1857_MemoryMap.xml" + linker_printf_width_precision_supported="Yes" linker_section_placement_file="$(ProjectDir)/flash_placement.xml" macros="DeviceFamily=LPC1800;DeviceSubFamily=LPC185x;Target=LPC1857;Placement=Flash;rootDir=../../../../..;lpcDir=../../../../../hw/mcu/nxp/lpcopen/lpc18xx/lpc_chip_18xx" package_dependencies="LPC1800" diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 6002ead3c..5058191f4 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -175,14 +175,22 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c // SET IDLE = 0 request // Device can stall if not support this request - tusb_control_request_t request = { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, - .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = 0, // idle_rate = 0 - .wIndex = p_interface_desc->bInterfaceNumber, - .wLength = 0 + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_IDLE, + .wValue = 0, // idle_rate = 0 + .wIndex = p_interface_desc->bInterfaceNumber, + .wLength = 0 }; - usbh_control_xfer( dev_addr, &request, NULL ); // TODO stall is valid + + // stall is a valid response for SET_IDLE, therefore we could ignore result of this request + tuh_control_xfer(dev_addr, &request, NULL, NULL); #if 0 //------------- Get Report Descriptor TODO HID parser -------------// diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 70d0db942..d6b6ea627 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -276,6 +276,8 @@ typedef struct TU_ATTR_PACKED uint8_t bNumConfigurations ; ///< Number of possible configurations. } tusb_desc_device_t; +TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); + // USB Binary Device Object Store (BOS) Descriptor typedef struct TU_ATTR_PACKED { @@ -431,7 +433,7 @@ typedef struct TU_ATTR_PACKED{ uint16_t wLength; } tusb_control_request_t; -TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "mostly compiler option issue"); +TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); // TODO move to somewhere suitable static inline uint8_t bm_request_type(uint8_t direction, uint8_t type, uint8_t recipient) diff --git a/src/host/usbh.c b/src/host/usbh.c index a7f6397cd..592eac267 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -108,6 +108,11 @@ static usbh_class_driver_t const usbh_class_drivers[] = enum { USBH_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) }; +enum { RESET_DELAY = 500 }; // 200 USB specs say only 50ms but many devices require much longer + +enum { CONFIG_NUM = 1 }; // default to use configuration 1 + + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -125,6 +130,9 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _usbh_ctrl_buf[CFG_TUSB_H //------------- Helper Function Prototypes -------------// static inline uint8_t get_new_address(void); +// from usbh_control.c +extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) //--------------------------------------------------------------------+ @@ -281,23 +289,21 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred // usbh_devices[ pipe_hdl.dev_addr ].control.xferred_bytes = xferred_bytes; not yet neccessary osal_semaphore_post( dev->control.sem_hdl, true ); // FIXME post within ISR } - else + + hcd_event_t event = { - hcd_event_t event = + .rhport = 0, // TODO correct rhport + .event_id = HCD_EVENT_XFER_COMPLETE, + .dev_addr = dev_addr, + .xfer_complete = { - .rhport = 0, - .event_id = HCD_EVENT_XFER_COMPLETE, - .dev_addr = dev_addr, - .xfer_complete = - { - .ep_addr = ep_addr, - .result = result, - .len = xferred_bytes - } - }; + .ep_addr = ep_addr, + .result = result, + .len = xferred_bytes + } + }; - hcd_event_handler(&event, in_isr); - } + hcd_event_handler(&event, in_isr); } void hcd_event_device_attach(uint8_t rhport, bool in_isr) @@ -373,8 +379,6 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura uint8_t const* p_desc = (uint8_t const*) desc_cfg; p_desc = tu_desc_next(p_desc); - TU_LOG2_MEM(desc_cfg, desc_cfg->wTotalLength, 0); - // parse each interfaces while( p_desc < _usbh_ctrl_buf + desc_cfg->wTotalLength ) { @@ -426,16 +430,226 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura return true; } -bool enum_task(hcd_event_t* event) +static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_LOG2_LOCATION(); + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + TU_LOG2("Device configured\r\n"); + usbh_device_t* dev = &_usbh_devices[dev_addr]; + dev->state = TUSB_DEVICE_STATE_CONFIGURED; + + // Parse configuration & set up drivers + parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); + + return true; +} + +static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - enum { - POWER_STABLE_DELAY = 100, - RESET_DELAY = 500, // 200 USB specs say only 50ms but many devices require much longer + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + TU_LOG2("Set Configuration Descriptor\r\n"); + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_CONFIGURATION, + .wValue = CONFIG_NUM, + .wIndex = 0, + .wLength = 0 }; + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, enum_set_config_complete) ); + + return true; +} + +static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + // TODO not enough buffer to hold configuration descriptor + tusb_desc_configuration_t const * desc_config = (tusb_desc_configuration_t const*) _usbh_ctrl_buf; + uint16_t total_len; + + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); + + TU_ASSERT(total_len <= CFG_TUSB_HOST_ENUM_BUFFER_SIZE); + + //Get full configuration descriptor + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), + .wIndex = 0, + .wLength = total_len + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_config_desc_complete) ); + + return true; +} + +static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + dev->vendor_id = desc_device->idVendor; + dev->product_id = desc_device->idProduct; + +// if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); + + TU_LOG2("Get 9 bytes of Configuration Descriptor\r\n"); + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), + .wIndex = 0, + .wLength = 9 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_9byte_config_desc_complete) ); + + return true; +} + +// After SET_ADDRESS is complete +static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(0 == dev_addr); + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + uint8_t const new_addr = (uint8_t const) request->wValue; + + usbh_device_t* new_dev = &_usbh_devices[new_addr]; + new_dev->addressed = 1; + + // TODO close device 0, may not be needed usbh_device_t* dev0 = &_usbh_devices[0]; - tusb_control_request_t request; + hcd_device_close(dev0->rhport, 0); + dev0->state = TUSB_DEVICE_STATE_UNPLUG; + + // open control pipe for new address + TU_ASSERT ( usbh_pipe_control_open(new_addr, new_dev->ep0_packet_size) ); + + // Get full device descriptor + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = TUSB_DESC_DEVICE << 8, + .wIndex = 0, + .wLength = sizeof(tusb_desc_device_t) + }; + TU_ASSERT(tuh_control_xfer(new_addr, &new_request, _usbh_ctrl_buf, enum_get_device_desc_complete)); + + return true; +} + +// After Get Device Descriptor of Address 0 +static bool enum_get_dev0_devic_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(0 == dev_addr); + + usbh_device_t* dev0 = &_usbh_devices[0]; + + if (XFER_RESULT_SUCCESS != result) + { +#if CFG_TUH_HUB + // TODO remove, waiting for next data on status pipe + if (dev0->hub_addr != 0) hub_status_pipe_queue( dev0->hub_addr); +#endif + + return false; + } + + // Reset device again before Set Address + TU_LOG2("Port reset \r\n"); + + if (dev0->hub_addr == 0) + { + // connected directly to roothub + hcd_port_reset( dev0->rhport ); // reset port after 8 byte descriptor + osal_task_delay(RESET_DELAY); + } +#if CFG_TUH_HUB + else + { + // FIXME hub_port_reset use usbh_control_xfer + if ( hub_port_reset(dev0->hub_addr, dev0->hub_port) ) + { + osal_task_delay(RESET_DELAY); + + // Acknowledge Port Reset Change if Reset Successful + hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE); + } + + (void) hub_status_pipe_queue( dev0->hub_addr ); // done with hub, waiting for next data on status pipe + } +#endif // CFG_TUH_HUB + + // Set Address + TU_LOG2("Set Address \r\n"); + uint8_t const new_addr = get_new_address(); + TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices + + usbh_device_t* new_dev = &_usbh_devices[new_addr]; + new_dev->rhport = dev0->rhport; + new_dev->hub_addr = dev0->hub_addr; + new_dev->hub_port = dev0->hub_port; + new_dev->speed = dev0->speed; + new_dev->connected = 1; + new_dev->ep0_packet_size = ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0; + + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_ADDRESS, + .wValue = new_addr, + .wIndex = 0, + .wLength = 0 + }; + + TU_ASSERT(tuh_control_xfer(0, &new_request, NULL, enum_set_address_complete)); + + return true; +} + +bool enum_task(hcd_event_t* event) +{ + usbh_device_t* dev0 = &_usbh_devices[0]; dev0->rhport = event->rhport; // TODO refractor integrate to device_pool dev0->hub_addr = event->connection.hub_addr; dev0->hub_port = event->connection.hub_port; @@ -445,14 +659,11 @@ bool enum_task(hcd_event_t* event) if (dev0->hub_addr == 0) { // wait until device is stable. Increase this if the first 8 bytes is failed to get - osal_task_delay(POWER_STABLE_DELAY); + osal_task_delay(RESET_DELAY); // device unplugged while delaying if ( !hcd_port_connect_status(dev0->rhport) ) return true; - hcd_port_reset( dev0->rhport ); // port must be reset to have correct speed operation - osal_task_delay(RESET_DELAY); - dev0->speed = hcd_port_speed_get( dev0->rhport ); } #if CFG_TUH_HUB @@ -460,8 +671,9 @@ bool enum_task(hcd_event_t* event) else { // TODO wait for PORT reset change instead - osal_task_delay(POWER_STABLE_DELAY); + osal_task_delay(RESET_DELAY); + // FIXME hub API use usbh_control_xfer hub_port_status_response_t port_status; TU_VERIFY_HDLR( hub_port_get_status(dev0->hub_addr, dev0->hub_port, &port_status), hub_status_pipe_queue( dev0->hub_addr) ); @@ -479,19 +691,27 @@ bool enum_task(hcd_event_t* event) } #endif // CFG_TUH_HUB + // TODO probably doesn't need to open/close each enumeration TU_ASSERT( usbh_pipe_control_open(0, 8) ); //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// TU_LOG2("Get 8 byte of Device Descriptor\r\n"); - request = (tusb_control_request_t ) { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = TUSB_DESC_DEVICE << 8, - .wIndex = 0, - .wLength = 8 + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = TUSB_DESC_DEVICE << 8, + .wIndex = 0, + .wLength = 8 }; - bool is_ok = usbh_control_xfer(0, &request, _usbh_ctrl_buf); + TU_ASSERT(tuh_control_xfer(0, &request, _usbh_ctrl_buf, enum_get_dev0_devic_desc_complete)); +#if 0 //------------- Reset device again before Set Address -------------// TU_LOG2("Port reset \r\n"); @@ -526,6 +746,14 @@ bool enum_task(hcd_event_t* event) uint8_t const new_addr = get_new_address(); TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices + usbh_device_t* new_dev = &_usbh_devices[new_addr]; + new_dev->rhport = dev0->rhport; + new_dev->hub_addr = dev0->hub_addr; + new_dev->hub_port = dev0->hub_port; + new_dev->speed = dev0->speed; + new_dev->connected = 1; + new_dev->ep0_packet_size = ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0; + request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, .bRequest = TUSB_REQ_SET_ADDRESS, @@ -533,7 +761,7 @@ bool enum_task(hcd_event_t* event) .wIndex = 0, .wLength = 0 }; - TU_ASSERT(usbh_control_xfer(0, &request, NULL)); + TU_ASSERT(tuh_control_xfer(0, &request, NULL, enum_set_address_complete)); //------------- update port info & close control pipe of addr0 -------------// usbh_device_t* new_dev = &_usbh_devices[new_addr]; @@ -613,6 +841,7 @@ bool enum_task(hcd_event_t* event) // Invoke callback if available if (tuh_mount_cb) tuh_mount_cb(new_addr); +#endif return true; } @@ -679,7 +908,7 @@ void tuh_task(void) if ( 0 == epnum ) { - // TODO control transfer + usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); }else { uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; diff --git a/src/host/usbh.h b/src/host/usbh.h index 91afb90a3..814770722 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -63,6 +63,8 @@ typedef struct { bool (* const xfer_cb) (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); void (* const close) (uint8_t); } usbh_class_driver_t; + +typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -87,10 +89,12 @@ static inline bool tuh_device_is_configured(uint8_t dev_addr) return tuh_device_get_state(dev_addr) == TUSB_DEVICE_STATE_CONFIGURED; } +bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); + //--------------------------------------------------------------------+ // APPLICATION CALLBACK //--------------------------------------------------------------------+ -TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); +//TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); /** Callback invoked when device is mounted (configured) */ TU_ATTR_WEAK void tuh_mount_cb (uint8_t dev_addr); @@ -107,9 +111,6 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - -bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, uint8_t* buffer, uint16_t buflen); - #ifdef __cplusplus } #endif diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c new file mode 100644 index 000000000..595c011f5 --- /dev/null +++ b/src/host/usbh_control.c @@ -0,0 +1,135 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_HOST_ENABLED + +#include "tusb.h" +#include "usbh_hcd.h" + +enum +{ + STAGE_SETUP, + STAGE_DATA, + STAGE_ACK +}; + +typedef struct +{ + tusb_control_request_t request TU_ATTR_ALIGNED(4); + + uint8_t stage; + uint8_t* buffer; + tuh_control_complete_cb_t complete_cb; +} usbh_control_xfer_t; + +static usbh_control_xfer_t _ctrl_xfer; + +//CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN +//static uint8_t _tuh_ctrl_buf[CFG_TUSB_HOST_ENUM_BUFFER_SIZE]; + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) +{ + usbh_device_t* dev = &_usbh_devices[dev_addr]; + const uint8_t rhport = dev->rhport; + + _ctrl_xfer.request = (*request); + _ctrl_xfer.buffer = buffer; + _ctrl_xfer.stage = STAGE_SETUP; + _ctrl_xfer.complete_cb = complete_cb; + + TU_LOG2("Control Setup: "); + TU_LOG2_VAR(request); + TU_LOG2("\r\n"); + + // Send setup packet + TU_ASSERT( hcd_setup_send(rhport, dev_addr, (uint8_t const*) &_ctrl_xfer.request) ); + + return true; +} + +static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) +{ + if (_ctrl_xfer.complete_cb) _ctrl_xfer.complete_cb(dev_addr, &_ctrl_xfer.request, result); +} + +bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + usbh_device_t* dev = &_usbh_devices[dev_addr]; + const uint8_t rhport = dev->rhport; + + tusb_control_request_t const * request = &_ctrl_xfer.request; + + if (XFER_RESULT_SUCCESS != result) + { + TU_LOG2("Control failed: result = %d\r\n", result); + + // terminate transfer if any stage failed + _xfer_complete(dev_addr, result); + }else + { + switch(_ctrl_xfer.stage) + { + case STAGE_SETUP: + _ctrl_xfer.stage = STAGE_DATA; + if (request->wLength) + { + // Note: initial data toggle is always 1 + hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); + return true; + } + __attribute__((fallthrough)); + + case STAGE_DATA: + _ctrl_xfer.stage = STAGE_ACK; + + if (request->wLength) + { + TU_LOG2("Control data:\r\n"); + TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2); + } + + // data toggle is always 1 + hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); + break; + + case STAGE_ACK: + _xfer_complete(dev_addr, result); + break; + + default: return false; + } + } + + return true; +} + +#endif diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index 435af96bb..f203f3baa 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -53,11 +53,20 @@ typedef struct { //------------- device descriptor -------------// uint16_t vendor_id; uint16_t product_id; + uint8_t ep0_packet_size; //------------- configuration descriptor -------------// - uint8_t interface_count; // bNumInterfaces alias + // uint8_t interface_count; // bNumInterfaces alias //------------- device -------------// + struct TU_ATTR_PACKED + { + uint8_t connected : 1; + uint8_t addressed : 1; + uint8_t configured : 1; + uint8_t suspended : 1; + }; + volatile uint8_t state; // device state, value from enum tusbh_device_state_t //------------- control pipe -------------// -- cgit v1.3.1 From 7a3b24827ed97c71a19c5add9e3ad6af5f08cf4b Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 7 Sep 2020 15:25:03 +0700 Subject: clean up --- src/host/usbh.c | 147 +++++--------------------------------------------------- 1 file changed, 12 insertions(+), 135 deletions(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index 592eac267..d8b3d6535 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -432,21 +432,27 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - TU_LOG2_LOCATION(); + (void) request; TU_ASSERT(XFER_RESULT_SUCCESS == result); TU_LOG2("Device configured\r\n"); usbh_device_t* dev = &_usbh_devices[dev_addr]; + dev->configured = 1; dev->state = TUSB_DEVICE_STATE_CONFIGURED; // Parse configuration & set up drivers + // TODO driver open still use usbh_control_xfer parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); + // Invoke callback if available + if (tuh_mount_cb) tuh_mount_cb(dev_addr); + return true; } static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { + (void) request; TU_ASSERT(XFER_RESULT_SUCCESS == result); TU_LOG2("Set Configuration Descriptor\r\n"); @@ -471,6 +477,7 @@ static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { + (void) request; TU_ASSERT(XFER_RESULT_SUCCESS == result); // TODO not enough buffer to hold configuration descriptor @@ -504,6 +511,7 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { + (void) request; TU_ASSERT(XFER_RESULT_SUCCESS == result); tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; @@ -576,6 +584,7 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c // After Get Device Descriptor of Address 0 static bool enum_get_dev0_devic_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { + (void) request; TU_ASSERT(0 == dev_addr); usbh_device_t* dev0 = &_usbh_devices[0]; @@ -647,7 +656,7 @@ static bool enum_get_dev0_devic_desc_complete(uint8_t dev_addr, tusb_control_req return true; } -bool enum_task(hcd_event_t* event) +static bool enum_device_attached(hcd_event_t* event) { usbh_device_t* dev0 = &_usbh_devices[0]; dev0->rhport = event->rhport; // TODO refractor integrate to device_pool @@ -711,138 +720,6 @@ bool enum_task(hcd_event_t* event) }; TU_ASSERT(tuh_control_xfer(0, &request, _usbh_ctrl_buf, enum_get_dev0_devic_desc_complete)); -#if 0 - //------------- Reset device again before Set Address -------------// - TU_LOG2("Port reset \r\n"); - - if (dev0->hub_addr == 0) - { - TU_ASSERT(is_ok); - - // connected directly to roothub - hcd_port_reset( dev0->rhport ); // reset port after 8 byte descriptor - osal_task_delay(RESET_DELAY); - } -#if CFG_TUH_HUB - else - { - // connected via a hub - TU_VERIFY_HDLR(is_ok, hub_status_pipe_queue( dev0->hub_addr) ); // TODO hub refractor - - if ( hub_port_reset(dev0->hub_addr, dev0->hub_port) ) - { - osal_task_delay(RESET_DELAY); - - // Acknowledge Port Reset Change if Reset Successful - hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE); - } - - (void) hub_status_pipe_queue( dev0->hub_addr ); // done with hub, waiting for next data on status pipe - } -#endif // CFG_TUH_HUB - - //------------- Set new address -------------// - TU_LOG2("Set Address \r\n"); - uint8_t const new_addr = get_new_address(); - TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices - - usbh_device_t* new_dev = &_usbh_devices[new_addr]; - new_dev->rhport = dev0->rhport; - new_dev->hub_addr = dev0->hub_addr; - new_dev->hub_port = dev0->hub_port; - new_dev->speed = dev0->speed; - new_dev->connected = 1; - new_dev->ep0_packet_size = ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0; - - request = (tusb_control_request_t ) { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, - .bRequest = TUSB_REQ_SET_ADDRESS, - .wValue = new_addr, - .wIndex = 0, - .wLength = 0 - }; - TU_ASSERT(tuh_control_xfer(0, &request, NULL, enum_set_address_complete)); - - //------------- update port info & close control pipe of addr0 -------------// - usbh_device_t* new_dev = &_usbh_devices[new_addr]; - new_dev->rhport = dev0->rhport; - new_dev->hub_addr = dev0->hub_addr; - new_dev->hub_port = dev0->hub_port; - new_dev->speed = dev0->speed; - - hcd_device_close(dev0->rhport, 0); // close device 0 - dev0->state = TUSB_DEVICE_STATE_UNPLUG; - - // open control pipe for new address - TU_ASSERT ( usbh_pipe_control_open(new_addr, ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0 ) ); - - //------------- Get full device descriptor -------------// - TU_LOG2("Get Device Descriptor \r\n"); - request = (tusb_control_request_t ) { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = TUSB_DESC_DEVICE << 8, - .wIndex = 0, - .wLength = 18 - }; - TU_ASSERT(usbh_control_xfer(new_addr, &request, _usbh_ctrl_buf)); - - // update device info TODO alignment issue - tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; - - if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); - - new_dev->vendor_id = desc_device->idVendor; - new_dev->product_id = desc_device->idProduct; - TU_ASSERT(desc_device->bNumConfigurations > 0); - - enum { CONFIG_NUM = 1 }; // default to use configuration 1 - - //------------- Get 9 bytes of configuration descriptor -------------// - TU_LOG2("Get 9 bytes of Configuration Descriptor\r\n"); - request = (tusb_control_request_t ) { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), - .wIndex = 0, - .wLength = 9 - }; - TU_ASSERT( usbh_control_xfer(new_addr, &request, _usbh_ctrl_buf)); - - // TODO not enough buffer to hold configuration descriptor - TU_ASSERT( CFG_TUSB_HOST_ENUM_BUFFER_SIZE >= ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength ); - - //------------- Get full configuration descriptor -------------// - TU_LOG2("Get full Configuration Descriptor\r\n"); - request.wLength = ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength; // full length - TU_ASSERT( usbh_control_xfer( new_addr, &request, _usbh_ctrl_buf ) ); - - // update configuration info - new_dev->interface_count = ((tusb_desc_configuration_t*) _usbh_ctrl_buf)->bNumInterfaces; - - //------------- Set Configure -------------// - TU_LOG2("Set Configuration Descriptor\r\n"); - request = (tusb_control_request_t ) { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, - .bRequest = TUSB_REQ_SET_CONFIGURATION, - .wValue = CONFIG_NUM, - .wIndex = 0, - .wLength = 0 - }; - TU_ASSERT(usbh_control_xfer( new_addr, &request, NULL )); - - TU_LOG2("Device configured\r\n"); - new_dev->state = TUSB_DEVICE_STATE_CONFIGURED; - - //------------- TODO Get String Descriptors -------------// - - // Parse configuration & set up drivers - parse_configuration_descriptor(new_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); - - // Invoke callback if available - if (tuh_mount_cb) tuh_mount_cb(new_addr); -#endif - return true; } @@ -880,7 +757,7 @@ void tuh_task(void) { case HCD_EVENT_DEVICE_ATTACH: TU_LOG2("USBH DEVICE ATTACH\r\n"); - enum_task(&event); + enum_device_attached(&event); break; case HCD_EVENT_DEVICE_REMOVE: -- cgit v1.3.1 From 2b54dcb9f621e52c5fd15a485a6ee423e208b186 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 7 Sep 2020 15:38:54 +0700 Subject: move functions around --- src/host/usbh.c | 583 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 297 insertions(+), 286 deletions(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index d8b3d6535..4932e662c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -128,7 +128,7 @@ static osal_queue_t _usbh_q; CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _usbh_ctrl_buf[CFG_TUSB_HOST_ENUM_BUFFER_SIZE]; //------------- Helper Function Prototypes -------------// -static inline uint8_t get_new_address(void); +static bool enum_new_device(hcd_event_t* event); // from usbh_control.c extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); @@ -370,199 +370,161 @@ static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_ } } -//--------------------------------------------------------------------+ -// ENUMERATION TASK -//--------------------------------------------------------------------+ -static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) +/* USB Host Driver task + * This top level thread manages all host controller event and delegates events to class-specific drivers. + * This should be called periodically within the mainloop or rtos thread. + * + @code + int main(void) + { + application_init(); + tusb_init(); + + while(1) // the mainloop + { + application_code(); + tuh_task(); // tinyusb host task + } + } + @endcode + */ +void tuh_task(void) { - usbh_device_t* dev = &_usbh_devices[dev_addr]; - uint8_t const* p_desc = (uint8_t const*) desc_cfg; - p_desc = tu_desc_next(p_desc); + // Skip if stack is not initialized + if ( !tusb_inited() ) return; - // parse each interfaces - while( p_desc < _usbh_ctrl_buf + desc_cfg->wTotalLength ) + // Loop until there is no more events in the queue + while (1) { - // skip until we see interface descriptor - if ( TUSB_DESC_INTERFACE != tu_desc_type(p_desc) ) - { - p_desc = tu_desc_next(p_desc); // skip the descriptor, increase by the descriptor's length - }else + hcd_event_t event; + if ( !osal_queue_receive(_usbh_q, &event) ) return; + + switch (event.event_id) { - tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; + case HCD_EVENT_DEVICE_ATTACH: + TU_LOG2("USBH DEVICE ATTACH\r\n"); + enum_new_device(&event); + break; - // Check if class is supported - uint8_t drv_id; - for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) - { - if ( usbh_class_drivers[drv_id].class_code == desc_itf->bInterfaceClass ) break; - } + case HCD_EVENT_DEVICE_REMOVE: + TU_LOG2("USBH DEVICE REMOVED\r\n"); + usbh_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port); - if( drv_id >= USBH_CLASS_DRIVER_COUNT ) - { - // skip unsupported class - p_desc = tu_desc_next(p_desc); - } - else + #if CFG_TUH_HUB + // TODO remove + if ( event.connection.hub_addr != 0) + { + // done with hub, waiting for next data on status pipe + (void) hub_status_pipe_queue( event.connection.hub_addr ); + } + #endif + break; + + case HCD_EVENT_XFER_COMPLETE: { - // Interface number must not be used already TODO alternate interface - TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff ); - dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; + usbh_device_t* dev = &_usbh_devices[event.dev_addr]; + uint8_t const ep_addr = event.xfer_complete.ep_addr; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); - if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) + TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + + if ( 0 == epnum ) { - // TODO Attach hub to Hub is not currently supported - // skip this interface - p_desc = tu_desc_next(p_desc); - } - else + usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + }else { - uint16_t itf_len = 0; + uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; + TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); - TU_LOG2("%s open\r\n", usbh_class_drivers[drv_id].name); - TU_ASSERT( usbh_class_drivers[drv_id].open(dev->rhport, dev_addr, desc_itf, &itf_len) ); - TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); - p_desc += itf_len; + TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); + usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); } } + break; + + default: break; } } - - return true; } -static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - TU_LOG2("Device configured\r\n"); - usbh_device_t* dev = &_usbh_devices[dev_addr]; - dev->configured = 1; - dev->state = TUSB_DEVICE_STATE_CONFIGURED; - - // Parse configuration & set up drivers - // TODO driver open still use usbh_control_xfer - parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); - - // Invoke callback if available - if (tuh_mount_cb) tuh_mount_cb(dev_addr); - - return true; -} - -static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +//--------------------------------------------------------------------+ +// INTERNAL HELPER +//--------------------------------------------------------------------+ +static uint8_t get_new_address(void) { - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - TU_LOG2("Set Configuration Descriptor\r\n"); - tusb_control_request_t const new_request = + for (uint8_t addr=1; addr <= CFG_TUSB_HOST_DEVICE_MAX; addr++) { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_OUT - }, - .bRequest = TUSB_REQ_SET_CONFIGURATION, - .wValue = CONFIG_NUM, - .wIndex = 0, - .wLength = 0 - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, enum_set_config_complete) ); - - return true; + if (_usbh_devices[addr].state == TUSB_DEVICE_STATE_UNPLUG) return addr; + } + return CFG_TUSB_HOST_DEVICE_MAX+1; } -static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - // TODO not enough buffer to hold configuration descriptor - tusb_desc_configuration_t const * desc_config = (tusb_desc_configuration_t const*) _usbh_ctrl_buf; - uint16_t total_len; - - // Use offsetof to avoid pointer to the odd/misaligned address - memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); - - TU_ASSERT(total_len <= CFG_TUSB_HOST_ENUM_BUFFER_SIZE); - - //Get full configuration descriptor - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), - .wIndex = 0, - .wLength = total_len - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_config_desc_complete) ); +//--------------------------------------------------------------------+ +// Enumeration Process +// is a lengthy process with a seires of control transfer to configure +// newly attached device. Each step is handled by a function in this +// section +//--------------------------------------------------------------------+ - return true; -} +static bool enum_get_addr0_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_set_address_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_get_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_get_9byte_config_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_get_config_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool enum_set_config_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); -static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool enum_new_device(hcd_event_t* event) { - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - - tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; - usbh_device_t* dev = &_usbh_devices[dev_addr]; - - dev->vendor_id = desc_device->idVendor; - dev->product_id = desc_device->idProduct; - -// if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); + usbh_device_t* dev0 = &_usbh_devices[0]; + dev0->rhport = event->rhport; // TODO refractor integrate to device_pool + dev0->hub_addr = event->connection.hub_addr; + dev0->hub_port = event->connection.hub_port; + dev0->state = TUSB_DEVICE_STATE_UNPLUG; - TU_LOG2("Get 9 bytes of Configuration Descriptor\r\n"); - tusb_control_request_t const new_request = + //------------- connected/disconnected directly with roothub -------------// + if (dev0->hub_addr == 0) { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), - .wIndex = 0, - .wLength = 9 - }; + // wait until device is stable. Increase this if the first 8 bytes is failed to get + osal_task_delay(RESET_DELAY); - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_9byte_config_desc_complete) ); + // device unplugged while delaying + if ( !hcd_port_connect_status(dev0->rhport) ) return true; - return true; -} + dev0->speed = hcd_port_speed_get( dev0->rhport ); + } +#if CFG_TUH_HUB + //------------- connected/disconnected via hub -------------// + else + { + // TODO wait for PORT reset change instead + osal_task_delay(RESET_DELAY); -// After SET_ADDRESS is complete -static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -{ - TU_ASSERT(0 == dev_addr); - TU_ASSERT(XFER_RESULT_SUCCESS == result); + // FIXME hub API use usbh_control_xfer + hub_port_status_response_t port_status; + TU_VERIFY_HDLR( hub_port_get_status(dev0->hub_addr, dev0->hub_port, &port_status), hub_status_pipe_queue( dev0->hub_addr) ); - uint8_t const new_addr = (uint8_t const) request->wValue; + // device unplugged while delaying + if ( !port_status.status.connection ) return true; - usbh_device_t* new_dev = &_usbh_devices[new_addr]; - new_dev->addressed = 1; + dev0->speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : + (port_status.status.low_speed ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; - // TODO close device 0, may not be needed - usbh_device_t* dev0 = &_usbh_devices[0]; - hcd_device_close(dev0->rhport, 0); - dev0->state = TUSB_DEVICE_STATE_UNPLUG; + // Acknowledge Port Reset Change + if (port_status.change.reset) + { + hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE); + } + } +#endif // CFG_TUH_HUB - // open control pipe for new address - TU_ASSERT ( usbh_pipe_control_open(new_addr, new_dev->ep0_packet_size) ); + // TODO probably doesn't need to open/close each enumeration + TU_ASSERT( usbh_pipe_control_open(0, 8) ); - // Get full device descriptor - tusb_control_request_t const new_request = + //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// + TU_LOG2("Get 8 byte of Device Descriptor\r\n"); + tusb_control_request_t const request = { .bmRequestType_bit = { @@ -573,16 +535,15 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c .bRequest = TUSB_REQ_GET_DESCRIPTOR, .wValue = TUSB_DESC_DEVICE << 8, .wIndex = 0, - .wLength = sizeof(tusb_desc_device_t) + .wLength = 8 }; - - TU_ASSERT(tuh_control_xfer(new_addr, &new_request, _usbh_ctrl_buf, enum_get_device_desc_complete)); + TU_ASSERT(tuh_control_xfer(0, &request, _usbh_ctrl_buf, enum_get_addr0_device_desc_complete)); return true; } // After Get Device Descriptor of Address 0 -static bool enum_get_dev0_devic_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { (void) request; TU_ASSERT(0 == dev_addr); @@ -630,82 +591,120 @@ static bool enum_get_dev0_devic_desc_complete(uint8_t dev_addr, tusb_control_req TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices usbh_device_t* new_dev = &_usbh_devices[new_addr]; - new_dev->rhport = dev0->rhport; - new_dev->hub_addr = dev0->hub_addr; - new_dev->hub_port = dev0->hub_port; - new_dev->speed = dev0->speed; - new_dev->connected = 1; - new_dev->ep0_packet_size = ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0; + new_dev->rhport = dev0->rhport; + new_dev->hub_addr = dev0->hub_addr; + new_dev->hub_port = dev0->hub_port; + new_dev->speed = dev0->speed; + new_dev->connected = 1; + new_dev->ep0_packet_size = ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0; + + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_ADDRESS, + .wValue = new_addr, + .wIndex = 0, + .wLength = 0 + }; + + TU_ASSERT(tuh_control_xfer(0, &new_request, NULL, enum_set_address_complete)); + + return true; +} + +// After SET_ADDRESS is complete +static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(0 == dev_addr); + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + uint8_t const new_addr = (uint8_t const) request->wValue; + + usbh_device_t* new_dev = &_usbh_devices[new_addr]; + new_dev->addressed = 1; + + // TODO close device 0, may not be needed + usbh_device_t* dev0 = &_usbh_devices[0]; + hcd_device_close(dev0->rhport, 0); + dev0->state = TUSB_DEVICE_STATE_UNPLUG; + + // open control pipe for new address + TU_ASSERT ( usbh_pipe_control_open(new_addr, new_dev->ep0_packet_size) ); + // Get full device descriptor tusb_control_request_t const new_request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_OUT + .direction = TUSB_DIR_IN }, - .bRequest = TUSB_REQ_SET_ADDRESS, - .wValue = new_addr, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = TUSB_DESC_DEVICE << 8, .wIndex = 0, - .wLength = 0 + .wLength = sizeof(tusb_desc_device_t) }; - TU_ASSERT(tuh_control_xfer(0, &new_request, NULL, enum_set_address_complete)); + TU_ASSERT(tuh_control_xfer(new_addr, &new_request, _usbh_ctrl_buf, enum_get_device_desc_complete)); return true; } -static bool enum_device_attached(hcd_event_t* event) +static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - usbh_device_t* dev0 = &_usbh_devices[0]; - dev0->rhport = event->rhport; // TODO refractor integrate to device_pool - dev0->hub_addr = event->connection.hub_addr; - dev0->hub_port = event->connection.hub_port; - dev0->state = TUSB_DEVICE_STATE_UNPLUG; + (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); - //------------- connected/disconnected directly with roothub -------------// - if (dev0->hub_addr == 0) - { - // wait until device is stable. Increase this if the first 8 bytes is failed to get - osal_task_delay(RESET_DELAY); + tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf; + usbh_device_t* dev = &_usbh_devices[dev_addr]; - // device unplugged while delaying - if ( !hcd_port_connect_status(dev0->rhport) ) return true; + dev->vendor_id = desc_device->idVendor; + dev->product_id = desc_device->idProduct; - dev0->speed = hcd_port_speed_get( dev0->rhport ); - } -#if CFG_TUH_HUB - //------------- connected/disconnected via hub -------------// - else +// if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); + + TU_LOG2("Get 9 bytes of Configuration Descriptor\r\n"); + tusb_control_request_t const new_request = { - // TODO wait for PORT reset change instead - osal_task_delay(RESET_DELAY); + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), + .wIndex = 0, + .wLength = 9 + }; - // FIXME hub API use usbh_control_xfer - hub_port_status_response_t port_status; - TU_VERIFY_HDLR( hub_port_get_status(dev0->hub_addr, dev0->hub_port, &port_status), hub_status_pipe_queue( dev0->hub_addr) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_9byte_config_desc_complete) ); - // device unplugged while delaying - if ( !port_status.status.connection ) return true; + return true; +} - dev0->speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : - (port_status.status.low_speed ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; +static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); - // Acknowledge Port Reset Change - if (port_status.change.reset) - { - hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE); - } - } -#endif // CFG_TUH_HUB + // TODO not enough buffer to hold configuration descriptor + tusb_desc_configuration_t const * desc_config = (tusb_desc_configuration_t const*) _usbh_ctrl_buf; + uint16_t total_len; - // TODO probably doesn't need to open/close each enumeration - TU_ASSERT( usbh_pipe_control_open(0, 8) ); + // Use offsetof to avoid pointer to the odd/misaligned address + memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); - //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// - TU_LOG2("Get 8 byte of Device Descriptor\r\n"); - tusb_control_request_t const request = + TU_ASSERT(total_len <= CFG_TUSB_HOST_ENUM_BUFFER_SIZE); + + //Get full configuration descriptor + tusb_control_request_t const new_request = { .bmRequestType_bit = { @@ -714,104 +713,116 @@ static bool enum_device_attached(hcd_event_t* event) .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = TUSB_DESC_DEVICE << 8, + .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), .wIndex = 0, - .wLength = 8 + .wLength = total_len }; - TU_ASSERT(tuh_control_xfer(0, &request, _usbh_ctrl_buf, enum_get_dev0_devic_desc_complete)); + + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_config_desc_complete) ); return true; } -/* USB Host Driver task - * This top level thread manages all host controller event and delegates events to class-specific drivers. - * This should be called periodically within the mainloop or rtos thread. - *_usbh_devices[dev_addr]. - @code - int main(void) +static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + TU_LOG2("Set Configuration Descriptor\r\n"); + tusb_control_request_t const new_request = + { + .bmRequestType_bit = { - application_init(); - tusb_init(); + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_CONFIGURATION, + .wValue = CONFIG_NUM, + .wIndex = 0, + .wLength = 0 + }; - while(1) // the mainloop - { - application_code(); + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, enum_set_config_complete) ); - tuh_task(); // tinyusb host task - } - } - @endcode - */ -void tuh_task(void) + return true; +} + +static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - // Skip if stack is not initialized - if ( !tusb_inited() ) return; + (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); - // Loop until there is no more events in the queue - while (1) - { - hcd_event_t event; - if ( !osal_queue_receive(_usbh_q, &event) ) return; + TU_LOG2("Device configured\r\n"); + usbh_device_t* dev = &_usbh_devices[dev_addr]; + dev->configured = 1; + dev->state = TUSB_DEVICE_STATE_CONFIGURED; - switch (event.event_id) - { - case HCD_EVENT_DEVICE_ATTACH: - TU_LOG2("USBH DEVICE ATTACH\r\n"); - enum_device_attached(&event); - break; + // Parse configuration & set up drivers + // TODO driver open still use usbh_control_xfer + parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); - case HCD_EVENT_DEVICE_REMOVE: - TU_LOG2("USBH DEVICE REMOVED\r\n"); - usbh_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port); + // Invoke callback if available + if (tuh_mount_cb) tuh_mount_cb(dev_addr); - #if CFG_TUH_HUB - // TODO remove - if ( event.connection.hub_addr != 0) - { - // done with hub, waiting for next data on status pipe - (void) hub_status_pipe_queue( event.connection.hub_addr ); - } - #endif - break; + return true; +} - case HCD_EVENT_XFER_COMPLETE: +static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) +{ + usbh_device_t* dev = &_usbh_devices[dev_addr]; + uint8_t const* p_desc = (uint8_t const*) desc_cfg; + p_desc = tu_desc_next(p_desc); + + // parse each interfaces + while( p_desc < _usbh_ctrl_buf + desc_cfg->wTotalLength ) + { + // skip until we see interface descriptor + if ( TUSB_DESC_INTERFACE != tu_desc_type(p_desc) ) + { + p_desc = tu_desc_next(p_desc); // skip the descriptor, increase by the descriptor's length + }else + { + tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; + + // Check if class is supportedVe + uint8_t drv_id; + for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) { - usbh_device_t* dev = &_usbh_devices[event.dev_addr]; - uint8_t const ep_addr = event.xfer_complete.ep_addr; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const ep_dir = tu_edpt_dir(ep_addr); + if ( usbh_class_drivers[drv_id].class_code == desc_itf->bInterfaceClass ) break; + } - TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + if( drv_id >= USBH_CLASS_DRIVER_COUNT ) + { + // skip unsupported class + p_desc = tu_desc_next(p_desc); + } + else + { + // Interface number must not be used already TODO alternate interface + TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff ); + dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; - if ( 0 == epnum ) + if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) { - usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - }else + // TODO Attach hub to Hub is not currently supported + // skip this interface + p_desc = tu_desc_next(p_desc); + } + else { - uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; - TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); + uint16_t itf_len = 0; - TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); - usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + TU_LOG2("%s open\r\n", usbh_class_drivers[drv_id].name); + TU_ASSERT( usbh_class_drivers[drv_id].open(dev->rhport, dev_addr, desc_itf, &itf_len) ); + TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); + p_desc += itf_len; } } - break; - - default: break; } } -} -//--------------------------------------------------------------------+ -// INTERNAL HELPER -//--------------------------------------------------------------------+ -static inline uint8_t get_new_address(void) -{ - for (uint8_t addr=1; addr <= CFG_TUSB_HOST_DEVICE_MAX; addr++) - { - if (_usbh_devices[addr].state == TUSB_DEVICE_STATE_UNPLUG) return addr; - } - return CFG_TUSB_HOST_DEVICE_MAX+1; + return true; } #endif -- cgit v1.3.1 From 8b9893cadab88fa4abd17d5b9856e0d08ef03796 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Sep 2020 15:48:11 +0700 Subject: introduce optional usbd_edpt_claim, usbd_edpt_release which can be used to gain exclusive access to usbd_edpt_xfer --- src/class/cdc/cdc_device.c | 38 ++++++++++++++++--------- src/device/usbd.c | 71 +++++++++++++++++++++++++++++++++++++++++++++- src/device/usbd_pvt.h | 6 ++++ 3 files changed, 101 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index b4ebfc92e..cd8904042 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -77,8 +77,8 @@ static void _prep_out_transaction (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - // skip if previous transfer not complete - if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_out) ) return; + // claim endpoint + TU_VERIFY( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out), ); // Prepare for incoming data but only allow what we can store in the ring buffer. uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff); @@ -161,17 +161,29 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - // skip if previous transfer not complete yet - TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in), 0 ); + // No data to send + if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0; - uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); - if ( count ) + uint8_t const rhport = TUD_OPT_RHPORT; + + // claim the endpoint first + TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); + + // we can be blocked by another write()/write_flush() from other thread. + // causing us to attempt to transfer on an busy endpoint. + uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); + + if ( count && tud_cdc_n_connected(itf) ) { - TU_VERIFY( tud_cdc_n_connected(itf), 0 ); // fifo is empty if not connected - TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); + TU_ASSERT( usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); + return count; + }else + { + // Release endpoint since we don't make any transfer + // Note: data is dropped if terminal is not connected + usbd_edpt_release(rhport, p_cdc->ep_in); + return 0; } - - return count; } uint32_t tud_cdc_n_write_available (uint8_t itf) @@ -194,7 +206,7 @@ void cdcd_init(void) p_cdc->wanted_char = -1; // default line coding is : stop bit = 1, parity = none, data bits = 8 - p_cdc->line_coding.bit_rate = 115200; + p_cdc->line_coding.bit_rate = 115200; p_cdc->line_coding.stop_bits = 0; p_cdc->line_coding.parity = 0; p_cdc->line_coding.data_bits = 8; @@ -421,10 +433,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if ( 0 == tud_cdc_n_write_flush(itf) ) { - // There is no data left, a ZLP should be sent if + // If there is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero // FIXME CFG_TUD_CDC_EP_BUFSIZE is not Endpoint packet size - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) + if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) { usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 6b91048b6..25d3748e1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -63,9 +63,11 @@ typedef struct { volatile bool busy : 1; volatile bool stalled : 1; + volatile bool claimed : 1; // TODO merge ep2drv here, 4-bit should be sufficient }ep_status[8][2]; + }usbd_device_t; static usbd_device_t _usbd_dev; @@ -237,6 +239,13 @@ static inline usbd_class_driver_t const * get_driver(uint8_t drvid) OSAL_QUEUE_DEF(OPT_MODE_DEVICE, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); static osal_queue_t _usbd_q; +// Mutex for claiming endpoint, only needed when using with preempted RTOS +#if CFG_TUSB_OS != OPT_OS_NONE +static osal_mutex_def_t _ubsd_mutexdef; +static osal_mutex_t _usbd_mutex; +#endif + + //--------------------------------------------------------------------+ // Prototypes //--------------------------------------------------------------------+ @@ -351,9 +360,15 @@ bool tud_init (void) tu_varclr(&_usbd_dev); +#if CFG_TUSB_OS != OPT_OS_NONE + // Init device mutex + _usbd_mutex = osal_mutex_create(&_ubsd_mutexdef); + TU_ASSERT(_usbd_mutex); +#endif + // Init device queue & task _usbd_q = osal_queue_create(&_usbd_qdef); - TU_ASSERT(_usbd_q != NULL); + TU_ASSERT(_usbd_q); // Get application driver if available if ( usbd_app_driver_get_cb ) @@ -478,6 +493,7 @@ void tud_task (void) TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); _usbd_dev.ep_status[epnum][ep_dir].busy = false; + _usbd_dev.ep_status[epnum][ep_dir].claimed = 0; if ( 0 == epnum ) { @@ -1076,6 +1092,56 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) return dcd_edpt_open(rhport, desc_ep); } +bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only claim the endpoint if it is not busy and not claimed yet. + bool ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0); + if (ret) + { + _usbd_dev.ep_status[epnum][dir].claimed = 1; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(_usbd_mutex); +#endif + + return ret; +} + +bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only release the endpoint if it is claimed and not busy + bool ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 1); + if (ret) + { + _usbd_dev.ep_status[epnum][dir].claimed = 0; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(_usbd_mutex); +#endif + + return ret; +} + bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -1083,6 +1149,9 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + // Attempt to transfer on busy or not claimed (skip now) endpoint, sound like an race condition ! + TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0 /*&& _usbd_dev.ep_status[epnum][dir].claimed == 1*/); + // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index a5d223329..5fa9a72a5 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -70,6 +70,12 @@ 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); +// Claim an endpoint before submitting a transfer +bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); + +// Release an endpoint without submitting a transfer +bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr); + // Check if endpoint transferring is complete bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr); -- cgit v1.3.1 From 33f0a18523accfcdebf186f33271dd92f8681b56 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Sep 2020 16:25:31 +0700 Subject: update cdc edpt read --- src/class/cdc/cdc_device.c | 12 +++++------- src/device/usbd.c | 2 ++ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index cd8904042..317355ed7 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -77,15 +77,13 @@ static void _prep_out_transaction (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + // Prepare for incoming data but only allow what we can store in the ring buffer. + uint16_t const available = tu_fifo_remaining(&p_cdc->rx_ff); + TU_VERIFY( available >= sizeof(p_cdc->epout_buf), ); + // claim endpoint TU_VERIFY( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out), ); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff); - if ( max_read >= sizeof(p_cdc->epout_buf) ) - { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); - } + usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); } //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index 25d3748e1..5a7d72124 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1162,7 +1162,9 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; }else { + // DCD error, mark endpoint as ready to allow next transfer _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].claimed = 0; TU_LOG2("failed\r\n"); TU_BREAKPOINT(); return false; -- cgit v1.3.1 From fe1b5dfa235550cc4eb63e237da50689fe407bf4 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Sep 2020 16:29:45 +0700 Subject: clean up --- src/class/cdc/cdc_device.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 317355ed7..8ea44b28d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -164,11 +164,10 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) uint8_t const rhport = TUD_OPT_RHPORT; - // claim the endpoint first - TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); + // Claim the endpoint first + TU_VnERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); - // we can be blocked by another write()/write_flush() from other thread. - // causing us to attempt to transfer on an busy endpoint. + // Pull data from FIFO uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); if ( count && tud_cdc_n_connected(itf) ) -- cgit v1.3.1 From ed6d48b81e8a5d1ed8b518921b30b87c7daecee5 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Sep 2020 16:45:54 +0700 Subject: typo --- src/class/cdc/cdc_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 8ea44b28d..0792e745d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -165,7 +165,7 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) uint8_t const rhport = TUD_OPT_RHPORT; // Claim the endpoint first - TU_VnERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); + TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); // Pull data from FIFO uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); -- cgit v1.3.1 From b15c209805978dc115fe38c72b3f7c235aed42ec Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Thu, 10 Sep 2020 13:36:07 +0200 Subject: Set new define because of build failure --- src/class/cdc/cdc_device.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 145381c42..1d7a64827 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -43,6 +43,10 @@ #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif +#ifndef CFG_TUD_CDC_CLEAR_AT_CONNECTION + #define CFG_TUD_CDC_CLEAR_AT_CONNECTION 0 +#endif + #ifdef __cplusplus extern "C" { #endif -- cgit v1.3.1 From 801f8b5b38b90cb3e15d0a1bb2accae58cde6130 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Sep 2020 23:32:08 +0700 Subject: update claim edpt for hid and midi --- src/class/cdc/cdc_device.c | 41 +++++++++++++++++++++++------------------ src/class/hid/hid_device.c | 13 ++++++++----- src/class/midi/midi_device.c | 27 +++++++++++++++++++++------ src/device/usbd_pvt.h | 3 ++- 4 files changed, 54 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 0792e745d..6c1bf6bb2 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -73,17 +73,17 @@ typedef struct //--------------------------------------------------------------------+ CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; -static void _prep_out_transaction (uint8_t itf) +static void _prep_out_transaction (cdcd_interface_t* p_cdc) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - // Prepare for incoming data but only allow what we can store in the ring buffer. uint16_t const available = tu_fifo_remaining(&p_cdc->rx_ff); TU_VERIFY( available >= sizeof(p_cdc->epout_buf), ); - // claim endpoint - TU_VERIFY( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out), ); - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + // claim endpoint and submit transfer + if ( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out) ) + { + usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + } } //--------------------------------------------------------------------+ @@ -121,8 +121,9 @@ uint32_t tud_cdc_n_available(uint8_t itf) uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) { - uint32_t num_read = tu_fifo_read_n(&_cdcd_itf[itf].rx_ff, buffer, bufsize); - _prep_out_transaction(itf); + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, bufsize); + _prep_out_transaction(p_cdc); return num_read; } @@ -133,8 +134,9 @@ bool tud_cdc_n_peek(uint8_t itf, int pos, uint8_t* chr) void tud_cdc_n_read_flush (uint8_t itf) { - tu_fifo_clear(&_cdcd_itf[itf].rx_ff); - _prep_out_transaction(itf); + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + tu_fifo_clear(&p_cdc->rx_ff); + _prep_out_transaction(p_cdc); } //--------------------------------------------------------------------+ @@ -142,11 +144,12 @@ void tud_cdc_n_read_flush (uint8_t itf) //--------------------------------------------------------------------+ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) { - uint16_t ret = tu_fifo_write_n(&_cdcd_itf[itf].tx_ff, buffer, bufsize); + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, bufsize); #if 0 // TODO issue with circuitpython's REPL // flush if queue more than endpoint size - if ( tu_fifo_count(&_cdcd_itf[itf].tx_ff) >= CFG_TUD_CDC_EP_BUFSIZE ) + if ( tu_fifo_count(&p_cdc->tx_ff) >= CFG_TUD_CDC_EP_BUFSIZE ) { tud_cdc_n_write_flush(itf); } @@ -164,7 +167,7 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) uint8_t const rhport = TUD_OPT_RHPORT; - // Claim the endpoint first + // Claim the endpoint TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); // Pull data from FIFO @@ -242,8 +245,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 // Find available interface cdcd_interface_t * p_cdc = NULL; - uint8_t cdc_id; - for(cdc_id=0; cdc_idrx_ff) ) tud_cdc_rx_cb(itf); // prepare for OUT transaction - _prep_out_transaction(itf); + _prep_out_transaction(p_cdc); } // Data sent to host, we continue to fetch from tx fifo to send. @@ -435,7 +437,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // FIXME CFG_TUD_CDC_EP_BUFSIZE is not Endpoint packet size if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) { - usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); + if ( usbd_edpt_claim(rhport, p_cdc->ep_in) ) + { + usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); + } } } } diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index c46fc591a..10267d734 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -72,18 +72,21 @@ static inline hidd_interface_t* get_interface_by_itfnum(uint8_t itf_num) //--------------------------------------------------------------------+ bool tud_hid_ready(void) { - uint8_t itf = 0; + uint8_t const itf = 0; uint8_t const ep_in = _hidd_itf[itf].ep_in; - return tud_ready() && (ep_in != 0) && usbd_edpt_ready(TUD_OPT_RHPORT, ep_in); + return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) { - TU_VERIFY( tud_hid_ready() ); - - uint8_t itf = 0; + uint8_t const rhport = 0; + uint8_t const itf = 0; hidd_interface_t * p_hid = &_hidd_itf[itf]; + // claim endpoint + TU_VERIFY( usbd_edpt_claim(rhport, p_hid->ep_in) ); + + // prepare data if (report_id) { len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE-1); diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 376b3670a..00b1bde92 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -153,15 +153,25 @@ void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bu static uint32_t write_flush(midid_interface_t* midi) { + // No data to send + if ( !tu_fifo_count(&midi->tx_ff) ) return 0; + + uint8_t const rhport = TUD_OPT_RHPORT; + // skip if previous transfer not complete - TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, midi->ep_in) ); + TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 ); uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); if (count > 0) { - TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, midi->ep_in, midi->epin_buf, count) ); + TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, midi->epin_buf, count), 0 ); + return count; + }else + { + // Release endpoint since we don't make any transfer + usbd_edpt_release(rhport, midi->ep_in); + return 0; } - return count; } uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize) @@ -405,17 +415,22 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 if (tud_midi_rx_cb) tud_midi_rx_cb(itf); // prepare for next + // TODO for now ep_out is not used by public API therefore there is no race condition, + // and does not need to claim like ep_in TU_ASSERT(usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE), false); } else if ( ep_addr == p_midi->ep_in ) { if (0 == write_flush(p_midi)) { - // There is no data left, a ZLP should be sent if + // If there is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero - if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) ) + if ( !tu_fifo_count(&p_midi->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE)) ) { - usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); + if ( usbd_edpt_claim(rhport, p_midi->ep_in) ) + { + usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); + } } } } diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 5fa9a72a5..09b285581 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -70,7 +70,8 @@ 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); -// Claim an endpoint before submitting a transfer +// Claim an endpoint before submitting a transfer. +// If caller does not make any transfer, it must release endpoint for others. bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); // Release an endpoint without submitting a transfer -- cgit v1.3.1 From ce4a9b9c3ad15a8a714959c89c7a39ba67970cfd Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Sep 2020 00:14:07 +0700 Subject: clean up --- src/device/usbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 5a7d72124..8fc0092eb 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1149,8 +1149,8 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); - // Attempt to transfer on busy or not claimed (skip now) endpoint, sound like an race condition ! - TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0 /*&& _usbd_dev.ep_status[epnum][dir].claimed == 1*/); + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return // and usbd task can preempt and clear the busy -- cgit v1.3.1 From 1804dba615653591a754c9221028c94a32e50495 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 12 Sep 2020 08:48:49 +0700 Subject: typo --- src/class/cdc/cdc_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 145381c42..3c679c48e 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -92,7 +92,7 @@ uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bu static inline uint32_t tud_cdc_n_write_char (uint8_t itf, char ch); -// Write a nul-terminated string +// Write a null-terminated string static inline uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str); -- cgit v1.3.1 From 5931d19666667e9a5b2b99082fb24392e3983399 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 13 Sep 2020 15:01:20 +0700 Subject: correct the TUD_HID_REPORT_DESC_GAMEPAD --- src/class/hid/hid_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index f7ad38bab..1e584e4c9 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -264,7 +264,7 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); HID_LOGICAL_MAX ( 1 ) ,\ HID_REPORT_COUNT ( 16 ) ,\ HID_REPORT_SIZE ( 1 ) ,\ - HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ /* X, Y, Z, Rz (min -127, max 127 ) */ \ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ HID_LOGICAL_MIN ( 0x81 ) ,\ -- cgit v1.3.1 From 3b0216d3bfe568e949fe1ea7c2c9f3f3a8dc6a4b Mon Sep 17 00:00:00 2001 From: Mark Lentczner Date: Sun, 13 Sep 2020 15:05:18 -0700 Subject: Update midi_device.c Fix a bug in writing SysEx messages. At the start of a new USB packet (4 bytes), while in the middle of a SysEx, the code mistakenly set the buffer length to 4, not the target length. As a consequence, the 3rd and 4th bytes from the last packet were included, after every byte of the SysEx after the first packet of three. The fix is simple, as it was just a typo, as can bee seen from the other branches in the same section of if/else statements: At the start of a new packet, the code should set up the target length... the buffer length should be left at 2 (as set on line 180). --- src/class/midi/midi_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 376b3670a..1a0bbd170 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -183,7 +183,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u if (data == 0xf7) { midi->write_buffer[0] = 0x5; } else { - midi->write_buffer_length = 4; + midi->write_target_length = 4; } } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { midi->write_buffer[0] = jack_id << 4 | msg; -- cgit v1.3.1 From 23e6ee2ea2e69f09b43c9f7736b95560a6e9ef7b Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 14 Sep 2020 22:14:31 +0700 Subject: cdc device: claim endpoint before checking fifo availability - add pre-check to reduce mutex lock in usbd_edpt_claim --- src/class/cdc/cdc_device.c | 23 ++++++++++++++++++----- src/device/usbd.c | 5 ++++- 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 6c1bf6bb2..e39adc5fa 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -75,14 +75,27 @@ CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; static void _prep_out_transaction (cdcd_interface_t* p_cdc) { + uint8_t const rhport = TUD_OPT_RHPORT; + uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); + // Prepare for incoming data but only allow what we can store in the ring buffer. - uint16_t const available = tu_fifo_remaining(&p_cdc->rx_ff); - TU_VERIFY( available >= sizeof(p_cdc->epout_buf), ); + // TODO Actually we can still carry out the transfer, keeping count of received bytes + // and slowly move it to the FIFO when read(). + // This pre-check reduces endpoint claiming + TU_VERIFY(available >= sizeof(p_cdc->epout_buf), ); + + // claim endpoint + TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out), ); - // claim endpoint and submit transfer - if ( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out) ) + // fifo can be changed before endpoint is claimed + available = tu_fifo_remaining(&p_cdc->rx_ff); + + if ( available >= sizeof(p_cdc->epout_buf) ) { + usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + }else { - usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + // Release endpoint since we don't make any transfer + usbd_edpt_release(rhport, p_cdc->ep_out); } } diff --git a/src/device/usbd.c b/src/device/usbd.c index 8fc0092eb..dfe30578e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1100,11 +1100,14 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) uint8_t const dir = tu_edpt_dir(ep_addr); #if CFG_TUSB_OS != OPT_OS_NONE + // pre-check to help reducing mutex lock + TU_VERIFY((_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0)); + osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); #endif // can only claim the endpoint if it is not busy and not claimed yet. - bool ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0); + bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0); if (ret) { _usbd_dev.ep_status[epnum][dir].claimed = 1; -- cgit v1.3.1 From 9c0d15fc43818282b6a92432e675dd214e51735e Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 14 Sep 2020 22:23:59 +0700 Subject: more const --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index dfe30578e..d1e984a0e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1132,7 +1132,7 @@ bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) #endif // can only release the endpoint if it is claimed and not busy - bool ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 1); + bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 1); if (ret) { _usbd_dev.ep_status[epnum][dir].claimed = 0; -- cgit v1.3.1 From 349c0f640e7d4532cc96fd28dea2dd11a5d43bde Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 14 Sep 2020 18:24:08 +0200 Subject: Implementation done, yet to be tested. --- src/common/tusb_fifo.c | 409 +++++++++++++++++++++++++++++++++++++++---------- src/common/tusb_fifo.h | 71 ++++----- 2 files changed, 356 insertions(+), 124 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 6ab158cca..4e274003b 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2020 Reinhard Panhuber * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -64,51 +65,288 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si f->item_size = item_size; f->overwritable = overwritable; - f->rd_idx = f->wr_idx = f->count = 0; + f->non_used_index_space = ((2^16)-1) % depth; + f->max_pointer_idx = ((2^16)-1) - f->non_used_index_space; + + f->rd_idx = f->wr_idx = 0; tu_fifo_unlock(f); return true; } +// TODO: To be changed!! static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) { return (idx < depth) ? idx : (idx-depth); } -// retrieve data from fifo -static inline void _ff_pull(tu_fifo_t* f, void * buffer, uint16_t n) +// send one item to FIFO WITHOUT updating write pointer +static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRel) +{ + memcpy(f->buffer + (wRel * f->item_size), data, n*f->item_size); +} + +// send n items to FIFO WITHOUT updating write pointer +static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRel) { - memcpy(buffer, - f->buffer + (f->rd_idx * f->item_size), - f->item_size*n); + if(wRel + n <= f->depth) // Linear mode only + { + memcpy(f->buffer + (wRel * f->item_size), data, n*f->item_size); + } + else // Wrap around + { + uint16_t nLin = f->depth - wRel; + + // Write data to linear part of buffer + memcpy(f->buffer + (wRel * f->item_size), data, nLin*f->item_size); + + // Write data wrapped around + memcpy(f->buffer, data + nLin*f->item_size, (n - nLin) * f->item_size); + } +} - f->rd_idx = _ff_mod(f->rd_idx + n, f->depth); - f->count -= n; +// get one item from FIFO WITHOUT updating write pointer +static inline void _ff_pull(tu_fifo_t* f, void const * p_buffer, uint16_t rRel) +{ + memcpy(p_buffer, f->buffer + (rRel * f->item_size), f->item_size); } -// send data to fifo -static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t n) +// get n items from FIFO WITHOUT updating write pointer +static void _ff_pull_n(tu_fifo_t* f, void const * p_buffer, uint16_t n, uint16_t rRel) { - memcpy(f->buffer + (f->wr_idx * f->item_size), - data, - f->item_size*n); + if(rRel + n <= f->depth) // Linear mode only + { + memcpy(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); + } + else // Wrap around + { + uint16_t nLin = f->depth - rRel; - f->wr_idx = _ff_mod(f->wr_idx + n, f->depth); + // Read data from linear part of buffer + memcpy(p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size); - if (tu_fifo_full(f)) + // Read data wrapped part + memcpy(p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size); + } +} + +// Advance an absolute pointer +static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t pos) +{ + // We limit the index space of p such that a correct wrap around happens + // Check for a wrap around or if we are in unused index space - This has to be checked first!! We are exploiting the wrap around to the correct index + if ((p > p + pos) || (p + pos >= f->max_pointer_idx)) { - f->rd_idx = f->wr_idx; // keep the full state (rd == wr && count = depth) + p = (p + pos) + f->non_used_index_space; } else { - f->count += n; + p += pos; + } + return p; +} + +// get relative from absolute pointer +static uint16_t get_relative_pointer(tu_fifo_t* f, uint16_t p, uint16_t pos) +{ + return _ff_mod(advance_pointer(f, p, pos), f->depth); +} + +// Works on local copies of w and r +static uint16_t _tu_fifo_count(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) +{ + uint16_t cnt = wAbs-rAbs; + + // In case we have non-power of two depth we need a further modification + if (rAbs > wAbs) cnt -= f->non_used_index_space; + + return cnt; +} + +// Works on local copies of w and r +static inline bool _tu_fifo_empty(uint16_t wAbs, uint16_t rAbs) +{ + return wAbs == rAbs; +} + +// Works on local copies of w and r +static inline bool _tu_fifo_full(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) +{ + return (_tu_fifo_count(f, wAbs, rAbs) == f->depth); +} + +// Works on local copies of w and r +// BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" +// EXAMPLE with buffer depth: 100 +// Maximum index space: (2^16)-1) - ((2^16)-1) % depth = 65500 +// If you produce 65500 / 100 = 655 buffer overflows, the write pointer will overflow as well and +// the check _tu_fifo_overflow() will not give you a valid result! Avoid such nasty things! +// Use _tu_fifo_correct_read_pointer() if overflow happened to set read pointer to correct index +// for reading latest items! +static inline bool _tu_fifo_overflow(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) +{ + return (_tu_fifo_count(f, wAbs, rAbs) > f->depth); +} + +// Works on local copies of w +// For more details see _tu_fifo_overflow()! +static inline void _tu_fifo_correct_read_pointer(tu_fifo_t* f, uint16_t wAbs) +{ + tu_fifo_lock(f); + f->rd_idx = advance_pointer(f, f->wr_idx, 1); + tu_fifo_unlock(f); +} + +// Works on local copies of w and r +static bool _tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t wAbs, uint16_t rAbs) +{ + uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); + + // Skip beginning of buffer + if (cnt == 0 || pos >= cnt) return false; + + uint16_t rRel = get_relative_pointer(f, rAbs, pos); + + // Peek data + _ff_pull(f, p_buffer, rRel); + + return true; +} + +// Works on local copies of w and r +static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs) +{ + uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); + + // Skip beginning of buffer + if (cnt == 0 || pos >= cnt) return 0; + + // Check if we can read something at and after pos - if too less is available we read what remains + cnt -= pos; + if (cnt < n) { + if (cnt == 0) return 0; + n = cnt; } + + uint16_t rRel = get_relative_pointer(f, rAbs, pos); + + // Peek data + _ff_pull_n(f, p_buffer, n, rRel); + + return n; +} + +// Works on local copies of w and r +static inline uint16_t _tu_fifo_remaining(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) +{ + return f->depth - _tu_fifo_count(f, wAbs, rAbs); } /******************************************************************************/ /*! - @brief Read one element out of the RX buffer. + @brief Get number of items in FIFO. + + As this function only reads the read and write pointers once, this function is + reentrant and thus thread and ISR save without any mutexes. + + @param[in] f + Pointer to the FIFO buffer to manipulate + + @returns Number of items in FIFO + */ +/******************************************************************************/ +uint16_t tu_fifo_count(tu_fifo_t* f) +{ + return _tu_fifo_count(f, f->wr_idx, f->rd_idx); +} + +/******************************************************************************/ +/*! + @brief Check if FIFO is empty. + + As this function only reads the read and write pointers once, this function is + reentrant and thus thread and ISR save without any mutexes. + + @param[in] f + Pointer to the FIFO buffer to manipulate + + @returns Number of items in FIFO + */ +/******************************************************************************/ +bool tu_fifo_empty(tu_fifo_t* f) +{ + return _tu_fifo_empty(f->wr_idx, f->rd_idx); +} + +/******************************************************************************/ +/*! + @brief Check if FIFO is full. + + As this function only reads the read and write pointers once, this function is + reentrant and thus thread and ISR save without any mutexes. + + @param[in] f + Pointer to the FIFO buffer to manipulate + + @returns Number of items in FIFO + */ +/******************************************************************************/ +bool tu_fifo_full(tu_fifo_t* f) +{ + return _tu_fifo_full(f, f->wr_idx, f->rd_idx); +} + +/******************************************************************************/ +/*! + @brief Get remaining space in FIFO. + + As this function only reads the read and write pointers once, this function is + reentrant and thus thread and ISR save without any mutexes. + + @param[in] f + Pointer to the FIFO buffer to manipulate + + @returns Number of items in FIFO + */ +/******************************************************************************/ +uint16_t tu_fifo_remaining(tu_fifo_t* f) +{ + return _tu_fifo_remaining(f, f->wr_idx, f->rd_idx); +} + +/******************************************************************************/ +/*! + @brief Check if overflow happened. + + BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" + EXAMPLE with buffer depth: 100 + Maximum index space: (2^16)-1) - ((2^16)-1) % depth = 65500 + If you produce 65500 / 100 = 655 buffer overflows, the write pointer will overflow as well and + the check _tu_fifo_overflow() will not give you a valid result! Avoid such nasty things! + Use tu_fifo_correct_read_pointer() if overflow happened to set read pointer to correct index + for reading latest items! + + @param[in] f + Pointer to the FIFO buffer to manipulate + + @returns True if overflow happened + */ +/******************************************************************************/ +bool tu_fifo_overflow(tu_fifo_t* f) +{ + return _tu_fifo_overflow(f, f->wr_idx, f->rd_idx); +} + +// Only use in case tu_fifo_overflow() returned true! +void tu_fifo_correct_read_pointer(tu_fifo_t* f) +{ + _tu_fifo_correct_read_pointer(f, f->wr_idx); +} + +/******************************************************************************/ +/*! + @brief Read one element out of the buffer. This function will return the element located at the array index of the read pointer, and then increment the read pointer index. If the read @@ -120,19 +358,22 @@ static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t n) Pointer to the place holder for data read from the buffer @returns TRUE if the queue is not empty -*/ + */ /******************************************************************************/ bool tu_fifo_read(tu_fifo_t* f, void * buffer) { - if( tu_fifo_empty(f) ) return false; + tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! - tu_fifo_lock(f); + uint16_t r = f->rd_idx; - _ff_pull(f, buffer, 1); + // Peek the data + bool ret = _tu_fifo_peek_at(f, 0, buffer, f->wr_idx, r); - tu_fifo_unlock(f); + // Advance pointer + f->rd_idx = advance_pointer(f, r, ret); - return true; + tu_fifo_unlock(f); + return ret; } /******************************************************************************/ @@ -149,35 +390,21 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) Number of element that buffer can afford @returns number of items read from the FIFO -*/ + */ /******************************************************************************/ -uint16_t tu_fifo_read_n (tu_fifo_t* f, void * buffer, uint16_t count) +uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t count) { - if(tu_fifo_empty(f)) return 0; + tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! - tu_fifo_lock(f); + uint16_t r = f->rd_idx; - // Limit up to fifo's count - if(count > f->count) count = f->count; + // Peek the data + count = _tu_fifo_peek_at_n(f, 0, buffer, count, f->wr_idx, r); - if(count + f->rd_idx <= f->depth) - { - _ff_pull(f, buffer, count); - } - else - { - uint16_t const part1 = f->depth - f->rd_idx; - - // Part 1: from rd_idx to end - _ff_pull(f, buffer, part1); - buffer = ((uint8_t*) buffer) + part1*f->item_size; - - // Part 2: start to remaining - _ff_pull(f, buffer, count-part1); - } + // Advance read pointer + f->rd_idx = advance_pointer(f, r, count); tu_fifo_unlock(f); - return count; } @@ -193,28 +420,37 @@ uint16_t tu_fifo_read_n (tu_fifo_t* f, void * buffer, uint16_t count) Pointer to the place holder for data read from the buffer @returns TRUE if the queue is not empty -*/ + */ /******************************************************************************/ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer) { - if ( pos >= f->count ) return false; - - tu_fifo_lock(f); + return _tu_fifo_peek_at(f, pos, p_buffer, f->wr_idx, f->rd_idx); +} - // rd_idx is pos=0 - uint16_t index = _ff_mod(f->rd_idx + pos, f->depth); - memcpy(p_buffer, - f->buffer + (index * f->item_size), - f->item_size); +/******************************************************************************/ +/*! + @brief Read n items without removing it from the FIFO - tu_fifo_unlock(f); + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] pos + Position to read from in the FIFO buffer + @param[in] p_buffer + Pointer to the place holder for data read from the buffer + @param[in] n + Number of items to peek - return true; + @returns Number of bytes written to p_buffer + */ +/******************************************************************************/ +uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n) +{ + return _tu_fifo_peek_at_n(f, pos, p_buffer, n, f->wr_idx, f->rd_idx); } /******************************************************************************/ /*! - @brief Write one element into the RX buffer. + @brief Write one element into the buffer. This function will write one element into the array index specified by the write pointer and increment the write index. If the write index @@ -227,15 +463,23 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer) @returns TRUE if the data was written to the FIFO (overwrittable FIFO will always return TRUE) -*/ + */ /******************************************************************************/ -bool tu_fifo_write (tu_fifo_t* f, const void * data) +bool tu_fifo_write(tu_fifo_t* f, const void * data) { - if ( tu_fifo_full(f) && !f->overwritable ) return false; - tu_fifo_lock(f); - _ff_push(f, data, 1); + uint16_t w = f->wr_idx; + + if ( _tu_fifo_full(f, w, f->rd_idx) && !f->overwritable ) return false; + + uint16_t wRel = get_relative_pointer(f, w, 0); + + // Write data + _ff_push(f, data, wRel); + + // Advance pointer + f->wr_idx = advance_pointer(f, w, 1); tu_fifo_unlock(f); @@ -255,47 +499,42 @@ bool tu_fifo_write (tu_fifo_t* f, const void * data) @param[in] count Number of element @return Number of written elements -*/ + */ /******************************************************************************/ -uint16_t tu_fifo_write_n (tu_fifo_t* f, const void * data, uint16_t count) +uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t count) { if ( count == 0 ) return 0; tu_fifo_lock(f); + uint16_t w = f->wr_idx, r = f->rd_idx; uint8_t const* buf8 = (uint8_t const*) data; if (!f->overwritable) { // Not overwritable limit up to full - count = tu_min16(count, tu_fifo_remaining(f)); + count = tu_min16(count, _tu_fifo_remaining(f, w, r)); } else if (count > f->depth) { // Only copy last part buf8 = buf8 + (count - f->depth) * f->item_size; count = f->depth; - f->wr_idx = 0; - f->rd_idx = 0; - f->count = 0; - } - if (count + f->wr_idx <= f->depth ) - { - _ff_push(f, buf8, count); + // We start writing at the read pointer's position since we fill the complete + // buffer and we do not want to modify the read pointer within a write function! + // This would end up in a race condition with read functions! + f->wr_idx = r; } - else - { - uint16_t const part1 = f->depth - f->wr_idx; - // Part 1: from wr_idx to end - _ff_push(f, buf8, part1); - buf8 += part1*f->item_size; + uint16_t wRel = get_relative_pointer(f, w, 0); + + // Write data + _ff_push_n(f, buf8, count, wRel); + + // Advance pointer + f->wr_idx = advance_pointer(f, w, count); - // Part 2: start to remaining - _ff_push(f, buf8, count-part1); - } - tu_fifo_unlock(f); return count; @@ -307,13 +546,13 @@ uint16_t tu_fifo_write_n (tu_fifo_t* f, const void * data, uint16_t count) @param[in] f Pointer to the FIFO buffer to manipulate -*/ + */ /******************************************************************************/ bool tu_fifo_clear(tu_fifo_t *f) { tu_fifo_lock(f); - f->rd_idx = f->wr_idx = f->count = 0; + f->rd_idx = f->wr_idx = 0; tu_fifo_unlock(f); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index fb0c896f3..56491c37b 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -52,14 +52,16 @@ */ typedef struct { - uint8_t* buffer ; ///< buffer pointer - uint16_t depth ; ///< max items - uint16_t item_size ; ///< size of each item - bool overwritable ; + uint8_t* buffer ; ///< buffer pointer + uint16_t depth ; ///< max items + uint16_t item_size ; ///< size of each item + bool overwritable ; - volatile uint16_t count ; ///< number of items in queue - volatile uint16_t wr_idx ; ///< write pointer - volatile uint16_t rd_idx ; ///< read pointer + uint16_t non_used_index_space ; ///< required for non-power-of-two buffer length + uint16_t max_pointer_idx ; ///< maximum absolute pointer index + + volatile uint16_t wr_idx ; ///< write pointer + volatile uint16_t rd_idx ; ///< read pointer #if CFG_FIFO_MUTEX tu_fifo_mutex_t mutex; @@ -67,13 +69,15 @@ typedef struct } tu_fifo_t; -#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - tu_fifo_t _name = { \ - .buffer = _name##_buf, \ - .depth = _depth, \ - .item_size = sizeof(_type), \ - .overwritable = _overwritable, \ +#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ + uint8_t _name##_buf[_depth*sizeof(_type)]; \ + tu_fifo_t _name = { \ + .buffer = _name##_buf, \ + .depth = _depth, \ + .item_size = sizeof(_type), \ + .overwritable = _overwritable, \ + .non_used_index_space = (2^16-1) % _depth, \ + .max_pointer_idx = (2^16-1) - ((2^16-1) % _depth), \ } bool tu_fifo_clear(tu_fifo_t *f); @@ -86,39 +90,28 @@ static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t mutex_hdl) } #endif -bool tu_fifo_write (tu_fifo_t* f, void const * p_data); -uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t count); +bool tu_fifo_write (tu_fifo_t* f, void const * p_data); +uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t count); + +bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); +uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count); -bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); -uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count); +bool tu_fifo_peek_at (tu_fifo_t* f, uint16_t pos, void * p_buffer); +uint16_t tu_fifo_peek_at_n (tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n); -bool tu_fifo_peek_at (tu_fifo_t* f, uint16_t pos, void * p_buffer); +uint16_t tu_fifo_count (tu_fifo_t* f); +void tu_fifo_correct_read_pointer (tu_fifo_t* f); +bool tu_fifo_empty (tu_fifo_t* f); +bool tu_fifo_full (tu_fifo_t* f); +uint16_t tu_fifo_remaining (tu_fifo_t* f); +bool tu_fifo_overflow (tu_fifo_t* f); +void tu_fifo_correct_read_pointer (tu_fifo_t* f); static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { return tu_fifo_peek_at(f, 0, p_buffer); } -static inline bool tu_fifo_empty(tu_fifo_t* f) -{ - return (f->count == 0); -} - -static inline bool tu_fifo_full(tu_fifo_t* f) -{ - return (f->count == f->depth); -} - -static inline uint16_t tu_fifo_count(tu_fifo_t* f) -{ - return f->count; -} - -static inline uint16_t tu_fifo_remaining(tu_fifo_t* f) -{ - return f->depth - f->count; -} - static inline uint16_t tu_fifo_depth(tu_fifo_t* f) { return f->depth; -- cgit v1.3.1 From 62a76c0e049998c6fda2f349503bee2fafd12bad Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 15 Sep 2020 16:08:23 +0200 Subject: nrf52: Fix edpt_dma_start() wrong condition check Operator < used in while condition was obviously incorrect. Loop starts with checking if unsigned variable is less then 0. This condition is always false. This reverses condition to follow intention of of the code. --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index cd35f2e5b..60da9fb25 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -122,7 +122,7 @@ static void edpt_dma_start(volatile uint32_t* reg_startep) // for the DMA complete by comparing current pending DMA with number of ENDED Events uint32_t ended = 0; - while ( _dcd.dma_pending < ((uint8_t) ended) ) + while ( _dcd.dma_pending > ((uint8_t) ended) ) { ended = NRF_USBD->EVENTS_ENDISOIN + NRF_USBD->EVENTS_ENDISOOUT; -- cgit v1.3.1 From 9dfb78e9d82d0386de555aa291242ddfe835cd18 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 15 Sep 2020 20:40:41 +0200 Subject: Tested, working. --- src/common/tusb_fifo.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 4e274003b..e7a2b469f 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -65,8 +65,8 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si f->item_size = item_size; f->overwritable = overwritable; - f->non_used_index_space = ((2^16)-1) % depth; - f->max_pointer_idx = ((2^16)-1) - f->non_used_index_space; + f->non_used_index_space = 0x10000 % depth; + f->max_pointer_idx = 0xFFFF - f->non_used_index_space; f->rd_idx = f->wr_idx = 0; @@ -78,13 +78,14 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si // TODO: To be changed!! static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) { - return (idx < depth) ? idx : (idx-depth); +// return (idx < depth) ? idx : (idx-depth); + return idx % depth; } // send one item to FIFO WITHOUT updating write pointer -static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRel) +static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t wRel) { - memcpy(f->buffer + (wRel * f->item_size), data, n*f->item_size); + memcpy(f->buffer + (wRel * f->item_size), data, f->item_size); } // send n items to FIFO WITHOUT updating write pointer @@ -107,13 +108,13 @@ static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRe } // get one item from FIFO WITHOUT updating write pointer -static inline void _ff_pull(tu_fifo_t* f, void const * p_buffer, uint16_t rRel) +static inline void _ff_pull(tu_fifo_t* f, void * p_buffer, uint16_t rRel) { memcpy(p_buffer, f->buffer + (rRel * f->item_size), f->item_size); } // get n items from FIFO WITHOUT updating write pointer -static void _ff_pull_n(tu_fifo_t* f, void const * p_buffer, uint16_t n, uint16_t rRel) +static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel) { if(rRel + n <= f->depth) // Linear mode only { @@ -136,7 +137,7 @@ static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t pos) { // We limit the index space of p such that a correct wrap around happens // Check for a wrap around or if we are in unused index space - This has to be checked first!! We are exploiting the wrap around to the correct index - if ((p > p + pos) || (p + pos >= f->max_pointer_idx)) + if ((p > p + pos) || (p + pos > f->max_pointer_idx)) { p = (p + pos) + f->non_used_index_space; } -- cgit v1.3.1 From 21299f90faf501422706ce36b6d3bb7c55bb3ecb Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 19 Sep 2020 11:46:43 +0200 Subject: Final cleanup. --- src/common/tusb_fifo.c | 148 ++++++++++++++++++++++++++++++++++++++----------- src/common/tusb_fifo.h | 19 ++++++- 2 files changed, 131 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index e7a2b469f..b83dfee4e 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -2,7 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Copyright (c) 2020 Reinhard Panhuber + * Copyright (c) 2020 Reinhard Panhuber - rework to unmasked pointers * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -75,10 +75,10 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si return true; } -// TODO: To be changed!! +// Static functions are intended to work on local variables + static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) { -// return (idx < depth) ? idx : (idx-depth); return idx % depth; } @@ -148,6 +148,22 @@ static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t pos) return p; } +// Backward an absolute pointer +static uint16_t backward_pointer(tu_fifo_t* f, uint16_t p, uint16_t pos) +{ + // We limit the index space of p such that a correct wrap around happens + // Check for a wrap around or if we are in unused index space - This has to be checked first!! We are exploiting the wrap around to the correct index + if ((p < p - pos) || (p - pos > f->max_pointer_idx)) + { + p = (p - pos) - f->non_used_index_space; + } + else + { + p -= pos; + } + return p; +} + // get relative from absolute pointer static uint16_t get_relative_pointer(tu_fifo_t* f, uint16_t p, uint16_t pos) { @@ -178,13 +194,15 @@ static inline bool _tu_fifo_full(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) } // Works on local copies of w and r -// BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" -// EXAMPLE with buffer depth: 100 -// Maximum index space: (2^16)-1) - ((2^16)-1) % depth = 65500 -// If you produce 65500 / 100 = 655 buffer overflows, the write pointer will overflow as well and -// the check _tu_fifo_overflow() will not give you a valid result! Avoid such nasty things! -// Use _tu_fifo_correct_read_pointer() if overflow happened to set read pointer to correct index -// for reading latest items! +//BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" +//EXAMPLE with buffer depth: 100 +//Maximum index space: (2^16) - (2^16) % depth = 65500 +//If you produce 65500 / 100 + 1 = 656 buffer overflows, the write pointer will overflow as well and +//the check _tu_fifo_overflow() will not give you a valid result! Avoid such nasty things! +//All reading functions (read, peek) check for overflows and correct read pointer on their own such +//that latest items are read. +//If required (e.g. for DMA use) you can also correct the read pointer by +//tu_fifo_correct_read_pointer(). static inline bool _tu_fifo_overflow(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) { return (_tu_fifo_count(f, wAbs, rAbs) > f->depth); @@ -194,16 +212,22 @@ static inline bool _tu_fifo_overflow(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) // For more details see _tu_fifo_overflow()! static inline void _tu_fifo_correct_read_pointer(tu_fifo_t* f, uint16_t wAbs) { - tu_fifo_lock(f); - f->rd_idx = advance_pointer(f, f->wr_idx, 1); - tu_fifo_unlock(f); + f->rd_idx = backward_pointer(f, wAbs, f->depth); } // Works on local copies of w and r +// Must be protected by mutexes since in case of an overflow read pointer gets modified static bool _tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t wAbs, uint16_t rAbs) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); + // Check overflow and correct if required + if (cnt > f->depth) + { + _tu_fifo_correct_read_pointer(f, wAbs); + cnt = f->depth; + } + // Skip beginning of buffer if (cnt == 0 || pos >= cnt) return false; @@ -216,10 +240,18 @@ static bool _tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16 } // Works on local copies of w and r +// Must be protected by mutexes since in case of an overflow read pointer gets modified static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); + // Check overflow and correct if required + if (cnt > f->depth) + { + _tu_fifo_correct_read_pointer(f, wAbs); + cnt = f->depth; + } + // Skip beginning of buffer if (cnt == 0 || pos >= cnt) return 0; @@ -322,11 +354,13 @@ uint16_t tu_fifo_remaining(tu_fifo_t* f) BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" EXAMPLE with buffer depth: 100 - Maximum index space: (2^16)-1) - ((2^16)-1) % depth = 65500 - If you produce 65500 / 100 = 655 buffer overflows, the write pointer will overflow as well and + Maximum index space: (2^16) - (2^16) % depth = 65500 + If you produce 65500 / 100 + 1 = 656 buffer overflows, the write pointer will overflow as well and the check _tu_fifo_overflow() will not give you a valid result! Avoid such nasty things! - Use tu_fifo_correct_read_pointer() if overflow happened to set read pointer to correct index - for reading latest items! + All reading functions (read, peek) check for overflows and correct read pointer on their own such + that latest items are read. + If required (e.g. for DMA use) you can also correct the read pointer by + tu_fifo_correct_read_pointer(). @param[in] f Pointer to the FIFO buffer to manipulate @@ -342,7 +376,9 @@ bool tu_fifo_overflow(tu_fifo_t* f) // Only use in case tu_fifo_overflow() returned true! void tu_fifo_correct_read_pointer(tu_fifo_t* f) { + tu_fifo_lock(f); _tu_fifo_correct_read_pointer(f, f->wr_idx); + tu_fifo_unlock(f); } /******************************************************************************/ @@ -350,8 +386,8 @@ void tu_fifo_correct_read_pointer(tu_fifo_t* f) @brief Read one element out of the buffer. This function will return the element located at the array index of the - read pointer, and then increment the read pointer index. If the read - pointer exceeds the maximum buffer size, it will roll over to zero. + read pointer, and then increment the read pointer index. + This function checks for an overflow and corrects read pointer if required. @param[in] f Pointer to the FIFO buffer to manipulate @@ -380,8 +416,8 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) /******************************************************************************/ /*! @brief This function will read n elements from the array index specified by - the read pointer and increment the read index. If the read index - exceeds the max buffer size, then it will roll over to zero. + the read pointer and increment the read index. + This function checks for an overflow and corrects read pointer if required. @param[in] f Pointer to the FIFO buffer to manipulate @@ -411,12 +447,13 @@ uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t count) /******************************************************************************/ /*! - @brief Read one item without removing it from the FIFO + @brief Read one item without removing it from the FIFO. + This function checks for an overflow and corrects read pointer if required. @param[in] f Pointer to the FIFO buffer to manipulate @param[in] pos - Position to read from in the FIFO buffer + Position to read from in the FIFO buffer with respect to read pointer @param[in] p_buffer Pointer to the place holder for data read from the buffer @@ -425,17 +462,21 @@ uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t count) /******************************************************************************/ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer) { - return _tu_fifo_peek_at(f, pos, p_buffer, f->wr_idx, f->rd_idx); + tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! + bool ret = _tu_fifo_peek_at(f, pos, p_buffer, f->wr_idx, f->rd_idx); + tu_fifo_unlock(f); + return ret; } /******************************************************************************/ /*! @brief Read n items without removing it from the FIFO + This function checks for an overflow and corrects read pointer if required. @param[in] f Pointer to the FIFO buffer to manipulate @param[in] pos - Position to read from in the FIFO buffer + Position to read from in the FIFO buffer with respect to read pointer @param[in] p_buffer Pointer to the place holder for data read from the buffer @param[in] n @@ -446,7 +487,10 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer) /******************************************************************************/ uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n) { - return _tu_fifo_peek_at_n(f, pos, p_buffer, n, f->wr_idx, f->rd_idx); + tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! + bool ret = _tu_fifo_peek_at_n(f, pos, p_buffer, n, f->wr_idx, f->rd_idx); + tu_fifo_unlock(f); + return ret; } /******************************************************************************/ @@ -454,8 +498,7 @@ uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t @brief Write one element into the buffer. This function will write one element into the array index specified by - the write pointer and increment the write index. If the write index - exceeds the max buffer size, then it will roll over to zero. + the write pointer and increment the write index. @param[in] f Pointer to the FIFO buffer to manipulate @@ -490,8 +533,7 @@ bool tu_fifo_write(tu_fifo_t* f, const void * data) /******************************************************************************/ /*! @brief This function will write n elements into the array index specified by - the write pointer and increment the write index. If the write index - exceeds the max buffer size, then it will roll over to zero. + the write pointer and increment the write index. @param[in] f Pointer to the FIFO buffer to manipulate @@ -543,7 +585,7 @@ uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t count) /******************************************************************************/ /*! - @brief Clear the fifo read and write pointers and set length to zero + @brief Clear the fifo read and write pointers @param[in] f Pointer to the FIFO buffer to manipulate @@ -552,10 +594,50 @@ uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t count) bool tu_fifo_clear(tu_fifo_t *f) { tu_fifo_lock(f); - f->rd_idx = f->wr_idx = 0; - tu_fifo_unlock(f); return true; } + +/******************************************************************************/ +/*! + @brief Advance write pointer - intended to be used in combination with DMA. + It is possible to fill the FIFO by use of a DMA in circular mode. Within + DMA ISRs you may update the write pointer to be able to read from the FIFO. + As long as the DMA is the only process writing into the FIFO this is safe + to use. + + USE WITH CARE - WE DO NOT CONDUCT SAFTY CHECKS HERE! + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] n + Number of items the write pointer moves forward + */ +/******************************************************************************/ +void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n) +{ + f->wr_idx = advance_pointer(f, f->wr_idx, n); +} + +/******************************************************************************/ +/*! + @brief Advance read pointer - intended to be used in combination with DMA. + It is possible to read from the FIFO by use of a DMA in linear mode. Within + DMA ISRs you may update the read pointer to be able to again write into the + FIFO. As long as the DMA is the only process reading from the FIFO this is + safe to use. + + USE WITH CARE - WE DO NOT CONDUCT SAFTY CHECKS HERE! + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] n + Number of items the read pointer moves forward + */ +/******************************************************************************/ +void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) +{ + f->rd_idx = advance_pointer(f, f->rd_idx, n); +} diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 56491c37b..66888ef19 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -31,6 +31,15 @@ #ifndef _TUSB_FIFO_H_ #define _TUSB_FIFO_H_ +// Due to the use of unmasked pointers, this FIFO does not suffer from loosing +// one item slice. Furthermore, write and read operations are completely +// decoupled as write and read functions do not modify a common state. Henceforth, +// writing or reading from the FIFO within an ISR is safe as long as no other +// process (thread or ISR) interferes. +// Also, this FIFO is ready to be used in combination with a DMA as the write and +// read pointers can be updated from within a DMA ISR. Overflows are detectable +// within a certain number (see tu_fifo_overflow()). + // mutex is only needed for RTOS // for OS None, we don't get preempted #define CFG_FIFO_MUTEX (CFG_TUSB_OS != OPT_OS_NONE) @@ -76,8 +85,8 @@ typedef struct .depth = _depth, \ .item_size = sizeof(_type), \ .overwritable = _overwritable, \ - .non_used_index_space = (2^16-1) % _depth, \ - .max_pointer_idx = (2^16-1) - ((2^16-1) % _depth), \ + .non_used_index_space = 0x10000 % _depth, \ + .max_pointer_idx = 0xFFFF - (0x10000 % _depth), \ } bool tu_fifo_clear(tu_fifo_t *f); @@ -100,13 +109,17 @@ bool tu_fifo_peek_at (tu_fifo_t* f, uint16_t pos, void * p_bu uint16_t tu_fifo_peek_at_n (tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n); uint16_t tu_fifo_count (tu_fifo_t* f); -void tu_fifo_correct_read_pointer (tu_fifo_t* f); bool tu_fifo_empty (tu_fifo_t* f); bool tu_fifo_full (tu_fifo_t* f); uint16_t tu_fifo_remaining (tu_fifo_t* f); bool tu_fifo_overflow (tu_fifo_t* f); void tu_fifo_correct_read_pointer (tu_fifo_t* f); +// Pointer modifications intended to be used in combinations with DMAs. +// USE WITH CARE - NO SAFTY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED! +void tu_fifo_advance_write_pointer (tu_fifo_t *f, uint16_t n); +void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); + static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { return tu_fifo_peek_at(f, 0, p_buffer); -- cgit v1.3.1 From 9bdeafb29503b65d2c46e71a4c7e80b753bad55a Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 23 Sep 2020 20:48:03 +0200 Subject: Change maximum depth to 2^15 which allows for a fast modulo substitute. Thus, however, overflows are detectable only for one time FIFO depth. --- src/common/tusb_fifo.c | 37 +++++++++++++++++-------------------- src/common/tusb_fifo.h | 40 ++++++++++++++++++++-------------------- 2 files changed, 37 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index b83dfee4e..84fc9bb8b 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -58,6 +58,8 @@ static void tu_fifo_unlock(tu_fifo_t *f) bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) { + if (depth > 0x8000) return false; // Maximum depth is 2^15 items + tu_fifo_lock(f); f->buffer = (uint8_t*) buffer; @@ -65,8 +67,8 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si f->item_size = item_size; f->overwritable = overwritable; - f->non_used_index_space = 0x10000 % depth; - f->max_pointer_idx = 0xFFFF - f->non_used_index_space; + f->max_pointer_idx = 2*depth - 1; // Limit index space to 2*depth - this allows for a fast "modulo" calculation but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable only if overflow happens once (important for unsupervised DMA applications) + f->non_used_index_space = 0xFFFF - f->max_pointer_idx; f->rd_idx = f->wr_idx = 0; @@ -79,7 +81,9 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) { - return idx % depth; +// return idx % depth; + idx -= depth & -(idx > depth); + return idx -= depth & -(idx > depth); } // send one item to FIFO WITHOUT updating write pointer @@ -194,15 +198,11 @@ static inline bool _tu_fifo_full(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) } // Works on local copies of w and r -//BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" -//EXAMPLE with buffer depth: 100 -//Maximum index space: (2^16) - (2^16) % depth = 65500 -//If you produce 65500 / 100 + 1 = 656 buffer overflows, the write pointer will overflow as well and -//the check _tu_fifo_overflow() will not give you a valid result! Avoid such nasty things! -//All reading functions (read, peek) check for overflows and correct read pointer on their own such -//that latest items are read. -//If required (e.g. for DMA use) you can also correct the read pointer by -//tu_fifo_correct_read_pointer(). +// BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" +// Only one overflow is allowed for this function to work e.g. if depth = 100, you must not +// write more than 2*depth-1 items in one rush without updating write pointer. Otherwise +// write pointer wraps and you pointer states are messed up. This can only happen if you +// use DMAs, write functions do not allow such an error. static inline bool _tu_fifo_overflow(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) { return (_tu_fifo_count(f, wAbs, rAbs) > f->depth); @@ -249,6 +249,7 @@ static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t pos, void * p_buffer, if (cnt > f->depth) { _tu_fifo_correct_read_pointer(f, wAbs); + rAbs = f->rd_idx; cnt = f->depth; } @@ -401,13 +402,11 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) { tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! - uint16_t r = f->rd_idx; - // Peek the data - bool ret = _tu_fifo_peek_at(f, 0, buffer, f->wr_idx, r); + bool ret = _tu_fifo_peek_at(f, 0, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable // Advance pointer - f->rd_idx = advance_pointer(f, r, ret); + f->rd_idx = advance_pointer(f, f->rd_idx, ret); tu_fifo_unlock(f); return ret; @@ -433,13 +432,11 @@ uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t count) { tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! - uint16_t r = f->rd_idx; - // Peek the data - count = _tu_fifo_peek_at_n(f, 0, buffer, count, f->wr_idx, r); + count = _tu_fifo_peek_at_n(f, 0, buffer, count, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable // Advance read pointer - f->rd_idx = advance_pointer(f, r, count); + f->rd_idx = advance_pointer(f, f->rd_idx, count); tu_fifo_unlock(f); return count; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 66888ef19..23f5d8449 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -48,7 +48,7 @@ #include #ifdef __cplusplus - extern "C" { +extern "C" { #endif #if CFG_FIFO_MUTEX @@ -61,16 +61,16 @@ */ typedef struct { - uint8_t* buffer ; ///< buffer pointer - uint16_t depth ; ///< max items - uint16_t item_size ; ///< size of each item - bool overwritable ; + uint8_t* buffer ; ///< buffer pointer + uint16_t depth ; ///< max items + uint16_t item_size ; ///< size of each item + bool overwritable ; - uint16_t non_used_index_space ; ///< required for non-power-of-two buffer length - uint16_t max_pointer_idx ; ///< maximum absolute pointer index + uint16_t non_used_index_space ; ///< required for non-power-of-two buffer length + uint16_t max_pointer_idx ; ///< maximum absolute pointer index - volatile uint16_t wr_idx ; ///< write pointer - volatile uint16_t rd_idx ; ///< read pointer + volatile uint16_t wr_idx ; ///< write pointer + volatile uint16_t rd_idx ; ///< read pointer #if CFG_FIFO_MUTEX tu_fifo_mutex_t mutex; @@ -78,16 +78,16 @@ typedef struct } tu_fifo_t; -#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - tu_fifo_t _name = { \ - .buffer = _name##_buf, \ - .depth = _depth, \ - .item_size = sizeof(_type), \ - .overwritable = _overwritable, \ - .non_used_index_space = 0x10000 % _depth, \ - .max_pointer_idx = 0xFFFF - (0x10000 % _depth), \ - } +#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ + uint8_t _name##_buf[_depth*sizeof(_type)]; \ + tu_fifo_t _name = { \ + .buffer = _name##_buf, \ + .depth = _depth, \ + .item_size = sizeof(_type), \ + .overwritable = _overwritable, \ + .max_pointer_idx = 2*_depth-1, \ + .non_used_index_space = 0xFFFF - 2*_depth-1, \ + } bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); @@ -131,7 +131,7 @@ static inline uint16_t tu_fifo_depth(tu_fifo_t* f) } #ifdef __cplusplus - } +} #endif #endif /* _TUSB_FIFO_H_ */ -- cgit v1.3.1 From 52c9a467b42c4448251753a295343496a9265b4f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 23 Sep 2020 21:36:30 +0200 Subject: Fix bug in modulo substitute. --- src/common/tusb_fifo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 84fc9bb8b..cf4e6a51a 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -82,8 +82,8 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) { // return idx % depth; - idx -= depth & -(idx > depth); - return idx -= depth & -(idx > depth); + idx -= depth & -(idx >= depth); + return idx -= depth & -(idx >= depth); } // send one item to FIFO WITHOUT updating write pointer -- cgit v1.3.1 From 9ddcfc09d7c0f076248307f76222d5b1db9e0882 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 25 Sep 2020 15:58:28 +0200 Subject: Fix wrong comments, rename pos to offset, rename overflow(). --- src/common/tusb_fifo.c | 69 +++++++++++++++++++++++++------------------------- src/common/tusb_fifo.h | 2 +- 2 files changed, 36 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index cf4e6a51a..1e0c6b5e7 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -111,13 +111,13 @@ static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRe } } -// get one item from FIFO WITHOUT updating write pointer +// get one item from FIFO WITHOUT updating read pointer static inline void _ff_pull(tu_fifo_t* f, void * p_buffer, uint16_t rRel) { memcpy(p_buffer, f->buffer + (rRel * f->item_size), f->item_size); } -// get n items from FIFO WITHOUT updating write pointer +// get n items from FIFO WITHOUT updating read pointer static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel) { if(rRel + n <= f->depth) // Linear mode only @@ -137,45 +137,45 @@ static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel) } // Advance an absolute pointer -static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t pos) +static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) { // We limit the index space of p such that a correct wrap around happens // Check for a wrap around or if we are in unused index space - This has to be checked first!! We are exploiting the wrap around to the correct index - if ((p > p + pos) || (p + pos > f->max_pointer_idx)) + if ((p > p + offset) || (p + offset > f->max_pointer_idx)) { - p = (p + pos) + f->non_used_index_space; + p = (p + offset) + f->non_used_index_space; } else { - p += pos; + p += offset; } return p; } // Backward an absolute pointer -static uint16_t backward_pointer(tu_fifo_t* f, uint16_t p, uint16_t pos) +static uint16_t backward_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) { // We limit the index space of p such that a correct wrap around happens // Check for a wrap around or if we are in unused index space - This has to be checked first!! We are exploiting the wrap around to the correct index - if ((p < p - pos) || (p - pos > f->max_pointer_idx)) + if ((p < p - offset) || (p - offset > f->max_pointer_idx)) { - p = (p - pos) - f->non_used_index_space; + p = (p - offset) - f->non_used_index_space; } else { - p -= pos; + p -= offset; } return p; } // get relative from absolute pointer -static uint16_t get_relative_pointer(tu_fifo_t* f, uint16_t p, uint16_t pos) +static uint16_t get_relative_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) { - return _ff_mod(advance_pointer(f, p, pos), f->depth); + return _ff_mod(advance_pointer(f, p, offset), f->depth); } // Works on local copies of w and r -static uint16_t _tu_fifo_count(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) +static inline uint16_t _tu_fifo_count(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) { uint16_t cnt = wAbs-rAbs; @@ -203,7 +203,7 @@ static inline bool _tu_fifo_full(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) // write more than 2*depth-1 items in one rush without updating write pointer. Otherwise // write pointer wraps and you pointer states are messed up. This can only happen if you // use DMAs, write functions do not allow such an error. -static inline bool _tu_fifo_overflow(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) +static inline bool _tu_fifo_overflowed(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) { return (_tu_fifo_count(f, wAbs, rAbs) > f->depth); } @@ -217,7 +217,7 @@ static inline void _tu_fifo_correct_read_pointer(tu_fifo_t* f, uint16_t wAbs) // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -static bool _tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t wAbs, uint16_t rAbs) +static bool _tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t wAbs, uint16_t rAbs) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); @@ -229,9 +229,9 @@ static bool _tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16 } // Skip beginning of buffer - if (cnt == 0 || pos >= cnt) return false; + if (cnt == 0 || offset >= cnt) return false; - uint16_t rRel = get_relative_pointer(f, rAbs, pos); + uint16_t rRel = get_relative_pointer(f, rAbs, offset); // Peek data _ff_pull(f, p_buffer, rRel); @@ -241,7 +241,7 @@ static bool _tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16 // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs) +static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); @@ -254,16 +254,16 @@ static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t pos, void * p_buffer, } // Skip beginning of buffer - if (cnt == 0 || pos >= cnt) return 0; + if (cnt == 0 || offset >= cnt) return 0; - // Check if we can read something at and after pos - if too less is available we read what remains - cnt -= pos; + // Check if we can read something at and after offset - if too less is available we read what remains + cnt -= offset; if (cnt < n) { if (cnt == 0) return 0; n = cnt; } - uint16_t rRel = get_relative_pointer(f, rAbs, pos); + uint16_t rRel = get_relative_pointer(f, rAbs, offset); // Peek data _ff_pull_n(f, p_buffer, n, rRel); @@ -354,10 +354,11 @@ uint16_t tu_fifo_remaining(tu_fifo_t* f) @brief Check if overflow happened. BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" - EXAMPLE with buffer depth: 100 - Maximum index space: (2^16) - (2^16) % depth = 65500 - If you produce 65500 / 100 + 1 = 656 buffer overflows, the write pointer will overflow as well and - the check _tu_fifo_overflow() will not give you a valid result! Avoid such nasty things! + Only one overflow is allowed for this function to work e.g. if depth = 100, you must not + write more than 2*depth-1 items in one rush without updating write pointer. Otherwise + write pointer wraps and you pointer states are messed up. This can only happen if you + use DMAs, write functions do not allow such an error. Avoid such nasty things! + All reading functions (read, peek) check for overflows and correct read pointer on their own such that latest items are read. If required (e.g. for DMA use) you can also correct the read pointer by @@ -369,9 +370,9 @@ uint16_t tu_fifo_remaining(tu_fifo_t* f) @returns True if overflow happened */ /******************************************************************************/ -bool tu_fifo_overflow(tu_fifo_t* f) +bool tu_fifo_overflowed(tu_fifo_t* f) { - return _tu_fifo_overflow(f, f->wr_idx, f->rd_idx); + return _tu_fifo_overflowed(f, f->wr_idx, f->rd_idx); } // Only use in case tu_fifo_overflow() returned true! @@ -449,7 +450,7 @@ uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t count) @param[in] f Pointer to the FIFO buffer to manipulate - @param[in] pos + @param[in] offset Position to read from in the FIFO buffer with respect to read pointer @param[in] p_buffer Pointer to the place holder for data read from the buffer @@ -457,10 +458,10 @@ uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t count) @returns TRUE if the queue is not empty */ /******************************************************************************/ -bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer) +bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) { tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! - bool ret = _tu_fifo_peek_at(f, pos, p_buffer, f->wr_idx, f->rd_idx); + bool ret = _tu_fifo_peek_at(f, offset, p_buffer, f->wr_idx, f->rd_idx); tu_fifo_unlock(f); return ret; } @@ -472,7 +473,7 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer) @param[in] f Pointer to the FIFO buffer to manipulate - @param[in] pos + @param[in] offset Position to read from in the FIFO buffer with respect to read pointer @param[in] p_buffer Pointer to the place holder for data read from the buffer @@ -482,10 +483,10 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer) @returns Number of bytes written to p_buffer */ /******************************************************************************/ -uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n) +uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t n) { tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! - bool ret = _tu_fifo_peek_at_n(f, pos, p_buffer, n, f->wr_idx, f->rd_idx); + bool ret = _tu_fifo_peek_at_n(f, offset, p_buffer, n, f->wr_idx, f->rd_idx); tu_fifo_unlock(f); return ret; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 23f5d8449..b87695743 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -112,7 +112,7 @@ uint16_t tu_fifo_count (tu_fifo_t* f); bool tu_fifo_empty (tu_fifo_t* f); bool tu_fifo_full (tu_fifo_t* f); uint16_t tu_fifo_remaining (tu_fifo_t* f); -bool tu_fifo_overflow (tu_fifo_t* f); +bool tu_fifo_overflowed (tu_fifo_t* f); void tu_fifo_correct_read_pointer (tu_fifo_t* f); // Pointer modifications intended to be used in combinations with DMAs. -- cgit v1.3.1 From 8dcb10493330513b5b017306634a936413f1ecd5 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 26 Sep 2020 11:00:31 +0200 Subject: Change modulo substitute to while ( idx >= depth) idx -= depth; --- src/common/tusb_fifo.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 1e0c6b5e7..f41cf9f6c 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -81,9 +81,8 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) { -// return idx % depth; - idx -= depth & -(idx >= depth); - return idx -= depth & -(idx >= depth); + while ( idx >= depth) idx -= depth; + return idx; } // send one item to FIFO WITHOUT updating write pointer -- cgit v1.3.1 From 6f3d0af1e65f9741cd9a735fea596e466645e234 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 26 Aug 2020 16:08:33 +0200 Subject: synopsys: Fix fifo allocation schema Recommended FIFO allocation schema includes 2 maximum endpoint sizes. Comment suggested that this is the case while it would work according to this description only in checked endpoints were ascending sizes. Also two same size endpoints would be counted as one. That is fixed by way sz is filled. Calculation used too much modulo operation while single division was enough to account for odd FIFO sizes. Extra space that is evenly distributed between Bulk and control endpoints was incorrectly calculated it could prevent allocation of ISO endpoint FIFO when bulk endpoints existed with smaller endpoint numbers. Minimum endpoint FIFO size is 16 32bit words, FIFO space requirement is now observed. --- src/portable/st/synopsys/dcd_synopsys.c | 42 +++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index c1b087dac..213a3ad98 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -1241,34 +1241,43 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration // Determine number of used out EPs of current configuration and size of two biggest out EPs uint8_t nUsedOutEPs = 0, cnt_ep, cnt_tt; - bool tmp; uint16_t sz[2] = {0, 0}; + uint16_t fifo_depth; for (cnt_ep = 0; cnt_ep < EP_MAX; cnt_ep++) { - tmp = false; for (cnt_tt = 0; cnt_tt <= TUSB_XFER_INTERRUPT; cnt_tt++) { - tmp |= report.ep_transfer_type[cnt_ep][TUSB_DIR_OUT][cnt_tt]; + if (report.ep_transfer_type[cnt_ep][TUSB_DIR_OUT][cnt_tt]) + { + nUsedOutEPs++; + break; + } } - nUsedOutEPs += tmp; - if (sz[0] < report.ep_size[cnt_ep][TUSB_DIR_OUT]) + fifo_depth = report.ep_size[cnt_ep][TUSB_DIR_OUT] / 4 + 1; + if (sz[0] < fifo_depth) { sz[1] = sz[0]; - sz[0] = report.ep_size[cnt_ep][TUSB_DIR_OUT]; + sz[0] = fifo_depth; + } + else if (sz[1] < report.ep_size[cnt_ep][TUSB_DIR_OUT]) + { + sz[1] = fifo_depth; } } // For configuration use the approach as explained in bus_reset() - _allocated_fifo_words = 15 + 2*nUsedOutEPs + (sz[0] / 4) + (sz[0] % 4 > 0 ? 1 : 0) + (sz[1] / 4) + (sz[1] % 4 > 0 ? 1 : 0) + 2; // again, i do not really know why we need + 2 but otherwise it does not work + _allocated_fifo_words = 13 + 1 + 1 + 2 * nUsedOutEPs + sz[0] + sz[1] + 2; // again, i do not really know why we need + 2 but otherwise it does not work usb_otg->GRXFSIZ = _allocated_fifo_words; // Control IN uses FIFO 0 with report.ep_size[0][TUSB_DIR_IN] bytes ( report.ep_size[0][TUSB_DIR_IN]/4 32-bit word ) - usb_otg->DIEPTXF0_HNPTXFSIZ = (report.ep_size[0][TUSB_DIR_IN]/4 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; + fifo_depth = report.ep_size[0][TUSB_DIR_IN] / 4; + fifo_depth = tu_max16(16, fifo_depth); + usb_otg->DIEPTXF0_HNPTXFSIZ = (fifo_depth << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - _allocated_fifo_words += report.ep_size[0][TUSB_DIR_IN]/4; // Since EP0 size MUST be a power of two we do not need to take care of remainders + _allocated_fifo_words += fifo_depth; // For configuration of remaining in EPs use the approach as explained in dcd_edpt_open() except that: // - ISO EPs only get EP size as FIFO size. More makes no sense since within one frame precisely EP size bytes are transfered and not more. @@ -1307,11 +1316,14 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration // Required space by EPs in words, number of bulk and control EPs uint16_t ep_sz_total = 0; + // Number of bulk and control EPs uint8_t nbc = 0; // EP0 is already taken care of so exclude that here for (cnt_ep = 1; cnt_ep < EP_MAX; cnt_ep++) { - ep_sz_total += report.ep_size[cnt_ep][TUSB_DIR_IN] / 4 + (report.ep_size[cnt_ep][TUSB_DIR_IN] % 4 > 0 ? 1 : 0); // Since we need full words take care of remainders! + fifo_depth = (report.ep_size[cnt_ep][TUSB_DIR_IN] + 3) / 4; // Since we need full words take care of remainders! + if (fifo_depth > 0 && fifo_depth < 16) fifo_depth = 16; // Minimum FIFO depth is 16 + ep_sz_total += fifo_depth; nbc += (report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] | report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]); } @@ -1321,8 +1333,7 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration return false; } - uint16_t extra_space = nbc > 0 ? fifo_remaining / nbc : 0; // If no bulk or control EPs are used we just leave the rest of the memory unused - uint16_t fifo_size; + uint16_t extra_space = nbc > 0 ? (fifo_remaining - ep_sz_total) / nbc : 0; // If no bulk or control EPs are used we just leave the rest of the memory unused // Setup FIFOs for (cnt_ep = 1; cnt_ep < EP_MAX; cnt_ep++) @@ -1330,9 +1341,10 @@ TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration // If EP is used if (report.ep_size[cnt_ep][TUSB_DIR_IN] > 0) { - fifo_size = report.ep_size[cnt_ep][TUSB_DIR_IN] / 4 + (report.ep_size[cnt_ep][TUSB_DIR_IN] % 4 > 0 ? 1 : 0) + ((report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] || report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]) ? extra_space : 0); - usb_otg->DIEPTXF[cnt_ep - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; - _allocated_fifo_words += fifo_size; + fifo_depth = (report.ep_size[cnt_ep][TUSB_DIR_IN] + 3) / 4 + ((report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] || report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]) ? extra_space : 0); + fifo_depth = tu_max16(16, fifo_depth); + usb_otg->DIEPTXF[cnt_ep - 1] = (fifo_depth << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; + _allocated_fifo_words += fifo_depth; } } -- cgit v1.3.1 From 5ad2f8efc6ce77d3f58f3292838367dea8c41826 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 26 Aug 2020 16:34:56 +0200 Subject: audio_device: Fix inline function specifiers Having just inline keyword for function specified in header may not be enough to generate code for function. Adding static solves this problem. static inline is used in all other inline functions in TinyUSB. --- src/class/audio/audio_device.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 11f444daa..2adb95252 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -196,23 +196,23 @@ uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, // Application API (Interface0) //--------------------------------------------------------------------+ -inline bool tud_audio_mounted (void); +static inline bool tud_audio_mounted (void); #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -inline uint16_t tud_audio_available (void); -inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); -inline void tud_audio_read_flush (void); +static inline uint16_t tud_audio_available (void); +static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); +static inline void tud_audio_read_flush (void); #endif #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); +static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -inline uint32_t tud_audio_int_ctr_available (void); -inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize); -inline void tud_audio_int_ctr_read_flush (void); -inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); +static inline uint32_t tud_audio_int_ctr_available (void); +static inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize); +static inline void tud_audio_int_ctr_read_flush (void); +static inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); #endif // Buffer control EP data and schedule a transmit @@ -269,52 +269,52 @@ TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_reque // Inline Functions //--------------------------------------------------------------------+ -inline bool tud_audio_mounted(void) +static inline bool tud_audio_mounted(void) { return tud_audio_n_mounted(0); } #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used +static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used { return tud_audio_n_write(0, channelId, buffer, bufsize); } #endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -inline uint16_t tud_audio_available(uint8_t channelId) +static inline uint16_t tud_audio_available(uint8_t channelId) { return tud_audio_n_available(0, channelId); } -inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize) { return tud_audio_n_read(0, channelId, buffer, bufsize); } -inline void tud_audio_read_flush(uint8_t channelId) +static inline void tud_audio_read_flush(uint8_t channelId) { tud_audio_n_read_flush(0, channelId); } #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -inline uint16_t tud_audio_int_ctr_available(void) +static inline uint16_t tud_audio_int_ctr_available(void) { return tud_audio_int_ctr_n_available(0); } -inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize) { return tud_audio_int_ctr_n_read(0, buffer, bufsize); } -inline void tud_audio_int_ctr_read_flush(void) +static inline void tud_audio_int_ctr_read_flush(void) { return tud_audio_int_ctr_n_read_flush(0); } -inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) { return tud_audio_int_ctr_n_write(0, buffer, bufsize); } -- cgit v1.3.1 From f4a44ee06337366680958013143657aa693c80ef Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 10:56:17 +0200 Subject: audio: Update ISO endpoint attributes Explicit feedback attribute was missing. No synchronization now also has definition. --- src/class/audio/audio.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 5e64549ed..0027217cb 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -497,11 +497,13 @@ typedef enum /// Isochronous End Point Attributes typedef enum { + TUSB_ISO_EP_ATT_NO_SYNC = 0x00, TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, TUSB_ISO_EP_ATT_SYNCHRONOUS = 0x0C, TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point - TUSB_ISO_EP_ATT_FB = 0x20, ///< Feedback End Point + TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point + TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback } tusb_iso_ep_attribute_t; /// Audio Class-Control Values UAC2 -- cgit v1.3.1 From e67fc808aada31a549399a0b0337b43ec45535d1 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:13:25 +0200 Subject: audio_device: Store rhport in interface data Some API uses interface number as argument, some wants to have rhport. To accommodate need of rhport for functions that don't have it rhport can be extracted from interface data. --- src/class/audio/audio_device.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index ebb8434cd..fd24d455c 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -48,6 +48,7 @@ //--------------------------------------------------------------------+ typedef struct { + uint8_t rhport; uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function #if CFG_TUD_AUDIO_EPSIZE_IN @@ -673,6 +674,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin if (!_audiod_itf[i].p_desc) { _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one + _audiod_itf[i].rhport = rhport; break; } } -- cgit v1.3.1 From 66b091282f31275fff859c4cf61c3026215a3db7 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:16:41 +0200 Subject: audio_device: Fix audio_rx_done_type_I_pcm_ff_cb prototype Function prototype did not have return type specified by mistake. --- src/class/audio/audio_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index fd24d455c..f83f395a8 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -135,7 +135,7 @@ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; extern const uint16_t tud_audio_desc_lengths[]; #if CFG_TUD_AUDIO_EPSIZE_OUT -static audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t const* buffer, uint32_t bufsize); +static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize); #endif #if CFG_TUD_AUDIO_EPSIZE_IN -- cgit v1.3.1 From ca4a42156ceeb8dd6b70edc02b2b762645c62c66 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:18:11 +0200 Subject: audio_device: Fix audio_rx_done_type_I_pcm_ff_cb bufor size check Function was not checking buffer size correctly due missing parenthesis. --- src/class/audio/audio_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index f83f395a8..23a2cea96 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -288,7 +288,8 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a (void) rhport; // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel - if (bufsize % CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX*CFG_TUD_AUDIO_N_CHANNELS_RX != 0) { + if (bufsize % (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX) != 0) + { return false; } -- cgit v1.3.1 From 28cf63c7dbe08677d614d16a435487ae03b3cce6 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:24:41 +0200 Subject: audio_device: Fix tud_audio_n_read_flush TU_VERIFY usage void function used TU_VERIFY in a way that returned bool value. It would not compile. --- src/class/audio/audio_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 23a2cea96..2660cf368 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -205,7 +205,7 @@ uint16_t tud_audio_n_read(uint8_t itf, uint8_t channelId, void* buffer, uint16_t void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); } -- cgit v1.3.1 From 759d5305062e5261d580fa64e40fc755db34c436 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:42:52 +0200 Subject: audio_device: Allow one FIFO for N channels This allow to build with single FIFO for devices with multiple channels. Having just one FIFO greatly reduces time needed to feed endpoint. This change also allows to have one FIFO with 24 bit samples that is not rounded up to 32 bit elements. CFG_TUD_AUDIO_RX_ITEMSIZE and CFG_TUD_AUDIO_TX_ITEMSIZE can be manually defined. This allows to use FIFO more efficiently when 24 bits samples are already using 3 bytes, in this case there is no need to put them into FIFO one by one. For 8, 16, 32 bits samples size efficient FIFO access is always used when single FIFO is selected. This also changes FIFO element size to 1, FIFO usage was confusing in some place it treated content as byte base in other it looked like ITEM size is to be used. Also bufsize that in most (maybe all) cases was really meaning item count. bufsize now mean buffer size in bytes so there is no confusion. --- src/class/audio/audio_device.c | 147 ++++++++++++++++++++++++++++++++++------- src/class/audio/audio_device.h | 60 ++++++++++++++++- 2 files changed, 179 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 2660cf368..181703f75 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -46,6 +46,19 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE +#ifndef CFG_TUD_AUDIO_TX_FIFO_COUNT +#define CFG_TUD_AUDIO_TX_FIFO_COUNT CFG_TUD_AUDIO_N_CHANNELS_TX +#endif +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE +#ifndef CFG_TUD_AUDIO_RX_FIFO_COUNT +#define CFG_TUD_AUDIO_RX_FIFO_COUNT CFG_TUD_AUDIO_N_CHANNELS_RX +#endif +#endif + typedef struct { uint8_t rhport; @@ -81,18 +94,18 @@ typedef struct // FIFO #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; - CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_FIFO_SIZE * CFG_TUD_AUDIO_TX_ITEMSIZE]; + tu_fifo_t tx_ff[CFG_TUD_AUDIO_TX_FIFO_COUNT]; + CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_TX_FIFO_COUNT][CFG_TUD_AUDIO_TX_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; + osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_TX_FIFO_COUNT]; #endif #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; - CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_FIFO_SIZE * CFG_TUD_AUDIO_RX_ITEMSIZE]; + tu_fifo_t rx_ff[CFG_TUD_AUDIO_RX_FIFO_COUNT]; + CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_RX_FIFO_COUNT][CFG_TUD_AUDIO_RX_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; + osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_RX_FIFO_COUNT]; #endif #endif @@ -190,7 +203,7 @@ bool tud_audio_n_mounted(uint8_t itf) //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - +#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId) { TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); @@ -208,7 +221,22 @@ void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId) TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); } +#else +uint16_t tud_audio_n_available(uint8_t itf) +{ + return tu_fifo_count(&_audiod_itf[itf].rx_ff[0]); +} +uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize) +{ + return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[0], buffer, bufsize); +} + +void tud_audio_n_read_flush (uint8_t itf) +{ + tu_fifo_clear(&_audiod_itf[itf].rx_ff[0]); +} +#endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -283,6 +311,7 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* // The following functions are used in case CFG_TUD_AUDIO_RX_FIFO_SIZE != 0 #if CFG_TUD_AUDIO_RX_FIFO_SIZE +#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize) { (void) rhport; @@ -318,7 +347,23 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a chId = 0; } } -} } + return true; +} +#else +static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t *audio, uint8_t *buffer, uint16_t bufsize) +{ + (void) rhport; + + // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel + if (bufsize % (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX) != 0) + { + return false; + } + + tu_fifo_write_n(&audio->rx_ff[0], buffer, bufsize); + return true; +} +#endif // CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 #endif //CFG_TUD_AUDIO_RX_FIFO_SIZE //--------------------------------------------------------------------+ @@ -336,9 +381,9 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* a * \param[in] len: # of array elements to copy * \return Number of bytes actually written */ - +#if CFG_TUD_AUDIO_EPSIZE_IN +#if !CFG_TUD_AUDIO_TX_FIFO_SIZE /* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers -#if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) { audiod_interface_t* audio = &_audiod_itf[itf]; @@ -365,11 +410,23 @@ uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t // Return number of bytes written return len; } -#endif - */ -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE +#else + +#if CFG_TUD_AUDIO_TX_FIFO_COUNT == 1 +uint16_t tud_audio_n_write(uint8_t itf, void const* data, uint16_t len) +{ + { + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->p_desc == NULL) + { + return 0; + } + return tu_fifo_write_n(&audio->tx_ff[0], data, len); + } +} +#else uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { audiod_interface_t* audio = &_audiod_itf[itf]; @@ -381,6 +438,23 @@ uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, ui } #endif +static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied); + +uint16_t tud_audio_n_write_flush(uint8_t itf) +{ + audiod_interface_t *audio = &_audiod_itf[itf]; + if (audio->p_desc == NULL) { + return 0; + } + + uint16_t n_bytes_copied; + TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio, &n_bytes_copied)); + return n_bytes_copied; +} + +#endif +#endif + #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t bufsize) { @@ -477,6 +551,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ #endif //CFG_TUD_AUDIO_EPSIZE_IN #if CFG_TUD_AUDIO_TX_FIFO_SIZE +#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) { // We encode directly into IN EP's buffer - abort if previous transfer not complete @@ -484,15 +559,15 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* // Determine amount of samples uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]); + uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]) / CFG_TUD_AUDIO_TX_ITEMSIZE; uint16_t nBytesToSend; uint8_t cntChannel; for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { - if (audio->tx_ff[cntChannel].count < nSamplesPerChannelToSend) + if (audio->tx_ff[cntChannel].count / CFG_TUD_AUDIO_TX_ITEMSIZE < nSamplesPerChannelToSend) { - nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count; + nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count * CFG_TUD_AUDIO_TX_ITEMSIZE; } } @@ -524,7 +599,7 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { // Get sample from buffer - tu_fifo_read(&audio->tx_ff[cntChannel], &sample); + tu_fifo_read_n(&audio->tx_ff[cntChannel], &sample, CFG_TUD_AUDIO_TX_ITEMSIZE); // Put it into EP's buffer - Let alignment problems be handled by memcpy memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); @@ -539,6 +614,30 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* return true; } +#else +static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) +{ + // We encode directly into IN EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); + + // Determine amount of samples + uint16_t nByteCount = tu_fifo_count(&audio->tx_ff[0]); + + nByteCount = tu_min16(nByteCount, CFG_TUD_AUDIO_EPSIZE_IN); + + // Check if there is enough + if (nByteCount == 0) + { + return true; + } + + nByteCount = tu_fifo_read_n(&audio->tx_ff[0], audio->epin_buf, nByteCount); + audio->epin_buf_cnt = nByteCount; + + return true; +} +#endif // CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) + #endif //CFG_TUD_AUDIO_TX_FIFO_SIZE // This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent @@ -588,7 +687,6 @@ static bool audio_int_ctr_done_cb(uint8_t rhport, audiod_interface_t* audio, uin //--------------------------------------------------------------------+ void audiod_init(void) { - uint8_t cnt; tu_memclr(_audiod_itf, sizeof(_audiod_itf)); for(uint8_t i=0; itx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, CFG_TUD_AUDIO_TX_ITEMSIZE, true); + tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); #endif @@ -607,9 +705,9 @@ void audiod_init(void) #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_RX_FIFO_COUNT; cnt++) { - tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, CFG_TUD_AUDIO_RX_ITEMSIZE, true); + tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); #endif @@ -634,16 +732,15 @@ void audiod_reset(uint8_t rhport) audiod_interface_t* audio = &_audiod_itf[i]; tu_memclr(audio, ITF_MEM_RESET_SIZE); - uint8_t cnt; #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_COUNT; cnt++) { tu_fifo_clear(&audio->tx_ff[cnt]); } #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - for (cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_RX_FIFO_COUNT; cnt++) { tu_fifo_clear(&audio->rx_ff[cnt]); } diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 2adb95252..2f48955f2 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -119,6 +119,7 @@ #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 #endif +#ifndef CFG_TUD_AUDIO_TX_ITEMSIZE #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 #define CFG_TUD_AUDIO_TX_ITEMSIZE 1 #elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 @@ -126,6 +127,11 @@ #else #define CFG_TUD_AUDIO_TX_ITEMSIZE 4 #endif +#endif + +#if CFG_TUD_AUDIO_TX_ITEMSIZE < CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX +#error FIFO element size (ITEMSIZE) must not be smaller then sample size +#endif #endif @@ -170,9 +176,15 @@ extern "C" { bool tud_audio_n_mounted (uint8_t itf); #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE +#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 uint16_t tud_audio_n_available (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); +#else +uint16_t tud_audio_n_available (uint8_t itf); +uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); +void tud_audio_n_read_flush (uint8_t itf); +#endif #endif /* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers @@ -182,7 +194,12 @@ uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t */ #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE +#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); +#else +uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); +#endif +uint16_t tud_audio_n_write_flush(uint8_t itf); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 @@ -205,7 +222,11 @@ static inline void tud_audio_read_flush (void); #endif #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE +#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); +#else +static inline uint16_t tud_audio_write (uint8_t const* buffer, uint16_t bufsize); +#endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 @@ -274,14 +295,31 @@ static inline bool tud_audio_mounted(void) return tud_audio_n_mounted(0); } -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize) // Short version if only one audio function is used +#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_TX_FIFO_SIZE && CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 +static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t n_bytes) // Short version if only one audio function is used +{ + return tud_audio_n_write(0, channelId, buffer, n_bytes); +} +#else +static inline uint16_t tud_audio_write (uint8_t const* buffer, uint16_t n_bytes) // Short version if only one audio function is used +{ + return tud_audio_n_write(0, buffer, n_bytes); +} +#endif + +static inline uint16_t tud_audio_write_flush (void) // Short version if only one audio function is used { - return tud_audio_n_write(0, channelId, buffer, bufsize); +#if CFG_TUD_AUDIO_TX_FIFO_SIZE + return tud_audio_n_write_flush(0); +#else + return 0; +#endif } #endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE +#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 static inline uint16_t tud_audio_available(uint8_t channelId) { return tud_audio_n_available(0, channelId); @@ -296,6 +334,22 @@ static inline void tud_audio_read_flush(uint8_t channelId) { tud_audio_n_read_flush(0, channelId); } +#else +static inline uint16_t tud_audio_available(void) +{ + return tud_audio_n_available(0); +} + +static inline uint16_t tud_audio_read(void *buffer, uint16_t bufsize) +{ + return tud_audio_n_read(0, buffer, bufsize); +} + +static inline void tud_audio_read_flush(void) +{ + tud_audio_n_read_flush(0); +} +#endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -- cgit v1.3.1 From 6b5233096978305f1d6a87ef83393ba50e8b0bd2 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 14 Sep 2020 10:22:54 +0200 Subject: synopsys: Remove compilation warning in dcd_edpt_close dcd_edpt_close() no longer modifies FIFO distribution. Code that that was commented out is removed along with variables that are no longer used. FIFO distribution among endpoints is handled upfront and does not need to be modified in open and close endpoint functions. --- src/portable/st/synopsys/dcd_synopsys.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 213a3ad98..0980720d6 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -809,20 +809,7 @@ static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall) */ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) { - USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - dcd_edpt_disable(rhport, ep_addr, false); -// if (dir == TUSB_DIR_IN) -// { -// uint16_t const fifo_size = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXFD_Msk) >> USB_OTG_DIEPTXF_INEPTXFD_Pos; -// uint16_t const fifo_start = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXSA_Msk) >> USB_OTG_DIEPTXF_INEPTXSA_Pos; -// // For now only endpoint that has FIFO at the end of FIFO memory can be closed without fuss. -// TU_ASSERT(fifo_start + fifo_size == _allocated_fifo_words,); -// _allocated_fifo_words -= fifo_size; -// } } void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) -- cgit v1.3.1 From 2ace98e943831784e6c9d81258babce2b7b3221c Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 14 Sep 2020 11:28:05 +0200 Subject: audio_device: Update explicit feedback support Feedback can be specified by the user code and will be sent at feedback endpoint specified interval. --- src/class/audio/audio_device.c | 76 ++++++++++++++++++++++++++++++++---------- src/class/audio/audio_device.h | 5 +++ src/device/usbd.h | 5 +++ 3 files changed, 68 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 181703f75..1b9cfe13a 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -121,10 +121,9 @@ typedef struct #if CFG_TUD_AUDIO_EPSIZE_OUT CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) - // TODO: required? - //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // uint16_t fb_val; // Feedback value for asynchronous mode! - //#endif +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). +#endif #endif @@ -643,18 +642,51 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* // This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) +static bool audio_fb_send(uint8_t rhport, audiod_interface_t *audio) { - (void) rhport; - (void) audio; + uint8_t fb[4]; + uint16_t len; - // Here we need to return the feedback value -#error RETURN YOUR FEEDBACK VALUE HERE! + if (audio->fb_val == 0) + { + len = 0; + return true; + } + else + { + len = 4; + // Here we need to return the feedback value + if (rhport == 0) + { + // For FS format is 10.14 + fb[0] = (audio->fb_val >> 2) & 0xFF; + fb[1] = (audio->fb_val >> 10) & 0xFF; + fb[2] = (audio->fb_val >> 18) & 0xFF; + // 4th byte is needed to work correctly with MS Windows + fb[3] = 0; + } + else + { + // For HS format is 16.16 + fb[0] = (audio->fb_val >> 0) & 0xFF; + fb[1] = (audio->fb_val >> 8) & 0xFF; + fb[2] = (audio->fb_val >> 16) & 0xFF; + fb[3] = (audio->fb_val >> 24) & 0xFF; + } + return usbd_edpt_xfer(rhport, audio->ep_fb, fb, len); + } - if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); - return 0; } +//static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) +//{ +// (void) rhport; +// (void) audio; +// +// if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); +// return 0; +//} + #endif // This function is called once a transmit of an interrupt control packet was successfully completed. Here, we get the remaining bytes to send @@ -918,7 +950,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 1) // Check if usage is explicit data feedback { _audiod_itf[idxDriver].ep_fb = ep_addr; @@ -1215,13 +1247,9 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // Transmission of feedback EP finished if (_audiod_itf[idxDriver].ep_fb == ep_addr) { - if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver])) - { - // Load with ZLP - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); - } + if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); - return true; + return audio_fb_send(rhport, &_audiod_itf[idxDriver]); } #endif #endif @@ -1403,4 +1431,16 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) return false; } +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback) +{ + audiod_interface_t *audio = &_audiod_itf[0]; + + audio->fb_val = feedback; + TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_fb), true); + + return audio_fb_send(rhport, audio); +} +#endif + #endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 2f48955f2..f4029a84c 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -259,6 +259,11 @@ TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_ #if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); +// User code should call this function with feedback value in 16.16 format for FS and HS. +// Value will be corrected for FS to 10.14 format automatically. +// (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). +// Feedback value will be sent at FB endpoint interval till it's changed. +bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN diff --git a/src/device/usbd.h b/src/device/usbd.h index 43af25076..a450bca7c 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -377,6 +377,11 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re #define TUD_AUDIO_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \ TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) +/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ +#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7 +#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval + // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source -- cgit v1.3.1 From 642a8b00c8bb733ddf84efbfbb6b3451bb747485 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 14 Sep 2020 12:31:00 +0200 Subject: synopsys: Fix odd/even frame handling for ISO Current implementation always sets odd/even bit for ISO transactions. This is a good strategy only if interval is 1. For ISO endpoint interval in (micro)frames is computed as 2^(interval-1), which means that odd/frame number should stay same for interval values > 1. With this change only when interval is 1 odd/even bit is modified. --- src/portable/st/synopsys/dcd_synopsys.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 0980720d6..4c670515a 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -136,6 +136,7 @@ typedef struct { uint8_t * buffer; uint16_t total_len; uint16_t max_size; + uint8_t interval; } xfer_ctl_t; // EP size and transfer type report @@ -440,7 +441,7 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK; // For ISO endpoint set correct odd/even bit for next frame. - if ((in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPTYP) == USB_OTG_DIEPCTL_EPTYP_0) + if ((in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPTYP) == USB_OTG_DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) { // Take odd/even bit from frame counter. uint32_t const odd_frame_now = (dev->DSTS & (1u << USB_OTG_DSTS_FNSOF_Pos)); @@ -457,6 +458,12 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c ((total_bytes << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) & USB_OTG_DOEPTSIZ_XFRSIZ_Msk); out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + if ((out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPTYP) == USB_OTG_DOEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) + { + // Take odd/even bit from frame counter. + uint32_t const odd_frame_now = (dev->DSTS & (1u << USB_OTG_DSTS_FNSOF_Pos)); + out_ep[epnum].DOEPCTL |= (odd_frame_now ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM_Msk : USB_OTG_DOEPCTL_SODDFRM_Msk); + } } } @@ -608,6 +615,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = desc_edpt->wMaxPacketSize.size; + xfer->interval = desc_edpt->bInterval; if(dir == TUSB_DIR_OUT) { -- cgit v1.3.1 From f55437d8898f46e6deee273306179c2a7f3f9b5d Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 14 Sep 2020 14:32:38 +0200 Subject: audio: Add descriptor for mono speaker This provides descriptor for mono speaker with explicit feedback. --- src/device/usbd.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index a450bca7c..7363159a4 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -431,6 +431,56 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) +// AUDIO simple descriptor (UAC2) for mono speaker +// - 1 Input Terminal, 2 Feature Unit (Mute and Volume Control), 3 Output Terminal, 4 Clock Source + +#define TUD_AUDIO_SPEAKER_MONO_FB_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN) + +#define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize, _epfb) \ + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ + /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\ + //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) #define TUD_USBTMC_APP_SUBCLASS 0x03u -- cgit v1.3.1 From 529622710ca6a234fa385402e4a298759a04ad72 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 28 Sep 2020 18:10:57 +0200 Subject: Cleanup for PR. --- src/class/audio/audio_device.c | 16 +++++--------- src/portable/st/synopsys/dcd_synopsys.c | 37 --------------------------------- 2 files changed, 5 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 1b9cfe13a..d208d1c84 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2020 Reinhard Panhuber + * Copyright (c) 2020 Reinhard Panhuber, Jerzy Kasenberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -66,7 +66,7 @@ typedef struct #if CFG_TUD_AUDIO_EPSIZE_IN uint8_t ep_in; // Outgoing (out of uC) audio data EP. - uint16_t epin_buf_cnt; // Count filling status of EP in buffer + uint16_t epin_buf_cnt; // Count filling status of EP in buffer - this is a shared state currently and is intended to be removed once EP buffers can be implemented as FIFOs! uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif @@ -468,7 +468,7 @@ uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_FIFO_SIZE = 0. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_FIFO_SIZE = 0 and use tud_audio_n_write_ep_in_buffer() (NOT IMPLEMENTED SO FAR). // n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. #if CFG_TUD_AUDIO_EPSIZE_IN @@ -925,10 +925,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * _audiod_itf[idxDriver].ep_in = ep_addr; _audiod_itf[idxDriver].ep_in_as_intf_num = itf; - // HERE WE WOULD NEED TO SCHEDULE OUR FIRST TRANSMIT, HOWEVER, WE ALSO WOULD FIRST NEED TO ENABLE SAMPLING AT ALL - HOW TO HANDLE THIS? - // Invoke callback - fill something in the FIFO here for now + // Invoke callback and trigger data generation - if not already running if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + // Schedule first transmit - in case no sample data is available a ZLP is loaded uint16_t n_bytes_copied; TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); } @@ -1218,12 +1218,6 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); // Transmission of ZLP is done by audiod_tx_done_cb() -// if (n_bytes_copied == 0) -// { -// // Load with ZLP -// return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); -// } - return true; } #endif diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 4c670515a..b3d82c3aa 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -690,43 +690,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } -///** -// * Close an EP. -// * -// * Currently, we only deactivate the EPs and do not fully disable them - this might not be necessary! -// * -// */ -//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); -// -// USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); -// -// if(dir == TUSB_DIR_IN) -// { -// USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); -// -// // Disable interrupt for this EP -// dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); -// -// // Clear USB active EP -// in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_USBAEP; -// } -// else -// { -// USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); -// -// // Disable interrupt for this EP -// dev->DAINTMSK &= ~(1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum));; -// -// // Clear USB active EP bit -// out_ep[epnum].DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP; -// -// } -//} - bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); -- cgit v1.3.1 From 9c837300f1d01593457f75b6e2a07a775ed3c5e1 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 28 Sep 2020 19:23:38 +0200 Subject: Fix minor issue. - Change set_EP0_max_pkt_size() to set_EP0_max_pkt_size(void). --- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index b3d82c3aa..5a89bb386 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -264,7 +264,7 @@ static void bus_reset(uint8_t rhport) } // Required after new configuration received in case EP0 max packet size has changed -static void set_EP0_max_pkt_size() +static void set_EP0_max_pkt_size(void) { USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); -- cgit v1.3.1 From da1c3c226b84faf2547a71fb7ed4acdb544d758b Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 28 Sep 2020 22:44:09 +0200 Subject: Change AUDIO_PROTOCOL_V1 to AUDIO_FUNC_PROTOCOL_CODE_UNDEF in midi.c. The USB specification does not define any AUDIO_PROTOCOL_V1! --- src/class/midi/midi_device.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index de05d93d1..a07acf0b8 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -300,9 +300,9 @@ void midid_reset(uint8_t rhport) uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) { // 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, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0); uint16_t drv_len = tu_desc_len(desc_itf); uint8_t const * p_desc = tu_desc_next(desc_itf); @@ -318,9 +318,9 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); 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, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && + AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); // Find available interface midid_interface_t * p_midi = NULL; -- cgit v1.3.1 From 13a9cbde7957de2d87731a85dcc0c7ea756e71b7 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 29 Sep 2020 23:30:35 +0200 Subject: Change AUDIO_FUNC_PROTOCOL_CODE_UNDEF for midi in usbd.h --- src/device/usbd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index 7363159a4..07156c079 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -260,11 +260,11 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re #define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) #define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ /* Audio Control (AC) Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V1, _stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, _stridx,\ /* AC Header */\ 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ /* MIDI Streaming (MS) Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, 0,\ /* MS Header */\ 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) -- cgit v1.3.1 From b2ce7a39b0d0b941ad7edb63f527b223568caa47 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 21 Sep 2020 15:23:56 +0200 Subject: device: Make number of endpoints configurable Currently number of endpoints was hard coded to 8. NRF52 has 9 IN and 9 OUT endpoints. ISO endpoints are 0x08 and 0x88 and without this change those two ISO endpoint could not be used. --- src/device/usbd.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index d1e984a0e..3a6ce9b6c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -37,6 +37,10 @@ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif +#ifndef CFG_TUD_EP_MAX +#define CFG_TUD_EP_MAX 9 +#endif + //--------------------------------------------------------------------+ // Device Data //--------------------------------------------------------------------+ @@ -57,7 +61,7 @@ typedef struct uint8_t speed; uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid ) + uint8_t ep2drv[CFG_TUD_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) struct TU_ATTR_PACKED { @@ -66,7 +70,7 @@ typedef struct volatile bool claimed : 1; // TODO merge ep2drv here, 4-bit should be sufficient - }ep_status[8][2]; + }ep_status[CFG_TUD_EP_MAX][2]; }usbd_device_t; @@ -249,7 +253,7 @@ static osal_mutex_t _usbd_mutex; //--------------------------------------------------------------------+ // Prototypes //--------------------------------------------------------------------+ -static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); +static void mark_interface_endpoint(uint8_t ep2drv[][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); static bool process_set_config(uint8_t rhport, uint8_t cfg_num); static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); @@ -842,7 +846,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } // Helper marking endpoint of interface belongs to class driver -static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) +static void mark_interface_endpoint(uint8_t ep2drv[][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) { uint16_t len = 0; -- cgit v1.3.1 From fceb8853c7e125d74fc4e13ca6ea6934248dbd21 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 21 Sep 2020 15:45:17 +0200 Subject: nrf5x: Add dcd_edpt_close Closing endpoints can be important when there are alternate instances. This adds functionality of closing endpoints similar to what exists in other drivers. --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src') diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 60da9fb25..f8190062b 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -310,6 +310,27 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + // CBI + if (dir == TUSB_DIR_OUT) + { + NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + epnum); + NRF_USBD->EPOUTEN &= ~TU_BIT(epnum); + } + else + { + NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPIN0_Pos + epnum); + NRF_USBD->EPINEN &= ~TU_BIT(epnum); + } + __ISB(); __DSB(); +} + bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { (void) rhport; -- cgit v1.3.1 From 6f5ee09511a84aa2614af95a13963b8419ee8926 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 21 Sep 2020 15:49:41 +0200 Subject: nrf5x: Increase size of mps to 16 bits msp stores max packet size. For ISO endpoints 8 bits is not enough so it's changed to 16 bits. --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index f8190062b..a78b74d62 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -62,7 +62,7 @@ typedef struct uint8_t* buffer; uint16_t total_len; volatile uint16_t actual_len; - uint8_t mps; // max packet size + uint16_t mps; // max packet size // nrf52840 will auto ACK OUT packet after DMA is done // indicate packet is already ACK @@ -205,7 +205,7 @@ static void xact_in_prepare(uint8_t epnum) xfer_td_t* xfer = get_td(epnum, TUSB_DIR_IN); // Each transaction is up to Max Packet Size - uint8_t const xact_len = tu_min16(xfer->total_len - xfer->actual_len, xfer->mps); + uint16_t const xact_len = tu_min16(xfer->total_len - xfer->actual_len, xfer->mps); NRF_USBD->EPIN[epnum].PTR = (uint32_t) xfer->buffer; NRF_USBD->EPIN[epnum].MAXCNT = xact_len; -- cgit v1.3.1 From 96da1ca4b86f58074b741c8a2437c2fd8be2b867 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 21 Sep 2020 15:53:15 +0200 Subject: nrf5x: Add support for ISO endpoints ISO endpoints were not covered so far by the driver code. This adds support for ISO IN and OUT endpoint handling. Registers for ISO IN(OUT) endpoints are placed just after normal IN(OUT) so in some cases common code could be used for handling all type of transfers. Generally code synchronizes ISO endpoint handling to SOF interrupt. This code does not change the way of how non-ISO endpoints are treated. Code uses strategy outlined in nRF52840 Produce Specification v1.0 sections 6.35.11.1 and 6.35.11.2. --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 152 +++++++++++++++++++++++++++++----- 1 file changed, 129 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index a78b74d62..b85d3776f 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -53,6 +53,9 @@ enum enum { + // Endpoint number is fixed (8) for ISOOUT and ISOIN. + EP_ISO_NUM = 8, + // CBI endpoints count EP_COUNT = 8 }; @@ -67,6 +70,9 @@ typedef struct // nrf52840 will auto ACK OUT packet after DMA is done // indicate packet is already ACK volatile bool data_received; + // Set to true when data was transferred from RAM to ISO IN output buffer. + // New data can be put in ISO IN output buffer after SOF. + bool iso_in_transfer_ready; } xfer_td_t; @@ -74,7 +80,8 @@ typedef struct static struct { // All 8 endpoints including control IN & OUT (offset 1) - xfer_td_t xfer[EP_COUNT][2]; + // +1 for ISO endpoints + xfer_td_t xfer[EP_COUNT + 1][2]; // Number of pending DMA that is started but not handled yet by dcd_int_handler(). // Since nRF can only carry one DMA can run at a time, this value is normally be either 0 or 1. @@ -173,6 +180,7 @@ static void xact_out_prepare(uint8_t epnum) { // Write zero value to SIZE register will allow hw to ACK (accept data) // If it is not already done by DMA + // SIZE.ISOOUT can also be accessed this way NRF_USBD->SIZE.EPOUT[epnum] = 0; } @@ -183,15 +191,32 @@ static void xact_out_prepare(uint8_t epnum) static void xact_out_dma(uint8_t epnum) { xfer_td_t* xfer = get_td(epnum, TUSB_DIR_OUT); + uint32_t xact_len; - uint8_t const xact_len = NRF_USBD->SIZE.EPOUT[epnum]; + if (epnum == EP_ISO_NUM) + { + xact_len = NRF_USBD->SIZE.ISOOUT; + // If ZERO bit is set, ignore ISOOUT length + if (xact_len & USBD_SIZE_ISOOUT_ZERO_Msk) xact_len = 0; + else + { + // Trigger DMA move data from Endpoint -> SRAM + NRF_USBD->ISOOUT.PTR = (uint32_t) xfer->buffer; + NRF_USBD->ISOOUT.MAXCNT = xact_len; - // Trigger DMA move data from Endpoint -> SRAM - NRF_USBD->EPOUT[epnum].PTR = (uint32_t) xfer->buffer; - NRF_USBD->EPOUT[epnum].MAXCNT = xact_len; + edpt_dma_start(&NRF_USBD->TASKS_STARTISOOUT); + } + } + else + { + xact_len = (uint8_t)NRF_USBD->SIZE.EPOUT[epnum]; - edpt_dma_start(&NRF_USBD->TASKS_STARTEPOUT[epnum]); + // Trigger DMA move data from Endpoint -> SRAM + NRF_USBD->EPOUT[epnum].PTR = (uint32_t) xfer->buffer; + NRF_USBD->EPOUT[epnum].MAXCNT = xact_len; + edpt_dma_start(&NRF_USBD->TASKS_STARTEPOUT[epnum]); + } xfer->buffer += xact_len; xfer->actual_len += xact_len; } @@ -296,14 +321,44 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) _dcd.xfer[epnum][dir].mps = desc_edpt->wMaxPacketSize.size; - if ( dir == TUSB_DIR_OUT ) + if (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS) { - NRF_USBD->INTENSET = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + epnum); - NRF_USBD->EPOUTEN |= TU_BIT(epnum); - }else + if (dir == TUSB_DIR_OUT) + { + NRF_USBD->INTENSET = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + epnum); + NRF_USBD->EPOUTEN |= TU_BIT(epnum); + }else + { + NRF_USBD->INTENSET = TU_BIT(USBD_INTEN_ENDEPIN0_Pos + epnum); + NRF_USBD->EPINEN |= TU_BIT(epnum); + } + } + else { - NRF_USBD->INTENSET = TU_BIT(USBD_INTEN_ENDEPIN0_Pos + epnum); - NRF_USBD->EPINEN |= TU_BIT(epnum); + TU_ASSERT(epnum == EP_ISO_NUM); + if (dir == TUSB_DIR_OUT) + { + // SPLIT ISO buffer when ISO IN endpoint is already opened. + if (_dcd.xfer[EP_ISO_NUM][TUSB_DIR_IN].mps) NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN; + // Clear old events + NRF_USBD->EVENTS_ENDISOOUT = 0; + // Clear SOF event in case interrupt was not enabled yet. + if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0) NRF_USBD->EVENTS_SOF = 0; + // Enable SOF and ISOOUT interrupts, and ISOOUT endpoint. + NRF_USBD->INTENSET = USBD_INTENSET_ENDISOOUT_Msk | USBD_INTENSET_SOF_Msk; + NRF_USBD->EPOUTEN |= USBD_EPOUTEN_ISOOUT_Msk; + } + else + { + NRF_USBD->EVENTS_ENDISOIN = 0; + // SPLIT ISO buffer when ISO OUT endpoint is already opened. + if (_dcd.xfer[EP_ISO_NUM][TUSB_DIR_OUT].mps) NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN; + // Clear SOF event in case interrupt was not enabled yet. + if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0) NRF_USBD->EVENTS_SOF = 0; + // Enable SOF and ISOIN interrupts, and ISOIN endpoint. + NRF_USBD->INTENSET = USBD_INTENSET_ENDISOIN_Msk | USBD_INTENSET_SOF_Msk; + NRF_USBD->EPINEN |= USBD_EPINEN_ISOIN_Msk; + } } __ISB(); __DSB(); @@ -317,16 +372,39 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - // CBI - if (dir == TUSB_DIR_OUT) + if (epnum != EP_ISO_NUM) { - NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + epnum); - NRF_USBD->EPOUTEN &= ~TU_BIT(epnum); + // CBI + if (dir == TUSB_DIR_OUT) + { + NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + epnum); + NRF_USBD->EPOUTEN &= ~TU_BIT(epnum); + } + else + { + NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPIN0_Pos + epnum); + NRF_USBD->EPINEN &= ~TU_BIT(epnum); + } } else { - NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPIN0_Pos + epnum); - NRF_USBD->EPINEN &= ~TU_BIT(epnum); + _dcd.xfer[EP_ISO_NUM][dir].mps = 0; + // ISO + if (dir == TUSB_DIR_OUT) + { + NRF_USBD->INTENCLR = USBD_INTENCLR_ENDISOOUT_Msk; + NRF_USBD->EPOUTEN &= ~USBD_EPOUTEN_ISOOUT_Msk; + NRF_USBD->EVENTS_ENDISOOUT = 0; + } + else + { + NRF_USBD->INTENCLR = USBD_INTENCLR_ENDISOIN_Msk; + NRF_USBD->EPINEN &= ~USBD_EPINEN_ISOIN_Msk; + } + // One of the ISO endpoints closed, no need to split buffers any more. + NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_OneDir; + // When both ISO endpoint are close there is no need for SOF any more. + if (_dcd.xfer[EP_ISO_NUM][TUSB_DIR_IN].mps + _dcd.xfer[EP_ISO_NUM][TUSB_DIR_OUT].mps == 0) NRF_USBD->INTENCLR = USBD_INTENCLR_SOF_Msk; } __ISB(); __DSB(); } @@ -382,11 +460,12 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); - if ( tu_edpt_number(ep_addr) == 0 ) + if ( epnum == 0 ) { NRF_USBD->TASKS_EP0STALL = 1; - }else + }else if (epnum != EP_ISO_NUM) { NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_Stall << USBD_EPSTALL_STALL_Pos) | ep_addr; } @@ -397,8 +476,9 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); - if ( tu_edpt_number(ep_addr) ) + if ( epnum != 0 && epnum != EP_ISO_NUM ) { // clear stall NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr; @@ -456,8 +536,31 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); } + // ISOIN: Data was moved to endpoint buffer, client will be notified in SOF + if ( int_status & USBD_INTEN_ENDISOIN_Msk ) + { + xfer_td_t* xfer = get_td(EP_ISO_NUM, TUSB_DIR_IN); + + xfer->actual_len = NRF_USBD->ISOIN.AMOUNT; + // Data transferred from RAM to endpoint output buffer. + // Next transfer can be scheduled after SOF. + xfer->iso_in_transfer_ready = true; + } + if ( int_status & USBD_INTEN_SOF_Msk ) { + // ISOOUT: Transfer data gathered in previous frame from buffer to RAM + if (NRF_USBD->EPOUTEN & USBD_EPOUTEN_ISOOUT_Msk) + { + xact_out_dma(EP_ISO_NUM); + } + // ISOIN: Notify client that data was transferred + xfer_td_t* xfer = get_td(EP_ISO_NUM, TUSB_DIR_IN); + if ( xfer->iso_in_transfer_ready ) + { + xfer->iso_in_transfer_ready = false; + dcd_event_xfer_complete(0, EP_ISO_NUM | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true); + } dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } @@ -539,8 +642,11 @@ void dcd_int_handler(uint8_t rhport) * Note: Since nRF controller auto ACK next packet without SW awareness * We must handle this stage before Host -> Endpoint just in case * 2 event happens at once + * ISO OUT: Transaction must fit in single packed, it can be shorter then total + * len if Host decides to sent fewer bytes, it this case transaction is also + * complete and next transfer is not initiated here like for CBI. */ - for(uint8_t epnum=0; epnum<8; epnum++) + for(uint8_t epnum=0; epnumdata_received = false; // Transfer complete if transaction len < Max Packet Size or total len is transferred - if ( (xact_len == xfer->mps) && (xfer->actual_len < xfer->total_len) ) + if ( (epnum != EP_ISO_NUM) && (xact_len == xfer->mps) && (xfer->actual_len < xfer->total_len) ) { // Prepare for next transaction xact_out_prepare(epnum); -- cgit v1.3.1 From 603ce17696dfb930f93649d82a87702fd89f303f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 1 Oct 2020 17:49:30 +0200 Subject: Change AUDIO_CS_INTERFACE_HEADER to AUDIO_CS_AC_INTERFACE_HEADER --- src/device/usbd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index 07156c079..69cb5319d 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -262,7 +262,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Audio Control (AC) Interface */\ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, _stridx,\ /* AC Header */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ + 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ /* MIDI Streaming (MS) Interface */\ 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, 0,\ /* MS Header */\ -- cgit v1.3.1 From 849681724af698c77b01a615595418ba2efd543e Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Thu, 1 Oct 2020 11:51:33 -0500 Subject: create N functions and inlines for multi hid interfaces --- src/class/hid/hid_device.c | 24 ++++++++++----------- src/class/hid/hid_device.h | 53 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 57 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 10267d734..04ea31326 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -70,17 +70,17 @@ static inline hidd_interface_t* get_interface_by_itfnum(uint8_t itf_num) //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ -bool tud_hid_ready(void) +bool tud_hid_n_ready(uint8_t itf) { - uint8_t const itf = 0; + //uint8_t const itf = 0; uint8_t const ep_in = _hidd_itf[itf].ep_in; return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } -bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) +bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len) { uint8_t const rhport = 0; - uint8_t const itf = 0; + //uint8_t const itf = 0; hidd_interface_t * p_hid = &_hidd_itf[itf]; // claim endpoint @@ -104,16 +104,16 @@ bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) return usbd_edpt_xfer(TUD_OPT_RHPORT, p_hid->ep_in, p_hid->epin_buf, len); } -bool tud_hid_boot_mode(void) +bool tud_hid_n_boot_mode(uint8_t itf) { - uint8_t itf = 0; + //uint8_t itf = 0; return _hidd_itf[itf].boot_mode; } //--------------------------------------------------------------------+ // KEYBOARD API //--------------------------------------------------------------------+ -bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) +bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) { hid_keyboard_report_t report; @@ -127,13 +127,13 @@ bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycod tu_memclr(report.keycode, 6); } - return tud_hid_report(report_id, &report, sizeof(report)); + return tud_hid_n_report(itf, report_id, &report, sizeof(report)); } //--------------------------------------------------------------------+ // MOUSE APPLICATION API //--------------------------------------------------------------------+ -bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) +bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) { hid_mouse_report_t report = { @@ -144,7 +144,7 @@ bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y .pan = horizontal }; - return tud_hid_report(report_id, &report, sizeof(report)); + return tud_hid_n_report(itf, report_id, &report, sizeof(report)); } //--------------------------------------------------------------------+ @@ -197,7 +197,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 p_hid->boot_mode = false; // default mode is REPORT p_hid->itf_num = desc_itf->bInterfaceNumber; - + // Use offsetof to avoid pointer to the odd/misaligned address memcpy(&p_hid->report_desc_len, (uint8_t*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength), 2); diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 1e584e4c9..e6961515c 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -50,25 +50,35 @@ #endif //--------------------------------------------------------------------+ -// Application API +// Application API (Multiple Ports) +// CFG_TUD_HID > 1 //--------------------------------------------------------------------+ // Check if the interface is ready to use -bool tud_hid_ready(void); +bool tud_hid_n_ready(uint8_t itf); // Check if current mode is Boot (true) or Report (false) -bool tud_hid_boot_mode(void); +bool tud_hid_n_boot_mode(uint8_t itf); // Send report to host -bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); +bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len); // KEYBOARD: convenient helper to send keyboard report if application // use template layout report as defined by hid_keyboard_report_t -bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); +bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); // MOUSE: convenient helper to send mouse report if application // use template layout report as defined by hid_mouse_report_t -bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); + +//--------------------------------------------------------------------+ +// Application API (Single Port) +//--------------------------------------------------------------------+ +static inline bool tud_hid_ready(void); +static inline bool tud_hid_boot_mode(void); +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); +static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); +static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); //--------------------------------------------------------------------+ // Callbacks (Weak is optional) @@ -95,6 +105,34 @@ TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode); // - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); +//--------------------------------------------------------------------+ +// Inline Functions +//--------------------------------------------------------------------+ +static inline bool tud_hid_ready(void) +{ + return tud_hid_n_ready(0); +} + +static inline bool tud_hid_boot_mode(void) +{ + return tud_hid_n_boot_mode(0); +} + +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) +{ + return tud_hid_n_report(0, report_id, report, len); +} + +static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) +{ + return tud_hid_n_keyboard_report(0, report_id, modifier, keycode); +} + +static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) +{ + return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); +} + /* --------------------------------------------------------------------+ * HID Report Descriptor Template * @@ -318,4 +356,3 @@ bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t e #endif #endif /* _TUSB_HID_DEVICE_H_ */ - -- cgit v1.3.1 From b7208d6f7e97e724853eb5d0e512a23005cc8790 Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Thu, 1 Oct 2020 12:51:48 -0500 Subject: add index to report descriptor callback. this is breaking and needs to be reviewed --- src/class/hid/hid_device.c | 2 +- src/class/hid/hid_device.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 04ea31326..b4c75e3fb 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -237,7 +237,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request } else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { - uint8_t const * desc_report = tud_hid_descriptor_report_cb(); + uint8_t const * desc_report = tud_hid_descriptor_report_cb((uint8_t) request->wIndex); tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); } else diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index e6961515c..1873c4f09 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -86,7 +86,8 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 // Invoked when received GET HID REPORT DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(void); +// TODO Talk about this change... because it is breaking. Might be better way to handle. +uint8_t const * tud_hid_descriptor_report_cb(uint8_t desc_index); // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. -- cgit v1.3.1 From 081af79009dc40ab41be9976d22629c7d251a50d Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Fri, 2 Oct 2020 16:02:00 -0500 Subject: fix simple pull request comments. Implement descriptor index hack. --- examples/device/hid_multipleinterface/src/main.c | 8 ++--- .../hid_multipleinterface/src/usb_descriptors.c | 5 ++-- .../hid_multipleinterface/src/usb_descriptors.h | 34 ---------------------- src/class/hid/hid_device.c | 20 ++++++++++--- src/class/hid/hid_device.h | 5 +++- 5 files changed, 25 insertions(+), 47 deletions(-) delete mode 100644 examples/device/hid_multipleinterface/src/usb_descriptors.h (limited to 'src') diff --git a/examples/device/hid_multipleinterface/src/main.c b/examples/device/hid_multipleinterface/src/main.c index 985d87246..2efb1f5cb 100644 --- a/examples/device/hid_multipleinterface/src/main.c +++ b/examples/device/hid_multipleinterface/src/main.c @@ -30,8 +30,6 @@ #include "bsp/board.h" #include "tusb.h" -#include "usb_descriptors.h" - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ @@ -138,13 +136,13 @@ void hid_task(void) uint8_t keycode[6] = { 0 }; keycode[0] = HID_KEY_A; - tud_hid_n_keyboard_report(keyboard_interface, REPORT_ID_KEYBOARD, 0, keycode); + tud_hid_n_keyboard_report(keyboard_interface, 0, 0, keycode); has_key = true; }else { // send empty key report if previously has key pressed - if (has_key) tud_hid_n_keyboard_report(keyboard_interface, REPORT_ID_KEYBOARD, 0, NULL); + if (has_key) tud_hid_n_keyboard_report(keyboard_interface, 0, 0, NULL); has_key = false; } } @@ -157,7 +155,7 @@ void hid_task(void) int8_t const delta = 5; // no button, right + down, no scroll pan - tud_hid_n_mouse_report(mouse_interface, REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0); + tud_hid_n_mouse_report(mouse_interface, 0, 0x00, delta, delta, 0, 0); // delay a bit before attempt to send keyboard report board_delay(10); diff --git a/examples/device/hid_multipleinterface/src/usb_descriptors.c b/examples/device/hid_multipleinterface/src/usb_descriptors.c index f8423bdd1..a1a98c773 100644 --- a/examples/device/hid_multipleinterface/src/usb_descriptors.c +++ b/examples/device/hid_multipleinterface/src/usb_descriptors.c @@ -24,7 +24,6 @@ */ #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. @@ -73,12 +72,12 @@ uint8_t const * tud_descriptor_device_cb(void) uint8_t const desc_hid_report1[] = { - TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD) ) + TUD_HID_REPORT_DESC_KEYBOARD() }; uint8_t desc_hid_report2[] = { - TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE) ) + TUD_HID_REPORT_DESC_MOUSE() }; // Invoked when received GET HID REPORT DESCRIPTOR diff --git a/examples/device/hid_multipleinterface/src/usb_descriptors.h b/examples/device/hid_multipleinterface/src/usb_descriptors.h deleted file mode 100644 index 6992d3349..000000000 --- a/examples/device/hid_multipleinterface/src/usb_descriptors.h +++ /dev/null @@ -1,34 +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_ - -enum -{ - REPORT_ID_KEYBOARD = 1, - REPORT_ID_MOUSE -}; - -#endif /* USB_DESCRIPTORS_H_ */ diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index b4c75e3fb..9e1c5fd33 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -67,12 +67,21 @@ static inline hidd_interface_t* get_interface_by_itfnum(uint8_t itf_num) return NULL; } +static inline uint8_t get_descindex_by_itfnum(uint8_t itf_num) +{ + for (uint8_t i=0; i < CFG_TUD_HID; i++ ) + { + if ( itf_num == _hidd_itf[i].itf_num ) return i; + } + + return 0; +} + //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ bool tud_hid_n_ready(uint8_t itf) { - //uint8_t const itf = 0; uint8_t const ep_in = _hidd_itf[itf].ep_in; return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } @@ -80,7 +89,6 @@ bool tud_hid_n_ready(uint8_t itf) bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len) { uint8_t const rhport = 0; - //uint8_t const itf = 0; hidd_interface_t * p_hid = &_hidd_itf[itf]; // claim endpoint @@ -106,7 +114,6 @@ bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_ bool tud_hid_n_boot_mode(uint8_t itf) { - //uint8_t itf = 0; return _hidd_itf[itf].boot_mode; } @@ -237,7 +244,12 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request } else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { - uint8_t const * desc_report = tud_hid_descriptor_report_cb((uint8_t) request->wIndex); + #if CFG_TUD_HID>1 + uint8_t const calculated_desc_index = get_descindex_by_itfnum((uint8_t) request->wIndex); + uint8_t const * desc_report = tud_hid_descriptor_report_cb(calculated_desc_index); + #else + uint8_t const * desc_report = tud_hid_descriptor_report_cb(); + #endif tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); } else diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 1873c4f09..30d99ce47 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -86,8 +86,11 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 // Invoked when received GET HID REPORT DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -// TODO Talk about this change... because it is breaking. Might be better way to handle. +#if CFG_TUD_HID>1 uint8_t const * tud_hid_descriptor_report_cb(uint8_t desc_index); +#else +uint8_t const * tud_hid_descriptor_report_cb(void); +#endif // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. -- cgit v1.3.1 From 2050dc0dc743294b07d0534278027da689bc6813 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Oct 2020 09:46:22 +0200 Subject: Revert #define CFG_TUSB_DEBUG 2 to #define CFG_TUSB_DEBUG 0 Change 1 << 31 to 0x100000000 in audio.h --- src/class/audio/audio.h | 2 +- src/tusb_option.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 0027217cb..7e591fbe6 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -489,7 +489,7 @@ typedef enum AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = (uint32_t) (1 << 31), + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, } audio_data_format_type_I_t; /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification diff --git a/src/tusb_option.h b/src/tusb_option.h index cd7a0543f..e1ee45bde 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -171,7 +171,7 @@ // Debug enable to print out error message #ifndef CFG_TUSB_DEBUG - #define CFG_TUSB_DEBUG 2 + #define CFG_TUSB_DEBUG 0 #endif // place data in accessible RAM for usb controller -- cgit v1.3.1 From 78477077b418a25efa58ef0fb426d0cacb24d902 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sat, 26 Sep 2020 04:24:30 +0200 Subject: Use C++11 static_assert when available --- src/common/tusb_compiler.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 6f6aa3c39..505542078 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -44,8 +44,10 @@ #endif // Compile-time Assert -#if __STDC_VERSION__ >= 201112L +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define TU_VERIFY_STATIC _Static_assert +#elif defined (__cplusplus) && __cplusplus >= 201103L + #define TU_VERIFY_STATIC static_assert #else #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } #endif -- cgit v1.3.1 From 51fb659533c4c417b6771a801756ccc02d2b85f7 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sat, 26 Sep 2020 04:26:59 +0200 Subject: Use tu_printf instead of printf --- src/common/tusb_verify.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 406f5e6ee..ab721b4d8 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -76,8 +76,8 @@ #if CFG_TUSB_DEBUG #include - #define _MESS_ERR(_err) printf("%s %d: failed, error = %s\r\n", __func__, __LINE__, tusb_strerr[_err]) - #define _MESS_FAILED() printf("%s %d: assert failed\r\n", __func__, __LINE__) + #define _MESS_ERR(_err) tu_printf("%s %d: failed, error = %s\r\n", __func__, __LINE__, tusb_strerr[_err]) + #define _MESS_FAILED() tu_printf("%s %d: assert failed\r\n", __func__, __LINE__) #else #define _MESS_ERR(_err) do {} while (0) #define _MESS_FAILED() do {} while (0) -- cgit v1.3.1 From e41d9202b81b0f3357c2feec2bca0c0a20b5478b Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sat, 26 Sep 2020 04:30:22 +0200 Subject: Allow overwriting TU_ASSERT etc macros --- src/common/tusb_verify.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index ab721b4d8..8b724aef8 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -142,7 +142,9 @@ #define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), false) #define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), _ret) +#ifndef TU_ASSERT #define TU_ASSERT(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__) +#endif // TODO remove TU_ASSERT_ERR() later @@ -163,10 +165,12 @@ /* ASSERT Error * basically TU_VERIFY Error with TU_BREAKPOINT() as handler *------------------------------------------------------------------*/ -#define ASERT_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, TU_BREAKPOINT()) -#define ASERT_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, TU_BREAKPOINT(), _ret) +#define ASSERT_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, TU_BREAKPOINT()) +#define ASSERT_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, TU_BREAKPOINT(), _ret) -#define TU_ASSERT_ERR(...) GET_3RD_ARG(__VA_ARGS__, ASERT_ERR_2ARGS, ASERT_ERR_1ARGS,UNUSED)(__VA_ARGS__) +#ifndef TU_ASSERT_ERR +#define TU_ASSERT_ERR(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_ERR_2ARGS, ASSERT_ERR_1ARGS,UNUSED)(__VA_ARGS__) +#endif /*------------------------------------------------------------------*/ /* ASSERT HDLR -- cgit v1.3.1 From 788dcc200de76c965208c428ab1e1de0e72c98c1 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sat, 26 Sep 2020 05:40:24 +0200 Subject: Change CFG_TUSB_CONFIG_FILE mechanism to improve header file scanning --- src/tusb_option.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/tusb_option.h b/src/tusb_option.h index 7e486bff0..28bbcf89e 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -110,11 +110,13 @@ // Allow to use command line to change the config name/location -#ifndef CFG_TUSB_CONFIG_FILE - #define CFG_TUSB_CONFIG_FILE "tusb_config.h" +#ifdef CFG_TUSB_CONFIG_FILE + #include CFG_TUSB_CONFIG_FILE +#else + #include "tusb_config.h" #endif -#include CFG_TUSB_CONFIG_FILE + /** \addtogroup group_configuration * @{ */ -- cgit v1.3.1 From 020ad47bb004cb01e2c7834a34d74da66cef3532 Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Mon, 5 Oct 2020 22:40:00 -0700 Subject: stm32: fix ISTR and CTR_RX/TX race conditions --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 18 +++++++++++------- src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h | 8 ++++++-- 2 files changed, 17 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 32179874e..033d7cbd7 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -203,6 +203,11 @@ static inline void reg16_clear_bits(__IO uint16_t *reg, uint16_t mask) { *reg = (uint16_t)(*reg & ~mask); } +// Bits in ISTR are cleared upon writing 0 +static inline void clear_istr_bits(uint16_t mask) { + USB->ISTR = ~mask; +} + void dcd_init (uint8_t rhport) { /* Clocks should already be enabled */ @@ -231,7 +236,7 @@ void dcd_init (uint8_t rhport) USB->BTABLE = DCD_STM32_BTABLE_BASE; - reg16_clear_bits(&USB->ISTR, USB_ISTR_ALL_EVENTS); // Clear pending interrupts + USB->ISTR = 0; // Clear pending interrupts // Reset endpoints to disabled for(uint32_t i=0; iISTR, USB_ISTR_RESET); + clear_istr_bits(USB_ISTR_RESET); dcd_handle_bus_reset(); dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); return; // Don't do the rest of the things here; perhaps they've been cleared? @@ -523,14 +528,13 @@ void dcd_int_handler(uint8_t rhport) { /* servicing of the endpoint correct transfer interrupt */ /* clear of the CTR flag into the sub */ dcd_ep_ctr_handler(); - reg16_clear_bits(&USB->ISTR, USB_ISTR_CTR); } if (int_status & USB_ISTR_WKUP) { reg16_clear_bits(&USB->CNTR, USB_CNTR_LPMODE); reg16_clear_bits(&USB->CNTR, USB_CNTR_FSUSP); - reg16_clear_bits(&USB->ISTR, USB_ISTR_WKUP); + clear_istr_bits(USB_ISTR_WKUP); dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } @@ -544,13 +548,13 @@ void dcd_int_handler(uint8_t rhport) { USB->CNTR |= USB_CNTR_LPMODE; /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ - reg16_clear_bits(&USB->ISTR, USB_ISTR_SUSP); + clear_istr_bits(USB_ISTR_SUSP); dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } #if USE_SOF if(int_status & USB_ISTR_SOF) { - reg16_clear_bits(&USB->ISTR, USB_ISTR_SOF); + clear_istr_bits(USB_ISTR_SOF); dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } #endif @@ -564,7 +568,7 @@ void dcd_int_handler(uint8_t rhport) { { remoteWakeCountdown--; } - reg16_clear_bits(&USB->ISTR, USB_ISTR_ESOF); + clear_istr_bits(USB_ISTR_ESOF); } } diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h index 4f2b2294e..d26c700d2 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h @@ -143,13 +143,17 @@ static inline uint32_t pcd_get_eptype(USB_TypeDef * USBx, uint32_t bEpNum) static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpNum) { uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); - regVal &= 0x7FFFu & USB_EPREG_MASK; + regVal &= USB_EPREG_MASK; + regVal &= ~USB_EP_CTR_RX; + regVal |= USB_EP_CTR_TX; // preserve CTR_TX (clears on writing 0) pcd_set_endpoint(USBx, bEpNum, regVal); } static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpNum) { uint32_t regVal = pcd_get_endpoint(USBx, bEpNum); - regVal &= regVal & 0xFF7FU & USB_EPREG_MASK; + regVal &= USB_EPREG_MASK; + regVal &= ~USB_EP_CTR_TX; + regVal |= USB_EP_CTR_RX; // preserve CTR_RX (clears on writing 0) pcd_set_endpoint(USBx, bEpNum,regVal); } /** -- cgit v1.3.1 From 3f54c27afa39a3b9f2e5911b566416be460389fb Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Oct 2020 13:36:03 +0700 Subject: fix audio_test build --- .github/workflows/build.yml | 1 + examples/device/audio_test/.skip.MCU_SAMD11 | 0 examples/device/audio_test/.skip.MCU_SAMG | 0 examples/device/audio_test/src/main.c | 44 +++++++++++++++-------- examples/rules.mk | 1 + src/class/audio/audio.h | 56 ++++++++++++++++++----------- src/class/audio/audio_device.c | 8 +++-- src/class/audio/audio_device.h | 9 ++++- src/common/tusb_common.h | 8 ++--- 9 files changed, 85 insertions(+), 42 deletions(-) create mode 100644 examples/device/audio_test/.skip.MCU_SAMD11 create mode 100644 examples/device/audio_test/.skip.MCU_SAMG (limited to 'src') diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index da1f9e5e0..a891408ca 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,6 +27,7 @@ jobs: fail-fast: false matrix: example: + - 'device/audio_test' - 'device/board_test' - 'device/cdc_dual_ports' - 'device/cdc_msc' diff --git a/examples/device/audio_test/.skip.MCU_SAMD11 b/examples/device/audio_test/.skip.MCU_SAMD11 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/audio_test/.skip.MCU_SAMG b/examples/device/audio_test/.skip.MCU_SAMG new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index e55c64c7c..2ea1d36c6 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -137,6 +137,7 @@ void audio_task(void) bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) { (void) rhport; + (void) pBuff; // We do not support any set range requests here, only current value requests TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); @@ -146,6 +147,8 @@ bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t ep = TU_U16_LOW(p_request->wIndex); + (void) channelNum; (void) ctrlSel; (void) ep; + return false; // Yet not implemented } @@ -153,6 +156,7 @@ bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) { (void) rhport; + (void) pBuff; // We do not support any set range requests here, only current value requests TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); @@ -162,6 +166,8 @@ bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_r uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t itf = TU_U16_LOW(p_request->wIndex); + (void) channelNum; (void) ctrlSel; (void) itf; + return false; // Yet not implemented } @@ -176,39 +182,43 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * uint8_t itf = TU_U16_LOW(p_request->wIndex); uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + (void) itf; + // We do not support any set range requests here, only current value requests TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); // If request is for our feature unit - if (entityID == 2) + if ( entityID == 2 ) { - switch (ctrlSel) + switch ( ctrlSel ) { case AUDIO_FU_CTRL_MUTE: - // Request uses format layout 1 - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); + // Request uses format layout 1 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); - mute[channelNum] = ((audio_control_cur_1_t *)pBuff)->bCur; + mute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; - TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); + TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); - return true; + return true; case AUDIO_FU_CTRL_VOLUME: - // Request uses format layout 2 - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); + // Request uses format layout 2 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); - volume[channelNum] = ((audio_control_cur_2_t *)pBuff)->bCur; + volume[channelNum] = ((audio_control_cur_2_t*) pBuff)->bCur; - TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); + TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); - return true; + return true; - // Unknown/Unsupported control - default: TU_BREAKPOINT(); return false; + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; } } - return false; // Yet not implemented + return false; // Yet not implemented } // Invoked when audio class specific get request received for an EP @@ -221,6 +231,8 @@ bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t ep = TU_U16_LOW(p_request->wIndex); + (void) channelNum; (void) ctrlSel; (void) ep; + // return tud_control_xfer(rhport, p_request, &tmp, 1); return false; // Yet not implemented @@ -236,6 +248,8 @@ bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_r uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t itf = TU_U16_LOW(p_request->wIndex); + (void) channelNum; (void) ctrlSel; (void) itf; + return false; // Yet not implemented } diff --git a/examples/rules.mk b/examples/rules.mk index dacb81363..066956a40 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -33,6 +33,7 @@ SRC_C += \ src/common/tusb_fifo.c \ src/device/usbd.c \ src/device/usbd_control.c \ + src/class/audio/audio_device.c \ src/class/cdc/cdc_device.c \ src/class/dfu/dfu_rt_device.c \ src/class/hid/hid_device.c \ diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 7e591fbe6..05e61f8df 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -469,28 +469,44 @@ typedef enum /// Additional Audio Device Class Codes - Source: Audio Data Formats /// A.1 - Audio Class-Format Type Codes UAC2 -typedef enum -{ - AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, - AUDIO_FORMAT_TYPE_I = 0x01, - AUDIO_FORMAT_TYPE_II = 0x02, - AUDIO_FORMAT_TYPE_III = 0x03, - AUDIO_FORMAT_TYPE_IV = 0x04, - AUDIO_EXT_FORMAT_TYPE_I = 0x81, - AUDIO_EXT_FORMAT_TYPE_II = 0x82, - AUDIO_EXT_FORMAT_TYPE_III = 0x83, -} audio_format_type_t; +//typedef enum +//{ +// AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, +// AUDIO_FORMAT_TYPE_I = 0x01, +// AUDIO_FORMAT_TYPE_II = 0x02, +// AUDIO_FORMAT_TYPE_III = 0x03, +// AUDIO_FORMAT_TYPE_IV = 0x04, +// AUDIO_EXT_FORMAT_TYPE_I = 0x81, +// AUDIO_EXT_FORMAT_TYPE_II = 0x82, +// AUDIO_EXT_FORMAT_TYPE_III = 0x83, +//} audio_format_type_t; + +#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00 +#define AUDIO_FORMAT_TYPE_I 0x01 +#define AUDIO_FORMAT_TYPE_II 0x02 +#define AUDIO_FORMAT_TYPE_III 0x03 +#define AUDIO_FORMAT_TYPE_IV 0x04 +#define AUDIO_EXT_FORMAT_TYPE_I 0x81 +#define AUDIO_EXT_FORMAT_TYPE_II 0x82 +#define AUDIO_EXT_FORMAT_TYPE_III 0x83 /// A.2.1 - Audio Class-Audio Data Format Type I UAC2 -typedef enum -{ - AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), - AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), - AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), - AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), - AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, -} audio_data_format_type_I_t; +//typedef enum +//{ +// AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), +// AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), +// AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), +// AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), +// AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), +// AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, +//} audio_data_format_type_I_t; + +#define AUDIO_DATA_FORMAT_TYPE_I_PCM ((uint32_t) (1 << 0)) +#define AUDIO_DATA_FORMAT_TYPE_I_PCM8 ((uint32_t) (1 << 1)) +#define AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT ((uint32_t) (1 << 2)) +#define AUDIO_DATA_FORMAT_TYPE_I_ALAW ((uint32_t) (1 << 3)) +#define AUDIO_DATA_FORMAT_TYPE_I_MULAW ((uint32_t) (1 << 4)) +#define AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA 0x100000000 /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index d208d1c84..0f501bb6e 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -564,9 +564,10 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { - if (audio->tx_ff[cntChannel].count / CFG_TUD_AUDIO_TX_ITEMSIZE < nSamplesPerChannelToSend) + uint16_t const count = tu_fifo_count(&audio->tx_ff[cntChannel]); + if (count / CFG_TUD_AUDIO_TX_ITEMSIZE < nSamplesPerChannelToSend) { - nSamplesPerChannelToSend = audio->tx_ff[cntChannel].count * CFG_TUD_AUDIO_TX_ITEMSIZE; + nSamplesPerChannelToSend = count * CFG_TUD_AUDIO_TX_ITEMSIZE; } } @@ -782,6 +783,8 @@ void audiod_reset(uint8_t rhport) uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { + (void) max_len; + TU_VERIFY ( TUSB_CLASS_AUDIO == itf_desc->bInterfaceClass && AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); @@ -1171,6 +1174,7 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; + (void) xferred_bytes; // Search for interface belonging to given end point address and proceed as required uint8_t idxDriver; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index f4029a84c..ab223de6f 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -33,7 +33,6 @@ #include "device/usbd.h" #include "audio.h" -#include "tusb_config.h" //--------------------------------------------------------------------+ // Class Driver Configuration @@ -59,6 +58,10 @@ #define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel #endif +#ifndef CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE +#define CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE 0 +#endif + #if CFG_TUD_AUDIO_TX_FIFO_SIZE && CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE #error TX_FIFOs and TX_DMA_RINGBUFFER can not be used simultaneously! #endif @@ -193,6 +196,10 @@ uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t #endif */ +#ifndef CFG_TUD_AUDIO_TX_FIFO_COUNT +#define CFG_TUD_AUDIO_TX_FIFO_COUNT 1 +#endif + #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE #if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index d95c0ffc4..15892fa33 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -47,10 +47,10 @@ #define U16_TO_U8S_BE(u16) TU_U16_HIGH(u16), TU_U16_LOW(u16) #define U16_TO_U8S_LE(u16) TU_U16_LOW(u16), TU_U16_HIGH(u16) -#define U32_B1_U8(u32) ((uint8_t) (((u32) >> 24) & 0x000000ff)) // MSB -#define U32_B2_U8(u32) ((uint8_t) (((u32) >> 16) & 0x000000ff)) -#define U32_B3_U8(u32) ((uint8_t) (((u32) >> 8) & 0x000000ff)) -#define U32_B4_U8(u32) ((uint8_t) ((u32) & 0x000000ff)) // LSB +#define U32_B1_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 24) & 0x000000ff)) // MSB +#define U32_B2_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 16) & 0x000000ff)) +#define U32_B3_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 8) & 0x000000ff)) +#define U32_B4_U8(u32) ((uint8_t) (((uint32_t) u32) & 0x000000ff)) // LSB #define U32_TO_U8S_BE(u32) U32_B1_U8(u32), U32_B2_U8(u32), U32_B3_U8(u32), U32_B4_U8(u32) #define U32_TO_U8S_LE(u32) U32_B4_U8(u32), U32_B3_U8(u32), U32_B2_U8(u32), U32_B1_U8(u32) -- cgit v1.3.1 From 74a1404bea4a2cf4fd8ecb4ce227f19ba9fbe1a0 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Oct 2020 13:36:27 +0700 Subject: tab -> spaces --- src/device/usbd.h | 506 +++++++++++++++++++++++++++--------------------------- 1 file changed, 253 insertions(+), 253 deletions(-) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index 69cb5319d..1b0f0cbd3 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -67,7 +67,7 @@ bool tud_suspended(void); // Check if device is ready to transfer static inline bool tud_ready(void) { - return tud_mounted() && !tud_suspended(); + return tud_mounted() && !tud_suspended(); } // Remote wake up host, only if suspended and enabled by host @@ -141,11 +141,11 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // total length, number of device caps #define TUD_BOS_DESCRIPTOR(_total_len, _caps_num) \ - 5, TUSB_DESC_BOS, U16_TO_U8S_LE(_total_len), _caps_num + 5, TUSB_DESC_BOS, U16_TO_U8S_LE(_total_len), _caps_num // Device Capability Platform 128-bit UUID + Data #define TUD_BOS_PLATFORM_DESCRIPTOR(...) \ - 4+TU_ARGS_NUM(__VA_ARGS__), TUSB_DESC_DEVICE_CAPABILITY, DEVICE_CAPABILITY_PLATFORM, 0x00, __VA_ARGS__ + 4+TU_ARGS_NUM(__VA_ARGS__), TUSB_DESC_DEVICE_CAPABILITY, DEVICE_CAPABILITY_PLATFORM, 0x00, __VA_ARGS__ //------------- WebUSB BOS Platform -------------// @@ -154,22 +154,22 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Vendor Code, iLandingPage #define TUD_BOS_WEBUSB_DESCRIPTOR(_vendor_code, _ipage) \ - TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_WEBUSB_UUID, U16_TO_U8S_LE(0x0100), _vendor_code, _ipage) + TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_WEBUSB_UUID, U16_TO_U8S_LE(0x0100), _vendor_code, _ipage) #define TUD_BOS_WEBUSB_UUID \ - 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, \ - 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 + 0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, \ + 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65 //------------- Microsoft OS 2.0 Platform -------------// #define TUD_BOS_MICROSOFT_OS_DESC_LEN 28 // Total Length of descriptor set, vendor code #define TUD_BOS_MS_OS_20_DESCRIPTOR(_desc_set_len, _vendor_code) \ - TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_MS_OS_20_UUID, U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(_desc_set_len), _vendor_code, 0) + TUD_BOS_PLATFORM_DESCRIPTOR(TUD_BOS_MS_OS_20_UUID, U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(_desc_set_len), _vendor_code, 0) #define TUD_BOS_MS_OS_20_UUID \ - 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, \ - 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F + 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, \ + 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F //--------------------------------------------------------------------+ // Configuration & Interface Descriptor Templates @@ -180,7 +180,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Config number, interface count, string index, total length, attribute, power in mA #define TUD_CONFIG_DESCRIPTOR(config_num, _itfcount, _stridx, _total_len, _attribute, _power_ma) \ - 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 + 9, TUSB_DESC_CONFIGURATION, U16_TO_U8S_LE(_total_len), _itfcount, config_num, _stridx, TU_BIT(7) | _attribute, (_power_ma)/2 //------------- CDC -------------// @@ -190,26 +190,26 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // CDC Descriptor Template // 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_NONE, 0,\ - /* CDC Control Interface */\ - 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 */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* CDC ACM: support line request */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ - /* CDC Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\ - /* CDC Data Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface Associate */\ + 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_NONE, _stridx,\ + /* CDC Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC Call */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* CDC ACM: support line request */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* Endpoint Notification */\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\ + /* CDC Data Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- MSC -------------// @@ -218,12 +218,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, string index, EP Out & EP In address, EP size #define TUD_MSC_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_MSC, MSC_SUBCLASS_SCSI, MSC_PROTOCOL_BOT, _stridx,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_MSC, MSC_SUBCLASS_SCSI, MSC_PROTOCOL_BOT, _stridx,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- HID -------------// @@ -233,12 +233,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // HID Input only descriptor // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval #define TUD_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ - /* HID descriptor */\ - 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + /* HID descriptor */\ + 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval // Length of template descriptor: 32 bytes #define TUD_HID_INOUT_DESC_LEN (9 + 9 + 7 + 7) @@ -246,57 +246,57 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // HID Input & Output descriptor // Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval #define TUD_HID_INOUT_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epout, _epin, _epsize, _ep_interval) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ - /* HID descriptor */\ - 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval, \ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + /* HID descriptor */\ + 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval, \ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval //------------- MIDI -------------// #define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) #define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ - /* Audio Control (AC) Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, _stridx,\ - /* AC Header */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ - /* MIDI Streaming (MS) Interface */\ - 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, 0,\ - /* MS Header */\ - 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) + /* Audio Control (AC) Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, _stridx,\ + /* AC Header */\ + 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ + /* MIDI Streaming (MS) Interface */\ + 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, 0,\ + /* MS Header */\ + 7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN) #define TUD_MIDI_JACKID_IN_EMB(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 1) + (uint8_t)(((_cablenum) - 1) * 4 + 1) #define TUD_MIDI_JACKID_IN_EXT(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 2) + (uint8_t)(((_cablenum) - 1) * 4 + 2) #define TUD_MIDI_JACKID_OUT_EMB(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 3) + (uint8_t)(((_cablenum) - 1) * 4 + 3) #define TUD_MIDI_JACKID_OUT_EXT(_cablenum) \ - (uint8_t)(((_cablenum) - 1) * 4 + 4) + (uint8_t)(((_cablenum) - 1) * 4 + 4) #define TUD_MIDI_DESC_JACK_LEN (6 + 6 + 9 + 9) #define TUD_MIDI_DESC_JACK(_cablenum) \ - /* MS In Jack (Embedded) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ - /* MS In Jack (External) */\ - 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ - /* MS Out Jack (Embedded), connected to In Jack External */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ - /* MS Out Jack (External), connected to In Jack Embedded */\ - 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 + /* MS In Jack (Embedded) */\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\ + /* MS In Jack (External) */\ + 6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\ + /* MS Out Jack (Embedded), connected to In Jack External */\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\ + /* MS Out Jack (External), connected to In Jack Embedded */\ + 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 #define TUD_MIDI_DESC_EP_LEN(_numcables) (7 + 4 + (_numcables)) #define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ - /* Endpoint */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* MS Endpoint (connected to embedded jack) */\ - (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables + /* Endpoint */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* MS Endpoint (connected to embedded jack) */\ + (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables // Length of template descriptor (88 bytes) #define TUD_MIDI_DESC_LEN (TUD_MIDI_DESC_HEAD_LEN + TUD_MIDI_DESC_JACK_LEN + TUD_MIDI_DESC_EP_LEN(1) * 2) @@ -305,181 +305,181 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // - 1 Embedded Jack In connected to 1 External Jack Out // - 1 Embedded Jack out connected to 1 External Jack In #define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ - TUD_MIDI_DESC_JACK(1),\ - TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ - TUD_MIDI_JACKID_IN_EMB(1),\ - TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ - TUD_MIDI_JACKID_OUT_EMB(1) + TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\ + TUD_MIDI_DESC_JACK(1),\ + TUD_MIDI_DESC_EP(_epout, _epsize, 1),\ + TUD_MIDI_JACKID_IN_EMB(1),\ + TUD_MIDI_DESC_EP(_epin, _epsize, 1),\ + TUD_MIDI_JACKID_OUT_EMB(1) //------------- AUDIO -------------// /* Standard Interface Association Descriptor (IAD) */ #define TUD_AUDIO_DESC_IAD_LEN 8 #define TUD_AUDIO_DESC_IAD(_firstitfs, _nitfs, _stridx) \ - TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx + TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx /* Standard AC Interface Descriptor(4.7.1) */ #define TUD_AUDIO_DESC_STD_AC_LEN 9 #define TUD_AUDIO_DESC_STD_AC(_itfnum, _nEPs, _stridx) /* _nEPs is 0 or 1 */\ - TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_INT_PROTOCOL_CODE_V2, _stridx + TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_INT_PROTOCOL_CODE_V2, _stridx /* Class-Specific AC Interface Header Descriptor(4.7.2) */ #define TUD_AUDIO_DESC_CS_AC_LEN 9 #define TUD_AUDIO_DESC_CS_AC(_bcdADC, _category, _totallen, _ctrl) /* _bcdADC : Audio Device Class Specification Release Number in Binary-Coded Decimal, _category : see audio_function_t, _totallen : Total number of bytes returned for the class-specific AudioControl interface i.e. Clock Source, Unit and Terminal descriptors - Do not include TUD_AUDIO_DESC_CS_AC_LEN, we already do this here*/ \ - TUD_AUDIO_DESC_CS_AC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(_bcdADC), _category, U16_TO_U8S_LE(_totallen + TUD_AUDIO_DESC_CS_AC_LEN), _ctrl + TUD_AUDIO_DESC_CS_AC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(_bcdADC), _category, U16_TO_U8S_LE(_totallen + TUD_AUDIO_DESC_CS_AC_LEN), _ctrl /* Clock Source Descriptor(4.7.2.1) */ #define TUD_AUDIO_DESC_CLK_SRC_LEN 8 #define TUD_AUDIO_DESC_CLK_SRC(_clkid, _attr, _ctrl, _assocTerm, _stridx) \ - TUD_AUDIO_DESC_CLK_SRC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, _clkid, _attr, _ctrl, _assocTerm, _stridx + TUD_AUDIO_DESC_CLK_SRC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, _clkid, _attr, _ctrl, _assocTerm, _stridx /* Input Terminal Descriptor(4.7.2.4) */ #define TUD_AUDIO_DESC_INPUT_TERM_LEN 17 #define TUD_AUDIO_DESC_INPUT_TERM(_termid, _termtype, _assocTerm, _clkid, _nchannelslogical, _channelcfg, _idxchannelnames, _ctrl, _stridx) \ - TUD_AUDIO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _clkid, _nchannelslogical, U32_TO_U8S_LE(_channelcfg), _idxchannelnames, U16_TO_U8S_LE(_ctrl), _stridx + TUD_AUDIO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _clkid, _nchannelslogical, U32_TO_U8S_LE(_channelcfg), _idxchannelnames, U16_TO_U8S_LE(_ctrl), _stridx /* Output Terminal Descriptor(4.7.2.5) */ #define TUD_AUDIO_DESC_OUTPUT_TERM_LEN 12 #define TUD_AUDIO_DESC_OUTPUT_TERM(_termid, _termtype, _assocTerm, _srcid, _clkid, _ctrl, _stridx) \ - TUD_AUDIO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _srcid, _clkid, U16_TO_U8S_LE(_ctrl), _stridx + TUD_AUDIO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _srcid, _clkid, U16_TO_U8S_LE(_ctrl), _stridx /* Feature Unit Descriptor(4.7.2.8) */ // 1 - Channel #define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN 6+(1+1)*4 #define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _stridx) \ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), _stridx + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), _stridx // For more channels, add definitions here /* Standard AS Interface Descriptor(4.9.1) */ #define TUD_AUDIO_DESC_STD_AS_INT_LEN 9 #define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ - TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_INT_PROTOCOL_CODE_V2, _stridx + TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_INT_PROTOCOL_CODE_V2, _stridx /* Class-Specific AS Interface Descriptor(4.9.2) */ #define TUD_AUDIO_DESC_CS_AS_INT_LEN 16 #define TUD_AUDIO_DESC_CS_AS_INT(_termid, _ctrl, _formattype, _formats, _nchannelsphysical, _channelcfg, _stridx) \ - TUD_AUDIO_DESC_CS_AS_INT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, _termid, _ctrl, _formattype, U32_TO_U8S_LE(_formats), _nchannelsphysical, U32_TO_U8S_LE(_channelcfg), _stridx + TUD_AUDIO_DESC_CS_AS_INT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, _termid, _ctrl, _formattype, U32_TO_U8S_LE(_formats), _nchannelsphysical, U32_TO_U8S_LE(_channelcfg), _stridx /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */ #define TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN 6 #define TUD_AUDIO_DESC_TYPE_I_FORMAT(_subslotsize, _bitresolution) /* _subslotsize is number of bytes per sample (i.e. subslot) and can be 1,2,3, or 4 */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _subslotsize, _bitresolution + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _subslotsize, _bitresolution /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */ #define TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN 7 #define TUD_AUDIO_DESC_STD_AS_ISO_EP(_ep, _attr, _maxEPsize, _interval) \ - TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN, TUSB_DESC_ENDPOINT, _ep, _attr, U16_TO_U8S_LE(_maxEPsize), _interval + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN, TUSB_DESC_ENDPOINT, _ep, _attr, U16_TO_U8S_LE(_maxEPsize), _interval /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ #define TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN 8 #define TUD_AUDIO_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \ - TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ #define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7 #define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source #define TUD_AUDIO_MIC_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) #define TUD_AUDIO_MIC_DESC_N_AS_INT 1 // Number of AS interfaces #define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ - /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ - /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ - /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ - /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ - /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ - /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ - /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ - /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ - /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ - /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ - /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) // AUDIO simple descriptor (UAC2) for mono speaker // - 1 Input Terminal, 2 Feature Unit (Mute and Volume Control), 3 Output Terminal, 4 Clock Source #define TUD_AUDIO_SPEAKER_MONO_FB_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN) + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN) #define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize, _epfb) \ - /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ - /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ - /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ - /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ - /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ - /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ - /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ - /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\ - /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ - /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ - /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ - /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ - /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\ + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ + /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\ //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) @@ -491,23 +491,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 */ \ - 0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx + /* 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) @@ -517,12 +517,12 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // Interface number, string index, EP Out & IN address, EP size #define TUD_VENDOR_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \ - /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _stridx,\ - /* Endpoint Out */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ - /* Endpoint In */\ - 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _stridx,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- DFU Runtime -------------// #define TUD_DFU_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) @@ -534,10 +534,10 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // DFU runtime descriptor // Interface number, string index, attributes, detach timeout, transfer size #define TUD_DFU_RT_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \ - /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_RT, _stridx, \ - /* Function */ \ - 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_RT, _stridx, \ + /* Function */ \ + 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) //------------- CDC-ECM -------------// @@ -548,26 +548,26 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // 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 */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ - /* CDC-ECM Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* CDC-ECM Functional Descriptor */\ - 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 (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 */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + /* 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 */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ + /* CDC-ECM Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* CDC-ECM Functional Descriptor */\ + 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 (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 */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 //------------- RNDIS -------------// @@ -590,26 +590,26 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // RNDIS Descriptor Template // Interface number, string index, EP notification address and size, EP data address (out, in) and size. #define TUD_RNDIS_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \ - /* Interface Association */\ - 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ - /* CDC Control Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ - /* CDC-ACM Header */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ - /* CDC Call Management */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ - /* ACM */\ - 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ - /* CDC Union */\ - 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* 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,\ - /* 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 + /* Interface Association */\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\ + /* CDC Control Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\ + /* CDC-ACM Header */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ + /* CDC Call Management */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\ + /* ACM */\ + 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\ + /* CDC Union */\ + 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ + /* 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,\ + /* 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 //------------- BT Radio -------------// #define TUD_BT_APP_CLASS (TUSB_CLASS_WIRELESS_CONTROLLER) @@ -626,20 +626,20 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re /* Primary Interface */ #define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ - /* Endpoint In for events */ \ - 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ - /* Endpoint In for ACL data */ \ - 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ - /* Endpoint Out for ACL data */ \ - 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 + 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Endpoint In for events */ \ + 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \ + /* Endpoint In for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1, \ + /* Endpoint Out for ACL data */ \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_BULK, U16_TO_U8S_LE(_ep_size), 1 #define TUD_BTH_ISO_ITF(_itfnum, _alt, _ep_in, _ep_out, _n) ,\ - /* Interface with 2 endpoints */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ - /* Isochronous endpoints */ \ - 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ - 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 + /* Interface with 2 endpoints */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 2, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \ + /* Isochronous endpoints */ \ + 7, TUSB_DESC_ENDPOINT, _ep_in, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1, \ + 7, TUSB_DESC_ENDPOINT, _ep_out, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(_n), 1 #define _FIRST(a, ...) a #define _REST(a, ...) __VA_ARGS__ @@ -647,24 +647,24 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re #define TUD_BTH_ISO_ITF_0(_itfnum, ...) #define TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 1, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 2, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_1(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 3, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_2(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 4, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_3(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 5, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_4(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITF_6(_itfnum, _ep_in, _ep_out, ...) TUD_BTH_ISO_ITF(_itfnum, (CFG_TUD_BTH_ISO_ALT_COUNT) - 6, _ep_in, _ep_out, _FIRST(__VA_ARGS__)) \ - TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) + TUD_BTH_ISO_ITF_5(_itfnum, _ep_in, _ep_out, _REST(__VA_ARGS__)) #define TUD_BTH_ISO_ITFS(_itfnum, _ep_in, _ep_out, ...) \ - TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) + TU_XSTRCAT(TUD_BTH_ISO_ITF_, CFG_TUD_BTH_ISO_ALT_COUNT)(_itfnum, _ep_in, _ep_out, __VA_ARGS__) // BT Primary controller descriptor // Interface number, string index, attributes, event endpoint, event endpoint size, interval, data in, data out, data endpoint size, iso endpoint sizes #define TUD_BTH_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size,...) \ - TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ - TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) + TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \ + TUD_BTH_ISO_ITFS(_itfnum + 1, _ep_in + 1, _ep_out + 1, __VA_ARGS__) #ifdef __cplusplus } -- cgit v1.3.1 From f700c08aeddd14ab5ae0a02a9eff330c5ae99dea Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 7 Oct 2020 10:57:12 +0200 Subject: Remove CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE which is not needed any more --- src/class/audio/audio_device.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index ab223de6f..d2f8155db 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -58,14 +58,6 @@ #define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel #endif -#ifndef CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE -#define CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE 0 -#endif - -#if CFG_TUD_AUDIO_TX_FIFO_SIZE && CFG_TUD_AUDIO_TX_DMA_RINGBUFFER_SIZE -#error TX_FIFOs and TX_DMA_RINGBUFFER can not be used simultaneously! -#endif - #ifndef CFG_TUD_AUDIO_RX_FIFO_SIZE #define CFG_TUD_AUDIO_RX_FIFO_SIZE 0 // Buffer size per channel #endif -- cgit v1.3.1 From db3fe97f62f22747df2c79a841bc1fb235f2f89e Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Wed, 7 Oct 2020 20:36:00 -0500 Subject: fix variable names. add itf n callbacks to multihid --- examples/device/hid_multipleinterface/src/main.c | 6 ++++-- .../hid_multipleinterface/src/usb_descriptors.c | 6 +++--- src/class/hid/hid_device.c | 22 +++++++++++++++++++--- src/class/hid/hid_device.h | 10 +++++++++- 4 files changed, 35 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/examples/device/hid_multipleinterface/src/main.c b/examples/device/hid_multipleinterface/src/main.c index 2efb1f5cb..b1957b9fc 100644 --- a/examples/device/hid_multipleinterface/src/main.c +++ b/examples/device/hid_multipleinterface/src/main.c @@ -167,9 +167,10 @@ void hid_task(void) // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) +uint16_t tud_hid_n_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { // TODO not Implemented + (void) itf; (void) report_id; (void) report_type; (void) buffer; @@ -180,9 +181,10 @@ uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) +void tud_hid_n_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { // TODO set LED based on CAPLOCK, NUMLOCK etc... + (void) itf; (void) report_id; (void) report_type; (void) buffer; diff --git a/examples/device/hid_multipleinterface/src/usb_descriptors.c b/examples/device/hid_multipleinterface/src/usb_descriptors.c index a1a98c773..396d22621 100644 --- a/examples/device/hid_multipleinterface/src/usb_descriptors.c +++ b/examples/device/hid_multipleinterface/src/usb_descriptors.c @@ -83,13 +83,13 @@ uint8_t desc_hid_report2[] = // 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(uint8_t desc_index) +uint8_t const * tud_hid_n_descriptor_report_cb(uint8_t itf) { - if (desc_index == 0) + if (itf == 0) { return desc_hid_report1; } - else if (desc_index == 1) + else if (itf == 1) { return desc_hid_report2; } diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 9e1c5fd33..ffd495306 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -67,7 +67,7 @@ static inline hidd_interface_t* get_interface_by_itfnum(uint8_t itf_num) return NULL; } -static inline uint8_t get_descindex_by_itfnum(uint8_t itf_num) +static inline uint8_t get_hid_index_by_itfnum(uint8_t itf_num) { for (uint8_t i=0; i < CFG_TUD_HID; i++ ) { @@ -230,6 +230,10 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) request->wIndex ); TU_ASSERT(p_hid); + #if CFG_TUD_HID>1 + uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t) request->wIndex); + #endif + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) { //------------- STD Request -------------// @@ -245,8 +249,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { #if CFG_TUD_HID>1 - uint8_t const calculated_desc_index = get_descindex_by_itfnum((uint8_t) request->wIndex); - uint8_t const * desc_report = tud_hid_descriptor_report_cb(calculated_desc_index); + uint8_t const * desc_report = tud_hid_n_descriptor_report_cb(hid_itf); #else uint8_t const * desc_report = tud_hid_descriptor_report_cb(); #endif @@ -268,7 +271,11 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); + #if CFG_TUD_HID>1 + uint16_t xferlen = tud_hid_n_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); + #else uint16_t xferlen = tud_hid_get_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); + #endif TU_ASSERT( xferlen > 0 ); tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); @@ -336,7 +343,12 @@ bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_requ uint8_t const report_type = tu_u16_high(p_request->wValue); uint8_t const report_id = tu_u16_low(p_request->wValue); + #if CFG_TUD_HID>1 + uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t)p_request->wIndex); + tud_hid_n_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); + #else tud_hid_set_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); + #endif } return true; @@ -358,7 +370,11 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if (ep_addr == p_hid->ep_out) { + #if CFG_TUD_HID>1 + tud_hid_n_set_report_cb(itf, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); + #else tud_hid_set_report_cb(0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); + #endif TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 30d99ce47..4b8cb17d5 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -87,7 +87,7 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 // Invoked when received GET HID REPORT DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete #if CFG_TUD_HID>1 -uint8_t const * tud_hid_descriptor_report_cb(uint8_t desc_index); +uint8_t const * tud_hid_n_descriptor_report_cb(uint8_t itf); #else uint8_t const * tud_hid_descriptor_report_cb(void); #endif @@ -95,11 +95,19 @@ uint8_t const * tud_hid_descriptor_report_cb(void); // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request +#if CFG_TUD_HID>1 +uint16_t tud_hid_n_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); +#else uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); +#endif // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) +#if CFG_TUD_HID>1 +void tud_hid_n_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); +#else void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); +#endif // Invoked when received SET_PROTOCOL request ( mode switch Boot <-> Report ) TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode); -- cgit v1.3.1 From 9edf4334c441afbcb24b723411c5cdef1fac56ec Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Thu, 1 Oct 2020 11:49:14 +0200 Subject: DA146xx: Allow receiving of packets larger then 64 bytes Internal FIFO for each endpoint is limited to 64 bytes. It is possible to have longer packets if respective FIFO is read during actual packet transmission. This change updates receive data path to allow packets (and endpoint size) larger then 64 bytes. If DMA is not used yet DMA is setup for reception of big packets. If DMA is already assigned to some transfer, code enables FIFO level warning interrupts and tries to read data before FIFO is filled up. --- src/portable/dialog/da146xx/dcd_da146xx.c | 258 +++++++++++++++++++++++------- 1 file changed, 203 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 602836e3a..9cc02e821 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -40,6 +40,24 @@ // We disable SOF for now until needed later on #define USE_SOF 0 +// Size of RX or TX FIFO. +#define FIFO_SIZE 64 + +#ifndef TU_DA1469X_FIFO_READ_THRESHOLD +// RX FIFO is 64 bytes. When endpoint size is greater then 64, FIFO warning interrupt +// is enabled to allow read incoming data during frame reception. +// It is possible to stay in interrupt reading whole packet at once, but it may be +// more efficient for MCU to read as much data as possible and when FIFO is hardly +// filled exit interrupt handler waiting for next FIFO warning level interrupt +// or packet end. +// When running at 96MHz code that reads FIFO based on number of bytes stored in +// USB_RXSx_REG.USB_RXCOUNT takes enough time to fill FIFO with two additional bytes. +// Settings this threshold above this allows to leave interrupt handler and wait +// for more bytes to before next ISR. This allows reduce overall ISR time to 1/3 +// of time that would be needed if ISR read as fast as possible. +#define TU_DA1469X_FIFO_READ_THRESHOLD 4 +#endif + #define EP_MAX 4 #define NFSR_NODE_RESET 0 @@ -119,6 +137,54 @@ typedef struct #define EP_REGS(first_ep_reg) (EPx_REGS*)(&USB->first_ep_reg) +// DMA channel pair to use, channel 6 will be used for RX channel 7 for TX direction. +#ifndef TU_DA146XX_DMA_RX_CHANNEL +#define TU_DA146XX_DMA_RX_CHANNEL 6 +#endif +#define DA146XX_DMA_USB_MUX (0x6 << (TU_DA146XX_DMA_RX_CHANNEL * 2)) +#define DA146XX_DMA_USB_MUX_MASK (0xF << (TU_DA146XX_DMA_RX_CHANNEL * 2)) + +typedef struct +{ + __IOM uint32_t DMAx_A_START_REG; + __IOM uint32_t DMAx_B_START_REG; + __IOM uint32_t DMAx_INT_REG; + __IOM uint32_t DMAx_LEN_REG; + __IOM uint32_t DMAx_CTRL_REG; + __IOM uint32_t DMAx_IDX_REG; + __IM uint32_t RESERVED[2]; // Extend structure size for array like usage, registers for each channel are 0x20 bytes apart. +} da146xx_dma_channel_t; + +#define DMA_CHANNEL_REGS(n) ((da146xx_dma_channel_t *)(DMA) + n) +#define RX_DMA_REGS DMA_CHANNEL_REGS(TU_DA146XX_DMA_RX_CHANNEL) +#define TX_DMA_REGS DMA_CHANNEL_REGS((TU_DA146XX_DMA_RX_CHANNEL) + 1) + +#define RX_DMA_START ((1 << DMA_DMA0_CTRL_REG_DMA_ON_Pos) |\ + (0 << DMA_DMA0_CTRL_REG_BW_Pos) | \ + (1 << DMA_DMA0_CTRL_REG_DREQ_MODE_Pos) | \ + (1 << DMA_DMA0_CTRL_REG_BINC_Pos) | \ + (0 << DMA_DMA0_CTRL_REG_AINC_Pos) | \ + (0 << DMA_DMA0_CTRL_REG_CIRCULAR_Pos) | \ + (2 << DMA_DMA0_CTRL_REG_DMA_PRIO_Pos) | \ + (0 << DMA_DMA0_CTRL_REG_DMA_IDLE_Pos) | \ + (0 << DMA_DMA0_CTRL_REG_DMA_INIT_Pos) | \ + (0 << DMA_DMA0_CTRL_REG_REQ_SENSE_Pos) | \ + (0 << DMA_DMA0_CTRL_REG_BURST_MODE_Pos) | \ + (0 << DMA_DMA0_CTRL_REG_BUS_ERROR_DETECT_Pos)) + +#define TX_DMA_START ((1 << DMA_DMA0_CTRL_REG_DMA_ON_Pos) |\ + (0 << DMA_DMA0_CTRL_REG_BW_Pos) | \ + (1 << DMA_DMA0_CTRL_REG_DREQ_MODE_Pos) | \ + (0 << DMA_DMA0_CTRL_REG_BINC_Pos) | \ + (1 << DMA_DMA0_CTRL_REG_AINC_Pos) | \ + (0 << DMA_DMA0_CTRL_REG_CIRCULAR_Pos) | \ + (2 << DMA_DMA0_CTRL_REG_DMA_PRIO_Pos) | \ + (0 << DMA_DMA0_CTRL_REG_DMA_IDLE_Pos) | \ + (0 << DMA_DMA0_CTRL_REG_DMA_INIT_Pos) | \ + (1 << DMA_DMA0_CTRL_REG_REQ_SENSE_Pos) | \ + (0 << DMA_DMA0_CTRL_REG_BURST_MODE_Pos) | \ + (0 << DMA_DMA0_CTRL_REG_BUS_ERROR_DETECT_Pos)) + // Dialog register fields and bit mask are very long. Filed masks repeat register names. // Those convenience macros are a way to reduce complexity of register modification lines. #define GET_BIT(val, field) (val & field ## _Msk) >> field ## _Pos @@ -151,6 +217,8 @@ static struct bool vbus_present; bool in_reset; xfer_ctl_t xfer_status[EP_MAX][2]; + // Endpoints that use DMA, one for each direction + uint8_t dma_ep[2]; } _dcd = { .vbus_present = false, @@ -258,35 +326,93 @@ static void transmit_packet(xfer_ctl_t * xfer) regs->txc = txc; } -static void receive_packet(xfer_ctl_t *xfer, uint16_t bytes_in_fifo) +static bool try_allocate_dma(uint8_t epnum, uint8_t dir) { - EPx_REGS *regs = xfer->regs; + // TODO: Disable interrupts while checking + if (_dcd.dma_ep[dir] == 0) + { + _dcd.dma_ep[dir] = epnum; + if (dir == TUSB_DIR_OUT) + USB->USB_DMA_CTRL_REG = (USB->USB_DMA_CTRL_REG & ~USB_USB_DMA_CTRL_REG_USB_DMA_RX_Msk) | + ((epnum - 1) << USB_USB_DMA_CTRL_REG_USB_DMA_RX_Pos); + else + USB->USB_DMA_CTRL_REG = (USB->USB_DMA_CTRL_REG & ~USB_USB_DMA_CTRL_REG_USB_DMA_TX_Msk) | + ((epnum - 1) << USB_USB_DMA_CTRL_REG_USB_DMA_TX_Pos); + USB->USB_DMA_CTRL_REG |= USB_USB_DMA_CTRL_REG_USB_DMA_EN_Msk; + } + return _dcd.dma_ep[dir] == epnum; +} + +static void start_rx_dma(volatile void *src, void *dst, uint16_t size) +{ + // Setup SRC and DST registers + RX_DMA_REGS->DMAx_A_START_REG = (uint32_t)src; + RX_DMA_REGS->DMAx_B_START_REG = (uint32_t)dst; + // Don't need DMA interrupt, read end is determined by RX_LAST or RX_ERR events. + RX_DMA_REGS->DMAx_INT_REG = size - 1; + RX_DMA_REGS->DMAx_LEN_REG = size - 1; + RX_DMA_REGS->DMAx_CTRL_REG = RX_DMA_START; +} + +static void start_rx_packet(xfer_ctl_t *xfer) +{ + uint8_t const epnum = tu_edpt_number(xfer->ep_addr); uint16_t remaining = xfer->total_len - xfer->transferred; + uint16_t size = tu_min16(remaining, xfer->max_packet_size); + + xfer->last_packet_size = 0; + if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE) + { + if (try_allocate_dma(epnum, TUSB_DIR_OUT)) + { + start_rx_dma(&xfer->regs->rxd, xfer->buffer + xfer->transferred, size); + } + else + { + // Other endpoint is using DMA in that direction, fall back to interrupts. + // For endpoint size greater then FIFO size enable FIFO level warning interrupt + // when FIFO has less then 17 bytes free. + xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RFWL_Msk; + USB->USB_FWMSK_REG |= 1 << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_RXWARN31_Pos); + } + } + else if (epnum != 0) + { + // If max_packet_size would fit in FIFO no need for FIFO level warning interrupt. + xfer->regs->rxc &= ~USB_USB_RXC1_REG_USB_RFWL_Msk; + USB->USB_FWMSK_REG &= ~(1 << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_RXWARN31_Pos)); + } + xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk; +} + +static void read_rx_fifo(xfer_ctl_t *xfer, uint16_t bytes_in_fifo) +{ + EPx_REGS *regs = xfer->regs; + uint16_t remaining = xfer->total_len - xfer->transferred - xfer->last_packet_size; uint16_t receive_this_time = bytes_in_fifo; - if (remaining <= bytes_in_fifo) receive_this_time = remaining; + if (remaining < bytes_in_fifo) receive_this_time = remaining; uint8_t *buf = xfer->buffer + xfer->transferred + xfer->last_packet_size; for (int i = 0; i < receive_this_time; ++i) buf[i] = regs->rxd; - xfer->transferred += receive_this_time; xfer->last_packet_size += receive_this_time; } static void handle_ep0_rx(void) { - int packet_size; + int fifo_bytes; uint32_t rxs0 = USB->USB_RXS0_REG; xfer_ctl_t *xfer = XFER_CTL_BASE(0, TUSB_DIR_OUT); - packet_size = GET_BIT(rxs0, USB_USB_RXS0_REG_USB_RCOUNT); + fifo_bytes = GET_BIT(rxs0, USB_USB_RXS0_REG_USB_RCOUNT); if (rxs0 & USB_USB_RXS0_REG_USB_SETUP_Msk) { xfer_ctl_t *xfer_in = XFER_CTL_BASE(0, TUSB_DIR_IN); // Setup packet is in - for (int i = 0; i < packet_size; ++i) _setup_packet[i] = USB->USB_RXD0_REG; + for (int i = 0; i < fifo_bytes; ++i) _setup_packet[i] = USB->USB_RXD0_REG; xfer->stall = 0; xfer->data1 = 1; @@ -302,21 +428,26 @@ static void handle_ep0_rx(void) { // Toggle bit does not match discard packet REG_SET_BIT(USB_RXC0_REG, USB_FLUSH); + xfer->last_packet_size = 0; } else { - receive_packet(xfer, packet_size); - xfer->data1 ^= 1; - - if (xfer->total_len == xfer->transferred || xfer->last_packet_size < xfer->max_packet_size) - { - dcd_event_xfer_complete(0, 0, xfer->transferred, XFER_RESULT_SUCCESS, true); - } - else + read_rx_fifo(xfer, fifo_bytes); + if (rxs0 & USB_USB_RXS0_REG_USB_RX_LAST_Msk) { + xfer->transferred += xfer->last_packet_size; + xfer->data1 ^= 1; + + if (xfer->total_len == xfer->transferred || xfer->last_packet_size < xfer->max_packet_size) + { + dcd_event_xfer_complete(0, 0, xfer->transferred, XFER_RESULT_SUCCESS, true); + } + else + { + // Re-enable reception + REG_SET_BIT(USB_RXC0_REG, USB_RX_EN); + } xfer->last_packet_size = 0; - // Re-enable reception - REG_SET_BIT(USB_RXC0_REG, USB_RX_EN); } } } @@ -357,44 +488,72 @@ static void handle_ep0_tx(void) static void handle_epx_rx_ev(uint8_t ep) { uint32_t rxs; - int packet_size; + int fifo_bytes; xfer_ctl_t *xfer = XFER_CTL_BASE(ep, TUSB_DIR_OUT); EPx_REGS *regs = xfer->regs; - rxs = regs->rxs; - - if (GET_BIT(rxs, USB_USB_RXS1_REG_USB_RX_ERR)) + do { - regs->rxc |= USB_USB_RXC1_REG_USB_FLUSH_Msk; - } - else - { - packet_size = GET_BIT(rxs, USB_USB_RXS1_REG_USB_RXCOUNT); - receive_packet(xfer, packet_size); - if (GET_BIT(rxs, USB_USB_RXS1_REG_USB_RX_LAST)) + rxs = regs->rxs; + + if (GET_BIT(rxs, USB_USB_RXS1_REG_USB_RX_ERR)) { - if (GET_BIT(rxs, USB_USB_RXS1_REG_USB_TOGGLE_RX) != xfer->data1) + regs->rxc |= USB_USB_RXC1_REG_USB_FLUSH_Msk; + xfer->last_packet_size = 0; + if (_dcd.dma_ep[TUSB_DIR_OUT] == ep) { - // Toggle bit does not match discard packet - regs->rxc |= USB_USB_RXC1_REG_USB_FLUSH_Msk; + // Stop DMA + RX_DMA_REGS->DMAx_CTRL_REG &= ~DMA_DMA0_CTRL_REG_DMA_ON_Msk; + // Restart DMA since packet was dropped, all parameters should still work. + RX_DMA_REGS->DMAx_CTRL_REG |= DMA_DMA0_CTRL_REG_DMA_ON_Msk; } - else + break; + } + else + { + if (_dcd.dma_ep[TUSB_DIR_OUT] == ep) { - xfer->data1 ^= 1; - if (xfer->total_len == xfer->transferred || xfer->last_packet_size < xfer->max_packet_size) + // Disable DMA and update last_packet_size with what DMA reported. + RX_DMA_REGS->DMAx_CTRL_REG &= ~DMA_DMA0_CTRL_REG_DMA_ON_Msk; + xfer->last_packet_size = RX_DMA_REGS->DMAx_IDX_REG; + // When DMA did not finished (packet was smaller then MPS), DMAx_IDX_REG holds exact number of bytes transmitted. + // When DMA finished value in DMAx_IDX_REG is one less then actual number of transmitted bytes. + if (xfer->last_packet_size == RX_DMA_REGS->DMAx_LEN_REG) xfer->last_packet_size++; + // Release DMA to use by other endpoints. + _dcd.dma_ep[TUSB_DIR_OUT] = 0; + } + fifo_bytes = GET_BIT(rxs, USB_USB_RXS1_REG_USB_RXCOUNT); + // FIFO maybe empty if DMA read it before or it's final iteration and function already read all that was to read. + if (fifo_bytes > 0) + { + read_rx_fifo(xfer, fifo_bytes); + } + if (GET_BIT(rxs, USB_USB_RXS1_REG_USB_RX_LAST)) + { + if (GET_BIT(rxs, USB_USB_RXS1_REG_USB_TOGGLE_RX) != xfer->data1) { - dcd_event_xfer_complete(0, xfer->ep_addr, xfer->transferred, XFER_RESULT_SUCCESS, true); + // Toggle bit does not match discard packet + regs->rxc |= USB_USB_RXC1_REG_USB_FLUSH_Msk; } else { - xfer->last_packet_size = 0; - // Re-enable reception - regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk; + xfer->data1 ^= 1; + xfer->transferred += xfer->last_packet_size; + if (xfer->total_len == xfer->transferred || xfer->last_packet_size < xfer->max_packet_size) + { + dcd_event_xfer_complete(0, xfer->ep_addr, xfer->transferred, XFER_RESULT_SUCCESS, true); + } + else + { + // Re-enable reception + start_rx_packet(xfer); + } } + xfer->last_packet_size = 0; } } - } + } while (fifo_bytes > TU_DA1469X_FIFO_READ_THRESHOLD); } static void handle_rx_ev(void) @@ -459,6 +618,7 @@ static void handle_bus_reset(void) _dcd.in_reset = true; dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + USB->USB_DMA_CTRL_REG = 0; USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk | #if USE_SOF @@ -595,6 +755,9 @@ void dcd_connect(uint8_t rhport) (void)rhport; REG_SET_BIT(USB_MCTRL_REG, USB_NAT); + + // Select chosen DMA to be triggered by USB. + DMA->DMA_REQ_MUX_REG = (DMA->DMA_REQ_MUX_REG & ~DA146XX_DMA_USB_MUX_MASK) | DA146XX_DMA_USB_MUX; } void dcd_disconnect(uint8_t rhport) @@ -666,22 +829,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t if (dir == TUSB_DIR_OUT) { - if (epnum != 0) - { - if (xfer->max_packet_size > 64) - { - // For endpoint size greater then FIFO size enable FIFO level warning interrupt - // when FIFO has less then 17 bytes free. - xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RFWL_Msk; - } - else - { - // If max_packet_size would fit in FIFO no need for FIFO level warning interrupt. - xfer->regs->rxc &= ~USB_USB_RXC1_REG_USB_RFWL_Msk; - } - } - // USB_RX_EN bit is in same place for all endpoints. - xfer->regs->rxc = USB_USB_RXC0_REG_USB_RX_EN_Msk; + start_rx_packet(xfer); } else // IN { -- cgit v1.3.1 From 6615dd90622ab72649c3a87cbcdc74038f5c412c Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 2 Oct 2020 12:38:43 +0200 Subject: DA146xx: Add dcd_edpt_close Closing endpoints can be important when there are alternate instances. This adds functionality of closing endpoints similar to what exists in other drivers. --- src/portable/dialog/da146xx/dcd_da146xx.c | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'src') diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 9cc02e821..6489fca95 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -814,6 +814,50 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + + (void)rhport; + + TU_ASSERT(epnum < EP_MAX,); + + if (epnum == 0) + { + USB->USB_MAMSK_REG &= ~(USB_USB_MAMSK_REG_USB_M_EP0_RX_Msk | + USB_USB_MAMSK_REG_USB_M_EP0_TX_Msk); + } + else + { + if (dir == TUSB_DIR_OUT) + { + xfer->regs->rxc = USB_USB_RXC1_REG_USB_FLUSH_Msk; + xfer->regs->epc_out = 0; + USB->USB_RXMSK_REG &= ~(0x101 << (epnum - 1)); + // Release DMA if needed + if (_dcd.dma_ep[TUSB_DIR_OUT] == epnum) + { + RX_DMA_REGS->DMAx_CTRL_REG &= ~DMA_DMA0_CTRL_REG_DMA_ON_Msk; + _dcd.dma_ep[TUSB_DIR_OUT] = 0; + } + } + else + { + xfer->regs->txc = USB_USB_TXC1_REG_USB_FLUSH_Msk; + xfer->regs->epc_in = 0; + USB->USB_TXMSK_REG &= ~(0x101 << (epnum - 1)); + // Release DMA if needed + if (_dcd.dma_ep[TUSB_DIR_IN] == epnum) + { + TX_DMA_REGS->DMAx_CTRL_REG &= ~DMA_DMA1_CTRL_REG_DMA_ON_Msk; + _dcd.dma_ep[TUSB_DIR_IN] = 0; + } + } + } +} + bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); -- cgit v1.3.1 From 33a5081bd1c712726f879ba65fee973b23480c27 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 2 Oct 2020 12:41:18 +0200 Subject: DA146xx: Add support for ISO endpoints Few changes were needed to have working ISO endpoints. --- src/portable/dialog/da146xx/dcd_da146xx.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 6489fca95..7f8f67383 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -210,6 +210,8 @@ typedef struct { uint8_t data1 : 1; // Endpoint is stalled uint8_t stall : 1; + // ISO endpoint + uint8_t iso : 1; } xfer_ctl_t; static struct @@ -290,7 +292,7 @@ static void transmit_packet(xfer_ctl_t * xfer) EPx_REGS *regs = xfer->regs; uint32_t txc; - txc = USB_USB_TXC1_REG_USB_TX_EN_Msk; + txc = USB_USB_TXC1_REG_USB_TX_EN_Msk | USB_USB_TXC1_REG_USB_IGN_ISOMSK_Msk; if (xfer->data1) txc |= USB_USB_TXC1_REG_USB_TOGGLE_TX_Msk; src = &xfer->buffer[xfer->transferred]; @@ -531,7 +533,7 @@ static void handle_epx_rx_ev(uint8_t ep) } if (GET_BIT(rxs, USB_USB_RXS1_REG_USB_RX_LAST)) { - if (GET_BIT(rxs, USB_USB_RXS1_REG_USB_TOGGLE_RX) != xfer->data1) + if (!xfer->iso && GET_BIT(rxs, USB_USB_RXS1_REG_USB_TOGGLE_RX) != xfer->data1) { // Toggle bit does not match discard packet regs->rxc |= USB_USB_RXC1_REG_USB_FLUSH_Msk; @@ -540,7 +542,7 @@ static void handle_epx_rx_ev(uint8_t ep) { xfer->data1 ^= 1; xfer->transferred += xfer->last_packet_size; - if (xfer->total_len == xfer->transferred || xfer->last_packet_size < xfer->max_packet_size) + if (xfer->total_len == xfer->transferred || xfer->last_packet_size < xfer->max_packet_size || xfer->iso) { dcd_event_xfer_complete(0, xfer->ep_addr, xfer->transferred, XFER_RESULT_SUCCESS, true); } @@ -787,8 +789,13 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) xfer->max_packet_size = desc_edpt->wMaxPacketSize.size; xfer->ep_addr = desc_edpt->bEndpointAddress; xfer->data1 = 0; + xfer->iso = 0; - if (epnum != 0 && desc_edpt->bmAttributes.xfer == 1) iso_mask = USB_USB_EPC1_REG_USB_ISO_Msk; + if (epnum != 0 && desc_edpt->bmAttributes.xfer == 1) + { + iso_mask = USB_USB_EPC1_REG_USB_ISO_Msk; + xfer->iso = 1; + } if (epnum == 0) { -- cgit v1.3.1 From d36bfddc301daf9993c24c75597d04c1c39347a8 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 7 Oct 2020 09:32:17 +0200 Subject: DA146xx: Allow transmitting of packets larger then 64 bytes FIFO is limited to 64 bytes yet MCU is capable of transmitting larger packets provided that FIFO will be filled on the fly and USB_USB_TXCx_REG_USB_LAST_Msk bit is set after FIFO is filled with all the data that should be transmitted. This change allows to use FIFO level warning interrupt to fill FIFO. When DMA is available it will be used instead of interrupts. Some function names were changed to better reflect what each function does. --- src/portable/dialog/da146xx/dcd_da146xx.c | 97 ++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 7f8f67383..42ba867d7 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -285,15 +285,12 @@ void tusb_vbus_changed(bool present) } } -static void transmit_packet(xfer_ctl_t * xfer) +static void fill_tx_fifo(xfer_ctl_t * xfer) { int left_to_send; uint8_t const *src; EPx_REGS *regs = xfer->regs; - uint32_t txc; - - txc = USB_USB_TXC1_REG_USB_TX_EN_Msk | USB_USB_TXC1_REG_USB_IGN_ISOMSK_Msk; - if (xfer->data1) txc |= USB_USB_TXC1_REG_USB_TOGGLE_TX_Msk; + uint8_t const epnum = tu_edpt_number(xfer->ep_addr); src = &xfer->buffer[xfer->transferred]; left_to_send = xfer->total_len - xfer->transferred; @@ -310,22 +307,23 @@ static void transmit_packet(xfer_ctl_t * xfer) xfer->last_packet_size++; left_to_send--; } - if (tu_edpt_number(xfer->ep_addr) != 0) + if (epnum != 0) { if (left_to_send > 0) { // Max packet size is set to value greater then FIFO. Enable fifo level warning // to handle larger packets. - txc |= USB_USB_TXC1_REG_USB_TFWL_Msk; + regs->txc |= (3 << USB_USB_TXC1_REG_USB_TFWL_Pos); + USB->USB_FWMSK_REG |= 1 << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_TXWARN31_Pos); } else { + xfer->regs->txc &= ~USB_USB_TXC1_REG_USB_TFWL_Msk; + USB->USB_FWMSK_REG &= ~(1 << (epnum - 1 + USB_USB_FWMSK_REG_USB_M_TXWARN31_Pos)); // Whole packet already in fifo, no need to refill it later. Mark last. - txc |= USB_USB_TXC1_REG_USB_LAST_Msk; + regs->txc |= USB_USB_TXC1_REG_USB_LAST_Msk; } } - // Enable transfer with correct interrupts enabled - regs->txc = txc; } static bool try_allocate_dma(uint8_t epnum, uint8_t dir) @@ -387,6 +385,43 @@ static void start_rx_packet(xfer_ctl_t *xfer) xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RX_EN_Msk; } +static void start_tx_dma(void *src, volatile void *dst, uint16_t size) +{ + // Setup SRC and DST registers + TX_DMA_REGS->DMAx_A_START_REG = (uint32_t)src; + TX_DMA_REGS->DMAx_B_START_REG = (uint32_t)dst; + // Interrupt not needed + TX_DMA_REGS->DMAx_INT_REG = size; + TX_DMA_REGS->DMAx_LEN_REG = size - 1; + TX_DMA_REGS->DMAx_CTRL_REG = TX_DMA_START; +} + +static void start_tx_packet(xfer_ctl_t *xfer) +{ + uint8_t const epnum = tu_edpt_number(xfer->ep_addr); + uint16_t remaining = xfer->total_len - xfer->transferred; + uint16_t size = tu_min16(remaining, xfer->max_packet_size); + EPx_REGS *regs = xfer->regs; + + xfer->last_packet_size = 0; + + regs->txc = USB_USB_TXC1_REG_USB_FLUSH_Msk; + regs->txc = USB_USB_TXC1_REG_USB_IGN_ISOMSK_Msk; + if (xfer->data1) xfer->regs->txc |= USB_USB_TXC1_REG_USB_TOGGLE_TX_Msk; + + if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE && try_allocate_dma(epnum, TUSB_DIR_IN)) + { + // Whole packet will be put in FIFO by DMA. Set LAST bit before start. + start_tx_dma(xfer->buffer + xfer->transferred, ®s->txd, size); + regs->txc |= USB_USB_TXC1_REG_USB_LAST_Msk; + } + else + { + fill_tx_fifo(xfer); + } + regs->txc |= USB_USB_TXC1_REG_USB_TX_EN_Msk; +} + static void read_rx_fifo(xfer_ctl_t *xfer, uint16_t bytes_in_fifo) { EPx_REGS *regs = xfer->regs; @@ -483,7 +518,7 @@ static void handle_ep0_tx(void) // Start from the beginning xfer->last_packet_size = 0; } - transmit_packet(xfer); + fill_tx_fifo(xfer); } } @@ -570,14 +605,23 @@ static void handle_rx_ev(void) static void handle_epx_tx_ev(xfer_ctl_t *xfer) { - uint32_t usb_txs1_reg; + uint8_t const epnum = tu_edpt_number(xfer->ep_addr); + uint32_t txs; EPx_REGS *regs = xfer->regs; - usb_txs1_reg = regs->USB_TXS1_REG; + txs = regs->txs; - if (GET_BIT(usb_txs1_reg, USB_USB_TXS1_REG_USB_TX_DONE)) + if (GET_BIT(txs, USB_USB_TXS1_REG_USB_TX_DONE)) { - if (GET_BIT(usb_txs1_reg, USB_USB_TXS1_REG_USB_ACK_STAT)) + if (_dcd.dma_ep[TUSB_DIR_IN] == epnum) + { + // Disable DMA and update last_packet_size with what DMA reported. + TX_DMA_REGS->DMAx_CTRL_REG &= ~DMA_DMA1_CTRL_REG_DMA_ON_Msk; + xfer->last_packet_size = TX_DMA_REGS->DMAx_IDX_REG + 1; + // Release DMA to used by other endpoints. + _dcd.dma_ep[TUSB_DIR_IN] = 0; + } + if (GET_BIT(txs, USB_USB_TXS1_REG_USB_ACK_STAT)) { // ACK received, update transfer state and DATA0/1 bit xfer->transferred += xfer->last_packet_size; @@ -590,12 +634,13 @@ static void handle_epx_tx_ev(xfer_ctl_t *xfer) return; } } - else - { - xfer->last_packet_size = 0; - } - transmit_packet(xfer); } + if (txs & USB_USB_TXS1_REG_USB_TX_URUN_Msk) + { + TU_LOG1("EP %d FIFO underrun\n", epnum); + } + // Start next or repeated packet. + start_tx_packet(xfer); } static void handle_tx_ev(void) @@ -665,9 +710,9 @@ static void handle_alt_ev(void) } } -static void handle_epx_tx_refill(uint8_t ep) +static void handle_epx_tx_warn_ev(uint8_t ep) { - transmit_packet(XFER_CTL_BASE(ep, TUSB_DIR_IN)); + fill_tx_fifo(XFER_CTL_BASE(ep, TUSB_DIR_IN)); } static void handle_fifo_warning(void) @@ -675,11 +720,11 @@ static void handle_fifo_warning(void) uint32_t fifo_warning = USB->USB_FWEV_REG; if (fifo_warning & 0x01) - handle_epx_tx_refill(1); + handle_epx_tx_warn_ev(1); if (fifo_warning & 0x02) - handle_epx_tx_refill(2); + handle_epx_tx_warn_ev(2); if (fifo_warning & 0x04) - handle_epx_tx_refill(3); + handle_epx_tx_warn_ev(3); if (fifo_warning & 0x10) handle_epx_rx_ev(1); if (fifo_warning & 0x20) @@ -884,7 +929,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t } else // IN { - transmit_packet(xfer); + start_tx_packet(xfer); } return true; -- cgit v1.3.1 From 298aa1b669a5c77f991c8161ba4c7d84f7a2b674 Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Thu, 8 Oct 2020 11:59:12 -0500 Subject: Cleanup per review on PR --- .../device/hid_multipleinterface/src/tusb_config.h | 2 +- .../hid_multipleinterface/src/usb_descriptors.c | 20 ++++++++++---------- src/class/hid/hid_device.c | 4 +++- 3 files changed, 14 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/examples/device/hid_multipleinterface/src/tusb_config.h b/examples/device/hid_multipleinterface/src/tusb_config.h index 9056d5173..412f9b004 100644 --- a/examples/device/hid_multipleinterface/src/tusb_config.h +++ b/examples/device/hid_multipleinterface/src/tusb_config.h @@ -101,7 +101,7 @@ #define CFG_TUD_VENDOR 0 // HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_EP_BUFSIZE 16 +#define CFG_TUD_HID_EP_BUFSIZE 8 #ifdef __cplusplus } diff --git a/examples/device/hid_multipleinterface/src/usb_descriptors.c b/examples/device/hid_multipleinterface/src/usb_descriptors.c index 396d22621..dd8ef7120 100644 --- a/examples/device/hid_multipleinterface/src/usb_descriptors.c +++ b/examples/device/hid_multipleinterface/src/usb_descriptors.c @@ -75,7 +75,7 @@ uint8_t const desc_hid_report1[] = TUD_HID_REPORT_DESC_KEYBOARD() }; -uint8_t desc_hid_report2[] = +uint8_t const desc_hid_report2[] = { TUD_HID_REPORT_DESC_MOUSE() }; @@ -86,15 +86,15 @@ uint8_t desc_hid_report2[] = uint8_t const * tud_hid_n_descriptor_report_cb(uint8_t itf) { if (itf == 0) - { - return desc_hid_report1; - } - else if (itf == 1) - { - return desc_hid_report2; - } - - return 0; + { + return desc_hid_report1; + } + else if (itf == 1) + { + return desc_hid_report2; + } + + return NULL; } //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index ffd495306..09daa0309 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -74,7 +74,7 @@ static inline uint8_t get_hid_index_by_itfnum(uint8_t itf_num) if ( itf_num == _hidd_itf[i].itf_num ) return i; } - return 0; + return 0xFF; } //--------------------------------------------------------------------+ @@ -232,6 +232,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request #if CFG_TUD_HID>1 uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t) request->wIndex); + TU_VERIFY(hid_itf<0xFF, 0); #endif if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) @@ -345,6 +346,7 @@ bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_requ #if CFG_TUD_HID>1 uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t)p_request->wIndex); + TU_VERIFY(hid_itf<0xFF, 0); tud_hid_n_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); #else tud_hid_set_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); -- cgit v1.3.1 From a4ba1f08275bc6fe8ce1f73d24f353861839cce7 Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Thu, 8 Oct 2020 12:08:13 -0500 Subject: Fix tu_verify args --- src/class/hid/hid_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 09daa0309..45b6aaaca 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -232,7 +232,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request #if CFG_TUD_HID>1 uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t) request->wIndex); - TU_VERIFY(hid_itf<0xFF, 0); + TU_VERIFY(hid_itf<0xFF); #endif if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) @@ -346,7 +346,7 @@ bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_requ #if CFG_TUD_HID>1 uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t)p_request->wIndex); - TU_VERIFY(hid_itf<0xFF, 0); + TU_VERIFY(hid_itf<0xFF); tud_hid_n_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); #else tud_hid_set_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); -- cgit v1.3.1 From 13abcb953fcd3d51983e9768619adde776af257e Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Oct 2020 20:24:10 +0700 Subject: rename multiple hid callback --- examples/device/hid_multiple_interface/src/main.c | 4 +-- .../hid_multiple_interface/src/usb_descriptors.c | 2 +- src/class/hid/hid_device.c | 8 +++--- src/class/hid/hid_device.h | 32 ++++++++++++---------- 4 files changed, 24 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/examples/device/hid_multiple_interface/src/main.c b/examples/device/hid_multiple_interface/src/main.c index 3599683c5..7cb1d75a7 100644 --- a/examples/device/hid_multiple_interface/src/main.c +++ b/examples/device/hid_multiple_interface/src/main.c @@ -166,7 +166,7 @@ void hid_task(void) // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_n_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) +uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { // TODO not Implemented (void) itf; @@ -180,7 +180,7 @@ uint16_t tud_hid_n_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_n_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) +void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { // TODO set LED based on CAPLOCK, NUMLOCK etc... (void) itf; diff --git a/examples/device/hid_multiple_interface/src/usb_descriptors.c b/examples/device/hid_multiple_interface/src/usb_descriptors.c index dd8ef7120..0d67d499a 100644 --- a/examples/device/hid_multiple_interface/src/usb_descriptors.c +++ b/examples/device/hid_multiple_interface/src/usb_descriptors.c @@ -83,7 +83,7 @@ uint8_t const desc_hid_report2[] = // 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_n_descriptor_report_cb(uint8_t itf) +uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) { if (itf == 0) { diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 45b6aaaca..b1a4bb8de 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -250,7 +250,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { #if CFG_TUD_HID>1 - uint8_t const * desc_report = tud_hid_n_descriptor_report_cb(hid_itf); + uint8_t const * desc_report = tud_hid_descriptor_report_cb(hid_itf); #else uint8_t const * desc_report = tud_hid_descriptor_report_cb(); #endif @@ -273,7 +273,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request uint8_t const report_id = tu_u16_low(request->wValue); #if CFG_TUD_HID>1 - uint16_t xferlen = tud_hid_n_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); + uint16_t xferlen = tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); #else uint16_t xferlen = tud_hid_get_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); #endif @@ -347,7 +347,7 @@ bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_requ #if CFG_TUD_HID>1 uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t)p_request->wIndex); TU_VERIFY(hid_itf<0xFF); - tud_hid_n_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); + tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); #else tud_hid_set_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); #endif @@ -373,7 +373,7 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if (ep_addr == p_hid->ep_out) { #if CFG_TUD_HID>1 - tud_hid_n_set_report_cb(itf, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); + tud_hid_set_report_cb(itf, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); #else tud_hid_set_report_cb(0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); #endif diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 4b8cb17d5..fc060f0ce 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -84,30 +84,20 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 // Callbacks (Weak is optional) //--------------------------------------------------------------------+ +#if CFG_TUD_HID > 1 + // Invoked when received GET HID REPORT DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -#if CFG_TUD_HID>1 -uint8_t const * tud_hid_n_descriptor_report_cb(uint8_t itf); -#else -uint8_t const * tud_hid_descriptor_report_cb(void); -#endif +uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf); // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -#if CFG_TUD_HID>1 -uint16_t tud_hid_n_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); -#else -uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); -#endif +uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -#if CFG_TUD_HID>1 -void tud_hid_n_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); -#else -void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); -#endif +void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); // Invoked when received SET_PROTOCOL request ( mode switch Boot <-> Report ) TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode); @@ -117,6 +107,18 @@ TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode); // - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); +#else + +uint8_t const * tud_hid_descriptor_report_cb(void); +uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); +void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); + +TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode); +TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); + +#endif + + //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ -- cgit v1.3.1 From 8ba0c362ccb72a04ec101610f4b7f9c8577a26da Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Oct 2020 20:51:20 +0700 Subject: update tud_hid_boot_mode_cb/tud_hid_set_idle_cb support mul interfaces also clean up code --- src/class/hid/hid_device.c | 90 ++++++++++++++++++++++++---------------------- src/class/hid/hid_device.h | 5 +-- 2 files changed, 50 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index b1a4bb8de..11da5f220 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -57,17 +57,7 @@ typedef struct CFG_TUSB_MEM_SECTION static hidd_interface_t _hidd_itf[CFG_TUD_HID]; /*------------- Helpers -------------*/ -static inline hidd_interface_t* get_interface_by_itfnum(uint8_t itf_num) -{ - for (uint8_t i=0; i < CFG_TUD_HID; i++ ) - { - if ( itf_num == _hidd_itf[i].itf_num ) return &_hidd_itf[i]; - } - - return NULL; -} - -static inline uint8_t get_hid_index_by_itfnum(uint8_t itf_num) +static inline uint8_t get_index_by_itfnum(uint8_t itf_num) { for (uint8_t i=0; i < CFG_TUD_HID; i++ ) { @@ -227,13 +217,10 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request { TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) request->wIndex ); - TU_ASSERT(p_hid); + uint8_t const hid_itf = get_index_by_itfnum((uint8_t) request->wIndex); + TU_VERIFY(hid_itf < CFG_TUD_HID); - #if CFG_TUD_HID>1 - uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t) request->wIndex); - TU_VERIFY(hid_itf<0xFF); - #endif + hidd_interface_t* p_hid = &_hidd_itf[hid_itf]; if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) { @@ -249,11 +236,11 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request } else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { - #if CFG_TUD_HID>1 - uint8_t const * desc_report = tud_hid_descriptor_report_cb(hid_itf); - #else - uint8_t const * desc_report = tud_hid_descriptor_report_cb(); - #endif + uint8_t const * desc_report = tud_hid_descriptor_report_cb( + #if CFG_TUD_HID > 1 + hid_itf // TODO for backward compatible callback, remove later when appropriate + #endif + ); tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); } else @@ -272,11 +259,12 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); - #if CFG_TUD_HID>1 - uint16_t xferlen = tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); - #else - uint16_t xferlen = tud_hid_get_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); - #endif + uint16_t xferlen = tud_hid_get_report_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength + ); TU_ASSERT( xferlen > 0 ); tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); @@ -293,7 +281,12 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request if ( tud_hid_set_idle_cb ) { // stall request if callback return false - if ( !tud_hid_set_idle_cb(p_hid->idle_rate) ) return false; + TU_VERIFY( tud_hid_set_idle_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + p_hid->idle_rate) + ); } tud_control_status(rhport, request); @@ -314,7 +307,15 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request case HID_REQ_CONTROL_SET_PROTOCOL: p_hid->boot_mode = 1 - request->wValue; // 0 is Boot, 1 is Report protocol - if (tud_hid_boot_mode_cb) tud_hid_boot_mode_cb(p_hid->boot_mode); + if (tud_hid_boot_mode_cb) + { + tud_hid_boot_mode_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + p_hid->boot_mode + ); + } tud_control_status(rhport, request); break; @@ -334,8 +335,11 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) { (void) rhport; - hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) p_request->wIndex ); - TU_ASSERT(p_hid); + + uint8_t const hid_itf = get_index_by_itfnum((uint8_t) p_request->wIndex); + TU_VERIFY(hid_itf < CFG_TUD_HID); + + hidd_interface_t* p_hid = &_hidd_itf[hid_itf]; if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bRequest == HID_REQ_CONTROL_SET_REPORT) @@ -344,13 +348,12 @@ bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_requ uint8_t const report_type = tu_u16_high(p_request->wValue); uint8_t const report_id = tu_u16_low(p_request->wValue); - #if CFG_TUD_HID>1 - uint8_t const hid_itf = get_hid_index_by_itfnum((uint8_t)p_request->wIndex); - TU_VERIFY(hid_itf<0xFF); - tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); - #else - tud_hid_set_report_cb(report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength); - #endif + tud_hid_set_report_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength + ); } return true; @@ -372,11 +375,12 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if (ep_addr == p_hid->ep_out) { - #if CFG_TUD_HID>1 - tud_hid_set_report_cb(itf, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); - #else - tud_hid_set_report_cb(0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); - #endif + tud_hid_set_report_cb( + #if CFG_TUD_HID > 1 + itf, // TODO for backward compatible callback, remove later when appropriate + #endif + 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes + ); TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index fc060f0ce..d5b5b7296 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -100,15 +100,16 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); // Invoked when received SET_PROTOCOL request ( mode switch Boot <-> Report ) -TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode); +TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t itf, uint8_t boot_mode); // Invoked when received SET_IDLE request. return false will stall the request // - Idle Rate = 0 : only send report if there is changes, i.e skip duplication // - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). -TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); +TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t itf, uint8_t idle_rate); #else +// TODO for backward compatible callback, remove later when appropriate uint8_t const * tud_hid_descriptor_report_cb(void); uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); -- cgit v1.3.1 From 032e84c9befa0797f6a6faf86fbfdff13ec77bbe Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 9 Oct 2020 19:50:05 +0200 Subject: Revert dcd_alloc_mem_for_conf() but keep changes from @kasjer for ISO EP Add tud_audio_set_itf_close_EP_cb() --- src/class/audio/audio_device.c | 6 +- src/class/audio/audio_device.h | 3 + src/device/dcd.h | 4 - src/device/usbd.c | 3 - src/portable/st/synopsys/dcd_synopsys.c | 469 ++++++++------------------------ 5 files changed, 115 insertions(+), 370 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 0f501bb6e..2c8ba300d 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -876,6 +876,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { _audiod_itf[idxDriver].ep_in_as_intf_num = 0; usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); + + // Invoke callback - can be used to stop data sampling + if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + _audiod_itf[idxDriver].ep_in = 0; // Necessary? } #endif @@ -928,7 +932,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * _audiod_itf[idxDriver].ep_in = ep_addr; _audiod_itf[idxDriver].ep_in_as_intf_num = itf; - // Invoke callback and trigger data generation - if not already running + // Invoke callback - can be used to trigger data sampling if not already running if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Schedule first transmit - in case no sample data is available a ZLP is loaded diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index d2f8155db..d86232720 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -272,6 +272,9 @@ TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_c // Invoked when audio set interface request received TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); +// Invoked when audio set interface request received which closes an EP +TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request); + // Invoked when audio class specific set request received for an EP TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); diff --git a/src/device/dcd.h b/src/device/dcd.h index c00e3c06d..776f782b8 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -115,10 +115,6 @@ void dcd_connect(uint8_t rhport) TU_ATTR_WEAK; // Disconnect by disabling internal pull-up resistor on D+/D- void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; -// Invoked when a set configuration request was received -// Helper to allow for dynamic EP buffer allocation according to configuration descriptor -TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg); - //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index d6d77dff2..90edc3dde 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -786,9 +786,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); // index is cfg_num-1 TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION); - // Allow for dynamic allocation of EP buffer for current configuration - only one configuration may be active according to USB specification - if (dcd_alloc_mem_for_conf) TU_ASSERT(dcd_alloc_mem_for_conf(rhport, desc_cfg)); - // Parse configuration descriptor _usbd_dev.remote_wakeup_support = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP) ? 1 : 0; _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED) ? 1 : 0; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 5a89bb386..ca306ff8f 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -47,53 +47,53 @@ #if TUSB_OPT_DEVICE_ENABLED && \ ( (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_SYNOPSYS)) || \ - CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ - CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ - (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \ + CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ + CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ + (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \ ) // EP_MAX : Max number of bi-directional endpoints including EP0 // EP_FIFO_SIZE : Size of dedicated USB SRAM #if CFG_TUSB_MCU == OPT_MCU_STM32F1 - #include "stm32f1xx.h" - #define EP_MAX_FS 4 - #define EP_FIFO_SIZE_FS 1280 +#include "stm32f1xx.h" +#define EP_MAX_FS 4 +#define EP_FIFO_SIZE_FS 1280 #elif CFG_TUSB_MCU == OPT_MCU_STM32F2 - #include "stm32f2xx.h" - #define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE +#include "stm32f2xx.h" +#define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS +#define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE #elif CFG_TUSB_MCU == OPT_MCU_STM32F4 - #include "stm32f4xx.h" - #define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE - #define EP_MAX_HS USB_OTG_HS_MAX_IN_ENDPOINTS - #define EP_FIFO_SIZE_HS USB_OTG_HS_TOTAL_FIFO_SIZE +#include "stm32f4xx.h" +#define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS +#define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE +#define EP_MAX_HS USB_OTG_HS_MAX_IN_ENDPOINTS +#define EP_FIFO_SIZE_HS USB_OTG_HS_TOTAL_FIFO_SIZE #elif CFG_TUSB_MCU == OPT_MCU_STM32H7 - #include "stm32h7xx.h" - #define EP_MAX_FS 9 - #define EP_FIFO_SIZE_FS 4096 - #define EP_MAX_HS 9 - #define EP_FIFO_SIZE_HS 4096 +#include "stm32h7xx.h" +#define EP_MAX_FS 9 +#define EP_FIFO_SIZE_FS 4096 +#define EP_MAX_HS 9 +#define EP_FIFO_SIZE_HS 4096 #elif CFG_TUSB_MCU == OPT_MCU_STM32F7 - #include "stm32f7xx.h" - #define EP_MAX_FS 6 - #define EP_FIFO_SIZE_FS 1280 - #define EP_MAX_HS 9 - #define EP_FIFO_SIZE_HS 4096 +#include "stm32f7xx.h" +#define EP_MAX_FS 6 +#define EP_FIFO_SIZE_FS 1280 +#define EP_MAX_HS 9 +#define EP_FIFO_SIZE_HS 4096 #elif CFG_TUSB_MCU == OPT_MCU_STM32L4 - #include "stm32l4xx.h" - #define EP_MAX_FS 6 - #define EP_FIFO_SIZE_FS 1280 +#include "stm32l4xx.h" +#define EP_MAX_FS 6 +#define EP_FIFO_SIZE_FS 1280 #else - #error "Unsupported MCUs" +#error "Unsupported MCUs" #endif @@ -105,16 +105,16 @@ // On STM32 we associate Port0 to OTG_FS, and Port1 to OTG_HS #if TUD_OPT_RHPORT == 0 - #define EP_MAX EP_MAX_FS - #define EP_FIFO_SIZE EP_FIFO_SIZE_FS - #define RHPORT_REGS_BASE USB_OTG_FS_PERIPH_BASE - #define RHPORT_IRQn OTG_FS_IRQn +#define EP_MAX EP_MAX_FS +#define EP_FIFO_SIZE EP_FIFO_SIZE_FS +#define RHPORT_REGS_BASE USB_OTG_FS_PERIPH_BASE +#define RHPORT_IRQn OTG_FS_IRQn #else - #define EP_MAX EP_MAX_HS - #define EP_FIFO_SIZE EP_FIFO_SIZE_HS - #define RHPORT_REGS_BASE USB_OTG_HS_PERIPH_BASE - #define RHPORT_IRQn OTG_HS_IRQn +#define EP_MAX EP_MAX_HS +#define EP_FIFO_SIZE EP_FIFO_SIZE_HS +#define RHPORT_REGS_BASE USB_OTG_HS_PERIPH_BASE +#define RHPORT_IRQn OTG_HS_IRQn #endif #define GLOBAL_BASE(_port) ((USB_OTG_GlobalTypeDef*) RHPORT_REGS_BASE) @@ -145,7 +145,7 @@ typedef struct TU_ATTR_PACKED { // The codes assigned to those fields, according to the USB specification, can be neatly used as indices. uint16_t ep_size[EP_MAX][2]; ///< dim 1: EP number, dim 2: EP direction denoted by TUSB_DIR_OUT (= 0) and TUSB_DIR_IN (= 1) bool ep_transfer_type[EP_MAX][2][4]; ///< dim 1: EP number, dim 2: EP direction, dim 3: transfer type, where 0 = Control, 1 = Isochronous, 2 = Bulk, and 3 = Interrupt - ///< I know very well that EP0 can only be used as control EP and we waste space here but for the sake of simplicity we accept that. It is used in a non-persistent way anyway! + ///< I know very well that EP0 can only be used as control EP and we waste space here but for the sake of simplicity we accept that. It is used in a non-persistent way anyway! } ep_sz_tt_report_t; typedef volatile uint32_t * usb_fifo_t; @@ -167,7 +167,7 @@ static void bus_reset(uint8_t rhport) USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); - // USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); + USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); tu_memclr(xfer_status, sizeof(xfer_status)); @@ -217,93 +217,28 @@ static void bus_reset(uint8_t rhport) // are enabled at least "2 x (Largest-EPsize/4) + 1" are recommended. Maybe provide a macro for application to // overwrite this. - // We rework this here and initialize the FIFOs here only for the USB reset case. The rest is done once a - // configuration was set from the host. For this initialization phase we use 64 bytes as FIFO size. - - // Found by trial: 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6 - not quite sure where 1 + 6 comes from but this works for 8/16/32/64 EP0 size - _allocated_fifo_words = 10 + 2 + CFG_TUD_ENDPOINT0_SIZE/4 + 1 + 6; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) - - // _allocated_fifo_words = 47 + 2*EP_MAX; // 64 bytes max packet size + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets) +#if TUD_OPT_HIGH_SPEED + _allocated_fifo_words = 271 + 2*EP_MAX; +#else + _allocated_fifo_words = 47 + 2*EP_MAX; +#endif usb_otg->GRXFSIZ = _allocated_fifo_words; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - usb_otg->DIEPTXF0_HNPTXFSIZ = (CFG_TUD_ENDPOINT0_SIZE/4 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; + usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - _allocated_fifo_words += CFG_TUD_ENDPOINT0_SIZE/4; + _allocated_fifo_words += 16; - // Set SETUP packet count to 3 - out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); - - usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; + // TU_LOG2_INT(_allocated_fifo_words); + // Fixed control EP0 size to 64 bytes + in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); + xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; - //#if TUD_OPT_HIGH_SPEED - // _allocated_fifo_words = 271 + 2*EP_MAX; - //#else - // _allocated_fifo_words = 47 + 2*EP_MAX; - //#endif - // - // usb_otg->GRXFSIZ = _allocated_fifo_words; - // - // // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - // usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - // - // _allocated_fifo_words += 16; - // - // // TU_LOG2_INT(_allocated_fifo_words); - // - // // Fixed control EP0 size to 64 bytes - // in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - // xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; - // - // // Set SETUP packet count to 3 - // out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); - // - // usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; -} - -// Required after new configuration received in case EP0 max packet size has changed -static void set_EP0_max_pkt_size(void) -{ - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); - - uint32_t enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos; - - // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL. - switch (enum_spd) - { - case 0x00: // High speed - always 64 byte - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; - break; - - case 0x03: // Full speed -#if CFG_TUD_ENDPOINT0_SIZE == 64 - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64; -#elif CFG_TUD_ENDPOINT0_SIZE == 32 - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - in_ep[0].DIEPCTL |= (0x01 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 32; -#elif CFG_TUD_ENDPOINT0_SIZE == 16 - in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - in_ep[0].DIEPCTL |= (0x02 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 16; -#elif CFG_TUD_ENDPOINT0_SIZE == 8 - in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 8; -#else -# error CFG_TUD_ENDPOINT0_SIZE MUST be 8, 16, 32, or 64! -#endif - break; + out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); - default: // Low speed - always 8 bytes - in_ep[0].DIEPCTL |= (0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); - xfer_status[0][TUSB_DIR_OUT].max_size = 8; - xfer_status[0][TUSB_DIR_IN].max_size = 8; - } + usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; } // Set turn-around timeout according to link speed @@ -536,8 +471,8 @@ void dcd_init (uint8_t rhport) if ( rhport == 0 ) usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; usb_otg->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | - USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | - USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); + USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | + USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0); // Enable global interrupt usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT; @@ -594,7 +529,7 @@ void dcd_disconnect(uint8_t rhport) bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { -// USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); @@ -620,15 +555,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) if(dir == TUSB_DIR_OUT) { out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | - (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) | - (desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos); + (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) | + (desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos); dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum)); } else { - // FIFO allocation done in dcd_alloc_mem_for_conf() - // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture // @@ -654,35 +587,35 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // - Interrupt is EPSize // - Bulk/ISO is max(EPSize, remaining-fifo / non-opened-EPIN) -// uint16_t const fifo_remaining = EP_FIFO_SIZE/4 - _allocated_fifo_words; -// uint16_t fifo_size = desc_edpt->wMaxPacketSize.size / 4; -// -// if ( desc_edpt->bmAttributes.xfer != TUSB_XFER_INTERRUPT ) -// { -// uint8_t opened = 0; -// for(uint8_t i = 0; i < EP_MAX; i++) -// { -// if ( (i != epnum) && (xfer_status[i][TUSB_DIR_IN].max_size > 0) ) opened++; -// } -// -// // EP Size or equally divided of remaining whichever is larger -// fifo_size = tu_max16(fifo_size, fifo_remaining / (EP_MAX - opened)); -// } -// -// // FIFO overflows, we probably need a better allocating scheme -// TU_ASSERT(fifo_size <= fifo_remaining); -// -// // DIEPTXF starts at FIFO #1. -// // Both TXFD and TXSA are in unit of 32-bit words. -// usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; -// -// _allocated_fifo_words += fifo_size; + uint16_t const fifo_remaining = EP_FIFO_SIZE/4 - _allocated_fifo_words; + uint16_t fifo_size = (desc_edpt->wMaxPacketSize.size + 3) / 4; // +3 for rounding up to next full word + + if ( desc_edpt->bmAttributes.xfer != TUSB_XFER_INTERRUPT ) + { + uint8_t opened = 0; + for(uint8_t i = 0; i < EP_MAX; i++) + { + if ( (i != epnum) && (xfer_status[i][TUSB_DIR_IN].max_size > 0) ) opened++; + } + + // EP Size or equally divided of remaining whichever is larger + fifo_size = tu_max16(fifo_size, fifo_remaining / (EP_MAX - opened)); + } + + // FIFO overflows, we probably need a better allocating scheme + TU_ASSERT(fifo_size <= fifo_remaining); + + // DIEPTXF starts at FIFO #1. + // Both TXFD and TXSA are in unit of 32-bit words. + usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; + + _allocated_fifo_words += fifo_size; in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | - (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) | - (desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos) | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | - (desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos); + (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) | + (desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos) | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) | + (desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos); dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum)); } @@ -780,7 +713,20 @@ static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall) */ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) { + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + dcd_edpt_disable(rhport, ep_addr, false); + if (dir == TUSB_DIR_IN) + { + uint16_t const fifo_size = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXFD_Msk) >> USB_OTG_DIEPTXF_INEPTXFD_Pos; + uint16_t const fifo_start = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXSA_Msk) >> USB_OTG_DIEPTXF_INEPTXSA_Pos; + // For now only endpoint that has FIFO at the end of FIFO memory can be closed without fuss. + TU_ASSERT(fifo_start + fifo_size == _allocated_fifo_words,); + _allocated_fifo_words -= fifo_size; + } } void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) @@ -892,7 +838,7 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ switch(pktsts) { case 0x01: // Global OUT NAK (Interrupt) - break; + break; case 0x02: // Out packet recvd { @@ -920,18 +866,18 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ case 0x04: // Setup packet done (Interrupt) out_ep[epnum].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos); - break; + break; case 0x06: // Setup packet recvd // We can receive up to three setup packets in succession, but // only the last one is valid. _setup_packet[0] = (* rx_fifo); _setup_packet[1] = (* rx_fifo); - break; + break; default: // Invalid TU_BREAKPOINT(); - break; + break; } } @@ -1049,9 +995,6 @@ void dcd_int_handler(uint8_t rhport) tusb_speed_t const speed = get_speed(rhport); set_turnaround(usb_otg, speed); - - set_EP0_max_pkt_size(); - dcd_event_bus_reset(rhport, speed, true); } @@ -1115,209 +1058,11 @@ void dcd_int_handler(uint8_t rhport) handle_epin_ints(rhport, dev, in_ep); } - // Check for Incomplete isochronous IN transfer - if(int_status & USB_OTG_GINTSTS_IISOIXFR) { - TU_LOG2(" IISOIXFR!\r\n"); - } -} - -// Helper function which parses through the current configuration descriptors to find the biggest EPs in size. -static bool get_ep_size_report(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg, ep_sz_tt_report_t * p_report) -{ - (void) rhport; - - // tu_memclr(p_report, sizeof(ep_sz_tt_report_t)); // This does not initialize the first two entries ... i do not know why! - - // EP0 sizes and usages are fixed - p_report->ep_size[0][TUSB_DIR_OUT] = p_report->ep_size[0][TUSB_DIR_IN] = CFG_TUD_ENDPOINT0_SIZE; - p_report->ep_transfer_type[0][TUSB_DIR_OUT][TUSB_XFER_CONTROL] = p_report->ep_transfer_type[0][TUSB_DIR_IN][TUSB_XFER_CONTROL] = true; - - // Parse interface descriptor - uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); - uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + desc_cfg->wTotalLength; - - uint8_t addr; - - while( p_desc < desc_end ) - { - if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) - { - - addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - - // Verify values - this checks may be omitted in case we trust the descriptors to be okay - TU_VERIFY(tu_edpt_number(addr) < EP_MAX); - TU_VERIFY(tu_edpt_dir(addr) <= TUSB_DIR_IN); - TU_VERIFY(((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer <= TUSB_XFER_INTERRUPT); - - p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)] = tu_max16(p_report->ep_size[tu_edpt_number(addr)][tu_edpt_dir(addr)], ((tusb_desc_endpoint_t const*) p_desc)->wMaxPacketSize.size); - p_report->ep_transfer_type[tu_edpt_number(addr)][tu_edpt_dir(addr)][((tusb_desc_endpoint_t const*) p_desc)->bmAttributes.xfer] = true; - } - p_desc = tu_desc_next(p_desc); // Proceed - } - return true; -} - -// Setup FIFO buffers at configuration time. -// The idea is to use this information such that the FIFOs need to be configured only once -// at configuration time and no more later. This makes it easy in case you want to close and open EPs for different -// purposes at any time (without taking care of other active EPs). You also avoid the nasty need of defragmenting -// the TX buffers, which is likely to happen. -// Certainly, this function does not allow for the highest possible flexibility as it only works in the worst case -// (all biggest EPs can be active at the same time). However, this should not be a problem for almost all applications. - -// Spare space is assigned equally divided to bulk and interrupt EPs. -// Pure isochronous EPs do not get any spare space as it does not make any sense. -TU_ATTR_WEAK bool dcd_alloc_mem_for_conf(uint8_t rhport, tusb_desc_configuration_t const * desc_cfg) -{ - (void) rhport; - - USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); - USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); - - // for(uint8_t n = 0; n < EP_MAX; n++) { - // out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; - // } - - out_ep[0].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; - - // Deactivate Interrupts? - dev->DAINTMSK &= ~((1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos)); - dev->DOEPMSK &= ~(USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM); - dev->DIEPMSK &= ~(USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM); - - // usb_otg->GINTMSK &= ~(USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT); - - // Determine maximum required spaces for individual EPs and what kind of usage (control, bulk, etc.) they are used for - ep_sz_tt_report_t report = {0}; // dim 1: EP number, dim 2: EP direction, dim 3: transfer type - TU_VERIFY(get_ep_size_report(rhport, desc_cfg, &report)); - - // With that information, set the following up: - // The RX buffer size (as it is a shared buffer here) is set to the sum of the two biggest out EPs plus all the required extra words used for setup packets etc. - // This should work well for all kinds of applications - - // Determine number of used out EPs of current configuration and size of two biggest out EPs - uint8_t nUsedOutEPs = 0, cnt_ep, cnt_tt; - uint16_t sz[2] = {0, 0}; - uint16_t fifo_depth; - - for (cnt_ep = 0; cnt_ep < EP_MAX; cnt_ep++) - { - for (cnt_tt = 0; cnt_tt <= TUSB_XFER_INTERRUPT; cnt_tt++) - { - if (report.ep_transfer_type[cnt_ep][TUSB_DIR_OUT][cnt_tt]) - { - nUsedOutEPs++; - break; - } - } - - fifo_depth = report.ep_size[cnt_ep][TUSB_DIR_OUT] / 4 + 1; - if (sz[0] < fifo_depth) - { - sz[1] = sz[0]; - sz[0] = fifo_depth; - } - else if (sz[1] < report.ep_size[cnt_ep][TUSB_DIR_OUT]) - { - sz[1] = fifo_depth; - } - } - - // For configuration use the approach as explained in bus_reset() - _allocated_fifo_words = 13 + 1 + 1 + 2 * nUsedOutEPs + sz[0] + sz[1] + 2; // again, i do not really know why we need + 2 but otherwise it does not work - - usb_otg->GRXFSIZ = _allocated_fifo_words; - - // Control IN uses FIFO 0 with report.ep_size[0][TUSB_DIR_IN] bytes ( report.ep_size[0][TUSB_DIR_IN]/4 32-bit word ) - fifo_depth = report.ep_size[0][TUSB_DIR_IN] / 4; - fifo_depth = tu_max16(16, fifo_depth); - usb_otg->DIEPTXF0_HNPTXFSIZ = (fifo_depth << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - - _allocated_fifo_words += fifo_depth; - - // For configuration of remaining in EPs use the approach as explained in dcd_edpt_open() except that: - // - ISO EPs only get EP size as FIFO size. More makes no sense since within one frame precisely EP size bytes are transfered and not more. - // Furthermore, double buffering is not possible (for this silicon) since once FIFO was written to and transmit bit was set you are - // not allowed to write to the FIFO any more until transmit was done. So you can not send something and buffer the next frame in the - // meantime into the buffer. TODO: check for high speed and uC types which can do this! - // - Interrupt EPs only get EP size as FIFO size - // - Bulk and control (other than EP0 - this is possible) get spare space equally divided - those profit the most from extra space - - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + w + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + w + GRXFSIZ - // | IN FIFO 1 | - // --------------- w + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // In FIFO is allocated by following rules: - // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". - // - Offset: allocated so far - // - Size - as described above - - // Determine required numbers - // Remaining space available in bytes - uint16_t const fifo_remaining = EP_FIFO_SIZE/4 - _allocated_fifo_words; - - // Required space by EPs in words, number of bulk and control EPs - uint16_t ep_sz_total = 0; - // Number of bulk and control EPs - uint8_t nbc = 0; - // EP0 is already taken care of so exclude that here - for (cnt_ep = 1; cnt_ep < EP_MAX; cnt_ep++) - { - fifo_depth = (report.ep_size[cnt_ep][TUSB_DIR_IN] + 3) / 4; // Since we need full words take care of remainders! - if (fifo_depth > 0 && fifo_depth < 16) fifo_depth = 16; // Minimum FIFO depth is 16 - ep_sz_total += fifo_depth; - nbc += (report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] | report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]); - } - - if (ep_sz_total > fifo_remaining) - { - // Too less space available to apply this allocation scheme - return false and set a flag such that a different approach may be used TODO: introduce flag - return false; - } - - uint16_t extra_space = nbc > 0 ? (fifo_remaining - ep_sz_total) / nbc : 0; // If no bulk or control EPs are used we just leave the rest of the memory unused - - // Setup FIFOs - for (cnt_ep = 1; cnt_ep < EP_MAX; cnt_ep++) - { - // If EP is used - if (report.ep_size[cnt_ep][TUSB_DIR_IN] > 0) - { - fifo_depth = (report.ep_size[cnt_ep][TUSB_DIR_IN] + 3) / 4 + ((report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_BULK] || report.ep_transfer_type[cnt_ep][TUSB_DIR_IN][TUSB_XFER_CONTROL]) ? extra_space : 0); - fifo_depth = tu_max16(16, fifo_depth); - usb_otg->DIEPTXF[cnt_ep - 1] = (fifo_depth << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; - _allocated_fifo_words += fifo_depth; - } - } - - // usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; - - // Enable interrupts - dev->DAINTMSK |= (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); - dev->DOEPMSK |= USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; - dev->DIEPMSK |= USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM; - - // USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT; - - out_ep[0].DOEPCTL |= USB_OTG_DOEPCTL_CNAK; - - return true; +// // Check for Incomplete isochronous IN transfer +// if(int_status & USB_OTG_GINTSTS_IISOIXFR) { +// printf(" IISOIXFR!\r\n"); +//// TU_LOG2(" IISOIXFR!\r\n"); +// } } #endif -- cgit v1.3.1 From f914e48d25cae6d5cda34d3193f46b74826e0e1a Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sat, 10 Oct 2020 05:00:55 +0200 Subject: Dynamically check STM32F3 IRQ remap option --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 40 +++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 32179874e..1a9b2137d 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -276,9 +276,23 @@ void dcd_int_enable (uint8_t rhport) #if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 NVIC_EnableIRQ(USB_IRQn); #elif CFG_TUSB_MCU == OPT_MCU_STM32F3 - NVIC_EnableIRQ(USB_HP_CAN_TX_IRQn); - NVIC_EnableIRQ(USB_LP_CAN_RX0_IRQn); - NVIC_EnableIRQ(USBWakeUp_IRQn); + // Some STM32F302/F303 devices allow to remap the USB interrupt vectors from + // shared USB/CAN IRQs to separate CAN and USB IRQs. + // This dynamically checks if this remap is active to enable the right IRQs. + #ifdef SYSCFG_CFGR1_USB_IT_RMP + if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) + { + NVIC_EnableIRQ(USB_HP_IRQn); + NVIC_EnableIRQ(USB_LP_IRQn); + NVIC_EnableIRQ(USBWakeUp_RMP_IRQn); + } + else + #endif + { + NVIC_EnableIRQ(USB_HP_CAN_TX_IRQn); + NVIC_EnableIRQ(USB_LP_CAN_RX0_IRQn); + NVIC_EnableIRQ(USBWakeUp_IRQn); + } #elif CFG_TUSB_MCU == OPT_MCU_STM32F1 NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn); NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); @@ -296,9 +310,23 @@ void dcd_int_disable(uint8_t rhport) #if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 NVIC_DisableIRQ(USB_IRQn); #elif CFG_TUSB_MCU == OPT_MCU_STM32F3 - NVIC_DisableIRQ(USB_HP_CAN_TX_IRQn); - NVIC_DisableIRQ(USB_LP_CAN_RX0_IRQn); - NVIC_DisableIRQ(USBWakeUp_IRQn); + // Some STM32F302/F303 devices allow to remap the USB interrupt vectors from + // shared USB/CAN IRQs to separate CAN and USB IRQs. + // This dynamically checks if this remap is active to disable the right IRQs. + #ifdef SYSCFG_CFGR1_USB_IT_RMP + if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) + { + NVIC_DisableIRQ(USB_HP_IRQn); + NVIC_DisableIRQ(USB_LP_IRQn); + NVIC_DisableIRQ(USBWakeUp_RMP_IRQn); + } + else + #endif + { + NVIC_DisableIRQ(USB_HP_CAN_TX_IRQn); + NVIC_DisableIRQ(USB_LP_CAN_RX0_IRQn); + NVIC_DisableIRQ(USBWakeUp_IRQn); + } #elif CFG_TUSB_MCU == OPT_MCU_STM32F1 NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn); NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn); -- cgit v1.3.1 From 87b989e8b4b497713cc4b88103dc6dfadc43e149 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Oct 2020 00:35:38 +0700 Subject: add usbh_edpt_claim/release implement USBH_EVENT_FUNC_CALL --- src/device/dcd.h | 2 +- src/host/hcd.h | 11 ++++++++ src/host/usbh.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++-- src/host/usbh.h | 9 ++++-- src/host/usbh_control.c | 8 +++++- src/host/usbh_hcd.h | 23 ++++++++++++++- 6 files changed, 120 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index a5c485f9e..b7e5a8da0 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -77,7 +77,7 @@ typedef struct TU_ATTR_ALIGNED(4) uint32_t len; }xfer_complete; - // USBD_EVENT_FUNC_CALL + // FUNC_CALL struct { void (*func) (void*); void* param; diff --git a/src/host/hcd.h b/src/host/hcd.h index ba3035300..db98f6110 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -45,6 +45,11 @@ typedef enum HCD_EVENT_DEVICE_ATTACH, HCD_EVENT_DEVICE_REMOVE, HCD_EVENT_XFER_COMPLETE, + + // Not an HCD event, just a convenient way to defer ISR function + USBH_EVENT_FUNC_CALL, + + HCD_EVENT_COUNT } hcd_eventid_t; typedef struct @@ -67,6 +72,12 @@ typedef struct uint8_t result; uint32_t len; } xfer_complete; + + // FUNC_CALL + struct { + void (*func) (void*); + void* param; + }func_call; }; } hcd_event_t; diff --git a/src/host/usbh.c b/src/host/usbh.c index 4932e662c..595024b9c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -169,6 +169,11 @@ bool tuh_init(void) dev->control.sem_hdl = osal_semaphore_create(&dev->control.sem_def); TU_ASSERT(dev->control.sem_hdl != NULL); +#if CFG_TUSB_OS != OPT_OS_NONE + dev->mutex = osal_mutex_create(&dev->mutexdef); + TU_ASSERT(dev->mutex); +#endif + memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping } @@ -187,6 +192,8 @@ bool tuh_init(void) } //------------- USBH control transfer -------------// + +// TODO remove bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data) { usbh_device_t* dev = &_usbh_devices[dev_addr]; @@ -216,6 +223,58 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8 return true; } +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + +#if CFG_TUSB_OS != OPT_OS_NONE + // pre-check to help reducing mutex lock + TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0)); + osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only claim the endpoint if it is not busy and not claimed yet. + bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0); + if (ret) + { + dev->ep_status[epnum][dir].claimed = 1; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(dev->mutex); +#endif + + return ret; +} + +bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only release the endpoint if it is claimed and not busy + bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1); + if (ret) + { + dev->ep_status[epnum][dir].claimed = 0; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(dev->mutex); +#endif + + return ret; +} + bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { usbh_device_t* dev = &_usbh_devices[dev_addr]; @@ -402,6 +461,8 @@ void tuh_task(void) switch (event.event_id) { case HCD_EVENT_DEVICE_ATTACH: + // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating + // one device before enumerating another one. TU_LOG2("USBH DEVICE ATTACH\r\n"); enum_new_device(&event); break; @@ -443,6 +504,10 @@ void tuh_task(void) } break; + case USBH_EVENT_FUNC_CALL: + if ( event.func_call.func ) event.func_call.func(event.func_call.param); + break; + default: break; } } @@ -465,6 +530,8 @@ static uint8_t get_new_address(void) // is a lengthy process with a seires of control transfer to configure // newly attached device. Each step is handled by a function in this // section +// TODO due to the shared _usbh_ctrl_buf, we must complete enumerating +// one device before enumerating another one. //--------------------------------------------------------------------+ static bool enum_get_addr0_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -785,7 +852,7 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura { tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; - // Check if class is supportedVe + // Check if class is supported uint8_t drv_id; for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) { @@ -799,6 +866,8 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura } else { + usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; + // Interface number must not be used already TODO alternate interface TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff ); dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; @@ -813,8 +882,8 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura { uint16_t itf_len = 0; - TU_LOG2("%s open\r\n", usbh_class_drivers[drv_id].name); - TU_ASSERT( usbh_class_drivers[drv_id].open(dev->rhport, dev_addr, desc_itf, &itf_len) ); + TU_LOG2("%s open\r\n", driver->name); + TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); p_desc += itf_len; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 814770722..fde1dd11c 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -65,6 +65,7 @@ typedef struct { } usbh_class_driver_t; typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -106,11 +107,15 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); // CLASS-USBH & INTERNAL API //--------------------------------------------------------------------+ -bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); - bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Claim an endpoint before submitting a transfer. +// If caller does not make any transfer, it must release endpoint for others. +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); + +bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); // TODO remove later + #ifdef __cplusplus } #endif diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 595c011f5..70800eba6 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -58,6 +58,8 @@ static usbh_control_xfer_t _ctrl_xfer; bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) { + // TODO need to claim the endpoint first + usbh_device_t* dev = &_usbh_devices[dev_addr]; const uint8_t rhport = dev->rhport; @@ -83,6 +85,10 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + (void) ep_addr; + (void) xferred_bytes; + + usbh_device_t* dev = &_usbh_devices[dev_addr]; const uint8_t rhport = dev->rhport; @@ -106,7 +112,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); return true; } - __attribute__((fallthrough)); + __attribute__((fallthrough)); case STAGE_DATA: _ctrl_xfer.stage = STAGE_ACK; diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index f203f3baa..20348eed1 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -40,6 +40,10 @@ #include "common/tusb_common.h" #include "osal/osal.h" +#ifndef CFG_TUH_EP_MAX +#define CFG_TUH_EP_MAX 9 +#endif + //--------------------------------------------------------------------+ // USBH-HCD common data structure //--------------------------------------------------------------------+ @@ -80,7 +84,24 @@ typedef struct { } control; uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid ) + uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + + struct TU_ATTR_PACKED + { + volatile bool busy : 1; + volatile bool stalled : 1; + volatile bool claimed : 1; + + // TODO merge ep2drv here, 4-bit should be sufficient + }ep_status[CFG_TUH_EP_MAX][2]; + + +// Mutex for claiming endpoint, only needed when using with preempted RTOS +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_def_t mutexdef; + osal_mutex_t mutex; +#endif + } usbh_device_t; extern usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including zero-address -- cgit v1.3.1 From 9c07a2a4e23e4d82e3cbb28e92bf1234e4a6ce09 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 Oct 2020 00:07:51 +0700 Subject: rework msc host - msc host enum is now async - implement async tuh_msc_scsi_command() / tuh_msc_request_sense() / tuh_msc_test_unit_ready() --- examples/host/cdc_msc_hid/src/msc_app.c | 15 +- src/class/msc/msc_host.c | 407 ++++++++++++++++++-------------- src/class/msc/msc_host.h | 75 ++---- src/host/usbh_control.c | 1 - 4 files changed, 252 insertions(+), 246 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 62bd961c1..53f0e6ac2 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -38,6 +38,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr) printf("A MassStorage device is mounted\r\n"); //------------- Disk Information -------------// +#if 0 // SCSI VendorID[8] & ProductID[16] from Inquiry Command uint8_t const* p_vendor = tuh_msc_get_vendor_name(dev_addr); uint8_t const* p_product = tuh_msc_get_product_name(dev_addr); @@ -47,6 +48,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr) putchar(' '); for(uint8_t i=0; i<16; i++) putchar(p_product[i]); putchar('\n'); +#endif uint32_t last_lba = 0; uint32_t block_size = 0; @@ -103,12 +105,11 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr) // } } -// invoked ISR context -void tuh_msc_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes) -{ - (void) dev_addr; - (void) event; - (void) xferred_bytes; -} +//void tuh_msc_scsi_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +//{ +// (void) dev_addr; +// (void) cbw; +// (void) csw; +//} #endif diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index f47bbd163..e8bed989c 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -37,19 +37,41 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION static msch_interface_t msch_data[CFG_TUSB_HOST_DEVICE_MAX]; +enum +{ + MSC_STAGE_IDLE = 0, + MSC_STAGE_CMD, + MSC_STAGE_DATA, + MSC_STAGE_STATUS, +}; + +typedef struct +{ + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; + + uint8_t max_lun; + + scsi_read_capacity10_resp_t capacity; + + volatile bool is_initialized; + uint8_t vendor_id[8]; + uint8_t product_id[16]; + + uint8_t stage; + void* buffer; + tuh_msc_complete_cb_t complete_cb; + + msc_cbw_t cbw; + msc_csw_t csw; +}msch_interface_t; -//------------- Initalization Data -------------// -static osal_semaphore_def_t msch_sem_def; -static osal_semaphore_t msch_sem_hdl; +CFG_TUSB_MEM_SECTION static msch_interface_t msch_data[CFG_TUSB_HOST_DEVICE_MAX]; // buffer used to read scsi information when mounted, largest response data currently is inquiry CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msch_buffer[sizeof(scsi_inquiry_resp_t)]; -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - //--------------------------------------------------------------------+ // PUBLIC API //--------------------------------------------------------------------+ @@ -65,25 +87,17 @@ bool tuh_msc_is_busy(uint8_t dev_addr) hcd_edpt_busy(dev_addr, msch_data[dev_addr-1].ep_in); } -uint8_t const* tuh_msc_get_vendor_name(uint8_t dev_addr) +bool tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size) { - return msch_data[dev_addr-1].is_initialized ? msch_data[dev_addr-1].vendor_id : NULL; -} + msch_interface_t* p_msc = &msch_data[dev_addr-1]; -uint8_t const* tuh_msc_get_product_name(uint8_t dev_addr) -{ - return msch_data[dev_addr-1].is_initialized ? msch_data[dev_addr-1].product_id : NULL; -} + if ( !p_msc->is_initialized ) return false; + TU_ASSERT(p_last_lba != NULL && p_block_size != NULL); -tusb_error_t tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size) -{ - if ( !msch_data[dev_addr-1].is_initialized ) return TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED; - TU_ASSERT(p_last_lba != NULL && p_block_size != NULL, TUSB_ERROR_INVALID_PARA); + (*p_last_lba) = p_msc->capacity.last_lba; + (*p_block_size) = p_msc->capacity.block_size; - (*p_last_lba) = msch_data[dev_addr-1].last_lba; - (*p_block_size) = (uint32_t) msch_data[dev_addr-1].block_size; - - return TUSB_ERROR_NONE; + return true; } //--------------------------------------------------------------------+ @@ -92,30 +106,27 @@ tusb_error_t tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32 static inline void msc_cbw_add_signature(msc_cbw_t *p_cbw, uint8_t lun) { p_cbw->signature = MSC_CBW_SIGNATURE; - p_cbw->tag = 0xCAFECAFE; + p_cbw->tag = 0x54555342; // TUSB p_cbw->lun = lun; } -static tusb_error_t msch_command_xfer(uint8_t dev_addr, msch_interface_t * p_msch, void* p_buffer) +bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb) { - if ( NULL != p_buffer) - { // there is data phase - if (p_msch->cbw.dir & TUSB_DIR_IN_MASK) - { - TU_ASSERT( hcd_pipe_xfer(dev_addr, p_msch->ep_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cbw_t), false), TUSB_ERROR_FAILED ); - TU_ASSERT( hcd_pipe_queue_xfer(dev_addr, p_msch->ep_in , p_buffer, p_msch->cbw.total_bytes), TUSB_ERROR_FAILED ); - }else - { - TU_ASSERT( hcd_pipe_queue_xfer(dev_addr, p_msch->ep_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cbw_t)), TUSB_ERROR_FAILED ); - TU_ASSERT( hcd_pipe_xfer(dev_addr, p_msch->ep_out , p_buffer, p_msch->cbw.total_bytes, false), TUSB_ERROR_FAILED ); - } - } + msch_interface_t* p_msc = &msch_data[dev_addr-1]; - TU_ASSERT( hcd_pipe_xfer(dev_addr, p_msch->ep_in , (uint8_t*) &p_msch->csw, sizeof(msc_csw_t), true), TUSB_ERROR_FAILED); + // TODO claim endpoint - return TUSB_ERROR_NONE; + p_msc->cbw = *cbw; + p_msc->stage = MSC_STAGE_CMD; + p_msc->buffer = data; + p_msc->complete_cb = complete_cb; + + TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t))); + + return true; } +#if 0 tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) { msch_interface_t* p_msch = &msch_data[dev_addr-1]; @@ -127,7 +138,7 @@ tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) p_msch->cbw.cmd_len = sizeof(scsi_inquiry_t); //------------- SCSI command -------------// - scsi_inquiry_t cmd_inquiry = + scsi_inquiry_t const cmd_inquiry = { .cmd_code = SCSI_CMD_INQUIRY, .alloc_length = sizeof(scsi_inquiry_resp_t) @@ -135,88 +146,51 @@ tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) memcpy(p_msch->cbw.command, &cmd_inquiry, p_msch->cbw.cmd_len); - TU_ASSERT_ERR ( msch_command_xfer(dev_addr, p_msch, p_data) ); - - return TUSB_ERROR_NONE; -} - -tusb_error_t tusbh_msc_read_capacity10(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) -{ - msch_interface_t* p_msch = &msch_data[dev_addr-1]; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - p_msch->cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); - p_msch->cbw.dir = TUSB_DIR_IN_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_read_capacity10_t); - - //------------- SCSI command -------------// - scsi_read_capacity10_t cmd_read_capacity10 = - { - .cmd_code = SCSI_CMD_READ_CAPACITY_10, - .lba = 0, - .partial_medium_indicator = 0 - }; - - memcpy(p_msch->cbw.command, &cmd_read_capacity10, p_msch->cbw.cmd_len); - - TU_ASSERT_ERR ( msch_command_xfer(dev_addr, p_msch, p_data) ); + TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, p_data) ); return TUSB_ERROR_NONE; } +#endif -tusb_error_t tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) +bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) { - (void) lun; // TODO [MSCH] multiple lun support - - msch_interface_t* p_msch = &msch_data[dev_addr-1]; - - //------------- Command Block Wrapper -------------// - p_msch->cbw.total_bytes = 18; - p_msch->cbw.dir = TUSB_DIR_IN_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_request_sense_t); + msc_cbw_t cbw = { 0 }; + msc_cbw_add_signature(&cbw, lun); - //------------- SCSI command -------------// - scsi_request_sense_t cmd_request_sense = - { - .cmd_code = SCSI_CMD_REQUEST_SENSE, - .alloc_length = 18 - }; + cbw.total_bytes = 0; // Number of bytes + cbw.dir = TUSB_DIR_OUT; + cbw.cmd_len = sizeof(scsi_test_unit_ready_t); + cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; + cbw.command[1] = lun; // according to wiki TODO need verification - memcpy(p_msch->cbw.command, &cmd_request_sense, p_msch->cbw.cmd_len); + TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb)); - TU_ASSERT_ERR ( msch_command_xfer(dev_addr, p_msch, p_data) ); - - return TUSB_ERROR_NONE; + return true; } -tusb_error_t tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, msc_csw_t * p_csw) +bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msch = &msch_data[dev_addr-1]; + msc_cbw_t cbw = { 0 }; + msc_cbw_add_signature(&cbw, lun); - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - - p_msch->cbw.total_bytes = 0; // Number of bytes - p_msch->cbw.dir = TUSB_DIR_OUT; - p_msch->cbw.cmd_len = sizeof(scsi_test_unit_ready_t); + cbw.total_bytes = 18; // TODO sense response + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_request_sense_t); - //------------- SCSI command -------------// - scsi_test_unit_ready_t cmd_test_unit_ready = + scsi_request_sense_t const cmd_request_sense = { - .cmd_code = SCSI_CMD_TEST_UNIT_READY, - .lun = lun // according to wiki + .cmd_code = SCSI_CMD_REQUEST_SENSE, + .alloc_length = 18 }; - memcpy(p_msch->cbw.command, &cmd_test_unit_ready, p_msch->cbw.cmd_len); + memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len); - // TODO MSCH refractor test uinit ready - TU_ASSERT( hcd_pipe_xfer(dev_addr, p_msch->ep_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cbw_t), false), TUSB_ERROR_FAILED ); - TU_ASSERT( hcd_pipe_xfer(dev_addr, p_msch->ep_in , (uint8_t*) p_csw, sizeof(msc_csw_t), true), TUSB_ERROR_FAILED ); + TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb)); - return TUSB_ERROR_NONE; + return true; } +#if 0 tusb_error_t tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) { msch_interface_t* p_msch = &msch_data[dev_addr-1]; @@ -229,7 +203,7 @@ tusb_error_t tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uin p_msch->cbw.cmd_len = sizeof(scsi_read10_t); //------------- SCSI command -------------// - scsi_read10_t cmd_read10 = + scsi_read10_t cmd_read10 =msch_sem_hdl { .cmd_code = SCSI_CMD_READ_10, .lba = tu_htonl(lba), @@ -238,7 +212,7 @@ tusb_error_t tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uin memcpy(p_msch->cbw.command, &cmd_read10, p_msch->cbw.cmd_len); - TU_ASSERT_ERR ( msch_command_xfer(dev_addr, p_msch, p_buffer)); + TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, p_buffer)); return TUSB_ERROR_NONE; } @@ -264,10 +238,11 @@ tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffe memcpy(p_msch->cbw.command, &cmd_write10, p_msch->cbw.cmd_len); - TU_ASSERT_ERR ( msch_command_xfer(dev_addr, p_msch, (void*) p_buffer)); + TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, (void*) p_buffer)); return TUSB_ERROR_NONE; } +#endif //--------------------------------------------------------------------+ // CLASS-USBH API (don't require to verify parameters) @@ -275,9 +250,75 @@ tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffe void msch_init(void) { tu_memclr(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); - msch_sem_hdl = osal_semaphore_create(&msch_sem_def); } + +void msch_close(uint8_t dev_addr) +{ + tu_memclr(&msch_data[dev_addr-1], sizeof(msch_interface_t)); + tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback +} + +static bool get_csw(uint8_t dev_addr, msch_interface_t * p_msc) +{ + p_msc->stage = MSC_STAGE_STATUS; + TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); + return true; +} + +bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +{ + msch_interface_t* p_msc = &msch_data[dev_addr-1]; + msc_cbw_t const * cbw = &p_msc->cbw; + msc_csw_t * csw = &p_msc->csw; + + switch (p_msc->stage) + { + case MSC_STAGE_CMD: + // Must be Command Block + TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t)); + + if ( cbw->total_bytes && p_msc->buffer ) + { + // Data stage if any + p_msc->stage = MSC_STAGE_DATA; + + uint8_t const ep_data = (cbw->dir & TUSB_DIR_IN_MASK) ? p_msc->ep_in : p_msc->ep_out; + TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, cbw->total_bytes)); + }else + { + // Status stage + get_csw(dev_addr, p_msc); + } + break; + + case MSC_STAGE_DATA: + get_csw(dev_addr, p_msc); + break; + + case MSC_STAGE_STATUS: + // SCSI op is complete + p_msc->stage = MSC_STAGE_IDLE; + + if (p_msc->complete_cb) p_msc->complete_cb(dev_addr, cbw, csw); + break; + + // unknown state + default: break; + } + + return true; +} + +//--------------------------------------------------------------------+ +// MSC Enumeration +//--------------------------------------------------------------------+ + +static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); +static bool open_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); +static bool open_read_capacity10_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); + bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) { TU_VERIFY (MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && @@ -311,30 +352,52 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it //------------- Get Max Lun -------------// TU_LOG2("MSC Get Max Lun\r\n"); - tusb_control_request_t request = { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, - .bRequest = MSC_REQ_GET_MAX_LUN, - .wValue = 0, - .wIndex = p_msc->itf_num, - .wLength = 1 + tusb_control_request_t request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = MSC_REQ_GET_MAX_LUN, + .wValue = 0, + .wIndex = p_msc->itf_num, + .wLength = 1 }; - // TODO STALL means zero - TU_ASSERT( usbh_control_xfer( dev_addr, &request, msch_buffer ) ); - p_msc->max_lun = msch_buffer[0]; + TU_ASSERT(tuh_control_xfer(dev_addr, &request, msch_buffer, open_get_maxlun_complete)); -#if 0 - //------------- Reset -------------// - request = (tusb_control_request_t) { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, - .bRequest = MSC_REQ_RESET, - .wValue = 0, - .wIndex = p_msc->itf_num, - .wLength = 0 + return true; +} + +static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) request; + + msch_interface_t* p_msc = &msch_data[dev_addr-1]; + + // STALL means zero + p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? msch_buffer[0] : 0; + + // MSCU Reset +#if 0 // not really needed + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = MSC_REQ_RESET, + .wValue = 0, + .wIndex = p_msc->itf_num, + .wLength = 0 }; - TU_ASSERT( usbh_control_xfer( dev_addr, &request, NULL ) ); + TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) ); #endif - enum { SCSI_XFER_TIMEOUT = 2000 }; +#if 0 //------------- SCSI Inquiry -------------// TU_LOG2("SCSI Inquiry\r\n"); tusbh_msc_inquiry(dev_addr, 0, msch_buffer); @@ -342,77 +405,63 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it memcpy(p_msc->vendor_id , ((scsi_inquiry_resp_t*) msch_buffer)->vendor_id , 8); memcpy(p_msc->product_id, ((scsi_inquiry_resp_t*) msch_buffer)->product_id, 16); +#endif - //------------- SCSI Read Capacity 10 -------------// - TU_LOG2("SCSI Read Capacity 10\r\n"); - tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer); - TU_ASSERT( osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT)); + // TODO multiple LUN support + TU_LOG2("SCSI Test Unit Ready\r\n"); + tuh_msc_test_unit_ready(dev_addr, 0, open_test_unit_ready_complete); - // NOTE: my toshiba thumb-drive stall the first Read Capacity and require the sequence - // Read Capacity --> Stalled --> Clear Stall --> Request Sense --> Read Capacity (2) to work - if ( hcd_edpt_stalled(dev_addr, p_msc->ep_in) ) + return true; +} + +static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +{ + if (csw->status == 0) { - // clear stall TODO abstract clear stall function - request = (tusb_control_request_t) { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_ENDPOINT, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, - .bRequest = TUSB_REQ_CLEAR_FEATURE, - .wValue = 0, - .wIndex = p_msc->ep_in, - .wLength = 0 - }; - - TU_ASSERT(usbh_control_xfer( dev_addr, &request, NULL )); - - hcd_edpt_clear_stall(dev_addr, p_msc->ep_in); - TU_ASSERT( osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT) ); // wait for SCSI status - - //------------- SCSI Request Sense -------------// - (void) tuh_msc_request_sense(dev_addr, 0, msch_buffer); - TU_ASSERT(osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT)); - - //------------- Re-read SCSI Read Capactity -------------// - tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer); - TU_ASSERT(osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT)); - } + TU_LOG2("SCSI Read Capacity 10\r\n"); - p_msc->last_lba = tu_ntohl( ((scsi_read_capacity10_resp_t*)msch_buffer)->last_lba ); - p_msc->block_size = (uint16_t) tu_ntohl( ((scsi_read_capacity10_resp_t*)msch_buffer)->block_size ); + msch_interface_t* p_msc = &msch_data[dev_addr-1]; + msc_cbw_t new_cbw = { 0 }; - p_msc->is_initialized = true; + msc_cbw_add_signature(&new_cbw, cbw->lun); + new_cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); + new_cbw.dir = TUSB_DIR_IN_MASK; + new_cbw.cmd_len = sizeof(scsi_read_capacity10_t); + new_cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; - tuh_msc_mounted_cb(dev_addr); + TU_ASSERT(tuh_msc_scsi_command(dev_addr, &new_cbw, &p_msc->capacity, open_read_capacity10_complete)); + }else + { + // Note: During enumeration, some device fails Test Unit Ready and require a few retries + // with Request Sense to start working !! + // TODO limit number of retries + TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, msch_buffer, open_request_sense_complete)); + } return true; } -bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +static bool open_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) { - msch_interface_t* p_msc = &msch_data[dev_addr-1]; - if ( ep_addr == p_msc->ep_in ) - { - if (p_msc->is_initialized) - { - tuh_msc_isr(dev_addr, event, xferred_bytes); - }else - { // still initializing under open subtask - osal_semaphore_post(msch_sem_hdl, true); - } - } - + TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, open_test_unit_ready_complete)); return true; } -void msch_close(uint8_t dev_addr) +static bool open_read_capacity10_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) { - tu_memclr(&msch_data[dev_addr-1], sizeof(msch_interface_t)); - osal_semaphore_reset(msch_sem_hdl); + TU_ASSERT(csw->status == 0); - tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback -} + msch_interface_t* p_msc = &msch_data[dev_addr-1]; -//--------------------------------------------------------------------+ -// INTERNAL & HELPER -//--------------------------------------------------------------------+ + // Note: Block size and last LBA are big-endian + p_msc->capacity.last_lba = tu_ntohl(p_msc->capacity.last_lba); + p_msc->capacity.block_size = tu_ntohl(p_msc->capacity.block_size); + // Enumeration is complete + p_msc->is_initialized = true; // open complete TODO remove + tuh_msc_mounted_cb(dev_addr); + + return true; +} #endif diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index a32134215..03231d17f 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -40,6 +40,9 @@ * \defgroup MSC_Host Host * The interface API includes status checking function, data transferring function and callback functions * @{ */ + +typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); + //--------------------------------------------------------------------+ // MASS STORAGE Application API //--------------------------------------------------------------------+ @@ -60,23 +63,9 @@ bool tuh_msc_is_mounted(uint8_t dev_addr); */ bool tuh_msc_is_busy(uint8_t dev_addr); -/** \brief Get SCSI vendor's name of MassStorage device - * \param[in] dev_addr device address - * \return pointer to vendor's name or NULL if specified device does not support MassStorage - * \note SCSI vendor's name is 8-byte length field in \ref scsi_inquiry_data_t. During enumeration, the stack has already - * retrieved (via SCSI INQUIRY) and store this information internally. There is no need for application to re-send SCSI INQUIRY - * command or allocate buffer for this. - */ -uint8_t const* tuh_msc_get_vendor_name(uint8_t dev_addr); +bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); -/** \brief Get SCSI product's name of MassStorage device - * \param[in] dev_addr device address - * \return pointer to product's name or NULL if specified device does not support MassStorage - * \note SCSI product's name is 16-byte length field in \ref scsi_inquiry_data_t. During enumeration, the stack has already - * retrieved (via SCSI INQUIRY) and store this information internally. There is no need for application to re-send SCSI INQUIRY - * command or allocate buffer for this. - */ -uint8_t const* tuh_msc_get_product_name(uint8_t dev_addr); +bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, void* response, uint32_t len); /** \brief Get SCSI Capacity of MassStorage device * \param[in] dev_addr device address @@ -87,8 +76,10 @@ uint8_t const* tuh_msc_get_product_name(uint8_t dev_addr); * retrieved (via SCSI READ CAPACITY 10) and store this information internally. There is no need for application * to re-send SCSI READ CAPACITY 10 command */ -tusb_error_t tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size); +bool tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size); + +#if 0 /** \brief Perform SCSI READ 10 command to read data from MassStorage device * \param[in] dev_addr device address * \param[in] lun Targeted Logical Unit @@ -116,29 +107,25 @@ tusb_error_t tuh_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uin * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function */ tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count); +#endif /** \brief Perform SCSI REQUEST SENSE command, used to retrieve sense data from MassStorage device * \param[in] dev_addr device address * \param[in] lun Targeted Logical Unit * \param[in] p_data Buffer to store response's data from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function + * \note This function is non-blocking and returns immediately. + * Callback is invoked when command is complete */ -tusb_error_t tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, uint8_t *p_data); +bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); /** \brief Perform SCSI TEST UNIT READY command to test if MassStorage device is ready * \param[in] dev_addr device address * \param[in] lun Targeted Logical Unit - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function + * \note This function is non-blocking and returns immediately. + * Callback is invoked when command is complete */ -tusb_error_t tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, msc_csw_t * p_csw); // TODO to be refractor +bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); + //tusb_error_t tusbh_msc_scsi_send(uint8_t dev_addr, uint8_t lun, bool is_direction_in, // uint8_t const * p_command, uint8_t cmd_len, @@ -157,39 +144,9 @@ void tuh_msc_mounted_cb(uint8_t dev_addr); */ void tuh_msc_unmounted_cb(uint8_t dev_addr); -/** \brief Callback function that is invoked when an transferring event occurred - * \param[in] dev_addr Address of device - * \param[in] event an value from \ref xfer_result_t - * \param[in] xferred_bytes Number of bytes transferred via USB bus - * \note event can be one of following - * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. - * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. - * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. - * \note - */ -void tuh_msc_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes); - - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -typedef struct -{ - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - uint8_t max_lun; - uint16_t block_size; - uint32_t last_lba; // last logical block address - - volatile bool is_initialized; - uint8_t vendor_id[8]; - uint8_t product_id[16]; - - msc_cbw_t cbw; - msc_csw_t csw; -}msch_interface_t; void msch_init(void); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 70800eba6..de55bd5e1 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -88,7 +88,6 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu (void) ep_addr; (void) xferred_bytes; - usbh_device_t* dev = &_usbh_devices[dev_addr]; const uint8_t rhport = dev->rhport; -- cgit v1.3.1 From 437ccac6968b9c31446756c49524f7306ef2acd8 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 Oct 2020 13:23:33 +0700 Subject: implement tuh_msc_scsi_inquiry() / tuh_msc_read_capacity() / tuh_msc_get_maxlun() --- examples/host/cdc_msc_hid/src/msc_app.c | 62 ++++++++++---- examples/obsolete/host/src/msc_host_app.c | 2 +- src/class/msc/msc_host.c | 131 +++++++++++------------------- src/class/msc/msc_host.h | 6 +- 4 files changed, 96 insertions(+), 105 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 53f0e6ac2..a45fba737 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -30,31 +30,59 @@ //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ +static scsi_inquiry_resp_t inquiry_resp; +static scsi_read_capacity10_resp_t capacity_resp; +uint32_t block_size; +uint32_t block_count; + +bool capacity_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +{ + (void) dev_addr; + (void) cbw; + + if (csw->status != 0) + { + printf("Read Capacity (10) failed\r\n"); + return false; + } + + // Capacity response field: Block size and Last LBA are both Big-Endian + block_count = tu_ntohl(capacity_resp.last_lba) + 1; + block_size = tu_ntohl(capacity_resp.block_size); + + printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size)); + printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size); + + return true; +} + +bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +{ + if (csw->status != 0) + { + printf("Inquiry failed\r\n"); + return false; + } + + // Print out Vendor ID, Product ID and Rev + printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev); + + // Read capacity of device + tuh_msc_read_capacity(dev_addr, cbw->lun, &capacity_resp, capacity_complete_cb); + + return true; +} //------------- IMPLEMENTATION -------------// void tuh_msc_mounted_cb(uint8_t dev_addr) { printf("A MassStorage device is mounted\r\n"); - //------------- Disk Information -------------// -#if 0 - // SCSI VendorID[8] & ProductID[16] from Inquiry Command - uint8_t const* p_vendor = tuh_msc_get_vendor_name(dev_addr); - uint8_t const* p_product = tuh_msc_get_product_name(dev_addr); - - for(uint8_t i=0; i<8; i++) putchar(p_vendor[i]); - - putchar(' '); - for(uint8_t i=0; i<16; i++) putchar(p_product[i]); - putchar('\n'); -#endif + block_size = block_count = 0; - uint32_t last_lba = 0; - uint32_t block_size = 0; - tuh_msc_get_capacity(dev_addr, &last_lba, &block_size); - printf("Disk Size: %ld MB\r\n", (last_lba+1)/ ((1024*1024)/block_size) ); - printf("LBA 0-0x%lX Block Size: %ld\r\n", last_lba, block_size); + uint8_t const lun = 0; + tuh_msc_scsi_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb); // // //------------- file system (only 1 LUN support) -------------// // uint8_t phy_disk = dev_addr-1; diff --git a/examples/obsolete/host/src/msc_host_app.c b/examples/obsolete/host/src/msc_host_app.c index 77747b536..8afb6ede8 100644 --- a/examples/obsolete/host/src/msc_host_app.c +++ b/examples/obsolete/host/src/msc_host_app.c @@ -64,7 +64,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr) putchar('\n'); uint32_t last_lba, block_size; - tuh_msc_get_capacity(dev_addr, &last_lba, &block_size); + tuh_msc_read_capacity(dev_addr, &last_lba, &block_size); printf("Disk Size: %d MB\n", (last_lba+1)/ ((1024*1024)/block_size) ); printf("LBA 0-0x%X Block Size: %d\n", last_lba, block_size); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index e8bed989c..7a46b6866 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -53,11 +53,7 @@ typedef struct uint8_t max_lun; - scsi_read_capacity10_resp_t capacity; - volatile bool is_initialized; - uint8_t vendor_id[8]; - uint8_t product_id[16]; uint8_t stage; void* buffer; @@ -75,6 +71,11 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msch_buffer[sizeof(scsi_i //--------------------------------------------------------------------+ // PUBLIC API //--------------------------------------------------------------------+ +uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) +{ + return msch_data[dev_addr-1].max_lun; +} + bool tuh_msc_is_mounted(uint8_t dev_addr) { return tuh_device_is_configured(dev_addr) && // is configured can be omitted @@ -87,19 +88,6 @@ bool tuh_msc_is_busy(uint8_t dev_addr) hcd_edpt_busy(dev_addr, msch_data[dev_addr-1].ep_in); } -bool tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size) -{ - msch_interface_t* p_msc = &msch_data[dev_addr-1]; - - if ( !p_msc->is_initialized ) return false; - TU_ASSERT(p_last_lba != NULL && p_block_size != NULL); - - (*p_last_lba) = p_msc->capacity.last_lba; - (*p_block_size) = p_msc->capacity.block_size; - - return true; -} - //--------------------------------------------------------------------+ // PUBLIC API: SCSI COMMAND //--------------------------------------------------------------------+ @@ -126,33 +114,46 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu return true; } -#if 0 -tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) +bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msch = &msch_data[dev_addr-1]; + msch_interface_t* p_msc = &msch_data[dev_addr-1]; + if ( !p_msc->is_initialized ) return false; - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - p_msch->cbw.total_bytes = sizeof(scsi_inquiry_resp_t); - p_msch->cbw.dir = TUSB_DIR_IN_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_inquiry_t); + msc_cbw_t cbw = { 0 }; + + msc_cbw_add_signature(&cbw, lun); + cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_read_capacity10_t); + cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; + + TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb)); + + return true; +} + +bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) +{ + msc_cbw_t cbw = { 0 }; + + msc_cbw_add_signature(&cbw, lun); + cbw.total_bytes = sizeof(scsi_inquiry_resp_t); + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_inquiry_t); - //------------- SCSI command -------------// scsi_inquiry_t const cmd_inquiry = { - .cmd_code = SCSI_CMD_INQUIRY, - .alloc_length = sizeof(scsi_inquiry_resp_t) + .cmd_code = SCSI_CMD_INQUIRY, + .alloc_length = sizeof(scsi_inquiry_resp_t) }; + memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len); - memcpy(p_msch->cbw.command, &cmd_inquiry, p_msch->cbw.cmd_len); - - TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, p_data) ); + TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb)); - return TUSB_ERROR_NONE; + return true; } -#endif -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) +bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) { msc_cbw_t cbw = { 0 }; msc_cbw_add_signature(&cbw, lun); @@ -252,20 +253,12 @@ void msch_init(void) tu_memclr(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); } - void msch_close(uint8_t dev_addr) { tu_memclr(&msch_data[dev_addr-1], sizeof(msch_interface_t)); tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback } -static bool get_csw(uint8_t dev_addr, msch_interface_t * p_msc) -{ - p_msc->stage = MSC_STAGE_STATUS; - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); - return true; -} - bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { msch_interface_t* p_msc = &msch_data[dev_addr-1]; @@ -288,12 +281,15 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 }else { // Status stage - get_csw(dev_addr, p_msc); + p_msc->stage = MSC_STAGE_STATUS; + TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); } break; case MSC_STAGE_DATA: - get_csw(dev_addr, p_msc); + // Status stage + p_msc->stage = MSC_STAGE_STATUS; + TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); break; case MSC_STAGE_STATUS: @@ -317,7 +313,6 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool open_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -static bool open_read_capacity10_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) { @@ -331,9 +326,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it for(uint32_t i=0; i<2; i++) { - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); - TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - + TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) @@ -378,6 +371,7 @@ static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t c // STALL means zero p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? msch_buffer[0] : 0; + p_msc->max_lun++; // MAX LUN is minus 1 by specs // MSCU Reset #if 0 // not really needed @@ -397,16 +391,6 @@ static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t c TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) ); #endif -#if 0 - //------------- SCSI Inquiry -------------// - TU_LOG2("SCSI Inquiry\r\n"); - tusbh_msc_inquiry(dev_addr, 0, msch_buffer); - TU_ASSERT( osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT) ); - - memcpy(p_msc->vendor_id , ((scsi_inquiry_resp_t*) msch_buffer)->vendor_id , 8); - memcpy(p_msc->product_id, ((scsi_inquiry_resp_t*) msch_buffer)->product_id, 16); -#endif - // TODO multiple LUN support TU_LOG2("SCSI Test Unit Ready\r\n"); tuh_msc_test_unit_ready(dev_addr, 0, open_test_unit_ready_complete); @@ -418,18 +402,11 @@ static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw { if (csw->status == 0) { - TU_LOG2("SCSI Read Capacity 10\r\n"); - msch_interface_t* p_msc = &msch_data[dev_addr-1]; - msc_cbw_t new_cbw = { 0 }; - - msc_cbw_add_signature(&new_cbw, cbw->lun); - new_cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); - new_cbw.dir = TUSB_DIR_IN_MASK; - new_cbw.cmd_len = sizeof(scsi_read_capacity10_t); - new_cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; - TU_ASSERT(tuh_msc_scsi_command(dev_addr, &new_cbw, &p_msc->capacity, open_read_capacity10_complete)); + // Unit is ready, Enumeration is complete + p_msc->is_initialized = true; // open complete TODO remove + tuh_msc_mounted_cb(dev_addr); }else { // Note: During enumeration, some device fails Test Unit Ready and require a few retries @@ -442,25 +419,9 @@ static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw } static bool open_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) -{ - TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, open_test_unit_ready_complete)); - return true; -} - -static bool open_read_capacity10_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) { TU_ASSERT(csw->status == 0); - - msch_interface_t* p_msc = &msch_data[dev_addr-1]; - - // Note: Block size and last LBA are big-endian - p_msc->capacity.last_lba = tu_ntohl(p_msc->capacity.last_lba); - p_msc->capacity.block_size = tu_ntohl(p_msc->capacity.block_size); - - // Enumeration is complete - p_msc->is_initialized = true; // open complete TODO remove - tuh_msc_mounted_cb(dev_addr); - + TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, open_test_unit_ready_complete)); return true; } diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 03231d17f..63b4753b1 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -63,9 +63,11 @@ bool tuh_msc_is_mounted(uint8_t dev_addr); */ bool tuh_msc_is_busy(uint8_t dev_addr); +uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); + bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); -bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, void* response, uint32_t len); +bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); /** \brief Get SCSI Capacity of MassStorage device * \param[in] dev_addr device address @@ -77,7 +79,7 @@ bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, void* response, uint32_ * to re-send SCSI READ CAPACITY 10 command */ -bool tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size); +bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); #if 0 /** \brief Perform SCSI READ 10 command to read data from MassStorage device -- cgit v1.3.1 From d92d1a03ca2df69856f02c64ae88d805d60ad088 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 Oct 2020 13:45:22 +0700 Subject: clean up --- src/class/msc/msc_host.c | 97 +++++++++++++++++++++++++----------------------- src/class/msc/msc_host.h | 5 ++- 2 files changed, 55 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 7a46b6866..8bf240ac7 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -53,7 +53,7 @@ typedef struct uint8_t max_lun; - volatile bool is_initialized; + volatile bool mounted; uint8_t stage; void* buffer; @@ -68,24 +68,32 @@ CFG_TUSB_MEM_SECTION static msch_interface_t msch_data[CFG_TUSB_HOST_DEVICE_MAX] // buffer used to read scsi information when mounted, largest response data currently is inquiry CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msch_buffer[sizeof(scsi_inquiry_resp_t)]; +static inline msch_interface_t* get_itf(uint8_t dev_addr) +{ + return &msch_data[dev_addr-1]; +} + //--------------------------------------------------------------------+ // PUBLIC API //--------------------------------------------------------------------+ uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) { - return msch_data[dev_addr-1].max_lun; + msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->max_lun; } -bool tuh_msc_is_mounted(uint8_t dev_addr) +bool tuh_msc_mounted(uint8_t dev_addr) { - return tuh_device_is_configured(dev_addr) && // is configured can be omitted - msch_data[dev_addr-1].is_initialized; + msch_interface_t* p_msc = get_itf(dev_addr); + + // is configured can be omitted + return tuh_device_is_configured(dev_addr) && p_msc->mounted; } bool tuh_msc_is_busy(uint8_t dev_addr) { - return msch_data[dev_addr-1].is_initialized && - hcd_edpt_busy(dev_addr, msch_data[dev_addr-1].ep_in); + msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->mounted && hcd_edpt_busy(dev_addr, p_msc->ep_in); } //--------------------------------------------------------------------+ @@ -100,7 +108,8 @@ static inline void msc_cbw_add_signature(msc_cbw_t *p_cbw, uint8_t lun) bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msc = &msch_data[dev_addr-1]; + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->mounted); // TODO claim endpoint @@ -116,8 +125,8 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msc = &msch_data[dev_addr-1]; - if ( !p_msc->is_initialized ) return false; + msch_interface_t* p_msc = get_itf(dev_addr); + if ( !p_msc->mounted ) return false; msc_cbw_t cbw = { 0 }; @@ -127,9 +136,7 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r cbw.cmd_len = sizeof(scsi_read_capacity10_t); cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; - TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb)); - - return true; + return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb); } bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) @@ -148,9 +155,7 @@ bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* re }; memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len); - TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb)); - - return true; + return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb); } bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) @@ -164,9 +169,7 @@ bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_ cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; cbw.command[1] = lun; // according to wiki TODO need verification - TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb)); - - return true; + return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb); } bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb) @@ -186,12 +189,11 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_ms memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len); - TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb)); - - return true; + return tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb); } #if 0 + tusb_error_t tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) { msch_interface_t* p_msch = &msch_data[dev_addr-1]; @@ -245,6 +247,27 @@ tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffe } #endif +#if 0 +// MSC interface Reset (not used now) +bool tuh_msc_reset(uint8_t dev_addr) +{ + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = MSC_REQ_RESET, + .wValue = 0, + .wIndex = p_msc->itf_num, + .wLength = 0 + }; + TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) ); +} +#endif + //--------------------------------------------------------------------+ // CLASS-USBH API (don't require to verify parameters) //--------------------------------------------------------------------+ @@ -261,7 +284,7 @@ void msch_close(uint8_t dev_addr) bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { - msch_interface_t* p_msc = &msch_data[dev_addr-1]; + msch_interface_t* p_msc = get_itf(dev_addr); msc_cbw_t const * cbw = &p_msc->cbw; msc_csw_t * csw = &p_msc->csw; @@ -319,7 +342,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it TU_VERIFY (MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol); - msch_interface_t* p_msc = &msch_data[dev_addr-1]; + msch_interface_t* p_msc = get_itf(dev_addr); //------------- Open Data Pipe -------------// tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); @@ -358,7 +381,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it .wIndex = p_msc->itf_num, .wLength = 1 }; - TU_ASSERT(tuh_control_xfer(dev_addr, &request, msch_buffer, open_get_maxlun_complete)); + TU_ASSERT(tuh_control_xfer(dev_addr, &request, &p_msc->max_lun, open_get_maxlun_complete)); return true; } @@ -367,30 +390,12 @@ static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t c { (void) request; - msch_interface_t* p_msc = &msch_data[dev_addr-1]; + msch_interface_t* p_msc = get_itf(dev_addr); // STALL means zero p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? msch_buffer[0] : 0; p_msc->max_lun++; // MAX LUN is minus 1 by specs - // MSCU Reset -#if 0 // not really needed - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = MSC_REQ_RESET, - .wValue = 0, - .wIndex = p_msc->itf_num, - .wLength = 0 - }; - TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) ); -#endif - // TODO multiple LUN support TU_LOG2("SCSI Test Unit Ready\r\n"); tuh_msc_test_unit_ready(dev_addr, 0, open_test_unit_ready_complete); @@ -402,10 +407,10 @@ static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw { if (csw->status == 0) { - msch_interface_t* p_msc = &msch_data[dev_addr-1]; + msch_interface_t* p_msc = get_itf(dev_addr); // Unit is ready, Enumeration is complete - p_msc->is_initialized = true; // open complete TODO remove + p_msc->mounted = true; tuh_msc_mounted_cb(dev_addr); }else { diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 63b4753b1..827311063 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -51,7 +51,10 @@ typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, ms * \retval true if device supports * \retval false if device does not support or is not mounted */ -bool tuh_msc_is_mounted(uint8_t dev_addr); + +// Check if device supports MassStorage interface. +// This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb() +bool tuh_msc_mounted(uint8_t dev_addr); /** \brief Check if the interface is currently busy or not * \param[in] dev_addr device address -- cgit v1.3.1 From 3623f578a4b9c75b61b1c7a7d0c0c3ff2440e690 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 Oct 2020 14:00:25 +0700 Subject: more clean up --- src/class/msc/msc_host.c | 5 ++-- src/class/msc/msc_host.h | 60 ++++++++++++------------------------------------ src/host/usbh.c | 5 +++- 3 files changed, 22 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 8bf240ac7..83423cfc7 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -109,7 +109,7 @@ static inline void msc_cbw_add_signature(msc_cbw_t *p_cbw, uint8_t lun) bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb) { msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); + // TU_VERIFY(p_msc->mounted); // TODO part of the enumeration also use scsi command // TODO claim endpoint @@ -278,7 +278,8 @@ void msch_init(void) void msch_close(uint8_t dev_addr) { - tu_memclr(&msch_data[dev_addr-1], sizeof(msch_interface_t)); + msch_interface_t* p_msc = get_itf(dev_addr); + tu_memclr(p_msc, sizeof(msch_interface_t)); tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback } diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 827311063..06b1067cc 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -44,13 +44,8 @@ typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); //--------------------------------------------------------------------+ -// MASS STORAGE Application API +// Application API //--------------------------------------------------------------------+ -/** \brief Check if device supports MassStorage interface or not - * \param[in] dev_addr device address - * \retval true if device supports - * \retval false if device does not support or is not mounted - */ // Check if device supports MassStorage interface. // This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb() @@ -66,22 +61,24 @@ bool tuh_msc_mounted(uint8_t dev_addr); */ bool tuh_msc_is_busy(uint8_t dev_addr); +// Get Max Lun uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); +// Carry out a full SCSI command (cbw, data, csw) in non-blocking manner. +// `complete_cb` callback is invoked when SCSI op is complete. +// return true if success, false if there is already pending operation. bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); +// Carry out SCSI INQUIRY command in non-blocking manner. bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); -/** \brief Get SCSI Capacity of MassStorage device - * \param[in] dev_addr device address - * \param[out] p_last_lba Last Logical Block Address of device - * \param[out] p_block_size Block Size of device in bytes - * \retval pointer to product's name or NULL if specified device does not support MassStorage - * \note MassStorage's capacity can be computed by last LBA x block size (in bytes). During enumeration, the stack has already - * retrieved (via SCSI READ CAPACITY 10) and store this information internally. There is no need for application - * to re-send SCSI READ CAPACITY 10 command - */ +// Carry out SCSI REQUEST SENSE (10) command in non-blocking manner. +bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); + +// Carry out SCSI REQUEST SENSE (10) command in non-blocking manner. +bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); +// Carry out SCSI READ CAPACITY (10) command in non-blocking manner. bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); #if 0 @@ -114,39 +111,12 @@ tusb_error_t tuh_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uin tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count); #endif -/** \brief Perform SCSI REQUEST SENSE command, used to retrieve sense data from MassStorage device - * \param[in] dev_addr device address - * \param[in] lun Targeted Logical Unit - * \param[in] p_data Buffer to store response's data from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) - * \note This function is non-blocking and returns immediately. - * Callback is invoked when command is complete - */ -bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); - -/** \brief Perform SCSI TEST UNIT READY command to test if MassStorage device is ready - * \param[in] dev_addr device address - * \param[in] lun Targeted Logical Unit - * \note This function is non-blocking and returns immediately. - * Callback is invoked when command is complete - */ -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); - - -//tusb_error_t tusbh_msc_scsi_send(uint8_t dev_addr, uint8_t lun, bool is_direction_in, -// uint8_t const * p_command, uint8_t cmd_len, -// uint8_t * p_response, uint32_t resp_len); - //------------- Application Callback -------------// -/** \brief Callback function that will be invoked when a device with MassStorage interface is mounted - * \param[in] dev_addr Address of newly mounted device - * \note This callback should be used by Application to set-up interface-related data - */ + +// Invoked when a device with MassStorage interface is mounted void tuh_msc_mounted_cb(uint8_t dev_addr); -/** \brief Callback function that will be invoked when a device with MassStorage interface is unmounted - * \param[in] dev_addr Address of newly unmounted device - * \note This callback should be used by Application to tear-down interface-related data - */ +// Invoked when a device with MassStorage interface is unmounted void tuh_msc_unmounted_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index 595024b9c..7d1201aa4 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -880,9 +880,12 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura } else { + TU_LOG2("%s open\r\n", driver->name); + uint16_t itf_len = 0; - TU_LOG2("%s open\r\n", driver->name); + // TODO class driver can perform control transfer when opening which is + // non-blocking --> need a way to coordinate composite device TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); p_desc += itf_len; -- cgit v1.3.1 From db70a35044bdec7092e89f269429cf87bbce6afe Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 13 Oct 2020 16:25:51 +0200 Subject: osal_none: Fix queue definition OSAL_QUEUE_DEF was not updated while FIFO was changed to use unmasked pointers. Two fields that are crucial to new functionality were left uninitialized resulting in FIFO slowing down in time. --- src/osal/osal_none.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 4a5843f8e..1d170d2fa 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -139,6 +139,8 @@ typedef osal_queue_def_t* osal_queue_t; .depth = _depth, \ .item_size = sizeof(_type), \ .overwritable = false, \ + .max_pointer_idx = (2*(_depth))-1, \ + .non_used_index_space = 0xFFFF-((2*(_depth))-1),\ }\ } -- cgit v1.3.1 From 8669fd738313e296c376312ba22945a003d81a4f Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Thu, 15 Oct 2020 15:34:12 +0200 Subject: audio: Add two channel feature unit descriptor Feature unit descriptor size depends on number of channels. So far only single channel feature unit was present. This change adds feature unit descriptor for two channels. --- src/device/usbd.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index 1b0f0cbd3..d48f37eb0 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -350,6 +350,11 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re #define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _stridx) \ TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), _stridx +// 2 - Channels +#define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN (6+(2+1)*4) +#define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _stridx) \ + TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), _stridx + // For more channels, add definitions here /* Standard AS Interface Descriptor(4.9.1) */ -- cgit v1.3.1 From c87ed8eff1ac1305f69dd83144890f5a6f752a6f Mon Sep 17 00:00:00 2001 From: Jacob Potter Date: Sun, 18 Oct 2020 16:55:14 -0600 Subject: Allow use of internal FS PHY on OTG_HS interface Some ST parts (like STM32F74xxx / STM32F75xxx) allow the USB_OTG_HS core to be used with either an external high-speed ULPI PHY or an internal full-speed-only (12mbps) PHY. Currently the code assumes than an ULPI PHY is used unless the chip has an internal high-speed PHY (`#if defined(USB_HS_PHYC)`), with no provision to use the internal FS PHY. --- src/portable/st/synopsys/dcd_synopsys.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index ca306ff8f..11678857c 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -416,7 +416,9 @@ void dcd_init (uint8_t rhport) if ( rhport == 1 ) { // On selected MCUs HS port1 can be used with external PHY via ULPI interface - +#if defined(TUD_OPT_SYNOPSYS_FS_PHY) + usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; +#else // deactivate internal PHY usb_otg->GCCFG &= ~USB_OTG_GCCFG_PWRDWN; @@ -425,6 +427,7 @@ void dcd_init (uint8_t rhport) // Select default internal VBUS Indicator and Drive for ULPI usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); +#endif #if defined(USB_HS_PHYC) // Highspeed with embedded UTMI PHYC @@ -467,8 +470,13 @@ void dcd_init (uint8_t rhport) set_speed(rhport, TUD_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL); - // Enable internal USB transceiver. + // Enable internal USB transceiver. Unconditional if using FS PHY on HS core. +#if defined(TUD_OPT_SYNOPSYS_FS_PHY) + usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; +#else if ( rhport == 0 ) usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; +#endif + usb_otg->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | -- cgit v1.3.1 From f5b72f5796554910e14040cf747d6eea9505ee1a Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sat, 24 Oct 2020 17:29:47 -0500 Subject: net_device: tweak 'pbuf chain' implementation --- src/class/net/net_device.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 1d7f9ce3a..238d64d81 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -374,8 +374,8 @@ static void handle_incoming_packet(uint32_t len) if (p) { + /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ memcpy(p->payload, pnt, size); - p->len = size; accepted = tud_network_recv_cb(p); if (!accepted) pbuf_free(p); @@ -441,11 +441,13 @@ void tud_network_xmit(struct pbuf *p) len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; data = transmitted + len; + /* traverse the "pbuf chain"; see ./lwip/src/core/pbuf.c for more info */ for(q = p; q != NULL; q = q->next) { memcpy(data, (char *)q->payload, q->len); data += q->len; len += q->len; + if (q->len == q->tot_len) break; } if (!_netd_itf.ecm_mode) -- cgit v1.3.1 From 01996457c8974de5fcb02dab32210ddb99f0134a Mon Sep 17 00:00:00 2001 From: Jacob Potter Date: Sat, 24 Oct 2020 17:11:32 -0600 Subject: CR feedback: compare CFG_TUSB_RHPORT1_MODE instead of using new macro --- src/portable/st/synopsys/dcd_synopsys.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 11678857c..6edb119c1 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -416,9 +416,7 @@ void dcd_init (uint8_t rhport) if ( rhport == 1 ) { // On selected MCUs HS port1 can be used with external PHY via ULPI interface -#if defined(TUD_OPT_SYNOPSYS_FS_PHY) - usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; -#else +#if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HIGH_SPEED // deactivate internal PHY usb_otg->GCCFG &= ~USB_OTG_GCCFG_PWRDWN; @@ -427,6 +425,8 @@ void dcd_init (uint8_t rhport) // Select default internal VBUS Indicator and Drive for ULPI usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI); +#else + usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; #endif #if defined(USB_HS_PHYC) @@ -470,11 +470,11 @@ void dcd_init (uint8_t rhport) set_speed(rhport, TUD_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL); - // Enable internal USB transceiver. Unconditional if using FS PHY on HS core. -#if defined(TUD_OPT_SYNOPSYS_FS_PHY) - usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; -#else + // Enable internal USB transceiver, unless using HS core (port 1) with external PHY. +#if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HIGH_SPEED if ( rhport == 0 ) usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; +#else + usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; #endif -- cgit v1.3.1 From 229be75a98af03bdbcfabb29b8a3ddd106ba5f30 Mon Sep 17 00:00:00 2001 From: Jacob Potter Date: Sat, 24 Oct 2020 17:16:05 -0600 Subject: Move into if statement --- src/portable/st/synopsys/dcd_synopsys.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 6edb119c1..9aeec79e6 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -471,12 +471,7 @@ void dcd_init (uint8_t rhport) set_speed(rhport, TUD_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL); // Enable internal USB transceiver, unless using HS core (port 1) with external PHY. -#if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HIGH_SPEED - if ( rhport == 0 ) usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; -#else - usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; -#endif - + if (!(rhport == 1 && (CFG_TUSB_RHPORT1_MODE & OPT_MODE_HIGH_SPEED))) usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN; usb_otg->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM | -- cgit v1.3.1 From a097b7e51aac7fc92708e1bc536e84a9ec2af3ec Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sat, 24 Oct 2020 20:27:57 -0500 Subject: net_device: re-factor code so as to not be specific to lwIP --- examples/device/net_lwip_webserver/src/main.c | 40 ++++++++++++++++++++++++--- src/class/net/net_device.c | 30 ++------------------ src/class/net/net_device.h | 15 +++++----- 3 files changed, 47 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index 020f4e4d6..27adce86f 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -99,7 +99,7 @@ static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) /* if the network driver can accept another packet, we make it happen */ if (tud_network_can_xmit()) { - tud_network_xmit(p); + tud_network_xmit(p, 0 /* unused for this example */); return ERR_OK; } @@ -152,17 +152,49 @@ bool dns_query_proc(const char *name, ip_addr_t *addr) return false; } -bool tud_network_recv_cb(struct pbuf *p) +bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { /* this shouldn't happen, but if we get another packet before parsing the previous, we must signal our inability to accept it */ if (received_frame) return false; - /* store away the pointer for service_traffic() to later handle */ - received_frame = p; + if (size) + { + struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); + + if (p) + { + /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ + memcpy(p->payload, src, size); + + /* store away the pointer for service_traffic() to later handle */ + received_frame = p; + } + } + return true; } +uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) +{ + struct pbuf *p = (struct pbuf *)ref; + struct pbuf *q; + uint16_t len = 0; + + (void)arg; /* unused for this example */ + + /* traverse the "pbuf chain"; see ./lwip/src/core/pbuf.c for more info */ + for(q = p; q != NULL; q = q->next) + { + memcpy(dst, (char *)q->payload, q->len); + dst += q->len; + len += q->len; + if (q->len == q->tot_len) break; + } + + return len; +} + static void service_traffic(void) { /* handle any packet received by tud_network_recv_cb() */ diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 238d64d81..65fd1ab53 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -366,23 +366,7 @@ static void handle_incoming_packet(uint32_t len) } } - bool accepted = false; - - if (size) - { - struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); - - if (p) - { - /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ - memcpy(p->payload, pnt, size); - accepted = tud_network_recv_cb(p); - - if (!accepted) pbuf_free(p); - } - } - - if (!accepted) + if (!tud_network_recv_cb(pnt, size)) { /* if a buffer was never handled by user code, we must renew on the user's behalf */ tud_network_recv_renew(); @@ -429,9 +413,8 @@ bool tud_network_can_xmit(void) return can_xmit; } -void tud_network_xmit(struct pbuf *p) +void tud_network_xmit(void *ref, uint16_t arg) { - struct pbuf *q; uint8_t *data; uint16_t len; @@ -441,14 +424,7 @@ void tud_network_xmit(struct pbuf *p) len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN; data = transmitted + len; - /* traverse the "pbuf chain"; see ./lwip/src/core/pbuf.c for more info */ - for(q = p; q != NULL; q = q->next) - { - memcpy(data, (char *)q->payload, q->len); - data += q->len; - len += q->len; - if (q->len == q->tot_len) break; - } + len += tud_network_xmit_cb(data, ref, arg); if (!_netd_itf.ecm_mode) { diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 0175ea56b..795b2f9e3 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -32,15 +32,13 @@ #include "device/usbd.h" #include "class/cdc/cdc.h" -// TODO should not include external files -#include "lwip/pbuf.h" -#include "netif/ethernet.h" - /* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ #define CFG_TUD_NET_ENDPOINT_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) /* Maximum Tranmission Unit (in bytes) of the network, including Ethernet header */ -#define CFG_TUD_NET_MTU (1500 + SIZEOF_ETH_HDR) +#ifndef CFG_TUD_NET_MTU +#define CFG_TUD_NET_MTU 1514 +#endif #ifdef __cplusplus extern "C" { @@ -54,7 +52,10 @@ void tud_network_init_cb(void); // client must provide this: return false if the packet buffer was not accepted -bool tud_network_recv_cb(struct pbuf *p); +bool tud_network_recv_cb(const uint8_t *src, uint16_t size); + +// client must provide this: copy from network stack packet pointer to dst +uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg); // client must provide this: 48-bit MAC address // TODO removed later since it is not part of tinyusb stack @@ -67,7 +68,7 @@ void tud_network_recv_renew(void); bool tud_network_can_xmit(void); // if network_can_xmit() returns true, network_xmit() can be called once -void tud_network_xmit(struct pbuf *p); +void tud_network_xmit(void *ref, uint16_t arg); //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API -- cgit v1.3.1 From 3ea813875034be8878d3f01a740c377ebb6c8306 Mon Sep 17 00:00:00 2001 From: Jacob Potter Date: Sat, 31 Oct 2020 10:57:53 -0600 Subject: Rename CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL This was a confusing name; "Ethernet control model" (CDC ECM) and "network control model" (CDC NCM) are two separate USB subclasses. --- src/class/cdc/cdc.h | 2 +- src/class/net/net_device.c | 6 +++--- src/device/usbd.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index f0488acbb..2c044ac7f 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -63,7 +63,7 @@ typedef enum CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL , ///< Telephone Control Model [USBPSTN1.2] CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL , ///< Multi-Channel Control Model [USBISDN1.2] CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL , ///< CAPI Control Model [USBISDN1.2] - CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL , ///< Ethernet Networking Control Model [USBECM1.2] + CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL , ///< Ethernet Networking Control Model [USBECM1.2] CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL , ///< ATM Networking Control Model [USBATM1.2] CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL , ///< Wireless Handset Control Model [USBWMC1.1] CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT , ///< Device Management [USBWMC1.1] diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 65fd1ab53..3a45a9b99 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -141,9 +141,9 @@ uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 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); + bool const is_ecm = (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL == itf_desc->bInterfaceSubClass && + 0x00 == itf_desc->bInterfaceProtocol); TU_VERIFY(is_rndis || is_ecm, 0); diff --git a/src/device/usbd.h b/src/device/usbd.h index d48f37eb0..0a446fdc2 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -554,9 +554,9 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re // 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,\ + 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_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,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_CONTROL_MODEL, 0, _desc_stridx,\ /* CDC-ECM Header */\ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\ /* CDC-ECM Union */\ -- cgit v1.3.1 From 67ac40b98d217dde82090bf10a0cf55af5d1c44b Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 1 Nov 2020 13:37:56 +0700 Subject: house keeping: make tu_print_mem format easier to compare with hex2dump --- examples/device/audio_test/src/tusb_config.h | 6 ++++-- src/common/tusb_common.h | 2 +- src/tusb.c | 24 ++++++++++++------------ 3 files changed, 17 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index 16f88a4da..5d94858ea 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -47,6 +47,10 @@ extern "C" { #define CFG_TUSB_OS OPT_OS_NONE +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG 0 +#endif + // CFG_TUSB_DEBUG is defined by compiler in DEBUG build // #define CFG_TUSB_DEBUG 0 @@ -105,8 +109,6 @@ extern "C" { // Size of control request buffer #define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 -#define CFG_TUSB_DEBUG 0 - #ifdef __cplusplus } #endif diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 15892fa33..f10be88ab 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -213,7 +213,7 @@ static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value // 2 : print out log #if CFG_TUSB_DEBUG -void tu_print_mem(void const *buf, uint16_t count, uint8_t indent); +void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); #ifdef CFG_TUSB_DEBUG_PRINTF extern int CFG_TUSB_DEBUG_PRINTF(const char *format, ...); diff --git a/src/tusb.c b/src/tusb.c index 1bc134dba..bed525b9f 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -70,20 +70,24 @@ char const* const tusb_strerr[TUSB_ERROR_COUNT] = { ERROR_TABLE(ERROR_STRING) }; static void dump_str_line(uint8_t const* buf, uint16_t count) { + tu_printf(" |"); + // each line is 16 bytes for(uint16_t i=0; i Date: Sun, 1 Nov 2020 17:46:46 +0700 Subject: added host set_config driver to resolve control conflict with SET_CONFIGURE for class driver - open will be called to open endpoint only - set_config called later to initialized class driver --- src/class/hid/hid_host.c | 91 +++++++++++++++++++++++++++++------------------- src/class/hid/hid_host.h | 1 + src/class/msc/msc_host.c | 32 +++++++++++------ src/class/msc/msc_host.h | 1 + src/host/usbh.c | 46 +++++++++++++++++++----- src/host/usbh.h | 12 ++++--- src/host/usbh_hcd.h | 3 +- 7 files changed, 126 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 5058191f4..a96eb6276 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -173,39 +173,6 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c tusb_desc_endpoint_t const * p_endpoint_desc = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint_desc->bDescriptorType, TUSB_ERROR_INVALID_PARA); - // SET IDLE = 0 request - // Device can stall if not support this request - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = 0, // idle_rate = 0 - .wIndex = p_interface_desc->bInterfaceNumber, - .wLength = 0 - }; - - // stall is a valid response for SET_IDLE, therefore we could ignore result of this request - tuh_control_xfer(dev_addr, &request, NULL, NULL); - -#if 0 - //------------- Get Report Descriptor TODO HID parser -------------// - if ( p_desc_hid->bNumDescriptors ) - { - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_INTERFACE), - TUSB_REQ_GET_DESCRIPTOR, (p_desc_hid->bReportType << 8), 0, - p_desc_hid->wReportLength, report_descriptor ), - error - ); - (void) error; // if error in getting report descriptor --> treating like there is none - } -#endif - if ( HID_SUBCLASS_BOOT == p_interface_desc->bInterfaceSubClass ) { #if CFG_TUH_HID_KEYBOARD @@ -213,7 +180,6 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c { TU_ASSERT( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) ); TU_LOG2_HEX(keyboardh_data[dev_addr-1].ep_in); - tuh_hid_keyboard_mounted_cb(dev_addr); } else #endif @@ -222,7 +188,6 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c { TU_ASSERT ( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) ); TU_LOG2_HEX(mouseh_data[dev_addr-1].ep_in); - tuh_hid_mouse_mounted_cb(dev_addr); } else #endif @@ -241,6 +206,62 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c return true; } +bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) +{ +#if 0 + //------------- Get Report Descriptor TODO HID parser -------------// + if ( p_desc_hid->bNumDescriptors ) + { + STASK_INVOKE( + usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_INTERFACE), + TUSB_REQ_GET_DESCRIPTOR, (p_desc_hid->bReportType << 8), 0, + p_desc_hid->wReportLength, report_descriptor ), + error + ); + (void) error; // if error in getting report descriptor --> treating like there is none + } +#endif + +#if 0 + // SET IDLE = 0 request + // Device can stall if not support this request + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_IDLE, + .wValue = 0, // idle_rate = 0 + .wIndex = p_interface_desc->bInterfaceNumber, + .wLength = 0 + }; + + // stall is a valid response for SET_IDLE, therefore we could ignore result of this request + tuh_control_xfer(dev_addr, &request, NULL, NULL); +#endif + + usbh_driver_set_config_complete(dev_addr, itf_num); + +#if CFG_TUH_HID_KEYBOARD + if ( keyboardh_data[dev_addr-1].itf_num == itf_num) + { + tuh_hid_keyboard_mounted_cb(dev_addr); + } +#endif + +#if CFG_TUH_HID_MOUSE + if ( mouseh_data[dev_addr-1].ep_in == itf_num ) + { + tuh_hid_mouse_mounted_cb(dev_addr); + } +#endif + + return true; +} + bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO may need to use this para later diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 324dad203..5c77398f8 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -197,6 +197,7 @@ void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); //--------------------------------------------------------------------+ void hidh_init(void); bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); +bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num); bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hidh_close(uint8_t dev_addr); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 83423cfc7..02ca81e77 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -334,9 +334,9 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 // MSC Enumeration //--------------------------------------------------------------------+ -static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -static bool open_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); +static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); +static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) { @@ -367,6 +367,14 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it p_msc->itf_num = itf_desc->bInterfaceNumber; (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + return true; +} + +bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + TU_ASSERT(p_msc->itf_num == itf_num); + //------------- Get Max Lun -------------// TU_LOG2("MSC Get Max Lun\r\n"); tusb_control_request_t request = @@ -379,15 +387,15 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it }, .bRequest = MSC_REQ_GET_MAX_LUN, .wValue = 0, - .wIndex = p_msc->itf_num, + .wIndex = itf_num, .wLength = 1 }; - TU_ASSERT(tuh_control_xfer(dev_addr, &request, &p_msc->max_lun, open_get_maxlun_complete)); + TU_ASSERT(tuh_control_xfer(dev_addr, &request, &p_msc->max_lun, config_get_maxlun_complete)); return true; } -static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { (void) request; @@ -399,17 +407,19 @@ static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t c // TODO multiple LUN support TU_LOG2("SCSI Test Unit Ready\r\n"); - tuh_msc_test_unit_ready(dev_addr, 0, open_test_unit_ready_complete); + tuh_msc_test_unit_ready(dev_addr, 0, config_test_unit_ready_complete); return true; } -static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) { if (csw->status == 0) { msch_interface_t* p_msc = get_itf(dev_addr); + usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); + // Unit is ready, Enumeration is complete p_msc->mounted = true; tuh_msc_mounted_cb(dev_addr); @@ -418,16 +428,16 @@ static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw // Note: During enumeration, some device fails Test Unit Ready and require a few retries // with Request Sense to start working !! // TODO limit number of retries - TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, msch_buffer, open_request_sense_complete)); + TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, msch_buffer, config_request_sense_complete)); } return true; } -static bool open_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) { TU_ASSERT(csw->status == 0); - TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, open_test_unit_ready_complete)); + TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, config_test_unit_ready_complete)); return true; } diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 06b1067cc..5913350b8 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -125,6 +125,7 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr); void msch_init(void); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); +bool msch_set_config(uint8_t dev_addr, uint8_t itf_num); bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void msch_close(uint8_t dev_addr); diff --git a/src/host/usbh.c b/src/host/usbh.c index 7d1201aa4..3e321652b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -67,6 +67,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_MSC, .init = msch_init, .open = msch_open, + .set_config = msch_set_config, .xfer_cb = msch_xfer_cb, .close = msch_close }, @@ -78,6 +79,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_HID, .init = hidh_init, .open = hidh_open_subtask, + .set_config = hidh_set_config, .xfer_cb = hidh_xfer_cb, .close = hidh_close }, @@ -308,6 +310,7 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const usbh_device_t* dev = &_usbh_devices[dev_addr]; // new endpoints belongs to latest interface (last valid value) + // TODO FIXME not true with ISO uint8_t drvid = 0xff; for(uint8_t i=0; i < sizeof(dev->itf2drv); i++) { @@ -525,6 +528,31 @@ static uint8_t get_new_address(void) return CFG_TUSB_HOST_DEVICE_MAX+1; } +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) +{ + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + for(itf_num++; itf_num < sizeof(dev->itf2drv); itf_num++) + { + // continue with next valid interface + uint8_t const drv_id = dev->itf2drv[itf_num]; + if (drv_id != 0xff) + { + usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; + TU_LOG2("%s set config itf = %u\r\n", driver->name, itf_num); + driver->set_config(dev_addr, itf_num); + break; + } + } + + // all interface are configured + if (itf_num == sizeof(dev->itf2drv)) + { + // Invoke callback if available + if (tuh_mount_cb) tuh_mount_cb(dev_addr); + } +} + //--------------------------------------------------------------------+ // Enumeration Process // is a lengthy process with a seires of control transfer to configure @@ -783,6 +811,7 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r .wValue = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), .wIndex = 0, .wLength = total_len + }; TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_config_desc_complete) ); @@ -795,6 +824,10 @@ static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request (void) request; TU_ASSERT(XFER_RESULT_SUCCESS == result); + // Parse configuration & set up drivers + // Driver open aren't allowed to make any usb transfer yet + parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); + TU_LOG2("Set Configuration Descriptor\r\n"); tusb_control_request_t const new_request = { @@ -825,12 +858,10 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co dev->configured = 1; dev->state = TUSB_DEVICE_STATE_CONFIGURED; - // Parse configuration & set up drivers - // TODO driver open still use usbh_control_xfer - parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); - - // Invoke callback if available - if (tuh_mount_cb) tuh_mount_cb(dev_addr); + // Start the Set Configuration process for interfaces (itf = 0xff) + // Since driver can perform control transfer within its set_config, this is done asynchronously. + // The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete() + usbh_driver_set_config_complete(dev_addr, 0xff); return true; } @@ -883,9 +914,6 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura TU_LOG2("%s open\r\n", driver->name); uint16_t itf_len = 0; - - // TODO class driver can perform control transfer when opening which is - // non-blocking --> need a way to coordinate composite device TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); p_desc += itf_len; diff --git a/src/host/usbh.h b/src/host/usbh.h index fde1dd11c..19ab72f54 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -58,10 +58,11 @@ typedef struct { uint8_t class_code; - void (* const init) (void); - bool (* const open)(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); - bool (* const xfer_cb) (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* const close) (uint8_t); + void (* const init )(void); + bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); + bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); + bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + void (* const close )(uint8_t dev_addr); } usbh_class_driver_t; typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -105,6 +106,7 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // CLASS-USBH & INTERNAL API +// TODO move to usbh_pvt.h //--------------------------------------------------------------------+ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); @@ -116,6 +118,8 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); // TODO remove later +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); + #ifdef __cplusplus } #endif diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index 20348eed1..79b547fb3 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -47,6 +47,8 @@ //--------------------------------------------------------------------+ // USBH-HCD common data structure //--------------------------------------------------------------------+ + +// TODO move to usbh.c typedef struct { //------------- port -------------// uint8_t rhport; @@ -95,7 +97,6 @@ typedef struct { // TODO merge ep2drv here, 4-bit should be sufficient }ep_status[CFG_TUH_EP_MAX][2]; - // Mutex for claiming endpoint, only needed when using with preempted RTOS #if CFG_TUSB_OS != OPT_OS_NONE osal_mutex_def_t mutexdef; -- cgit v1.3.1 From 6eafdfab935be976ba3198f63a576ed0add05cb6 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 2 Nov 2020 00:54:04 +0700 Subject: update usbh with hub to use async control transfer work ok with msc + hub, but definitely need more testing. --- src/host/hub.c | 305 ++++++++++++++++++++++++++++++++++++---------------- src/host/hub.h | 9 +- src/host/usbh.c | 169 +++++++++++++++++++---------- src/host/usbh.h | 2 + src/host/usbh_hcd.h | 2 +- 5 files changed, 331 insertions(+), 156 deletions(-) (limited to 'src') diff --git a/src/host/hub.c b/src/host/hub.c index ed96713e2..f778ef203 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -33,21 +33,21 @@ //--------------------------------------------------------------------+ #include "hub.h" -extern void osal_task_delay(uint32_t msec); // TODO remove - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ typedef struct { uint8_t itf_num; - uint8_t ep_status; - uint8_t port_number; + uint8_t ep_in; + uint8_t port_count; uint8_t status_change; // data from status change interrupt endpoint + + hub_port_status_response_t port_status; }usbh_hub_t; CFG_TUSB_MEM_SECTION static usbh_hub_t hub_data[CFG_TUSB_HOST_DEVICE_MAX]; -TU_ATTR_ALIGNED(4) CFG_TUSB_MEM_SECTION static uint8_t hub_enum_buffer[sizeof(descriptor_hub_desc_t)]; +TU_ATTR_ALIGNED(4) CFG_TUSB_MEM_SECTION static uint8_t _hub_buffer[sizeof(descriptor_hub_desc_t)]; //OSAL_SEM_DEF(hub_enum_semaphore); //static osal_semaphore_handle_t hub_enum_sem_hdl; @@ -55,25 +55,30 @@ TU_ATTR_ALIGNED(4) CFG_TUSB_MEM_SECTION static uint8_t hub_enum_buffer[sizeof(de //--------------------------------------------------------------------+ // HUB //--------------------------------------------------------------------+ -bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature) +bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb) { - TU_ASSERT(HUB_FEATURE_PORT_CONNECTION_CHANGE <= feature && feature <= HUB_FEATURE_PORT_RESET_CHANGE); - - tusb_control_request_t request = { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, - .bRequest = HUB_REQUEST_CLEAR_FEATURE, - .wValue = feature, - .wIndex = hub_port, - .wLength = 0 + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_OTHER, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HUB_REQUEST_CLEAR_FEATURE, + .wValue = feature, + .wIndex = hub_port, + .wLength = 0 }; - TU_ASSERT( usbh_control_xfer( hub_addr, &request, NULL ) ); + TU_LOG2("HUB Clear Port Feature: addr = 0x%02X, port = %u, feature = %u\r\n", hub_addr, hub_port, feature); + TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); return true; } -bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, hub_port_status_response_t* resp) +bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb) { - tusb_control_request_t request = + tusb_control_request_t const request = { .bmRequestType_bit = { @@ -81,31 +86,35 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, hub_port_status_res .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, - .bRequest = HUB_REQUEST_GET_STATUS, .wValue = 0, .wIndex = hub_port, .wLength = 4 }; - TU_ASSERT( usbh_control_xfer( hub_addr, &request, hub_enum_buffer ) ); - - memcpy(resp, hub_enum_buffer, sizeof(hub_port_status_response_t)); + TU_LOG2("HUB Get Port Status: addr = 0x%02X, port = %u\r\n", hub_addr, hub_port); + TU_ASSERT( tuh_control_xfer( hub_addr, &request, resp, complete_cb) ); return true; } -bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port) +bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb) { - //------------- Set Port Reset -------------// - tusb_control_request_t request = { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, - .bRequest = HUB_REQUEST_SET_FEATURE, - .wValue = HUB_FEATURE_PORT_RESET, - .wIndex = hub_port, - .wLength = 0 + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_OTHER, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HUB_REQUEST_SET_FEATURE, + .wValue = HUB_FEATURE_PORT_RESET, + .wIndex = hub_port, + .wLength = 0 }; - TU_ASSERT( usbh_control_xfer( hub_addr, &request, NULL ) ); + TU_LOG2("HUB Reset Port: addr = 0x%02X, port = %u\r\n", hub_addr, hub_port); + TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); return true; } @@ -133,42 +142,179 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); hub_data[dev_addr-1].itf_num = itf_desc->bInterfaceNumber; - hub_data[dev_addr-1].ep_status = ep_desc->bEndpointAddress; + hub_data[dev_addr-1].ep_in = ep_desc->bEndpointAddress; (*p_length) = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); + return true; +} + +static bool config_get_hub_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); + +static bool config_get_hub_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + usbh_hub_t* p_hub = &hub_data[dev_addr-1]; + + // only use number of ports in hub descriptor + descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer; + p_hub->port_count = desc_hub->bNbrPorts; + + // May need to GET_STATUS + + // Ports must be powered on to be able to detect connection + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_OTHER, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HUB_REQUEST_SET_FEATURE, + .wValue = HUB_FEATURE_PORT_POWER, + .wIndex = 1, // starting with port 1 + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_port_power_complete) ); + + return true; +} + +static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(XFER_RESULT_SUCCESS == result); + usbh_hub_t* p_hub = &hub_data[dev_addr-1]; + + if (request->wIndex == p_hub->port_count) + { + // All ports are power -> queue notification status endpoint and + // complete the SET CONFIGURATION + TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1) ); + + usbh_driver_set_config_complete(dev_addr, p_hub->itf_num); + }else + { + tusb_control_request_t new_request = *request; + new_request.wIndex++; // power next port + + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_port_power_complete) ); + } + + return true; +} + +bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) +{ + usbh_hub_t* p_hub = &hub_data[dev_addr-1]; + TU_ASSERT(itf_num == p_hub->itf_num); + //------------- Get Hub Descriptor -------------// - tusb_control_request_t request = { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, - .bRequest = HUB_REQUEST_GET_DESCRIPTOR, - .wValue = 0, - .wIndex = 0, - .wLength = sizeof(descriptor_hub_desc_t) + tusb_control_request_t request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = HUB_REQUEST_GET_DESCRIPTOR, + .wValue = 0, + .wIndex = 0, + .wLength = sizeof(descriptor_hub_desc_t) }; - TU_ASSERT( usbh_control_xfer( dev_addr, &request, hub_enum_buffer ) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &request, _hub_buffer, config_get_hub_desc_complete) ); + + return true; +} + +static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); + +static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(result == XFER_RESULT_SUCCESS); - // only care about this field in hub descriptor - hub_data[dev_addr-1].port_number = ((descriptor_hub_desc_t*) hub_enum_buffer)->bNbrPorts; + // usbh_hub_t * p_hub = &hub_data[dev_addr-1]; + uint8_t const port_num = (uint8_t) request->wIndex; - //------------- Set Port_Power on all ports -------------// - // TODO may only power port with attached - request = (tusb_control_request_t ) { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, - .bRequest = HUB_REQUEST_SET_FEATURE, - .wValue = HUB_FEATURE_PORT_POWER, - .wIndex = 0, - .wLength = 0 + // submit attach event + hcd_event_t event = + { + .rhport = usbh_get_rhport(dev_addr), + .event_id = HCD_EVENT_DEVICE_ATTACH, + .connection = + { + .hub_addr = dev_addr, + .hub_port = port_num + } }; - for(uint8_t i=1; i <= hub_data[dev_addr-1].port_number; i++) + hcd_event_handler(&event, false); + + return true; +} + +static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(result == XFER_RESULT_SUCCESS); + + usbh_hub_t * p_hub = &hub_data[dev_addr-1]; + uint8_t const port_num = (uint8_t) request->wIndex; + + if ( p_hub->port_status.status.connection ) { - request.wIndex = i; - TU_ASSERT( usbh_control_xfer( dev_addr, &request, NULL ) ); + // Reset port if attach event + hub_port_reset(dev_addr, port_num, connection_port_reset_complete); + }else + { + // submit detach event + hcd_event_t event = + { + .rhport = usbh_get_rhport(dev_addr), + .event_id = HCD_EVENT_DEVICE_REMOVE, + .connection = + { + .hub_addr = dev_addr, + .hub_port = port_num + } + }; + + hcd_event_handler(&event, false); } - // Queue notification status endpoint - TU_ASSERT( usbh_edpt_xfer(dev_addr, hub_data[dev_addr-1].ep_status, &hub_data[dev_addr-1].status_change, 1) ); + return true; +} + +static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(result == XFER_RESULT_SUCCESS); + usbh_hub_t * p_hub = &hub_data[dev_addr-1]; + uint8_t const port_num = (uint8_t) request->wIndex; + + // Connection change + if (p_hub->port_status.change.connection) + { + // Port is powered and enabled + //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); + + // Acknowledge Port Connection Change + hub_port_clear_feature(dev_addr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete); + }else + { + // Other changes are: Enable, Suspend, Over Current, Reset, L1 state + // TODO clear change + + // prepare for next hub status + // TODO continue with status_change, or maybe we can do it again with status + hub_status_pipe_queue(dev_addr); + } return true; } @@ -179,55 +325,23 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 { (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports (void) ep_addr; + TU_ASSERT( result == XFER_RESULT_SUCCESS); usbh_hub_t * p_hub = &hub_data[dev_addr-1]; - if ( result == XFER_RESULT_SUCCESS ) + TU_LOG2("Port Status Change = 0x%02X\r\n", p_hub->status_change); + for (uint8_t port=1; port <= p_hub->port_count; port++) { - TU_LOG2("Port Status Change = 0x%02X\r\n", p_hub->status_change); - for (uint8_t port=1; port <= p_hub->port_number; port++) + // TODO HUB ignore bit0 hub_status_change + if ( tu_bit_test(p_hub->status_change, port) ) { - // TODO HUB ignore bit0 hub_status_change - if ( tu_bit_test(p_hub->status_change, port) ) - { - hub_port_status_response_t port_status; - hub_port_get_status(dev_addr, port, &port_status); - - // Connection change - if (port_status.change.connection) - { - // Port is powered and enabled - //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); - - // Acknowledge Port Connection Change - hub_port_clear_feature(dev_addr, port, HUB_FEATURE_PORT_CONNECTION_CHANGE); - - // Reset port if attach event - if ( port_status.status.connection ) hub_port_reset(dev_addr, port); - - hcd_event_t event = - { - .rhport = _usbh_devices[dev_addr].rhport, - .event_id = port_status.status.connection ? HCD_EVENT_DEVICE_ATTACH : HCD_EVENT_DEVICE_REMOVE, - .connection = - { - .hub_addr = dev_addr, - .hub_port = port - } - }; - - hcd_event_handler(&event, true); - } - } + hub_port_get_status(dev_addr, port, &p_hub->port_status, connection_get_status_complete); + break; } - // NOTE: next status transfer is queued by usbh.c after handling this request - } - else - { - // TODO [HUB] check if hub is still plugged before polling status endpoint since failed usually mean hub unplugged -// TU_ASSERT ( hub_status_pipe_queue(dev_addr) ); } + // NOTE: next status transfer is queued by usbh.c after handling this request + return true; } @@ -239,7 +353,8 @@ void hub_close(uint8_t dev_addr) bool hub_status_pipe_queue(uint8_t dev_addr) { - return hcd_pipe_xfer(dev_addr, hub_data[dev_addr-1].ep_status, &hub_data[dev_addr-1].status_change, 1, true); + usbh_hub_t * p_hub = &hub_data[dev_addr-1]; + return hcd_pipe_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1, true); } diff --git a/src/host/hub.h b/src/host/hub.h index f00f13de7..35d8ad629 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -36,7 +36,7 @@ #ifndef _TUSB_HUB_H_ #define _TUSB_HUB_H_ -#include +#include "common/tusb_common.h" #include "usbh.h" #ifdef __cplusplus @@ -172,9 +172,9 @@ typedef struct { TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); -bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port); -bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, hub_port_status_response_t* resp); -bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature); +bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb); +bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb); +bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb); bool hub_status_pipe_queue(uint8_t dev_addr); //--------------------------------------------------------------------+ @@ -182,6 +182,7 @@ bool hub_status_pipe_queue(uint8_t dev_addr); //--------------------------------------------------------------------+ void hub_init(void); bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); +bool hub_set_config(uint8_t dev_addr, uint8_t itf_num); bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hub_close(uint8_t dev_addr); diff --git a/src/host/usbh.c b/src/host/usbh.c index 3e321652b..4239cd1ec 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -91,6 +91,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_HUB, .init = hub_init, .open = hub_open, + .set_config = hub_set_config, .xfer_cb = hub_xfer_cb, .close = hub_close }, @@ -135,6 +136,11 @@ static bool enum_new_device(hcd_event_t* event); // from usbh_control.c extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +uint8_t usbh_get_rhport(uint8_t dev_addr) +{ + return _usbh_devices[dev_addr].rhport; +} + //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) //--------------------------------------------------------------------+ @@ -562,6 +568,9 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) // one device before enumerating another one. //--------------------------------------------------------------------+ +static bool enum_request_addr0_device_desc(void); +static bool enum_request_set_addr(void); + static bool enum_get_addr0_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool enum_set_address_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool enum_get_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -570,6 +579,92 @@ static bool enum_get_config_desc_complete (uint8_t dev_addr, tusb_control_ static bool enum_set_config_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); +static bool enum_hub_clear_reset0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) dev_addr; (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + enum_request_addr0_device_desc(); + return true; +} + +static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) dev_addr; (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + usbh_device_t* dev0 = &_usbh_devices[0]; + + enum_request_set_addr(); + + // done with hub, waiting for next data on status pipe + (void) hub_status_pipe_queue( dev0->hub_addr ); + + return true; +} + +static bool enum_hub_get_status_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) dev_addr; (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + usbh_device_t* dev0 = &_usbh_devices[0]; + + hub_port_status_response_t port_status; + memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); + + if ( !port_status.status.connection ) + { + // device unplugged while delaying, nothing else to do, queue hub status + return hub_status_pipe_queue(dev_addr); + } + + dev0->speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : + (port_status.status.low_speed ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; + + // Acknowledge Port Reset Change + if (port_status.change.reset) + { + hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset0_complete); + } + + return true; +} + + +static bool enum_request_set_addr(void) +{ + // Set Address + TU_LOG2("Set Address \r\n"); + uint8_t const new_addr = get_new_address(); + TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices + + usbh_device_t* dev0 = &_usbh_devices[0]; + usbh_device_t* new_dev = &_usbh_devices[new_addr]; + + new_dev->rhport = dev0->rhport; + new_dev->hub_addr = dev0->hub_addr; + new_dev->hub_port = dev0->hub_port; + new_dev->speed = dev0->speed; + new_dev->connected = 1; + new_dev->ep0_packet_size = ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0; + + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_ADDRESS, + .wValue = new_addr, + .wIndex = 0, + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(0, &new_request, NULL, enum_set_address_complete) ); + + return true; +} + static bool enum_new_device(hcd_event_t* event) { usbh_device_t* dev0 = &_usbh_devices[0]; @@ -581,39 +676,31 @@ static bool enum_new_device(hcd_event_t* event) //------------- connected/disconnected directly with roothub -------------// if (dev0->hub_addr == 0) { - // wait until device is stable. Increase this if the first 8 bytes is failed to get + // wait until device is stable osal_task_delay(RESET_DELAY); // device unplugged while delaying if ( !hcd_port_connect_status(dev0->rhport) ) return true; dev0->speed = hcd_port_speed_get( dev0->rhport ); + + enum_request_addr0_device_desc(); } #if CFG_TUH_HUB //------------- connected/disconnected via hub -------------// else { - // TODO wait for PORT reset change instead + // wait until device is stable osal_task_delay(RESET_DELAY); - - // FIXME hub API use usbh_control_xfer - hub_port_status_response_t port_status; - TU_VERIFY_HDLR( hub_port_get_status(dev0->hub_addr, dev0->hub_port, &port_status), hub_status_pipe_queue( dev0->hub_addr) ); - - // device unplugged while delaying - if ( !port_status.status.connection ) return true; - - dev0->speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : - (port_status.status.low_speed ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; - - // Acknowledge Port Reset Change - if (port_status.change.reset) - { - hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE); - } + TU_ASSERT( hub_port_get_status(dev0->hub_addr, dev0->hub_port, _usbh_ctrl_buf, enum_hub_get_status_complete) ); } #endif // CFG_TUH_HUB + return true; +} + +static bool enum_request_addr0_device_desc(void) +{ // TODO probably doesn't need to open/close each enumeration TU_ASSERT( usbh_pipe_control_open(0, 8) ); @@ -632,7 +719,7 @@ static bool enum_new_device(hcd_event_t* event) .wIndex = 0, .wLength = 8 }; - TU_ASSERT(tuh_control_xfer(0, &request, _usbh_ctrl_buf, enum_get_addr0_device_desc_complete)); + TU_ASSERT( tuh_control_xfer(0, &request, _usbh_ctrl_buf, enum_get_addr0_device_desc_complete) ); return true; } @@ -663,52 +750,22 @@ static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_r // connected directly to roothub hcd_port_reset( dev0->rhport ); // reset port after 8 byte descriptor osal_task_delay(RESET_DELAY); + + enum_request_set_addr(); } #if CFG_TUH_HUB else { - // FIXME hub_port_reset use usbh_control_xfer - if ( hub_port_reset(dev0->hub_addr, dev0->hub_port) ) - { - osal_task_delay(RESET_DELAY); + // after RESET_DELAY the hub_port_reset() already complete + TU_ASSERT( hub_port_reset(dev0->hub_addr, dev0->hub_port, NULL) ); - // Acknowledge Port Reset Change if Reset Successful - hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE); - } + osal_task_delay(RESET_DELAY); - (void) hub_status_pipe_queue( dev0->hub_addr ); // done with hub, waiting for next data on status pipe + // Acknowledge Port Reset Change if Reset Successful + TU_ASSERT( hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset1_complete) ); } #endif // CFG_TUH_HUB - // Set Address - TU_LOG2("Set Address \r\n"); - uint8_t const new_addr = get_new_address(); - TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices - - usbh_device_t* new_dev = &_usbh_devices[new_addr]; - new_dev->rhport = dev0->rhport; - new_dev->hub_addr = dev0->hub_addr; - new_dev->hub_port = dev0->hub_port; - new_dev->speed = dev0->speed; - new_dev->connected = 1; - new_dev->ep0_packet_size = ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0; - - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_OUT - }, - .bRequest = TUSB_REQ_SET_ADDRESS, - .wValue = new_addr, - .wIndex = 0, - .wLength = 0 - }; - - TU_ASSERT(tuh_control_xfer(0, &new_request, NULL, enum_set_address_complete)); - return true; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 19ab72f54..7db918348 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -120,6 +120,8 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8 void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); +uint8_t usbh_get_rhport(uint8_t dev_addr); + #ifdef __cplusplus } #endif diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index 79b547fb3..dd0616704 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -97,7 +97,7 @@ typedef struct { // TODO merge ep2drv here, 4-bit should be sufficient }ep_status[CFG_TUH_EP_MAX][2]; -// Mutex for claiming endpoint, only needed when using with preempted RTOS + // Mutex for claiming endpoint, only needed when using with preempted RTOS #if CFG_TUSB_OS != OPT_OS_NONE osal_mutex_def_t mutexdef; osal_mutex_t mutex; -- cgit v1.3.1 From 2efdc2fb64fec2cba26dc3fd4651583bc0dcf7b3 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 2 Nov 2020 08:46:24 +0700 Subject: get hub work more reliably --- src/host/hub.c | 6 +++--- src/host/usbh.c | 32 +++++++++++++++++++++++++------- 2 files changed, 28 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/host/hub.c b/src/host/hub.c index f778ef203..2191c4560 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -71,7 +71,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, .wLength = 0 }; - TU_LOG2("HUB Clear Port Feature: addr = 0x%02X, port = %u, feature = %u\r\n", hub_addr, hub_port, feature); + TU_LOG2("HUB Clear Port Feature: addr = %u port = %u, feature = %u\r\n", hub_addr, hub_port, feature); TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); return true; } @@ -92,7 +92,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_con .wLength = 4 }; - TU_LOG2("HUB Get Port Status: addr = 0x%02X, port = %u\r\n", hub_addr, hub_port); + TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port); TU_ASSERT( tuh_control_xfer( hub_addr, &request, resp, complete_cb) ); return true; } @@ -113,7 +113,7 @@ bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_ .wLength = 0 }; - TU_LOG2("HUB Reset Port: addr = 0x%02X, port = %u\r\n", hub_addr, hub_port); + TU_LOG2("HUB Reset Port: addr = %u port = %u\r\n", hub_addr, hub_port); TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); return true; } diff --git a/src/host/usbh.c b/src/host/usbh.c index 4239cd1ec..61db0d8b0 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -601,7 +601,25 @@ static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_reques return true; } -static bool enum_hub_get_status_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool enum_hub_get_status1_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) dev_addr; (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + usbh_device_t* dev0 = &_usbh_devices[0]; + + hub_port_status_response_t port_status; + memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t)); + + // Acknowledge Port Reset Change if Reset Successful + if (port_status.change.reset) + { + TU_ASSERT( hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset1_complete) ); + } + + return true; +} + +static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { (void) dev_addr; (void) request; TU_ASSERT(XFER_RESULT_SUCCESS == result); @@ -692,7 +710,7 @@ static bool enum_new_device(hcd_event_t* event) { // wait until device is stable osal_task_delay(RESET_DELAY); - TU_ASSERT( hub_port_get_status(dev0->hub_addr, dev0->hub_port, _usbh_ctrl_buf, enum_hub_get_status_complete) ); + TU_ASSERT( hub_port_get_status(dev0->hub_addr, dev0->hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete) ); } #endif // CFG_TUH_HUB @@ -736,7 +754,7 @@ static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_r { #if CFG_TUH_HUB // TODO remove, waiting for next data on status pipe - if (dev0->hub_addr != 0) hub_status_pipe_queue( dev0->hub_addr); + if (dev0->hub_addr != 0) hub_status_pipe_queue(dev0->hub_addr); #endif return false; @@ -758,13 +776,13 @@ static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_r { // after RESET_DELAY the hub_port_reset() already complete TU_ASSERT( hub_port_reset(dev0->hub_addr, dev0->hub_port, NULL) ); - osal_task_delay(RESET_DELAY); - // Acknowledge Port Reset Change if Reset Successful - TU_ASSERT( hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset1_complete) ); + tuh_task(); // FIXME temporarily to clean up port_reset control transfer + + TU_ASSERT( hub_port_get_status(dev0->hub_addr, dev0->hub_port, _usbh_ctrl_buf, enum_hub_get_status1_complete) ); } -#endif // CFG_TUH_HUB +#endif return true; } -- cgit v1.3.1 From 14461beffa4f2e12bc37d523701be65fabd0d8ce Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 2 Nov 2020 09:19:34 +0700 Subject: remove legacy blocking usbh_control_xfer() reworking cdc host driver --- src/class/cdc/cdc_host.c | 50 +++++++++++++++++++++++++++++++++--------------- src/class/cdc/cdc_host.h | 13 +++++++++++++ src/host/usbh.c | 48 +--------------------------------------------- src/host/usbh_hcd.h | 10 ---------- 4 files changed, 49 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index ae1eef8a7..a897fb58a 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -51,9 +51,14 @@ typedef struct { //--------------------------------------------------------------------+ static cdch_data_t cdch_data[CFG_TUSB_HOST_DEVICE_MAX]; +static inline cdch_data_t* get_itf(uint8_t dev_addr) +{ + return &cdch_data[dev_addr-1]; +} + bool tuh_cdc_mounted(uint8_t dev_addr) { - cdch_data_t* cdc = &cdch_data[dev_addr-1]; + cdch_data_t* cdc = get_itf(dev_addr); return cdc->ep_in && cdc->ep_out; } @@ -61,7 +66,7 @@ bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid) { if ( !tuh_cdc_mounted(dev_addr) ) return false; - cdch_data_t const * p_cdc = &cdch_data[dev_addr-1]; + cdch_data_t const * p_cdc = get_itf(dev_addr); switch (pipeid) { @@ -111,6 +116,27 @@ bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is return hcd_pipe_xfer(dev_addr, ep_in, p_buffer, length, is_notify); } +bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb) +{ + cdch_data_t const * p_cdc = get_itf(dev_addr); + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, + .wValue = (rts ? 2 : 0) | (dtr ? 1 : 0), + .wIndex = p_cdc->itf_num, + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, complete_cb) ); + return true; +} + //--------------------------------------------------------------------+ // USBH-CLASS DRIVER API //--------------------------------------------------------------------+ @@ -132,7 +158,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it cdch_data_t * p_cdc; p_desc = tu_desc_next(itf_desc); - p_cdc = &cdch_data[dev_addr-1]; + p_cdc = get_itf(dev_addr); p_cdc->itf_num = itf_desc->bInterfaceNumber; p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; // TODO 0xff is consider as rndis candidate, other is virtual Com @@ -194,18 +220,12 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it } } - // FIXME move to seperate API : connect - tusb_control_request_t request = - { - .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, - .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, - .wValue = 0x03, // dtr on, cst on - .wIndex = p_cdc->itf_num, - .wLength = 0 - }; - - TU_ASSERT( usbh_control_xfer(dev_addr, &request, NULL) ); + return true; +} +bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num) +{ + (void) dev_addr; (void) itf_num; return true; } @@ -218,7 +238,7 @@ bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 void cdch_close(uint8_t dev_addr) { - cdch_data_t * p_cdc = &cdch_data[dev_addr-1]; + cdch_data_t * p_cdc = get_itf(dev_addr); tu_memclr(p_cdc, sizeof(cdch_data_t)); } diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index f28a0a713..66c2f0727 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -44,6 +44,18 @@ * \defgroup CDC_Serial_Host Host * @{ */ +bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb); + +static inline bool tuh_cdc_connect(uint8_t dev_addr, tuh_control_complete_cb_t complete_cb) +{ + return tuh_cdc_set_control_line_state(dev_addr, true, true, complete_cb); +} + +static inline bool tuh_cdc_disconnect(uint8_t dev_addr, tuh_control_complete_cb_t complete_cb) +{ + return tuh_cdc_set_control_line_state(dev_addr, false, false, complete_cb); +} + /** \brief Check if device support CDC Serial interface or not * \param[in] dev_addr device address * \retval true if device supports @@ -113,6 +125,7 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i //--------------------------------------------------------------------+ void cdch_init(void); bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); +bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num); bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void cdch_close(uint8_t dev_addr); diff --git a/src/host/usbh.c b/src/host/usbh.c index 61db0d8b0..e7347ff56 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -56,6 +56,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = .class_code = TUSB_CLASS_CDC, .init = cdch_init, .open = cdch_open, + .set_config = cdch_set_config, .xfer_cb = cdch_xfer_cb, .close = cdch_close }, @@ -174,9 +175,6 @@ bool tuh_init(void) { usbh_device_t * const dev = &_usbh_devices[i]; - dev->control.sem_hdl = osal_semaphore_create(&dev->control.sem_def); - TU_ASSERT(dev->control.sem_hdl != NULL); - #if CFG_TUSB_OS != OPT_OS_NONE dev->mutex = osal_mutex_create(&dev->mutexdef); TU_ASSERT(dev->mutex); @@ -199,38 +197,6 @@ bool tuh_init(void) return true; } -//------------- USBH control transfer -------------// - -// TODO remove -bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data) -{ - usbh_device_t* dev = &_usbh_devices[dev_addr]; - const uint8_t rhport = dev->rhport; - - dev->control.request = *request; - dev->control.pipe_status = 0; - - // Setup Stage - hcd_setup_send(rhport, dev_addr, (uint8_t*) &dev->control.request); - TU_VERIFY(osal_semaphore_wait(dev->control.sem_hdl, OSAL_TIMEOUT_NORMAL)); - - // Data stage : first data toggle is always 1 - if ( request->wLength ) - { - hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), data, request->wLength); - TU_VERIFY(osal_semaphore_wait(dev->control.sem_hdl, OSAL_TIMEOUT_NORMAL)); - } - - // Status : data toggle is always 1 - hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); - TU_VERIFY(osal_semaphore_wait(dev->control.sem_hdl, OSAL_TIMEOUT_NORMAL)); - - if ( XFER_RESULT_STALLED == dev->control.pipe_status ) return false; - if ( XFER_RESULT_FAILED == dev->control.pipe_status ) return false; - - return true; -} - bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -291,9 +257,6 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ bool usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) { - osal_semaphore_reset( _usbh_devices[dev_addr].control.sem_hdl ); - //osal_mutex_reset( usbh_devices[dev_addr].control.mutex_hdl ); - tusb_desc_endpoint_t ep0_desc = { .bLength = sizeof(tusb_desc_endpoint_t), @@ -349,15 +312,6 @@ void hcd_event_handler(hcd_event_t const* event, bool in_isr) // interrupt caused by a TD (with IOC=1) in pipe of class class_code void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) { - usbh_device_t* dev = &_usbh_devices[ dev_addr ]; - - if (0 == tu_edpt_number(ep_addr)) - { - dev->control.pipe_status = result; -// usbh_devices[ pipe_hdl.dev_addr ].control.xferred_bytes = xferred_bytes; not yet neccessary - osal_semaphore_post( dev->control.sem_hdl, true ); // FIXME post within ISR - } - hcd_event_t event = { .rhport = 0, // TODO correct rhport diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index dd0616704..abc7fd250 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -75,16 +75,6 @@ typedef struct { volatile uint8_t state; // device state, value from enum tusbh_device_state_t - //------------- control pipe -------------// - struct { - volatile uint8_t pipe_status; -// uint8_t xferred_bytes; TODO not yet necessary - tusb_control_request_t request; - - osal_semaphore_def_t sem_def; - osal_semaphore_t sem_hdl; // used to synchronize with HCD when control xfer complete - } control; - uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) -- cgit v1.3.1 From 6fcd540cb68483b1b1b25344a1a5e4560c77e276 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 2 Nov 2020 16:50:46 +0700 Subject: enable cdc auto flush on write() if there is enough data in the fifo --- README.md | 2 +- src/class/cdc/cdc_device.c | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index 05f3521c4..072dfc841 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![tinyUSB_240x100](https://user-images.githubusercontent.com/249515/62646655-f9393200-b978-11e9-9c53-484862f15503.png) -[![Build Status](https://github.com/hathach/tinyusb/workflows/Build/badge.svg)](https://github.com/hathach/tinyusb/actions) [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) [![Coverity](https://img.shields.io/coverity/scan/458.svg)](https://scan.coverity.com/projects/tinyusb) +[![Build Status](https://github.com/hathach/tinyusb/workflows/Build/badge.svg)](https://github.com/hathach/tinyusb/actions) [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) TinyUSB is an open-source cross-platform USB Host/Device stack for embedded system, designed to be memory-safe with no dynamic allocation and thread-safe with all interrupt events are deferred then handled in the non-ISR task function. diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index e39adc5fa..e54b7d260 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -34,6 +34,11 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +enum +{ + BULK_PACKET_SIZE = (TUD_OPT_HIGH_SPEED ? 512 : 64) +}; + typedef struct { uint8_t itf_num; @@ -160,13 +165,11 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, bufsize); -#if 0 // TODO issue with circuitpython's REPL - // flush if queue more than endpoint size - if ( tu_fifo_count(&p_cdc->tx_ff) >= CFG_TUD_CDC_EP_BUFSIZE ) + // flush if queue more than packet size + if ( tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE ) { tud_cdc_n_write_flush(itf); } -#endif return ret; } @@ -250,8 +253,8 @@ void cdcd_reset(uint8_t rhport) uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { // Only support ACM subclass - TU_VERIFY ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); + TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); // Note: 0xFF can be used with RNDIS TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA), 0); @@ -446,9 +449,8 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if ( 0 == tud_cdc_n_write_flush(itf) ) { // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - // FIXME CFG_TUD_CDC_EP_BUFSIZE is not Endpoint packet size - if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_CDC_EP_BUFSIZE)) ) + // xferred_bytes is multiple of EP Packet size and not zero + if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE-1))) ) { if ( usbd_edpt_claim(rhport, p_cdc->ep_in) ) { -- cgit v1.3.1 From 2907b1e4382df313ba8eb713fa4d0e3d3bc6e7cf Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 7 Nov 2020 10:37:33 +0700 Subject: clean up --- src/host/usbh.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/host/usbh.h b/src/host/usbh.h index 7db918348..12c9164dd 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -116,8 +116,6 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ // If caller does not make any transfer, it must release endpoint for others. bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); -bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); // TODO remove later - void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); uint8_t usbh_get_rhport(uint8_t dev_addr); -- cgit v1.3.1 From 23b6b66f4daa128c2bfce3559a71a737868e142a Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 7 Nov 2020 23:43:39 +0700 Subject: release 0.7.0 with changelog and doc update --- CONTRIBUTORS.md | 134 +++++++++++++++++++++++++-------------------- README.md | 5 +- changelog.md | 140 ++++++++++++++++++++++++++++++++++++------------ docs/getting_started.md | 21 ++++---- src/tusb_option.h | 2 +- 5 files changed, 197 insertions(+), 105 deletions(-) (limited to 'src') diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index f7d77afe3..bcd6959e9 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -1,63 +1,79 @@ # TinyUSB contributors (sorted alphabetically) -* **[Adafruit Team](https://github.com/adafruit)** - * Main supporter and sponsor for hardware boards and kits - * Discussion and suggestion for feature and improvement - * Design the project logo - -* **[arturo182](https://github.com/arturo182)** - * Board support for MiMX RT1010 evaluation kit - -* **[Ha Thach](https://github.com/hathach)** - * Author and maintainer - * Most features development - -* **[Jan Dümpelmann](https://github.com/duempel)** - * Improvements to Synopsys device controller driver (DCD) for STM32 MCUs - -* **[Jeff Epler](https://github.com/jepler)** - * Improvement to MIDI device driver - -* **[Kamil Tomaszewski](https://github.com/kamtom480)** - * Sony CXD56 device driver port for spresnese board - -* **[Nathan Conrad](https://github.com/pigrew)** - * STM32 fsdev Fullspeed device driver port for STM32 L0, F0, F1, F3 etc ... - * USBTMC class driver support with example - * Various improvement e.g Zero-length packet, Lint setup - * Board support for STM32F070RB Nucleo, STM32F303 Discovery - -* **[Peter Lawrence](https://github.com/majbthrd)** - * Nuvoton NUC 120, 121, 125, 126, 505 device driver port - * USBNET RNDIS, CDC-ECM, CDC-EEM class driver - * Added `net_lwip_webserver` example for demonstration of usbnet with lwip - * Board support for NuTiny NUC120, NUC121s, NUC125s, NUC126V, NUC505 - * Complete multiple class interfaces & add cdc_dual_ports example - -* **[Scott Shawcroft](https://github.com/tannewt)** - * SAMD21 and SAMD51 device driver port - * MIDI device class driver support - * Improvement to USBD control transfer, MSC, CDC class driver - * Board support for Metro M0 & M4 express - * Write the execellent porting.md documentation - * Introduce inital Makefile - -* **[Sean Cross](https://github.com/xobs)** - * ValentyUSB eptri device driver port - * Board support for fomu - -* **[Sylvain "tnt" Munaut](https://github.com/smunaut)** - * DFU runtime support with example - -* **[Timon Skerutsch](https://github.com/PTS93)** - * hid_test.js script and extensive test for bi-directional raw HID - -* **[Tod E. Kurt](https://github.com/todbot)** - * hid_test.js script and extensive test for bi-directional raw HID - -* **[William D. Jones](https://github.com/cr1901)** - * Synopsys DesignWare device driver port for STM32 L4, F2, F4, F7, H7 etc ... - * TI MSP430 device driver port - * Board support for STM32F407 Discovery, STM32H743 Nucleo, pyboard v1.1, msp_exp430f5529lp etc ... +- **[Adafruit Team](https://github.com/adafruit)** + - Main supporter and sponsor for hardware boards and kits + - Discussion and suggestion for feature and improvement + - Design the project logo + +- **[Ha Thach](https://github.com/hathach)** + - *Author and maintainer* + - Most features development + +- **[Hristo Gochkov](https://github.com/me-no-dev)** + - Improve ESP32s2 DCD + +- **[Jan Dümpelmann](https://github.com/duempel)** + - Improve transfer performance for Synopsys DCD for STM32 MCUs + +- **[Jeff Epler](https://github.com/jepler)** + - Improve MIDI class driver + +- **[Jerzy Kasenberg](https://github.com/kasjer)** + - Add new DCD port for **Dialog DA1469x** + - Add new class driver for **Bluetooth HCI** + - Add ISO transfer for STM32 Synopsys, Nordic nRF, Dialog DA1469x + - Improve Audio driver and add uac2_headset example + - Improve STM32 Synopsys DCD with various PRs + +- **[Kamil Tomaszewski](https://github.com/kamtom480)** + - Add new DCD port for **Sony CXD56** (spresnese board) + +- **[Kay Sievers](https://github.com/kaysievers)** + - Improve MIDI driver with packet API + +- **[Nathan Conrad](https://github.com/pigrew)** + - Add new DCD port for **STM32 fsdev** Fullspeed device for STM32 L0, F0, F1, F3 etc ... + - Add new class driver for **USB Test and Measurement Class (USBTMC)** + - Various improvement e.g Zero-length packet, Lint setup + - Board support for STM32F070RB Nucleo, STM32F303 Discovery + +- **[Peter Lawrence](https://github.com/majbthrd)** + - Add new DCD port for **Nuvoton NUC 120, 121, 125, 126, 505** + - Add new class driver for **USBNET RNDIS, CDC-ECM** + - Add *net_lwip_webserver* example for demonstration of usbnet with lwip + - Board support for NuTiny NUC120, NUC121s, NUC125s, NUC126V, NUC505 + - Improve multiple cdc interfaces API & add cdc_dual_ports example + +- **[Reinhard Panhuber](https://github.com/PanRe)** + - Add new class driver for **USB Audio Class 2.0 (UAC2)** + - Enhance tu_fifo with unmasked pointer, which better support DMA + +- **[Scott Shawcroft](https://github.com/tannewt)** + - Add new DCD port for **SAMD21 and SAMD51** + - Add new class driver for **Musical Instrument Digital Interface (MIDI)** + - Improve USBD control transfer, MSC, CDC class driver + - Board support for Metro M0 & M4 express + - Write the execellent porting.md documentation + - Add initial Makefile + +- **[Sean Cross](https://github.com/xobs)** + - Add new DCD port for **ValentyUSB eptri** (fomu board) + +- **[Sylvain "tnt" Munaut](https://github.com/smunaut)** + - Add new class driver for DFU Runtime + +- **[Timon Skerutsch](https://github.com/PTS93)** + - Add hid_test.js script and extensive test for bi-directional raw HID + +- **[Tod E. Kurt](https://github.com/todbot)** + - Add hid_test.js script and extensive test for bi-directional raw HID + +- **[Uwe Bonnes](https://github.com/UweBonnes)** + - Improve STM32 Synopsys highspeed DCD + +- **[William D. Jones](https://github.com/cr1901)** + - Add new DCD port for **Synopsys DesignWare** for STM32 L4, F2, F4, F7, H7 etc ... + - Add new DCD port for **TI MSP430** + - Board support for STM32F407 Discovery, STM32H743 Nucleo, pyboard v1.1, msp_exp430f5529lp etc ... **[Full contributors list](https://github.com/hathach/tinyusb/contributors).** diff --git a/README.md b/README.md index 072dfc841..372b52c18 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ The stack supports the following MCUs: - **Espressif:** ESP32-S2 - **Dialog:** DA1469x -- **MicroChip:** SAMD11, SAMD21, SAMD51, SAME5x, SAMG (device only) +- **MicroChip:** SAMD11, SAMD21, SAMD51, SAME5x, SAMG55 - **NordicSemi:** nRF52833, nRF52840 - **Nuvoton:** NUC120, NUC121/NUC125, NUC126, NUC505 - **NXP:** @@ -49,7 +49,10 @@ The stack supports the following MCUs: Supports multiple device configurations by dynamically changing usb descriptors. Low power functions such like suspend, resume, and remote wakeup. Following device classes are supported: +- USB Audio Class 2.0 (UAC2) still work in progress +- Bluetooth Host Controller Interface (BTH HCI) - Communication Class (CDC) +- Device Firmware Update (DFU): only Runtinme - Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ... - Mass Storage Class (MSC): with multiple LUNs - Musical Instrument Digital Interface (MIDI) diff --git a/changelog.md b/changelog.md index a71a986f2..6b17e1666 100644 --- a/changelog.md +++ b/changelog.md @@ -1,46 +1,118 @@ # TinyUSB Changelog -## Master branch (WIP) - -### Breaking - -- 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 - - Give application full control of IRQ handler, can be useful e.g signaling there is new usb event without constant polling - -### MCU - -- Added support for Espressif ESP32-S2 and saola-1 board -- All default IRQ Handler is renamed to `dcd_int_handler()` -- STM32 Synopsys - - Bus events disconnection/suspend/resume are supported -- Added `dcd_connect()` and `dcd_disconnect()` to enable/disable internal pullup on D+/D- on supported MCUs. -- Added `dcd_edpt_close()` for STM32 FSDev - -### Device Stack - -- tud_cdc_n_write_flush() return number of bytes forced to transfer instead of bool +## 0.7.0 - 2020.11.08 + +### Device Controller Driver + +- Added new support for Espressif ESP32-S2 +- Added new support for Dialog DA1469x +- Enhance STM32 Synopsys + - Support bus events disconnection/suspend/resume/wakeup + - Improve transfer performance with optimizing xfer and fifo size + - Support Highspeed port (OTG_HS) with both internal and external PHY + - Support multiple usb ports with rhport=1 is highspeed on selected MCUs e.g H743, F23. It is possible to have OTG_HS to run on Fullspeed PHY (e.g lacking external PHY) + - Add ISO transfer, fix odd/even frame + - Fix FIFO flush during stall + - Implement dcd_edpt_close() API + - Support F105, F107 +- Enhance STM32 fsdev + - Improve dcd fifo allocation + - Fix ISTR race condition + - Support remap USB IRQ on supported MCUs + - Implement dcd_edpt_close() API +- Enhance NUC 505: enhance set configure behavior +- Enhance SAMD + - Fix race condition with setup packet + - Add SAMD11 option `OPT_MCU_SAMD11` + - Add SAME5x option `OPT_MCU_SAME5X` +- Fix SAMG control data toggle and stall race condition +- Enhance nRF + - Fix hanged when tud_task() is called within critical section (disabled interrupt) + - Fix disconnect bus event not submitted + - Implement ISO transfer and dcd_edpt_close() + +### USB Device + +**USBD** + +- Add new class driver for **Bluetooth HCI** class driver with example can be found in [mynewt-tinyusb-example](https://github.com/hathach/mynewt-tinyusb-example) since it needs mynewt OS to run with. +- Fix USBD endpoint usage racing condition with `usbd_edpt_claim()/usbd_edpt_release()` +- Added `tud_task_event_ready()` and `osal_queue_empty()`. This API is needed to check before enter low power mode with WFI/WFE +- Rename USB IRQ Handler to `dcd_int_handler()`. Application must define IRQ handler in which it calls this API. +- Add `dcd_connect()` and `dcd_disconnect()` to enable/disable internal pullup on D+/D- on supported MCUs. +- Add `usbd_edpt_open()` +- Remove `dcd_set_config()` +- Add *OPT_OS_CUMSTOM* as hook for application to overwrite and/or add their own OS implementation +- Support SET_INTERFACE, GET_INTERFACE request +- Add Logging for debug with optional uart/rtt/swo printf retarget or `CFG_TUSB_DEBUG_PRINTF` hook +- Add IAR compiler support - Support multiple configuration descriptors. `TUD_CONFIG_DESCRIPTOR()` template has extra config_num as 1st argument -- Improve class driver management - - Driver detection is done by open() API +- Improve USB Highspeed support with actual link speed detection with `dcd_event_bus_reset()` +- Enhance class driver management + - `usbd_driver_open()` add max length argument, and return length of interface (0 for not supported). Return value is used for finding appropriate driver + - Add application implemented class driver via `usbd_app_driver_get_cb()` - IAD is handled to assign driver id -- Improve Alternate Interface request with `SET_INTERFACE()` (not fully supported yet). -- Fixed CDC ZLP response #260 -- Remove ACM-EEM due to lack of support from host - -### Others - -- Added OPT_OS_CUMSTOM as hook for application to overwrite and/or add their own OS implementation -- Enhanced `net_lwip_webserver` example with multiple configuration: RNDIS for Windows, CDC-ECM for macOS (Linux will work with both) - -## 0.6.0 - 2019.03.30 +- Added `tud_descriptor_device_qualifier_cb()` callback +- Optimize `tu_fifo` bulk write/read transfer +- Forward non-std control request to class driver +- Let application handle Microsoft OS 1.0 Descriptors (the 0xEE index string) +- Fix OSAL FreeRTOS yield from ISR + +**Class Drivers** + +- USBNET: remove ACM-EEM due to lack of support from host +- USBTMC: fix descriptors when INT EP is disabled +- CDC: + - Send zero length packet for end of data when needed + - Add `tud_cdc_tx_complete_cb()` callback + - Change tud_cdc_n_write_flush() return number of bytes forced to transfer, and flush when writing enough data to fifo +- MIDI: + - Add packet interface + - Add multiple jack descriptors + - Fix MIDI driver for sysex +- DFU Runtime: fix response to SET_INTERFACE and DFU_GETSTATUS request +- Rename some configure macro to make it clear that those are used directly for endpoint transfer + - CFG_TUD_HID_BUFSIZE to `CFG_TUD_HID_EP_BUFSIZE + - CFG_TUD_CDC_EPSIZE to CFG_TUD_CDC_EP_BUFSIZE + - CFG_TUD_MSC_BUFSIZE to CFG_TUD_MSC_EP_BUFSIZE + - CFG_TUD_MIDI_EPSIZE to CFG_TUD_MIDI_EP_BUFSIZE +- HID: + - Fix gamepad template descriptor + - Add multiple HID interface API + - Add extra comma to HID_REPORT_ID + +### USB Host + +- Rework USB host stack (still work in progress) + - Fix compile error with pipehandle + - Rework usbh control and enumeration as non-blocking +- Improve Hub, MSC, HID host driver + +### Examples + +- Add new hid_composite_freertos +- Add new dynamic_configuration to demonstrate how to switch configuration descriptors +- Add new hid_multiple_interface +- Enhance `net_lwip_webserver` example + - Add multiple configuration: RNDIS for Windows, CDC-ECM for macOS (Linux will work with both) + - Update lwip to STABLE-2_1_2_RELEASE for net_lwip_webserver +- Added new Audio example: audio_test uac2_headsest + +### New Boards + +- Espressif ESP32-S2: saola_1, kaluga_1 +- STM32: F746 Nucleo, H743 Eval, H743 Nucleo, F723 discovery, stlink v3 mini, STM32L4r5 Nucleo +- Dialog DA1469x dk pro and dk usb +- Microchip: Great Scoot Gadgets' LUNA, samd11_xplained, D5035-01, atsamd21 xplained pro +- nRF: ItsyBitsy nRF52840 + +## 0.6.0 - 2020.03.30 Added **CONTRIBUTORS.md** to give proper credit for contributors to the stack. Special thanks to [Nathan Conrad](https://github.com/pigrew), [Peter Lawrence](https://github.com/majbthrd) and [William D. Jones](https://github.com/cr1901) and others for spending their precious time to add lots of features and ports for this release. ### Added -**MCU** +**MCUs** - Added support for Microchip SAMG55 - Added support for Nordic nRF52833 diff --git a/docs/getting_started.md b/docs/getting_started.md index 8d22a3127..06dcbd136 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -4,14 +4,15 @@ It is relatively simple to incorporate tinyusb to your (existing) project -1. Copy or `git submodule` this repo into your project in a subfolder. Let's say it is *your_project/tinyusb* -2. Add all the .c in the src folder to your project settings (uvproj, ewp, makefile) -3. Add *your_project/tinysb* to your include path. Also make sure your current include path also contains the configuration file tusb_config.h. Or you could simply put the tusb_config.h into the tinyusb folder as well. -4. Make sure all required macros are all defined properly in tusb_config.h (configure file in demo application is sufficient, but you need to add a few more such as CFG_TUSB_MCU, CFG_TUSB_OS since they are passed by IDE/compiler to maintain a unique configure for all boards). -5. If you use the device stack, make sure you have created/modified usb descriptors for your own need. Ultimately you need to implement all **tud_descriptor_** callbacks for that stack to work. -6. Add tusb_init() call to your reset initialization code. -7. Implement all enabled classes's callbacks. -8. If you don't use any RTOSes at all, you need to continuously and/or periodically call tud_task()/tuh_task() function. All of the callbacks and functionality are handled and invoke within the call of that task runner. +- Copy or `git submodule` this repo into your project in a subfolder. Let's say it is *your_project/tinyusb* +- Add all the .c in the `tinyusb/src` folder to your project +- Add *your_project/tinyusb/src* to your include path. Also make sure your current include path also contains the configuration file tusb_config.h. +- Make sure all required macros are all defined properly in tusb_config.h (configure file in demo application is sufficient, but you need to add a few more such as CFG_TUSB_MCU, CFG_TUSB_OS since they are passed by IDE/compiler to maintain a unique configure for all boards). +- If you use the device stack, make sure you have created/modified usb descriptors for your own need. Ultimately you need to implement all **tud_descriptor_** callbacks for the stack to work. +- Add tusb_init() call to your reset initialization code. +- Call `tud_int_handler()` (device stack) and/or `tuh_int_handler()` in your USB IRQ Handler +- Implement all enabled classes's callbacks. +- If you don't use any RTOSes at all, you need to continuously and/or periodically call tud_task()/tuh_task() function. All of the callbacks and functionality are handled and invoke within the call of that task runner. ~~~{.c} int main(void) @@ -23,8 +24,8 @@ int main(void) { your_application_code(); - tud_task(); // tinyusb device task - tuh_task(); // tinyusb host task + tud_task(); // device task + tuh_task(); // host task } } ~~~ diff --git a/src/tusb_option.h b/src/tusb_option.h index 393940282..2dd2b5841 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -28,7 +28,7 @@ #define _TUSB_OPTION_H_ #define TUSB_VERSION_MAJOR 0 -#define TUSB_VERSION_MINOR 5 +#define TUSB_VERSION_MINOR 7 #define TUSB_VERSION_REVISION 0 #define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION) -- cgit v1.3.1 From 496c7c701a5a4491c8a393fc580b5df2f29c1e22 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 9 Nov 2020 01:23:19 +0700 Subject: fix ci --- hw/bsp/same70_xplained/board.mk | 5 +++-- src/portable/template/dcd_template.c | 14 -------------- tools/build_all.py | 4 ++++ 3 files changed, 7 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/hw/bsp/same70_xplained/board.mk b/hw/bsp/same70_xplained/board.mk index 87b59d2d2..efe597fe3 100644 --- a/hw/bsp/same70_xplained/board.mk +++ b/hw/bsp/same70_xplained/board.mk @@ -41,8 +41,9 @@ INC += \ $(TOP)/$(ASF_DIR)/CMSIS/Core/Include # For TinyUSB port source -VENDOR = microchip -CHIP_FAMILY = samg +#SRC_C += src/portable/template/dcd_template.c +VENDOR = . +CHIP_FAMILY = template # For freeRTOS port source FREERTOS_PORT = ARM_CM7 diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 812bb7866..618812416 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -45,20 +45,6 @@ void dcd_init (uint8_t rhport) (void) rhport; } -#if HAS_INTERNAL_PULLUP -// Enable internal D+/D- pullup -void dcd_connect(uint8_t rhport) TU_ATTR_WEAK -{ - (void) rhport; -} - -// Disable internal D+/D- pullup -void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK -{ - (void) rhport; -} -#endif - // Enable device interrupt void dcd_int_enable (uint8_t rhport) { diff --git a/tools/build_all.py b/tools/build_all.py index 0dc555d2f..172cb2070 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -76,6 +76,10 @@ def skip_example(example, board): if 'CROSS_COMPILE = xtensa-esp32s2-elf-' in mk_contents: return 1 + # Skip all OPT_MCU_NONE these are WIP port + if '-DCFG_TUSB_MCU=OPT_MCU_NONE' in mk_contents: + return 1 + # Skip if CFG_TUSB_MCU in board.mk to match skip file for skip_file in glob.iglob(ex_dir + '/.skip.MCU_*'): mcu_cflag = '-DCFG_TUSB_MCU=OPT_' + os.path.basename(skip_file).split('.')[2] -- cgit v1.3.1 From 54e29e9ff451d5e30eb59d0411adbe5d4993c59b Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Wed, 18 Nov 2020 09:42:50 +0100 Subject: Implementation of the discussed changes - remove usbd_edpt_xfer_abort - rename tu_fifo_change_mode to tu_fifo_set_mode - remove CFG_TUD_CDC_CLEAR_AT_CONNECTION definition - remove auto fifo clear at connection event - add tud_cdc_n_write_clear function --- src/class/cdc/cdc_device.c | 21 +++++++++++---------- src/class/cdc/cdc_device.h | 13 +++++++++---- src/common/tusb_fifo.c | 4 +++- src/common/tusb_fifo.h | 2 +- src/device/usbd.c | 27 --------------------------- src/device/usbd_pvt.h | 3 --- 6 files changed, 24 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 7eace24ff..2d0aed238 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -207,6 +207,10 @@ uint32_t tud_cdc_n_write_available (uint8_t itf) return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff); } +bool tud_cdc_n_write_clear (uint8_t itf) +{ + return tu_fifo_clear(&_cdcd_itf[itf].tx_ff); +} //--------------------------------------------------------------------+ // USBD Driver API @@ -229,6 +233,9 @@ void cdcd_init(void) // config fifo tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); + // tx fifo is set to overwritable at initialization and will be changed to not overwritable + // if terminal supports DTR bit. Without DTR we do not know if data is actually polled by terminal. + // In this way, the most current data is prioritized. tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); #if CFG_FIFO_MUTEX @@ -384,20 +391,14 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request bool const dtr = tu_bit_test(request->wValue, 0); bool const rts = tu_bit_test(request->wValue, 1); -#if CFG_TUD_CDC_CLEAR_AT_CONNECTION - // DTE connected event (if DTE supports DTR bit) - if ( dtr && !tu_bit_test(p_cdc->line_state, 0) ) - { - // Clear not transmitted data - usbd_edpt_xfer_abort(rhport, p_cdc->ep_in); - tu_fifo_clear(&p_cdc->tx_ff); - } -#endif + // TODO if terminal supports DTR we can check for an connection event here and + // clear the fifo as well as ongoing transfers with new usbd_edpt_xfer_abort api. + // Until then user can self clear the buffer with tud_cdc_n_write_clear in tud_cdc_line_state_cb p_cdc->line_state = (uint8_t) request->wValue; // Disable fifo overwriting if DTR bit is set - tu_fifo_change_mode(&p_cdc->tx_ff, (dtr?false:true)); + tu_fifo_set_mode(&p_cdc->tx_ff, !dtr); TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 3bd2741bc..342025961 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -43,10 +43,6 @@ #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif -#ifndef CFG_TUD_CDC_CLEAR_AT_CONNECTION - #define CFG_TUD_CDC_CLEAR_AT_CONNECTION 0 -#endif - #ifdef __cplusplus extern "C" { #endif @@ -106,6 +102,9 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf); // Return the number of bytes (characters) available for writing to TX FIFO buffer in a single n_write operation. uint32_t tud_cdc_n_write_available (uint8_t itf); +// Clear the transmit FIFO +bool tud_cdc_n_write_clear (uint8_t itf); + //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ @@ -125,6 +124,7 @@ static inline uint32_t tud_cdc_write (void const* buffer, uint32_t buf static inline uint32_t tud_cdc_write_str (char const* str); static inline uint32_t tud_cdc_write_flush (void); static inline uint32_t tud_cdc_write_available (void); +static inline bool tud_cdc_write_clear (void); //--------------------------------------------------------------------+ // Application Callback API (weak is optional) @@ -234,6 +234,11 @@ static inline uint32_t tud_cdc_write_available(void) return tud_cdc_n_write_available(0); } +static inline bool tud_cdc_write_clear(void) +{ + return tud_cdc_n_write_clear(0); +} + /** @} */ /** @} */ diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 470e26b77..444c60f96 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -603,9 +603,11 @@ bool tu_fifo_clear(tu_fifo_t *f) @param[in] f Pointer to the FIFO buffer to manipulate + @param[in] overwritable + Overwritable mode the fifo is set to */ /******************************************************************************/ -bool tu_fifo_change_mode(tu_fifo_t *f, bool overwritable) +bool tu_fifo_set_mode(tu_fifo_t *f, bool overwritable) { tu_fifo_lock(f); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 603a74609..abb301b5f 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -89,7 +89,7 @@ typedef struct .non_used_index_space = 0xFFFF - 2*_depth-1, \ } -bool tu_fifo_change_mode(tu_fifo_t *f, bool overwritable); +bool tu_fifo_set_mode(tu_fifo_t *f, bool overwritable); bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); diff --git a/src/device/usbd.c b/src/device/usbd.c index 8d3fbac59..90edc3dde 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1191,33 +1191,6 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } -bool usbd_edpt_xfer_abort(uint8_t rhport, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - TU_LOG2(" Abort XFER EP %02X ... ", ep_addr); - - // Abort API is optional for DCD - if ( dcd_edpt_xfer_abort ) - { - if ( dcd_edpt_xfer_abort(rhport, ep_addr) ) - { - _usbd_dev.ep_status[epnum][dir].busy = false; - TU_LOG2("OK\r\n"); - return true; - }else - { - TU_LOG2("failed\r\n"); - return false; - } - }else - { - TU_LOG2("no DCD support\r\n"); - return false; - } -} - bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) { (void) rhport; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 4eb17a501..09b285581 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -70,9 +70,6 @@ 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); -// Abort a scheduled transfer -bool usbd_edpt_xfer_abort(uint8_t rhport, uint8_t ep_addr); - // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); -- cgit v1.3.1 From 339b1a772350321d0f9d4f84e93c5360247e3f17 Mon Sep 17 00:00:00 2001 From: Jan Dümpelmann Date: Wed, 18 Nov 2020 11:12:06 +0100 Subject: Remove dcd_edpt_xfer_abort from DCD header --- src/device/dcd.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index 2c4bf4348..776f782b8 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -133,9 +133,6 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); -// Abort a ongoing transfer -TU_ATTR_WEAK bool dcd_edpt_xfer_abort(uint8_t rhport, uint8_t ep_addr); - // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); -- cgit v1.3.1 From 3c31d0805130e9551f97afae94f765b5d032991b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Nov 2020 21:01:33 +0700 Subject: merge class driver control_request & control_complete to control_xfer_cb() migrated msc_device --- src/class/msc/msc_device.c | 19 ++++++------------- src/class/msc/msc_device.h | 3 +-- src/common/tusb_types.h | 7 +++++++ src/device/usbd.c | 39 +++++++++++++++++++-------------------- src/device/usbd.h | 2 +- src/device/usbd_control.c | 8 ++++---- src/device/usbd_pvt.h | 5 ++++- 7 files changed, 42 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index f3f2e536e..cfb8a43a3 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -186,10 +186,14 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 return drv_len; } -// Handle class control request +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_request) +bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request) { + // nothing to do with DATA & ACK stage + if (stage != CONTROL_STAGE_SETUP) return true; + // Handle class request only TU_VERIFY(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); @@ -219,17 +223,6 @@ bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque return true; } -// Invoked when class request DATA stage is finished. -// return false to stall control endpoint (e.g Host send non-sense DATA) -bool mscd_control_complete(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - (void) request; - - // nothing to do - return true; -} - // return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) // In case of a failed status, sense key must be set for reason of failure int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 3aa93ffd7..f1e6c40f4 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -161,8 +161,7 @@ TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); void mscd_init (void); void mscd_reset (uint8_t rhport); uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool mscd_control_request (uint8_t rhport, tusb_control_request_t const * p_request); -bool mscd_control_complete (uint8_t rhport, tusb_control_request_t const * p_request); +bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request); bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index d6b6ea627..5ab15aa3c 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -250,6 +250,13 @@ typedef enum MS_OS_20_FEATURE_VENDOR_REVISION = 0x08 } microsoft_os_20_type_t; +enum +{ + CONTROL_STAGE_SETUP, + CONTROL_STAGE_DATA, + CONTROL_STAGE_ACK +}; + //--------------------------------------------------------------------+ // USB Descriptors //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index 90edc3dde..02f631dea 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -97,7 +97,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = cdcd_init, .reset = cdcd_reset, .open = cdcd_open, - .control_request = cdcd_control_request, + .control_xfer_cb = cdcd_control_request, .control_complete = cdcd_control_complete, .xfer_cb = cdcd_xfer_cb, .sof = NULL @@ -110,8 +110,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = mscd_init, .reset = mscd_reset, .open = mscd_open, - .control_request = mscd_control_request, - .control_complete = mscd_control_complete, + .control_xfer_cb = mscd_control_xfer_cb, .xfer_cb = mscd_xfer_cb, .sof = NULL }, @@ -123,7 +122,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = hidd_init, .reset = hidd_reset, .open = hidd_open, - .control_request = hidd_control_request, + .control_xfer_cb = hidd_control_request, .control_complete = hidd_control_complete, .xfer_cb = hidd_xfer_cb, .sof = NULL @@ -134,9 +133,9 @@ static usbd_class_driver_t const _usbd_driver[] = { DRIVER_NAME("AUDIO") .init = audiod_init, - .reset = audiod_reset, + .reset = audiod_reset, .open = audiod_open, - .control_request = audiod_control_request, + .control_xfer_cb = audiod_control_request, .control_complete = audiod_control_complete, .xfer_cb = audiod_xfer_cb, .sof = NULL @@ -149,7 +148,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = midid_init, .open = midid_open, .reset = midid_reset, - .control_request = midid_control_request, + .control_xfer_cb = midid_control_request, .control_complete = midid_control_complete, .xfer_cb = midid_xfer_cb, .sof = NULL @@ -162,7 +161,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = vendord_init, .reset = vendord_reset, .open = vendord_open, - .control_request = tud_vendor_control_request_cb, + .control_xfer_cb = tud_vendor_control_request_cb, .control_complete = tud_vendor_control_complete_cb, .xfer_cb = vendord_xfer_cb, .sof = NULL @@ -175,7 +174,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = usbtmcd_init_cb, .reset = usbtmcd_reset_cb, .open = usbtmcd_open_cb, - .control_request = usbtmcd_control_request_cb, + .control_xfer_cb = usbtmcd_control_request_cb, .control_complete = usbtmcd_control_complete_cb, .xfer_cb = usbtmcd_xfer_cb, .sof = NULL @@ -188,7 +187,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = dfu_rtd_init, .reset = dfu_rtd_reset, .open = dfu_rtd_open, - .control_request = dfu_rtd_control_request, + .control_xfer_cb = dfu_rtd_control_request, .control_complete = dfu_rtd_control_complete, .xfer_cb = dfu_rtd_xfer_cb, .sof = NULL @@ -201,7 +200,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = netd_init, .reset = netd_reset, .open = netd_open, - .control_request = netd_control_request, + .control_xfer_cb = netd_control_request, .control_complete = netd_control_complete, .xfer_cb = netd_xfer_cb, .sof = NULL, @@ -214,7 +213,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = btd_init, .reset = btd_reset, .open = btd_open, - .control_request = btd_control_request, + .control_xfer_cb = btd_control_request, .control_complete = btd_control_complete, .xfer_cb = btd_xfer_cb, .sof = NULL @@ -274,7 +273,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // from usbd_control.c void usbd_control_reset(void); void usbd_control_set_request(tusb_control_request_t const *request); -void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ); +void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); @@ -313,12 +312,12 @@ static char const* const _tusb_std_request_str[] = }; // for usbd_control to print the name of control complete driver -void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const * )) +void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) { for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { usbd_class_driver_t const * driver = get_driver(i); - if ( driver->control_complete == control_complete ) + if ( driver->control_xfer_cb == callback ) { TU_LOG2(" %s control complete\r\n", driver->name); return; @@ -565,9 +564,9 @@ void tud_task (void) // Helper to invoke class driver control request handler static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request) { - usbd_control_set_complete_callback(driver->control_complete); + usbd_control_set_complete_callback(driver->control_xfer_cb); TU_LOG2(" %s control request\r\n", driver->name); - return driver->control_request(rhport, request); + return driver->control_xfer_cb(rhport, CONTROL_STAGE_SETUP, request); } // This handles the actual request and its response. @@ -581,10 +580,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { - TU_VERIFY(tud_vendor_control_request_cb); + TU_VERIFY(tud_vendor_control_xfer_cb); - if (tud_vendor_control_complete_cb) usbd_control_set_complete_callback(tud_vendor_control_complete_cb); - return tud_vendor_control_request_cb(rhport, p_request); + usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); + return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); } #if CFG_TUSB_DEBUG >= 2 diff --git a/src/device/usbd.h b/src/device/usbd.h index e88f64ba8..cf7e9f0db 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -125,7 +125,7 @@ TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en); TU_ATTR_WEAK void tud_resume_cb(void); // Invoked when received control request with VENDOR TYPE -TU_ATTR_WEAK bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); +TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); // Invoked when vendor control request is complete TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index db0eb70a7..f1edad376 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -33,7 +33,7 @@ #include "dcd.h" #if CFG_TUSB_DEBUG >= 2 -extern void usbd_driver_print_control_complete_name(bool (*control_complete) (uint8_t, tusb_control_request_t const *)); +extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif enum @@ -50,7 +50,7 @@ typedef struct uint16_t data_len; uint16_t total_xferred; - bool (*complete_cb) (uint8_t, tusb_control_request_t const *); + usbd_control_xfer_cb_t complete_cb; } usbd_control_xfer_t; static usbd_control_xfer_t _ctrl_xfer; @@ -146,7 +146,7 @@ void usbd_control_reset(void) } // TODO may find a better way -void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ) +void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ) { _ctrl_xfer.complete_cb = fp; } @@ -199,7 +199,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); #endif - is_ok = _ctrl_xfer.complete_cb(rhport, &_ctrl_xfer.request); + is_ok = _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_DATA, &_ctrl_xfer.request); } if ( is_ok ) diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 09b285581..57331041b 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -46,7 +46,7 @@ typedef struct void (* init ) (void); void (* reset ) (uint8_t rhport); uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); - bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void (* sof ) (uint8_t rhport); /* optional */ @@ -57,6 +57,9 @@ typedef struct // Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; + +typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + //--------------------------------------------------------------------+ // USBD Endpoint API //--------------------------------------------------------------------+ -- cgit v1.3.1 From dd07fecc5f37c85b87060c7f7158d26ff19757a6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Nov 2020 21:26:06 +0700 Subject: migrate cdc_device to new control_xfer_cb --- src/class/cdc/cdc_device.c | 85 +++++++++++++++++++--------------------------- src/class/cdc/cdc_device.h | 11 +++--- src/class/msc/msc_device.h | 10 +++--- src/device/usbd.c | 3 +- src/device/usbd_control.c | 9 +++++ 5 files changed, 55 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index e54b7d260..2933dcd3d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -315,38 +315,10 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 return drv_len; } -// Invoked when class request DATA stage is finished. -// return false to stall control endpoint (e.g Host send non-sense DATA) -bool cdcd_control_complete(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - - //------------- Class Specific Request -------------// - TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - uint8_t itf = 0; - cdcd_interface_t* p_cdc = _cdcd_itf; - - // Identify which interface to use - for ( ; ; itf++, p_cdc++) - { - if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false; - - if ( p_cdc->itf_num == request->wIndex ) break; - } - - // Invoke callback - if ( CDC_REQUEST_SET_LINE_CODING == request->bRequest ) - { - if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); - } - - return true; -} - -// Handle class control request +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request) +bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { // Handle class request only TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); @@ -365,34 +337,47 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request switch ( request->bRequest ) { case CDC_REQUEST_SET_LINE_CODING: - TU_LOG2(" Set Line Coding\r\n"); - tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + if (stage == CONTROL_STAGE_SETUP) + { + TU_LOG2(" Set Line Coding\r\n"); + tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + } + else if ( stage == CONTROL_STAGE_ACK) + { + if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); + } break; case CDC_REQUEST_GET_LINE_CODING: - TU_LOG2(" Get Line Coding\r\n"); - tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + if (stage == CONTROL_STAGE_SETUP) + { + TU_LOG2(" Get Line Coding\r\n"); + tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + } break; case CDC_REQUEST_SET_CONTROL_LINE_STATE: - { - // CDC PSTN v1.2 section 6.3.12 - // Bit 0: Indicates if DTE is present or not. - // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) - // Bit 1: Carrier control for half-duplex modems. - // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) - bool const dtr = tu_bit_test(request->wValue, 0); - bool const rts = tu_bit_test(request->wValue, 1); - - p_cdc->line_state = (uint8_t) request->wValue; + if (stage == CONTROL_STAGE_SETUP) + { + tud_control_status(rhport, request); + } + else if (stage == CONTROL_STAGE_ACK) + { + // CDC PSTN v1.2 section 6.3.12 + // Bit 0: Indicates if DTE is present or not. + // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) + // Bit 1: Carrier control for half-duplex modems. + // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) + bool const dtr = tu_bit_test(request->wValue, 0); + bool const rts = tu_bit_test(request->wValue, 1); - TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); + p_cdc->line_state = (uint8_t) request->wValue; - tud_control_status(rhport, request); + TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); - // Invoke callback - if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); - } + // Invoke callback + if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); + } break; default: return false; // stall unsupported request diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 3c679c48e..3e68e2a88 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -236,12 +236,11 @@ static inline uint32_t tud_cdc_write_available(void) //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ -void cdcd_init (void); -void cdcd_reset (uint8_t rhport); -uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool cdcd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void cdcd_init (void); +void cdcd_reset (uint8_t rhport); +uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool cdcd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index f1e6c40f4..469f2f2f7 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -158,11 +158,11 @@ TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void mscd_init (void); -void mscd_reset (uint8_t rhport); -uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request); -bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void mscd_init (void); +void mscd_reset (uint8_t rhport); +uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request); +bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index 02f631dea..dbe11d380 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -97,8 +97,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = cdcd_init, .reset = cdcd_reset, .open = cdcd_open, - .control_xfer_cb = cdcd_control_request, - .control_complete = cdcd_control_complete, + .control_xfer_cb = cdcd_control_xfer_cb, .xfer_cb = cdcd_xfer_cb, .sof = NULL }, diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index f1edad376..bb631320a 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -171,7 +171,16 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction ) { TU_ASSERT(0 == xferred_bytes); + + // invoke optional dcd hook if available if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); + + if (_ctrl_xfer.complete_cb) + { + // TODO refactor with usbd_driver_print_control_complete_name + _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_ACK, &_ctrl_xfer.request); + } + return true; } -- cgit v1.3.1 From dc9a30983982717b1a0e8b48833fca841de5e70e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Nov 2020 22:00:49 +0700 Subject: migrate hid device to new control xfer cb --- src/class/hid/hid_device.c | 190 +++++++++++++++++++++++---------------------- src/class/hid/hid_device.h | 11 ++- src/device/usbd.c | 3 +- 3 files changed, 102 insertions(+), 102 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 11da5f220..1f03f8862 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -211,9 +211,10 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 return drv_len; } -// Handle class control request +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request) +bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); @@ -225,27 +226,29 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) { //------------- STD Request -------------// - uint8_t const desc_type = tu_u16_high(request->wValue); - uint8_t const desc_index = tu_u16_low (request->wValue); - (void) desc_index; - - if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) - { - TU_VERIFY(p_hid->hid_descriptor != NULL); - TU_VERIFY(tud_control_xfer(rhport, request, (void*) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength)); - } - else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) - { - uint8_t const * desc_report = tud_hid_descriptor_report_cb( - #if CFG_TUD_HID > 1 - hid_itf // TODO for backward compatible callback, remove later when appropriate - #endif - ); - tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); - } - else + if ( stage == CONTROL_STAGE_SETUP ) { - return false; // stall unsupported request + uint8_t const desc_type = tu_u16_high(request->wValue); + //uint8_t const desc_index = tu_u16_low (request->wValue); + + if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) + { + TU_VERIFY(p_hid->hid_descriptor != NULL); + TU_VERIFY(tud_control_xfer(rhport, request, (void*) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength)); + } + else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) + { + uint8_t const * desc_report = tud_hid_descriptor_report_cb( + #if CFG_TUD_HID > 1 + hid_itf // TODO for backward compatible callback, remove later when appropriate + #endif + ); + tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); + } + else + { + return false; // stall unsupported request + } } } else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) @@ -254,70 +257,98 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request switch( request->bRequest ) { case HID_REQ_CONTROL_GET_REPORT: - { - // wValue = Report Type | Report ID - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); + if ( stage == CONTROL_STAGE_SETUP ) + { + uint8_t const report_type = tu_u16_high(request->wValue); + uint8_t const report_id = tu_u16_low(request->wValue); - uint16_t xferlen = tud_hid_get_report_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength - ); - TU_ASSERT( xferlen > 0 ); + uint16_t xferlen = tud_hid_get_report_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength + ); + TU_ASSERT( xferlen > 0 ); - tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); - } + tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); + } break; case HID_REQ_CONTROL_SET_REPORT: - TU_VERIFY(request->wLength <= sizeof(p_hid->epout_buf)); - tud_control_xfer(rhport, request, p_hid->epout_buf, request->wLength); + if ( stage == CONTROL_STAGE_SETUP ) + { + TU_VERIFY(request->wLength <= sizeof(p_hid->epout_buf)); + tud_control_xfer(rhport, request, p_hid->epout_buf, request->wLength); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + uint8_t const report_type = tu_u16_high(request->wValue); + uint8_t const report_id = tu_u16_low(request->wValue); + + tud_hid_set_report_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength + ); + } break; case HID_REQ_CONTROL_SET_IDLE: - p_hid->idle_rate = tu_u16_high(request->wValue); - if ( tud_hid_set_idle_cb ) + if ( stage == CONTROL_STAGE_SETUP ) { - // stall request if callback return false - TU_VERIFY( tud_hid_set_idle_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - p_hid->idle_rate) - ); + p_hid->idle_rate = tu_u16_high(request->wValue); + if ( tud_hid_set_idle_cb ) + { + // stall request if callback return false + TU_VERIFY( tud_hid_set_idle_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + p_hid->idle_rate) + ); + } + + tud_control_status(rhport, request); } - - tud_control_status(rhport, request); break; case HID_REQ_CONTROL_GET_IDLE: - // TODO idle rate of report - tud_control_xfer(rhport, request, &p_hid->idle_rate, 1); + if ( stage == CONTROL_STAGE_SETUP ) + { + // TODO idle rate of report + tud_control_xfer(rhport, request, &p_hid->idle_rate, 1); + } break; case HID_REQ_CONTROL_GET_PROTOCOL: - { - uint8_t protocol = (uint8_t)(1-p_hid->boot_mode); // 0 is Boot, 1 is Report protocol - tud_control_xfer(rhport, request, &protocol, 1); - } + if ( stage == CONTROL_STAGE_SETUP ) + { + // 0 is Boot, 1 is Report protocol + uint8_t protocol = (uint8_t)(1-p_hid->boot_mode); + tud_control_xfer(rhport, request, &protocol, 1); + } break; case HID_REQ_CONTROL_SET_PROTOCOL: - p_hid->boot_mode = 1 - request->wValue; // 0 is Boot, 1 is Report protocol - - if (tud_hid_boot_mode_cb) + if ( stage == CONTROL_STAGE_SETUP ) { - tud_hid_boot_mode_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - p_hid->boot_mode - ); + // 0 is Boot, 1 is Report protocol + p_hid->boot_mode = 1 - request->wValue; + tud_control_status(rhport, request); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if (tud_hid_boot_mode_cb) + { + tud_hid_boot_mode_cb( + #if CFG_TUD_HID > 1 + hid_itf, // TODO for backward compatible callback, remove later when appropriate + #endif + p_hid->boot_mode + ); + } } - - tud_control_status(rhport, request); break; default: return false; // stall unsupported request @@ -330,35 +361,6 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * request return true; } -// Invoked when class request DATA stage is finished. -// return false to stall control endpoint (e.g Host send non-sense DATA) -bool hidd_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - - uint8_t const hid_itf = get_index_by_itfnum((uint8_t) p_request->wIndex); - TU_VERIFY(hid_itf < CFG_TUD_HID); - - hidd_interface_t* p_hid = &_hidd_itf[hid_itf]; - - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - p_request->bRequest == HID_REQ_CONTROL_SET_REPORT) - { - // wValue = Report Type | Report ID - uint8_t const report_type = tu_u16_high(p_request->wValue); - uint8_t const report_id = tu_u16_low(p_request->wValue); - - tud_hid_set_report_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - report_id, (hid_report_type_t) report_type, p_hid->epout_buf, p_request->wLength - ); - } - - return true; -} - bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index d5b5b7296..2d4c59d8f 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -359,12 +359,11 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hidd_init (void); -void hidd_reset (uint8_t rhport); -uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool hidd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool hidd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hidd_init (void); +void hidd_reset (uint8_t rhport); +uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index dbe11d380..1e6722ffb 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -121,8 +121,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = hidd_init, .reset = hidd_reset, .open = hidd_open, - .control_xfer_cb = hidd_control_request, - .control_complete = hidd_control_complete, + .control_xfer_cb = hidd_control_xfer_cb, .xfer_cb = hidd_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From e2abb089f4e96cd7731bc97067566541090a1eda Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 15:30:36 +0700 Subject: migrate midi device to new control xfer cb --- src/class/midi/midi_device.c | 12 +++--------- src/class/midi/midi_device.h | 11 +++++------ src/device/usbd.c | 3 +-- 3 files changed, 9 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index a07acf0b8..b61df59aa 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -375,17 +375,11 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint return drv_len; } -bool midid_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) +bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { (void) rhport; - (void) p_request; - return true; -} - -bool midid_control_request(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - (void) p_request; + (void) stage; + (void) request; // driver doesn't support any request yet return false; diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index b8fb55cc2..9235448f2 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -142,12 +142,11 @@ static inline bool tud_midi_send (uint8_t const packet[4]) //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void midid_init (void); -void midid_reset (uint8_t rhport); -uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool midid_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool midid_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void midid_init (void); +void midid_reset (uint8_t rhport); +uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool midid_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index 1e6722ffb..3686ec28c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -146,8 +146,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = midid_init, .open = midid_open, .reset = midid_reset, - .control_xfer_cb = midid_control_request, - .control_complete = midid_control_complete, + .control_xfer_cb = midid_control_xfer_cb, .xfer_cb = midid_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From 8813f9d3b8a997e7a16c61a094f117a50c6ae435 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 15:32:16 +0700 Subject: clean up --- src/class/midi/midi_device.c | 3 + src/device/usbd.c | 146 +++++++++++++++++++++---------------------- 2 files changed, 76 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index b61df59aa..ce4c9cafe 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -375,6 +375,9 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint return drv_len; } +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { (void) rhport; diff --git a/src/device/usbd.c b/src/device/usbd.c index 3686ec28c..bea41b592 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -93,43 +93,43 @@ static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_CDC { - DRIVER_NAME("CDC") - .init = cdcd_init, - .reset = cdcd_reset, - .open = cdcd_open, - .control_xfer_cb = cdcd_control_xfer_cb, - .xfer_cb = cdcd_xfer_cb, - .sof = NULL + DRIVER_NAME("CDC") + .init = cdcd_init, + .reset = cdcd_reset, + .open = cdcd_open, + .control_xfer_cb = cdcd_control_xfer_cb, + .xfer_cb = cdcd_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_MSC { - DRIVER_NAME("MSC") - .init = mscd_init, - .reset = mscd_reset, - .open = mscd_open, - .control_xfer_cb = mscd_control_xfer_cb, - .xfer_cb = mscd_xfer_cb, - .sof = NULL + DRIVER_NAME("MSC") + .init = mscd_init, + .reset = mscd_reset, + .open = mscd_open, + .control_xfer_cb = mscd_control_xfer_cb, + .xfer_cb = mscd_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_HID { - DRIVER_NAME("HID") - .init = hidd_init, - .reset = hidd_reset, - .open = hidd_open, - .control_xfer_cb = hidd_control_xfer_cb, - .xfer_cb = hidd_xfer_cb, - .sof = NULL + DRIVER_NAME("HID") + .init = hidd_init, + .reset = hidd_reset, + .open = hidd_open, + .control_xfer_cb = hidd_control_xfer_cb, + .xfer_cb = hidd_xfer_cb, + .sof = NULL }, #endif -#if CFG_TUD_AUDIO -{ - DRIVER_NAME("AUDIO") + #if CFG_TUD_AUDIO + { + DRIVER_NAME("AUDIO") .init = audiod_init, .reset = audiod_reset, .open = audiod_open, @@ -137,83 +137,83 @@ static usbd_class_driver_t const _usbd_driver[] = .control_complete = audiod_control_complete, .xfer_cb = audiod_xfer_cb, .sof = NULL -}, -#endif + }, + #endif #if CFG_TUD_MIDI { - DRIVER_NAME("MIDI") - .init = midid_init, - .open = midid_open, - .reset = midid_reset, - .control_xfer_cb = midid_control_xfer_cb, - .xfer_cb = midid_xfer_cb, - .sof = NULL + DRIVER_NAME("MIDI") + .init = midid_init, + .open = midid_open, + .reset = midid_reset, + .control_xfer_cb = midid_control_xfer_cb, + .xfer_cb = midid_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_VENDOR { - DRIVER_NAME("VENDOR") - .init = vendord_init, - .reset = vendord_reset, - .open = vendord_open, - .control_xfer_cb = tud_vendor_control_request_cb, - .control_complete = tud_vendor_control_complete_cb, - .xfer_cb = vendord_xfer_cb, - .sof = NULL + DRIVER_NAME("VENDOR") + .init = vendord_init, + .reset = vendord_reset, + .open = vendord_open, + .control_xfer_cb = tud_vendor_control_request_cb, + .control_complete = tud_vendor_control_complete_cb, + .xfer_cb = vendord_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_USBTMC { - DRIVER_NAME("TMC") - .init = usbtmcd_init_cb, - .reset = usbtmcd_reset_cb, - .open = usbtmcd_open_cb, - .control_xfer_cb = usbtmcd_control_request_cb, - .control_complete = usbtmcd_control_complete_cb, - .xfer_cb = usbtmcd_xfer_cb, - .sof = NULL + DRIVER_NAME("TMC") + .init = usbtmcd_init_cb, + .reset = usbtmcd_reset_cb, + .open = usbtmcd_open_cb, + .control_xfer_cb = usbtmcd_control_request_cb, + .control_complete = usbtmcd_control_complete_cb, + .xfer_cb = usbtmcd_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_DFU_RT { - DRIVER_NAME("DFU-RT") - .init = dfu_rtd_init, - .reset = dfu_rtd_reset, - .open = dfu_rtd_open, - .control_xfer_cb = dfu_rtd_control_request, - .control_complete = dfu_rtd_control_complete, - .xfer_cb = dfu_rtd_xfer_cb, - .sof = NULL + DRIVER_NAME("DFU-RT") + .init = dfu_rtd_init, + .reset = dfu_rtd_reset, + .open = dfu_rtd_open, + .control_xfer_cb = dfu_rtd_control_request, + .control_complete = dfu_rtd_control_complete, + .xfer_cb = dfu_rtd_xfer_cb, + .sof = NULL }, #endif #if CFG_TUD_NET { - DRIVER_NAME("NET") - .init = netd_init, - .reset = netd_reset, - .open = netd_open, - .control_xfer_cb = netd_control_request, - .control_complete = netd_control_complete, - .xfer_cb = netd_xfer_cb, - .sof = NULL, + DRIVER_NAME("NET") + .init = netd_init, + .reset = netd_reset, + .open = netd_open, + .control_xfer_cb = netd_control_request, + .control_complete = netd_control_complete, + .xfer_cb = netd_xfer_cb, + .sof = NULL, }, #endif #if CFG_TUD_BTH { - DRIVER_NAME("BTH") - .init = btd_init, - .reset = btd_reset, - .open = btd_open, - .control_xfer_cb = btd_control_request, - .control_complete = btd_control_complete, - .xfer_cb = btd_xfer_cb, - .sof = NULL + DRIVER_NAME("BTH") + .init = btd_init, + .reset = btd_reset, + .open = btd_open, + .control_xfer_cb = btd_control_request, + .control_complete = btd_control_complete, + .xfer_cb = btd_xfer_cb, + .sof = NULL }, #endif }; -- cgit v1.3.1 From 7df979673db0e2e268c576a8a4d738069cf5e32b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 15:38:56 +0700 Subject: migrate usbtmc device to new control xfer cb --- src/class/usbtmc/usbtmc_device.c | 17 +++++++---------- src/class/usbtmc/usbtmc_device.h | 3 +-- src/device/usbd.c | 3 +-- 3 files changed, 9 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index bc5f23f42..88776d169 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -575,7 +575,13 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint return false; } -bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request) { +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + // nothing to do with DATA and ACK stage + if ( stage != CONTROL_STAGE_SETUP ) return true; uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; #if (CFG_TUD_USBTMC_ENABLE_488) @@ -855,13 +861,4 @@ bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * r TU_VERIFY(false); } -bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request) -{ - (void)rhport; - //------------- Class Specific Request -------------// - TU_ASSERT (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - return true; -} - #endif /* CFG_TUD_TSMC */ diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h index a6b5e4cca..622800315 100644 --- a/src/class/usbtmc/usbtmc_device.h +++ b/src/class/usbtmc/usbtmc_device.h @@ -111,8 +111,7 @@ bool tud_usbtmc_start_bus_read(void); uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); void usbtmcd_reset_cb(uint8_t rhport); bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -bool usbtmcd_control_request_cb(uint8_t rhport, tusb_control_request_t const * request); -bool usbtmcd_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); +bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); void usbtmcd_init_cb(void); /************************************************************ diff --git a/src/device/usbd.c b/src/device/usbd.c index bea41b592..1d328ad5f 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -171,8 +171,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = usbtmcd_init_cb, .reset = usbtmcd_reset_cb, .open = usbtmcd_open_cb, - .control_xfer_cb = usbtmcd_control_request_cb, - .control_complete = usbtmcd_control_complete_cb, + .control_xfer_cb = usbtmcd_control_xfer_cb, .xfer_cb = usbtmcd_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From 3cc1979adbfb8f91ce4a938573e729e8b80d4627 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 15:42:32 +0700 Subject: migrate dfu runtime device to new control xfer cb --- src/class/dfu/dfu_rt_device.c | 15 ++++++--------- src/class/dfu/dfu_rt_device.h | 3 +-- src/device/usbd.c | 3 +-- 3 files changed, 8 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index d4c3ecb62..38644615a 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -85,17 +85,14 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui return drv_len; } -bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request) +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - (void) rhport; - (void) request; + // nothing to do with DATA and ACK stage + if ( stage != CONTROL_STAGE_SETUP ) return true; - // nothing to do - return true; -} - -bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request) -{ TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 91ead88c6..643e25d8f 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -66,8 +66,7 @@ TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb conventi void dfu_rtd_init(void); void dfu_rtd_reset(uint8_t rhport); uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request); -bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request); +bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus diff --git a/src/device/usbd.c b/src/device/usbd.c index 1d328ad5f..b629a1ff8 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -183,8 +183,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = dfu_rtd_init, .reset = dfu_rtd_reset, .open = dfu_rtd_open, - .control_xfer_cb = dfu_rtd_control_request, - .control_complete = dfu_rtd_control_complete, + .control_xfer_cb = dfu_rtd_control_xfer_cb, .xfer_cb = dfu_rtd_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From 61ad7bef7140d8e06343a5ce4e15d3a2fe7f158a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 15:50:11 +0700 Subject: migrate vendor device to new control xfer cb --- examples/device/webusb_serial/src/main.c | 19 +++++++------------ src/device/usbd.c | 3 +-- src/device/usbd.h | 4 ---- 3 files changed, 8 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/examples/device/webusb_serial/src/main.c b/examples/device/webusb_serial/src/main.c index e1a098048..9309bbf6e 100644 --- a/examples/device/webusb_serial/src/main.c +++ b/examples/device/webusb_serial/src/main.c @@ -143,9 +143,14 @@ void tud_resume_cb(void) // WebUSB use vendor class //--------------------------------------------------------------------+ -// Invoked when received VENDOR control request -bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request) +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { + // nothing to with DATA & ACK stage + if (stage != CONTROL_STAGE_SETUP ) return true; + switch (request->bRequest) { case VENDOR_REQUEST_WEBUSB: @@ -194,16 +199,6 @@ bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const return true; } -// Invoked when DATA Stage of VENDOR's request is complete -bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - (void) request; - - // nothing to do - return true; -} - void webserial_task(void) { if ( web_serial_connected ) diff --git a/src/device/usbd.c b/src/device/usbd.c index b629a1ff8..9773245c8 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -158,8 +158,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = vendord_init, .reset = vendord_reset, .open = vendord_open, - .control_xfer_cb = tud_vendor_control_request_cb, - .control_complete = tud_vendor_control_complete_cb, + .control_xfer_cb = tud_vendor_control_xfer_cb, .xfer_cb = vendord_xfer_cb, .sof = NULL }, diff --git a/src/device/usbd.h b/src/device/usbd.h index cf7e9f0db..ef248e4ca 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -127,10 +127,6 @@ TU_ATTR_WEAK void tud_resume_cb(void); // Invoked when received control request with VENDOR TYPE TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -// Invoked when vendor control request is complete -TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request); - - //--------------------------------------------------------------------+ // Binary Device Object Store (BOS) Descriptor Templates //--------------------------------------------------------------------+ -- cgit v1.3.1 From 9f853685ae06c4eac03b277d61440de28d5ba41a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 16:13:58 +0700 Subject: migrate bth device to new control xfer cb --- src/class/bth/bth_device.c | 54 +++++++++++++++++++++++----------------------- src/class/bth/bth_device.h | 11 +++++----- src/device/usbd.c | 3 +-- 3 files changed, 33 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index 252e20e37..c63b994e2 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -186,43 +186,43 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ return drv_len; } -bool btd_control_complete(uint8_t rhport, tusb_control_request_t const *request) +bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) { (void)rhport; - // Handle class request only - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength); - - return true; -} - -bool btd_control_request(uint8_t rhport, tusb_control_request_t const *request) -{ - (void)rhport; - - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && - request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) - { - // HCI command packet addressing for single function Primary Controllers - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); - } - else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) + if ( stage == CONTROL_STAGE_SETUP ) { - if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE) { - // TODO: Set interface it would involve changing size of endpoint size + // HCI command packet addressing for single function Primary Controllers + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0); } - else + else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) { - // HCI command packet for Primary Controller function in a composite device - TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); + if (request->bRequest == TUSB_REQ_SET_INTERFACE && _btd_itf.itf_num + 1 == request->wIndex) + { + // TODO: Set interface it would involve changing size of endpoint size + } + else + { + // HCI command packet for Primary Controller function in a composite device + TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == _btd_itf.itf_num); + } } + else return false; + + return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength); + } + else if ( stage == CONTROL_STAGE_DATA ) + { + // Handle class request only + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength); } - else return false; - return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength); + return true; } bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) diff --git a/src/class/bth/bth_device.h b/src/class/bth/bth_device.h index 5e5468084..1b90d0915 100755 --- a/src/class/bth/bth_device.h +++ b/src/class/bth/bth_device.h @@ -96,12 +96,11 @@ bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void btd_init (void); -void btd_reset (uint8_t rhport); -uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool btd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool btd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void btd_init (void); +void btd_reset (uint8_t rhport); +uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool btd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const *request); +bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index 9773245c8..5639e1354 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -207,8 +207,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = btd_init, .reset = btd_reset, .open = btd_open, - .control_xfer_cb = btd_control_request, - .control_complete = btd_control_complete, + .control_xfer_cb = btd_control_xfer_cb, .xfer_cb = btd_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From d6461abe7835c336ddfb165817ec966ebd259d62 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 16:30:03 +0700 Subject: clean up --- src/class/bth/bth_device.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index c63b994e2..f8215e7dd 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -186,6 +186,9 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ return drv_len; } +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) { (void)rhport; -- cgit v1.3.1 From c4bc8b25613a74f932202047751d4cc73c0254bd Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 16:59:33 +0700 Subject: migrate net device to new control xfer cb --- src/class/net/net_device.c | 177 ++++++++++++++++++++++----------------------- src/class/net/net_device.h | 13 ++-- src/device/usbd.c | 3 +- 3 files changed, 94 insertions(+), 99 deletions(-) (limited to 'src') diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index 3a45a9b99..ce1131223 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -220,26 +220,6 @@ uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 return drv_len; } -// Invoked when class request DATA stage is finished. -// return false to stall control endpoint (e.g Host send nonsense DATA) -bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - - // 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) - { - if ( !_netd_itf.ecm_mode ) - { - rndis_class_set_handler(notify.rndis_buf, request->wLength); - } - } - - return true; -} - static void ecm_report(bool nc) { notify.ecm_buf = (nc) ? ecm_notify_nc : ecm_notify_csc; @@ -247,99 +227,116 @@ static void ecm_report(bool nc) netd_report((uint8_t *)¬ify.ecm_buf, (nc) ? sizeof(notify.ecm_buf.header) : sizeof(notify.ecm_buf)); } -// Handle class control request +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request) +bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - switch ( request->bmRequestType_bit.type ) + if ( stage == CONTROL_STAGE_SETUP ) { - case TUSB_REQ_TYPE_STANDARD: - switch ( request->bRequest ) - { - case TUSB_REQ_GET_INTERFACE: + switch ( request->bmRequestType_bit.type ) + { + case TUSB_REQ_TYPE_STANDARD: + switch ( request->bRequest ) { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum); + case TUSB_REQ_GET_INTERFACE: + { + uint8_t const req_itfnum = (uint8_t) request->wIndex; + TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum); - tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); - } - break; + tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1); + } + break; - case TUSB_REQ_SET_INTERFACE: - { - uint8_t const req_itfnum = (uint8_t) request->wIndex; - uint8_t const req_alt = (uint8_t) request->wValue; + 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); + // 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); + // ACM-ECM only: qequest to enable/disable network activities + TU_VERIFY(_netd_itf.ecm_mode); - _netd_itf.itf_data_alt = req_alt; + _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 ) + 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 { - 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 + // 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 } - }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; - tud_control_status(rhport, request); + // unsupported request + default: return false; } - break; + break; - // unsupported request - default: return false; - } - break; - - case TUSB_REQ_TYPE_CLASS: - TU_VERIFY (_netd_itf.itf_num == request->wIndex); + 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) + if (_netd_itf.ecm_mode) { - 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 *) ((void*) 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); + /* 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 { - tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf)); + if (request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *) ((void*) 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; + break; - // unsupported request - default: return false; + // unsupported request + default: return false; + } + } + else if ( stage == CONTROL_STAGE_DATA ) + { + // 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) + { + if ( !_netd_itf.ecm_mode ) + { + rndis_class_set_handler(notify.rndis_buf, request->wLength); + } + } } return true; diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 795b2f9e3..38c47d647 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -73,13 +73,12 @@ void tud_network_xmit(void *ref, uint16_t arg); //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ -void netd_init (void); -void netd_reset (uint8_t rhport); -uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request); -bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void netd_report (uint8_t *buf, uint16_t len); +void netd_init (void); +void netd_reset (uint8_t rhport); +uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void netd_report (uint8_t *buf, uint16_t len); #ifdef __cplusplus } diff --git a/src/device/usbd.c b/src/device/usbd.c index 5639e1354..4d2b44005 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -194,8 +194,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = netd_init, .reset = netd_reset, .open = netd_open, - .control_xfer_cb = netd_control_request, - .control_complete = netd_control_complete, + .control_xfer_cb = netd_control_xfer_cb, .xfer_cb = netd_xfer_cb, .sof = NULL, }, -- cgit v1.3.1 From cebb375eac0d560b53341012aa69ae2a54f4fbaf Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 17:20:05 +0700 Subject: migrate audio device to new control xfer cb --- src/class/audio/audio_device.c | 18 ++++++++++++++++-- src/class/audio/audio_device.h | 9 ++++----- src/device/usbd.c | 3 +-- 3 files changed, 21 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 2c8ba300d..8581925e4 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -989,7 +989,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Invoked when class request DATA stage is finished. // return false to stall control EP (e.g Host send non-sense DATA) -bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) +static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_request) { // Handle audio class specific set requests if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) @@ -1065,7 +1065,7 @@ bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const * p_re // Handle class control request // return false to stall control endpoint (e.g unsupported request) -bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) +static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_request) { (void) rhport; @@ -1175,6 +1175,20 @@ bool audiod_control_request(uint8_t rhport, tusb_control_request_t const * p_req return false; } +bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( stage == CONTROL_STAGE_SETUP ) + { + return audiod_control_request(rhport, request); + } + else if ( stage == CONTROL_STAGE_DATA ) + { + return audiod_control_complete(rhport, request); + } + + return true; +} + bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index d86232720..5061501ce 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -384,11 +384,10 @@ static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t b //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void audiod_init (void); -void audiod_reset (uint8_t rhport); -uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool audiod_control_request (uint8_t rhport, tusb_control_request_t const * request); -bool audiod_control_complete (uint8_t rhport, tusb_control_request_t const * request); +void audiod_init (void); +void audiod_reset (uint8_t rhport); +uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool audiod_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus diff --git a/src/device/usbd.c b/src/device/usbd.c index 4d2b44005..15174f2ab 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -133,8 +133,7 @@ static usbd_class_driver_t const _usbd_driver[] = .init = audiod_init, .reset = audiod_reset, .open = audiod_open, - .control_xfer_cb = audiod_control_request, - .control_complete = audiod_control_complete, + .control_xfer_cb = audiod_control_xfer_cb, .xfer_cb = audiod_xfer_cb, .sof = NULL }, -- cgit v1.3.1 From e4144d8b47b438ff57a09c54de49e7e6c68d9343 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Nov 2020 17:21:01 +0700 Subject: remove control_complete --- src/device/usbd_pvt.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 57331041b..212c3a202 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -47,7 +47,6 @@ typedef struct void (* reset ) (uint8_t rhport); uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request); bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void (* sof ) (uint8_t rhport); /* optional */ } usbd_class_driver_t; -- cgit v1.3.1 From 14138f105e6fa487fa0a0ed40db6f27e1c6039fb Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Nov 2020 13:12:51 +0700 Subject: have tusb_init() return true instead of TUSB_ERROR_NONE --- src/class/bth/bth_device.c | 2 +- src/common/tusb_error.h | 1 + src/tusb.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index f8215e7dd..481dc134e 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -249,7 +249,7 @@ bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t if (tud_bt_acl_data_sent_cb) tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes); } - return TUSB_ERROR_NONE; + return true; } #endif diff --git a/src/common/tusb_error.h b/src/common/tusb_error.h index f600c4ae3..d7ad8c318 100644 --- a/src/common/tusb_error.h +++ b/src/common/tusb_error.h @@ -54,6 +54,7 @@ ENTRY(TUSB_ERROR_FAILED )\ /// \brief Error Code returned +/// TODO obsolete and to be remove typedef enum { ERROR_TABLE(ERROR_ENUM) diff --git a/src/tusb.c b/src/tusb.c index b4731f844..31452e897 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -52,7 +52,7 @@ bool tusb_init(void) _initialized = true; - return TUSB_ERROR_NONE; + return true; } bool tusb_inited(void) -- cgit v1.3.1 From 4b4f88078503648b38444feee1fda322b65baa43 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Nov 2020 23:40:13 +0700 Subject: add tud_ready() check in tud_cdc_n_write_flush() other clean up --- examples/device/cdc_msc/src/main.c | 10 ---------- src/class/cdc/cdc_device.c | 19 +++++++++++++------ src/common/tusb_fifo.c | 2 +- src/common/tusb_fifo.h | 2 +- 4 files changed, 15 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_msc/src/main.c b/examples/device/cdc_msc/src/main.c index e4477927f..cf2bfd7c9 100644 --- a/examples/device/cdc_msc/src/main.c +++ b/examples/device/cdc_msc/src/main.c @@ -145,16 +145,6 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) void tud_cdc_rx_cb(uint8_t itf) { (void) itf; - uint8_t const line_state = tud_cdc_get_line_state(); - - // Provide information that terminal did not set DTR bit - if( !(line_state & 0x01) ) - { - tud_cdc_write_str("\r\nTinyUSB example: Your terminal did not set DTR bit\r\n"); - tud_cdc_write_flush(); - // Clear rx fifo since we do not read the data - tud_cdc_read_flush(); - } } //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index bd1d9b0d4..58f485a5d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -178,6 +178,9 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + // Skip if usb is not ready yet + TU_VERIFY( tud_ready(), 0 ); + // No data to send if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0; @@ -231,9 +234,10 @@ void cdcd_init(void) p_cdc->line_coding.parity = 0; p_cdc->line_coding.data_bits = 8; - // config fifo + // Config RX fifo tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); - // tx fifo is set to overwritable at initialization and will be changed to not overwritable + + // Config TX fifo as overwritable at initialization and will be changed to non-overwritable // if terminal supports DTR bit. Without DTR we do not know if data is actually polled by terminal. // In this way, the most current data is prioritized. tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); @@ -251,9 +255,12 @@ void cdcd_reset(uint8_t rhport) for(uint8_t i=0; irx_ff); + tu_fifo_clear(&p_cdc->tx_ff); + tu_fifo_set_overwritable(&p_cdc->tx_ff, true); } } @@ -381,7 +388,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t p_cdc->line_state = (uint8_t) request->wValue; // Disable fifo overwriting if DTR bit is set - tu_fifo_set_mode(&p_cdc->tx_ff, !dtr); + tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr); TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 444c60f96..608bfd081 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -607,7 +607,7 @@ bool tu_fifo_clear(tu_fifo_t *f) Overwritable mode the fifo is set to */ /******************************************************************************/ -bool tu_fifo_set_mode(tu_fifo_t *f, bool overwritable) +bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { tu_fifo_lock(f); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index abb301b5f..b965386ab 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -89,7 +89,7 @@ typedef struct .non_used_index_space = 0xFFFF - 2*_depth-1, \ } -bool tu_fifo_set_mode(tu_fifo_t *f, bool overwritable); +bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); -- cgit v1.3.1 From 148eea141798cd9aefea49aaedc06c885ab7a3aa Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 24 Nov 2020 21:49:12 +0700 Subject: add tud_connected() which return true as long as we receive the very first SETUP packet from host. --- src/device/usbd.c | 7 ++++++- src/device/usbd.h | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 15174f2ab..4ecc2a2f9 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -326,9 +326,14 @@ tusb_speed_t tud_speed_get(void) return (tusb_speed_t) _usbd_dev.speed; } +bool tud_connected(void) +{ + return _usbd_dev.connected; +} + bool tud_mounted(void) { - return _usbd_dev.cfg_num ? 1 : 0; + return _usbd_dev.cfg_num ? true : false; } bool tud_suspended(void) diff --git a/src/device/usbd.h b/src/device/usbd.h index ef248e4ca..360567743 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -56,6 +56,9 @@ extern void dcd_int_handler(uint8_t rhport); // Get current bus speed tusb_speed_t tud_speed_get(void); +// Check if device is connected (may not mounted/configured yet) +bool tud_connected(void); + // Check if device is connected and configured bool tud_mounted(void); -- cgit v1.3.1 From f5e13d589826b25791464f2fe2050d36739ad56e Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 24 Nov 2020 23:42:30 +0700 Subject: msc only invoke scsi complete callback after status transaction is complete --- src/class/msc/msc_device.c | 36 +- src/common/sys_queue.h | 871 --------------------------------------------- 2 files changed, 18 insertions(+), 889 deletions(-) delete mode 100644 src/common/sys_queue.h (limited to 'src') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index cfb8a43a3..a4ea5f6fb 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -585,6 +585,24 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_LOG2(" SCSI Status: %u\r\n", p_csw->status); // TU_LOG2_MEM(p_csw, xferred_bytes, 2); + // Invoke complete callback if defined + // Note: There is racing issue with samd51 + qspi flash testing with arduino + // if complete_cb() is invoked after queuing the status. + switch(p_cbw->command[0]) + { + case SCSI_CMD_READ_10: + if ( tud_msc_read10_complete_cb ) tud_msc_read10_complete_cb(p_cbw->lun); + break; + + case SCSI_CMD_WRITE_10: + if ( tud_msc_write10_complete_cb ) tud_msc_write10_complete_cb(p_cbw->lun); + break; + + default: + if ( tud_msc_scsi_complete_cb ) tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command); + break; + } + // Move to default CMD stage p_msc->stage = MSC_STAGE_CMD; @@ -608,24 +626,6 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t } else { - // Invoke complete callback if defined - // Note: There is racing issue with samd51 + qspi flash testing with arduino - // if complete_cb() is invoked after queuing the status. - switch(p_cbw->command[0]) - { - case SCSI_CMD_READ_10: - if ( tud_msc_read10_complete_cb ) tud_msc_read10_complete_cb(p_cbw->lun); - break; - - case SCSI_CMD_WRITE_10: - if ( tud_msc_write10_complete_cb ) tud_msc_write10_complete_cb(p_cbw->lun); - break; - - default: - if ( tud_msc_scsi_complete_cb ) tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command); - break; - } - // Move to Status Sent stage p_msc->stage = MSC_STAGE_STATUS_SENT; diff --git a/src/common/sys_queue.h b/src/common/sys_queue.h deleted file mode 100644 index 443f01b22..000000000 --- a/src/common/sys_queue.h +++ /dev/null @@ -1,871 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - * $FreeBSD$ - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -#include - -/* - * This file defines four types of data structures: singly-linked lists, - * singly-linked tail queues, lists and tail queues. - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A singly-linked tail queue is headed by a pair of pointers, one to the - * head of the list and the other to the tail of the list. The elements are - * singly linked for minimum space and pointer manipulation overhead at the - * expense of O(n) removal for arbitrary elements. New elements can be added - * to the list after an existing element, at the head of the list, or at the - * end of the list. Elements being removed from the head of the tail queue - * should use the explicit macro for this purpose for optimum efficiency. - * A singly-linked tail queue may only be traversed in the forward direction. - * Singly-linked tail queues are ideal for applications with large datasets - * and few or no removals or for implementing a FIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may be traversed in either direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * For details on the use of these macros, see the queue(3) manual page. - * - * Below is a summary of implemented functions where: - * + means the macro is available - * - means the macro is not available - * s means the macro is available but is slow (runs in O(n) time) - * - * SLIST LIST STAILQ TAILQ - * _HEAD + + + + - * _CLASS_HEAD + + + + - * _HEAD_INITIALIZER + + + + - * _ENTRY + + + + - * _CLASS_ENTRY + + + + - * _INIT + + + + - * _EMPTY + + + + - * _FIRST + + + + - * _NEXT + + + + - * _PREV - + - + - * _LAST - - + + - * _LAST_FAST - - - + - * _FOREACH + + + + - * _FOREACH_FROM + + + + - * _FOREACH_SAFE + + + + - * _FOREACH_FROM_SAFE + + + + - * _FOREACH_REVERSE - - - + - * _FOREACH_REVERSE_FROM - - - + - * _FOREACH_REVERSE_SAFE - - - + - * _FOREACH_REVERSE_FROM_SAFE - - - + - * _INSERT_HEAD + + + + - * _INSERT_BEFORE - + - + - * _INSERT_AFTER + + + + - * _INSERT_TAIL - - + + - * _CONCAT s s + + - * _REMOVE_AFTER + - + - - * _REMOVE_HEAD + - + - - * _REMOVE s + s + - * _SWAP + + + + - * - */ -#ifdef QUEUE_MACRO_DEBUG -#warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH -#define QUEUE_MACRO_DEBUG_TRACE -#define QUEUE_MACRO_DEBUG_TRASH -#endif - -#ifdef QUEUE_MACRO_DEBUG_TRACE -/* Store the last 2 places the queue element or head was altered */ -struct qm_trace { - unsigned long lastline; - unsigned long prevline; - const char *lastfile; - const char *prevfile; -}; - -#define TRACEBUF struct qm_trace trace; -#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } , - -#define QMD_TRACE_HEAD(head) do { \ - (head)->trace.prevline = (head)->trace.lastline; \ - (head)->trace.prevfile = (head)->trace.lastfile; \ - (head)->trace.lastline = __LINE__; \ - (head)->trace.lastfile = __FILE__; \ -} while (0) - -#define QMD_TRACE_ELEM(elem) do { \ - (elem)->trace.prevline = (elem)->trace.lastline; \ - (elem)->trace.prevfile = (elem)->trace.lastfile; \ - (elem)->trace.lastline = __LINE__; \ - (elem)->trace.lastfile = __FILE__; \ -} while (0) - -#else /* !QUEUE_MACRO_DEBUG_TRACE */ -#define QMD_TRACE_ELEM(elem) -#define QMD_TRACE_HEAD(head) -#define TRACEBUF -#define TRACEBUF_INITIALIZER -#endif /* QUEUE_MACRO_DEBUG_TRACE */ - -#ifdef QUEUE_MACRO_DEBUG_TRASH -#define TRASHIT(x) do {(x) = (void *)-1;} while (0) -#define QMD_IS_TRASHED(x) ((x) == (void *)(intptr_t)-1) -#else /* !QUEUE_MACRO_DEBUG_TRASH */ -#define TRASHIT(x) -#define QMD_IS_TRASHED(x) 0 -#endif /* QUEUE_MACRO_DEBUG_TRASH */ - -#if defined(QUEUE_MACRO_DEBUG_TRACE) || defined(QUEUE_MACRO_DEBUG_TRASH) -#define QMD_SAVELINK(name, link) void **name = (void *)&(link) -#else /* !QUEUE_MACRO_DEBUG_TRACE && !QUEUE_MACRO_DEBUG_TRASH */ -#define QMD_SAVELINK(name, link) -#endif /* QUEUE_MACRO_DEBUG_TRACE || QUEUE_MACRO_DEBUG_TRASH */ - -#ifdef __cplusplus -/* - * In C++ there can be structure lists and class lists: - */ -#define QUEUE_TYPEOF(type) type -#else -#define QUEUE_TYPEOF(type) struct type -#endif - -/* - * Singly-linked List declarations. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_CLASS_HEAD(name, type) \ -struct name { \ - class type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -#define SLIST_CLASS_ENTRY(type) \ -struct { \ - class type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List functions. - */ -#if (defined(_KERNEL) && defined(INVARIANTS)) -#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) do { \ - if (*(prevp) != (elm)) \ - panic("Bad prevptr *(%p) == %p != %p", \ - (prevp), *(prevp), (elm)); \ -} while (0) -#else -#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) -#endif - -#define SLIST_CONCAT(head1, head2, type, field) do { \ - QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \ - if (curelm == NULL) { \ - if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \ - SLIST_INIT(head2); \ - } else if (SLIST_FIRST(head2) != NULL) { \ - while (SLIST_NEXT(curelm, field) != NULL) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \ - SLIST_INIT(head2); \ - } \ -} while (0) - -#define SLIST_EMPTY(head) ((head)->slh_first == NULL) - -#define SLIST_FIRST(head) ((head)->slh_first) - -#define SLIST_FOREACH(var, head, field) \ - for ((var) = SLIST_FIRST((head)); \ - (var); \ - (var) = SLIST_NEXT((var), field)) - -#define SLIST_FOREACH_FROM(var, head, field) \ - for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ - (var); \ - (var) = SLIST_NEXT((var), field)) - -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SLIST_FIRST((head)); \ - (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ - for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ - (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ - for ((varp) = &SLIST_FIRST((head)); \ - ((var) = *(varp)) != NULL; \ - (varp) = &SLIST_NEXT((var), field)) - -#define SLIST_INIT(head) do { \ - SLIST_FIRST((head)) = NULL; \ -} while (0) - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ - SLIST_NEXT((slistelm), field) = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ - SLIST_FIRST((head)) = (elm); \ -} while (0) - -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ - if (SLIST_FIRST((head)) == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } \ - else { \ - QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \ - while (SLIST_NEXT(curelm, field) != (elm)) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_REMOVE_AFTER(curelm, field); \ - } \ - TRASHIT(*oldnext); \ -} while (0) - -#define SLIST_REMOVE_AFTER(elm, field) do { \ - SLIST_NEXT(elm, field) = \ - SLIST_NEXT(SLIST_NEXT(elm, field), field); \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ -} while (0) - -#define SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \ - QMD_SLIST_CHECK_PREVPTR(prevp, elm); \ - *(prevp) = SLIST_NEXT(elm, field); \ - TRASHIT((elm)->field.sle_next); \ -} while (0) - -#define SLIST_SWAP(head1, head2, type) do { \ - QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \ - SLIST_FIRST(head1) = SLIST_FIRST(head2); \ - SLIST_FIRST(head2) = swap_first; \ -} while (0) - -/* - * Singly-linked Tail queue declarations. - */ -#define STAILQ_HEAD(name, type) \ -struct name { \ - struct type *stqh_first;/* first element */ \ - struct type **stqh_last;/* addr of last next element */ \ -} - -#define STAILQ_CLASS_HEAD(name, type) \ -struct name { \ - class type *stqh_first; /* first element */ \ - class type **stqh_last; /* addr of last next element */ \ -} - -#define STAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).stqh_first } - -#define STAILQ_ENTRY(type) \ -struct { \ - struct type *stqe_next; /* next element */ \ -} - -#define STAILQ_CLASS_ENTRY(type) \ -struct { \ - class type *stqe_next; /* next element */ \ -} - -/* - * Singly-linked Tail queue functions. - */ -#define STAILQ_CONCAT(head1, head2) do { \ - if (!STAILQ_EMPTY((head2))) { \ - *(head1)->stqh_last = (head2)->stqh_first; \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_INIT((head2)); \ - } \ -} while (0) - -#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) - -#define STAILQ_FIRST(head) ((head)->stqh_first) - -#define STAILQ_FOREACH(var, head, field) \ - for((var) = STAILQ_FIRST((head)); \ - (var); \ - (var) = STAILQ_NEXT((var), field)) - -#define STAILQ_FOREACH_FROM(var, head, field) \ - for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ - (var); \ - (var) = STAILQ_NEXT((var), field)) - -#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = STAILQ_FIRST((head)); \ - (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ - for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ - (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define STAILQ_INIT(head) do { \ - STAILQ_FIRST((head)) = NULL; \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_NEXT((tqelm), field) = (elm); \ -} while (0) - -#define STAILQ_INSERT_HEAD(head, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_FIRST((head)) = (elm); \ -} while (0) - -#define STAILQ_INSERT_TAIL(head, elm, field) do { \ - STAILQ_NEXT((elm), field) = NULL; \ - *(head)->stqh_last = (elm); \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_LAST(head, type, field) \ - (STAILQ_EMPTY((head)) ? NULL : \ - __containerof((head)->stqh_last, \ - QUEUE_TYPEOF(type), field.stqe_next)) - -#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) - -#define STAILQ_REMOVE(head, elm, type, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ - if (STAILQ_FIRST((head)) == (elm)) { \ - STAILQ_REMOVE_HEAD((head), field); \ - } \ - else { \ - QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \ - while (STAILQ_NEXT(curelm, field) != (elm)) \ - curelm = STAILQ_NEXT(curelm, field); \ - STAILQ_REMOVE_AFTER(head, curelm, field); \ - } \ - TRASHIT(*oldnext); \ -} while (0) - -#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ - if ((STAILQ_NEXT(elm, field) = \ - STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_REMOVE_HEAD(head, field) do { \ - if ((STAILQ_FIRST((head)) = \ - STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_SWAP(head1, head2, type) do { \ - QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \ - QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \ - STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_FIRST(head2) = swap_first; \ - (head2)->stqh_last = swap_last; \ - if (STAILQ_EMPTY(head1)) \ - (head1)->stqh_last = &STAILQ_FIRST(head1); \ - if (STAILQ_EMPTY(head2)) \ - (head2)->stqh_last = &STAILQ_FIRST(head2); \ -} while (0) - - -/* - * List declarations. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_CLASS_HEAD(name, type) \ -struct name { \ - class type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -#define LIST_CLASS_ENTRY(type) \ -struct { \ - class type *le_next; /* next element */ \ - class type **le_prev; /* address of previous next element */ \ -} - -/* - * List functions. - */ - -#if (defined(_KERNEL) && defined(INVARIANTS)) -/* - * QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME) - * - * If the list is non-empty, validates that the first element of the list - * points back at 'head.' - */ -#define QMD_LIST_CHECK_HEAD(head, field) do { \ - if (LIST_FIRST((head)) != NULL && \ - LIST_FIRST((head))->field.le_prev != \ - &LIST_FIRST((head))) \ - panic("Bad list head %p first->prev != head", (head)); \ -} while (0) - -/* - * QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME) - * - * If an element follows 'elm' in the list, validates that the next element - * points back at 'elm.' - */ -#define QMD_LIST_CHECK_NEXT(elm, field) do { \ - if (LIST_NEXT((elm), field) != NULL && \ - LIST_NEXT((elm), field)->field.le_prev != \ - &((elm)->field.le_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) - -/* - * QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME) - * - * Validates that the previous element (or head of the list) points to 'elm.' - */ -#define QMD_LIST_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.le_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) -#else -#define QMD_LIST_CHECK_HEAD(head, field) -#define QMD_LIST_CHECK_NEXT(elm, field) -#define QMD_LIST_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ - -#define LIST_CONCAT(head1, head2, type, field) do { \ - QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \ - if (curelm == NULL) { \ - if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \ - LIST_FIRST(head2)->field.le_prev = \ - &LIST_FIRST((head1)); \ - LIST_INIT(head2); \ - } \ - } else if (LIST_FIRST(head2) != NULL) { \ - while (LIST_NEXT(curelm, field) != NULL) \ - curelm = LIST_NEXT(curelm, field); \ - LIST_NEXT(curelm, field) = LIST_FIRST(head2); \ - LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \ - LIST_INIT(head2); \ - } \ -} while (0) - -#define LIST_EMPTY(head) ((head)->lh_first == NULL) - -#define LIST_FIRST(head) ((head)->lh_first) - -#define LIST_FOREACH(var, head, field) \ - for ((var) = LIST_FIRST((head)); \ - (var); \ - (var) = LIST_NEXT((var), field)) - -#define LIST_FOREACH_FROM(var, head, field) \ - for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ - (var); \ - (var) = LIST_NEXT((var), field)) - -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = LIST_FIRST((head)); \ - (var) && ((tvar) = LIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ - for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ - (var) && ((tvar) = LIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define LIST_INIT(head) do { \ - LIST_FIRST((head)) = NULL; \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - QMD_LIST_CHECK_NEXT(listelm, field); \ - if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ - LIST_NEXT((listelm), field)->field.le_prev = \ - &LIST_NEXT((elm), field); \ - LIST_NEXT((listelm), field) = (elm); \ - (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - QMD_LIST_CHECK_PREV(listelm, field); \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - LIST_NEXT((elm), field) = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - QMD_LIST_CHECK_HEAD((head), field); \ - if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ - LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ - LIST_FIRST((head)) = (elm); \ - (elm)->field.le_prev = &LIST_FIRST((head)); \ -} while (0) - -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_PREV(elm, head, type, field) \ - ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ - __containerof((elm)->field.le_prev, \ - QUEUE_TYPEOF(type), field.le_next)) - -#define LIST_REMOVE(elm, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.le_next); \ - QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ - QMD_LIST_CHECK_NEXT(elm, field); \ - QMD_LIST_CHECK_PREV(elm, field); \ - if (LIST_NEXT((elm), field) != NULL) \ - LIST_NEXT((elm), field)->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = LIST_NEXT((elm), field); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ -} while (0) - -#define LIST_SWAP(head1, head2, type, field) do { \ - QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \ - LIST_FIRST((head1)) = LIST_FIRST((head2)); \ - LIST_FIRST((head2)) = swap_tmp; \ - if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ - swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ - if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ - swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ -} while (0) - -/* - * Tail queue declarations. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ - TRACEBUF \ -} - -#define TAILQ_CLASS_HEAD(name, type) \ -struct name { \ - class type *tqh_first; /* first element */ \ - class type **tqh_last; /* addr of last next element */ \ - TRACEBUF \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ - TRACEBUF \ -} - -#define TAILQ_CLASS_ENTRY(type) \ -struct { \ - class type *tqe_next; /* next element */ \ - class type **tqe_prev; /* address of previous next element */ \ - TRACEBUF \ -} - -/* - * Tail queue functions. - */ -#if (defined(_KERNEL) && defined(INVARIANTS)) -/* - * QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME) - * - * If the tailq is non-empty, validates that the first element of the tailq - * points back at 'head.' - */ -#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ - if (!TAILQ_EMPTY(head) && \ - TAILQ_FIRST((head))->field.tqe_prev != \ - &TAILQ_FIRST((head))) \ - panic("Bad tailq head %p first->prev != head", (head)); \ -} while (0) - -/* - * QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME) - * - * Validates that the tail of the tailq is a pointer to pointer to NULL. - */ -#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ - if (*(head)->tqh_last != NULL) \ - panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ -} while (0) - -/* - * QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME) - * - * If an element follows 'elm' in the tailq, validates that the next element - * points back at 'elm.' - */ -#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ - if (TAILQ_NEXT((elm), field) != NULL && \ - TAILQ_NEXT((elm), field)->field.tqe_prev != \ - &((elm)->field.tqe_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) - -/* - * QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME) - * - * Validates that the previous element (or head of the tailq) points to 'elm.' - */ -#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.tqe_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) -#else -#define QMD_TAILQ_CHECK_HEAD(head, field) -#define QMD_TAILQ_CHECK_TAIL(head, headname) -#define QMD_TAILQ_CHECK_NEXT(elm, field) -#define QMD_TAILQ_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ - -#define TAILQ_CONCAT(head1, head2, field) do { \ - if (!TAILQ_EMPTY(head2)) { \ - *(head1)->tqh_last = (head2)->tqh_first; \ - (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ - (head1)->tqh_last = (head2)->tqh_last; \ - TAILQ_INIT((head2)); \ - QMD_TRACE_HEAD(head1); \ - QMD_TRACE_HEAD(head2); \ - } \ -} while (0) - -#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) - -#define TAILQ_FIRST(head) ((head)->tqh_first) - -#define TAILQ_FOREACH(var, head, field) \ - for ((var) = TAILQ_FIRST((head)); \ - (var); \ - (var) = TAILQ_NEXT((var), field)) - -#define TAILQ_FOREACH_FROM(var, head, field) \ - for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ - (var); \ - (var) = TAILQ_NEXT((var), field)) - -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST((head)); \ - (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ - for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ - (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var); \ - (var) = TAILQ_PREV((var), headname, field)) - -#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ - for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ - (var); \ - (var) = TAILQ_PREV((var), headname, field)) - -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ - (var) = (tvar)) - -#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \ - for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ - (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ - (var) = (tvar)) - -#define TAILQ_INIT(head) do { \ - TAILQ_FIRST((head)) = NULL; \ - (head)->tqh_last = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - QMD_TAILQ_CHECK_NEXT(listelm, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else { \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - } \ - TAILQ_NEXT((listelm), field) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&(listelm)->field); \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - QMD_TAILQ_CHECK_PREV(listelm, field); \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - TAILQ_NEXT((elm), field) = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&(listelm)->field); \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - QMD_TAILQ_CHECK_HEAD(head, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ - TAILQ_FIRST((head))->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - TAILQ_FIRST((head)) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - QMD_TAILQ_CHECK_TAIL(head, field); \ - TAILQ_NEXT((elm), field) = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) - -/* - * The FAST function is fast in that it causes no data access other - * then the access to the head. The standard LAST function above - * will cause a data access of both the element you want and - * the previous element. FAST is very useful for instances when - * you may want to prefetch the last data element. - */ -#define TAILQ_LAST_FAST(head, type, field) \ - (TAILQ_EMPTY(head) ? NULL : __containerof((head)->tqh_last, QUEUE_TYPEOF(type), field.tqe_next)) - -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) - -#define TAILQ_REMOVE(head, elm, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ - QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ - QMD_TAILQ_CHECK_NEXT(elm, field); \ - QMD_TAILQ_CHECK_PREV(elm, field); \ - if ((TAILQ_NEXT((elm), field)) != NULL) \ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else { \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - QMD_TRACE_HEAD(head); \ - } \ - *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_SWAP(head1, head2, type, field) do { \ - QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \ - QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \ - (head1)->tqh_first = (head2)->tqh_first; \ - (head1)->tqh_last = (head2)->tqh_last; \ - (head2)->tqh_first = swap_first; \ - (head2)->tqh_last = swap_last; \ - if ((swap_first = (head1)->tqh_first) != NULL) \ - swap_first->field.tqe_prev = &(head1)->tqh_first; \ - else \ - (head1)->tqh_last = &(head1)->tqh_first; \ - if ((swap_first = (head2)->tqh_first) != NULL) \ - swap_first->field.tqe_prev = &(head2)->tqh_first; \ - else \ - (head2)->tqh_last = &(head2)->tqh_first; \ -} while (0) - -#endif /* !_SYS_QUEUE_H_ */ -- cgit v1.3.1 From 94527951a0fef9c1383ff9a3bbc8167f21008f4e Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Nov 2020 15:54:55 +0700 Subject: add bus suspend & resume support for esp32s2 --- examples/device/hid_composite_freertos/src/main.c | 7 ++++++- src/portable/espressif/esp32s2/dcd_esp32s2.c | 18 +++++++++++++++++- src/portable/st/synopsys/dcd_synopsys.c | 8 ++++---- 3 files changed, 27 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/examples/device/hid_composite_freertos/src/main.c b/examples/device/hid_composite_freertos/src/main.c index de065ee64..83c68b515 100644 --- a/examples/device/hid_composite_freertos/src/main.c +++ b/examples/device/hid_composite_freertos/src/main.c @@ -58,7 +58,12 @@ StaticTimer_t blinky_tmdef; TimerHandle_t blinky_tm; // static task for usbd -#define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) +#if CFG_TUSB_DEBUG + #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE) +#else + #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) +#endif + StackType_t usb_device_stack[USBD_STACK_SIZE]; StaticTask_t usb_device_taskdef; diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 58d92e728..81e63816e 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -218,6 +218,9 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) void dcd_remote_wakeup(uint8_t rhport) { (void)rhport; + + // TODO must manually clear this bit after 1-15 ms + // USB0.DCTL |= USB_RMTWKUPSIG_M; } // connect by enabling internal pull-up resistor on D+/D- @@ -670,6 +673,7 @@ static void handle_epin_ints(void) static void _dcd_int_handler(void* arg) { (void) arg; + uint8_t const rhport = 0; const uint32_t int_status = USB0.gintsts; //const uint32_t int_msk = USB0.gintmsk; @@ -695,7 +699,19 @@ static void _dcd_int_handler(void* arg) // the end of reset. USB0.gintsts = USB_ENUMDONE_M; enum_done_processing(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); + } + + if(int_status & USB_USBSUSP_M) + { + USB0.gintsts = USB_USBSUSP_M; + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + } + + if(int_status & USB_WKUPINT_M) + { + USB0.gintsts = USB_WKUPINT_M; + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); } if (int_status & USB_OTGINT_M) diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 9aeec79e6..c18dcde51 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -507,21 +507,21 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; + + // TODO must manually clear this bit after 1-15 ms + // USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); + // dev->DCTL |= USB_OTG_DCTL_RWUSIG; } void dcd_connect(uint8_t rhport) { - (void) rhport; USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - dev->DCTL &= ~USB_OTG_DCTL_SDIS; } void dcd_disconnect(uint8_t rhport) { - (void) rhport; USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - dev->DCTL |= USB_OTG_DCTL_SDIS; } -- cgit v1.3.1 From 8b34f2fca8f57a615f66773329fd238a9e416855 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Nov 2020 16:05:44 +0700 Subject: fix ci --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 4 ++-- src/portable/st/synopsys/dcd_synopsys.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 81e63816e..cd66af805 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -723,7 +723,7 @@ static void _dcd_int_handler(void* arg) if (otg_int & USB_SESENDDET_M) { - dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); } USB0.gotgint = otg_int; @@ -732,7 +732,7 @@ static void _dcd_int_handler(void* arg) #if USE_SOF if (int_status & USB_SOF_M) { USB0.gintsts = USB_SOF_M; - dcd_event_bus_signal(0, DCD_EVENT_SOF, true); // do nothing actually + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); // do nothing actually } #endif diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index c18dcde51..35c814460 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -515,12 +515,14 @@ void dcd_remote_wakeup(uint8_t rhport) void dcd_connect(uint8_t rhport) { + (void) rhport; USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); dev->DCTL &= ~USB_OTG_DCTL_SDIS; } void dcd_disconnect(uint8_t rhport) { + (void) rhport; USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); dev->DCTL |= USB_OTG_DCTL_SDIS; } -- cgit v1.3.1 From 2bbfc56bd8b52c9d5f6cdcfb1ab76cd868ddacd7 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Fri, 27 Nov 2020 00:49:25 +0900 Subject: added support for frdm_kl25z --- hw/bsp/board_mcu.h | 2 +- hw/bsp/frdm_kl25z/board.mk | 46 ++++ hw/bsp/frdm_kl25z/frdm_kl25z.c | 148 +++++++++++++ src/portable/nxp/khci/dcd_khci.c | 459 +++++++++++++++++++++++++++++++++++++++ src/tusb_option.h | 4 + 5 files changed, 658 insertions(+), 1 deletion(-) create mode 100644 hw/bsp/frdm_kl25z/board.mk create mode 100644 hw/bsp/frdm_kl25z/frdm_kl25z.c create mode 100644 src/portable/nxp/khci/dcd_khci.c (limited to 'src') diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index eedae43f7..1cf0ad03c 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -46,7 +46,7 @@ #include "chip.h" #elif CFG_TUSB_MCU == OPT_MCU_LPC51UXX || CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC55XX + CFG_TUSB_MCU == OPT_MCU_LPC55XX || CFG_TUSB_MCU == OPT_MCU_MKL25ZXX #include "fsl_device_registers.h" #elif CFG_TUSB_MCU == OPT_MCU_NRF5X diff --git a/hw/bsp/frdm_kl25z/board.mk b/hw/bsp/frdm_kl25z/board.mk new file mode 100644 index 000000000..9d86c4542 --- /dev/null +++ b/hw/bsp/frdm_kl25z/board.mk @@ -0,0 +1,46 @@ +CFLAGS += \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m0plus \ + -DCPU_MKL25Z128VLK4 \ + -DCFG_TUSB_MCU=OPT_MCU_MKL25ZXX + +# mcu driver cause following warnings +CFLAGS += -Wno-error=unused-parameter + +MCU_DIR = hw/mcu/nxp/sdk/devices/MKL25Z4 + +# All source paths should be relative to the top level. +LD_FILE = $(MCU_DIR)/gcc/MKL25Z128xxx4_flash.ld + +SRC_C += \ + $(MCU_DIR)/system_MKL25Z4.c \ + $(MCU_DIR)/project_template/clock_config.c \ + $(MCU_DIR)/drivers/fsl_clock.c \ + $(MCU_DIR)/drivers/fsl_gpio.c \ + $(MCU_DIR)/drivers/fsl_lpsci.c + +INC += \ + $(TOP)/hw/bsp/$(BOARD) \ + $(TOP)/$(MCU_DIR)/../../CMSIS/Include \ + $(TOP)/$(MCU_DIR) \ + $(TOP)/$(MCU_DIR)/drivers \ + $(TOP)/$(MCU_DIR)/project_template \ + +SRC_S += $(MCU_DIR)/gcc/startup_MKL25Z4.S + +# For TinyUSB port source +VENDOR = nxp +CHIP_FAMILY = khci + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM0 + +# For flash-jlink target +JLINK_DEVICE = MKL25Z128xxx4 + +# For flash-pyocd target +PYOCD_TARGET = mkl25zl128 + +# flash using pyocd +flash: flash-pyocd diff --git a/hw/bsp/frdm_kl25z/frdm_kl25z.c b/hw/bsp/frdm_kl25z/frdm_kl25z.c new file mode 100644 index 000000000..7d3a173ed --- /dev/null +++ b/hw/bsp/frdm_kl25z/frdm_kl25z.c @@ -0,0 +1,148 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018, hathach (tinyusb.org) + * Copyright (c) 2020, Koji Kitayama + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "../board.h" +#include "fsl_device_registers.h" +#include "fsl_gpio.h" +#include "fsl_port.h" +#include "fsl_clock.h" +#include "fsl_lpsci.h" + +#include "clock_config.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB0_IRQHandler(void) +{ + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ +// LED +#define LED_PINMUX IOMUXC_GPIO_AD_B0_09_GPIO1_IO09 +#define LED_PORT GPIOB +#define LED_PIN_CLOCK kCLOCK_PortB +#define LED_PIN_PORT PORTB +#define LED_PIN 19U +#define LED_PIN_FUNCTION kPORT_MuxAsGpio +#define LED_STATE_ON 0 + +// UART +#define UART_PORT UART0 +#define UART_PIN_CLOCK kCLOCK_PortA +#define UART_PIN_PORT PORTA +#define UART_PIN_RX 1u +#define UART_PIN_TX 2u +#define UART_PIN_FUNCTION kPORT_MuxAlt2 +#define SOPT5_UART0RXSRC_UART_RX 0x00u /*!< UART0 receive data source select: UART0_RX pin */ +#define SOPT5_UART0TXSRC_UART_TX 0x00u /*!< UART0 transmit data source select: UART0_TX pin */ + +const uint8_t dcd_data[] = { 0x00 }; + +void board_init(void) +{ + BOARD_BootClockRUN(); + SystemCoreClockUpdate(); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + // LED + CLOCK_EnableClock(LED_PIN_CLOCK); + PORT_SetPinMux(LED_PIN_PORT, LED_PIN, LED_PIN_FUNCTION); + gpio_pin_config_t led_config = { kGPIO_DigitalOutput, 0 }; + GPIO_PinInit(LED_PORT, LED_PIN, &led_config); + board_led_write(true); + + // UART + CLOCK_EnableClock(UART_PIN_CLOCK); + PORT_SetPinMux(UART_PIN_PORT, UART_PIN_RX, UART_PIN_FUNCTION); + PORT_SetPinMux(UART_PIN_PORT, UART_PIN_TX, UART_PIN_FUNCTION); + SIM->SOPT5 = ((SIM->SOPT5 & + (~(SIM_SOPT5_UART0TXSRC_MASK | SIM_SOPT5_UART0RXSRC_MASK))) + | SIM_SOPT5_UART0TXSRC(SOPT5_UART0TXSRC_UART_TX) + | SIM_SOPT5_UART0RXSRC(SOPT5_UART0RXSRC_UART_RX) + ); + + lpsci_config_t uart_config; + CLOCK_SetLpsci0Clock(1); + LPSCI_GetDefaultConfig(&uart_config); + uart_config.baudRate_Bps = CFG_BOARD_UART_BAUDRATE; + uart_config.enableTx = true; + uart_config.enableRx = true; + LPSCI_Init(UART_PORT, &uart_config, CLOCK_GetPllFllSelClkFreq()); + + // USB + CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcPll0, CLOCK_GetFreq(kCLOCK_PllFllSelClk)); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + GPIO_WritePinOutput(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +} + +uint32_t board_button_read(void) +{ + return 0; +} + +int board_uart_read(uint8_t* buf, int len) +{ + LPSCI_ReadBlocking(UART_PORT, buf, len); + return len; +} + +int board_uart_write(void const * buf, int len) +{ + LPSCI_WriteBlocking(UART_PORT, (uint8_t*)buf, len); + return len; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler(void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c new file mode 100644 index 000000000..aab847b82 --- /dev/null +++ b/src/portable/nxp/khci/dcd_khci.c @@ -0,0 +1,459 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Koji Kitayama + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX ) + +#include "fsl_device_registers.h" +#define KHCI USB0 + +#include "device/dcd.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +enum { + TOK_PID_OUT = 0x1u, + TOK_PID_IN = 0x9u, + TOK_PID_SETUP = 0xDu, +}; + +typedef struct TU_ATTR_PACKED +{ + union { + uint32_t head; + struct { + union { + uint16_t ctl; + struct { + uint16_t zeros : 2; + uint16_t tok_pid : 4; + uint16_t data : 1; + uint16_t own : 1; + uint16_t rsvd0 : 8; + }; + struct { + uint16_t dmy0 : 2; + uint16_t bdt_stall: 1; + uint16_t dts : 1; + uint16_t ninc : 1; + uint16_t keep : 1; + uint16_t dmy1 : 10; + }; + }; + uint16_t bc : 10; + uint16_t rsvd1 : 6; + }; + }; + uint8_t *addr; +}buffer_descriptor_t; + +TU_VERIFY_STATIC( sizeof(buffer_descriptor_t) == 8, "size is not correct" ); + +typedef struct TU_ATTR_PACKED +{ + union { + uint32_t state; + struct { + uint32_t max_packet_size: 11; + uint32_t reserved0 : 5; + uint32_t odd : 1; + uint32_t reserved1 :15; + }; + }; + uint16_t length; + uint16_t remaining; +}endpoint_state_t; + +TU_VERIFY_STATIC( sizeof(endpoint_state_t) == 8, "size is not correct" ); + +typedef struct +{ + union { + /* [#EP][OUT,IN][EVEN,ODD] */ + buffer_descriptor_t bdt[16][2][2]; + uint16_t bda[512]; + }; + TU_ATTR_ALIGNED(4) union { + endpoint_state_t endpoint[16][2]; + endpoint_state_t endpoint_unified[16 * 2]; + }; + uint8_t setup_packet[8]; + uint8_t addr; +}dcd_data_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +// BDT(Buffer Descriptor Table) must be 256-byte aligned +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(512) static dcd_data_t _dcd; + +TU_VERIFY_STATIC( sizeof(_dcd.bdt) == 512, "size is not correct" ); + +static void prepare_next_setup_packet(uint8_t rhport) +{ + const unsigned out_odd = _dcd.endpoint[0][0].odd; + const unsigned in_odd = _dcd.endpoint[0][1].odd; + if (_dcd.bdt[0][0][out_odd].own) { + TU_LOG1("DCD fail to prepare the next SETUP %d %d\r\n", out_odd, in_odd); + return; + } + _dcd.bdt[0][0][out_odd].data = 0; + _dcd.bdt[0][0][out_odd ^ 1].data = 1; + _dcd.bdt[0][1][in_odd].data = 1; + _dcd.bdt[0][1][in_odd ^ 1].data = 0; + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), + _dcd.setup_packet, sizeof(_dcd.setup_packet)); +} + +static void process_stall(uint8_t rhport) +{ + if (KHCI->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK) { + /* clear stall condition of the control pipe */ + prepare_next_setup_packet(rhport); + KHCI->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; + KHCI->ENDPOINT[1].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; + } +} + +static void process_tokdne(uint8_t rhport) +{ + const unsigned s = KHCI->STAT; + KHCI->ISTAT = USB_ISTAT_TOKDNE_MASK; /* fetch the next token if received */ + buffer_descriptor_t *bd = (buffer_descriptor_t *)&_dcd.bda[s]; + endpoint_state_t *ep = &_dcd.endpoint_unified[s >> 3]; + unsigned odd = (s & USB_STAT_ODD_MASK) ? 1 : 0; + + /* fetch pid before discarded by the next steps */ + const unsigned pid = bd->tok_pid; + /* reset values for a next transfer */ + bd->bdt_stall = 0; + bd->dts = 1; + bd->ninc = 0; + bd->keep = 0; + /* update the odd variable to prepare for the next transfer */ + ep->odd = odd ^ 1; + if (pid == TOK_PID_SETUP) { + dcd_event_setup_received(rhport, bd->addr, true); + KHCI->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; + return; + } + + const unsigned bc = bd->bc; + const unsigned remaining = ep->remaining - bc; + if (remaining && bc == ep->max_packet_size) { + /* continue the transferring consecutive data */ + ep->remaining = remaining; + const int next_remaining = remaining - ep->max_packet_size; + if (next_remaining > 0) { + /* prepare to the after next transfer */ + bd->addr += ep->max_packet_size * 2; + bd->bc = next_remaining > ep->max_packet_size ? ep->max_packet_size: next_remaining; + __DSB(); + bd->own = 1; /* the own bit must set after addr */ + } + return; + } + const unsigned length = ep->length; + dcd_event_xfer_complete(rhport, + ((s & USB_STAT_TX_MASK) << 4) | (s >> USB_STAT_ENDP_SHIFT), + length - remaining, XFER_RESULT_SUCCESS, true); + if (0 == (s & USB_STAT_ENDP_MASK) && 0 == length) { + /* After completion a ZLP of control transfer, + * it prepares for the next steup transfer. */ + if (_dcd.addr) { + /* When the transfer was the SetAddress, + * the device address should be updated here. */ + KHCI->ADDR = _dcd.addr; + _dcd.addr = 0; + } + prepare_next_setup_packet(rhport); + } +} + +static void process_bus_reset(uint8_t rhport) +{ + KHCI->USBCTRL &= ~USB_USBCTRL_SUSP_MASK; + KHCI->CTL |= USB_CTL_ODDRST_MASK; + KHCI->ADDR = 0; + KHCI->INTEN = (KHCI->INTEN & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; + + KHCI->ENDPOINT[0].ENDPT = USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPRXEN_MASK | USB_ENDPT_EPTXEN_MASK; + for (unsigned i = 1; i < 16; ++i) { + KHCI->ENDPOINT[i].ENDPT = 0; + } + buffer_descriptor_t *bd = _dcd.bdt[0][0]; + for (unsigned i = 0; i < sizeof(_dcd.bdt)/sizeof(*bd); ++i, ++bd) { + bd->head = 0; + } + const endpoint_state_t ep0 = { + .max_packet_size = CFG_TUD_ENDPOINT0_SIZE, + .odd = 0, + .length = 0, + .remaining = 0, + }; + _dcd.endpoint[0][0] = ep0; + _dcd.endpoint[0][1] = ep0; + tu_memclr(_dcd.endpoint[1], sizeof(_dcd.endpoint) - sizeof(_dcd.endpoint[0])); + _dcd.addr = 0; + prepare_next_setup_packet(rhport); + KHCI->CTL &= ~USB_CTL_ODDRST_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); +} + +static void process_bus_inactive(uint8_t rhport) +{ + (void) rhport; + const unsigned inten = KHCI->INTEN; + KHCI->INTEN = (inten & ~USB_INTEN_SLEEPEN_MASK) | USB_INTEN_RESUMEEN_MASK; + KHCI->USBCTRL |= USB_USBCTRL_SUSP_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); +} + +static void process_bus_active(uint8_t rhport) +{ + (void) rhport; + KHCI->USBCTRL &= ~USB_USBCTRL_SUSP_MASK; + const unsigned inten = KHCI->INTEN; + KHCI->INTEN = (inten & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); +} + +/*------------------------------------------------------------------*/ +/* Device API + *------------------------------------------------------------------*/ +void dcd_init(uint8_t rhport) +{ + (void) rhport; + + KHCI->USBTRC0 |= USB_USBTRC0_USBRESET_MASK; + while (KHCI->USBTRC0 & USB_USBTRC0_USBRESET_MASK); + tu_memclr(&_dcd, sizeof(_dcd)); + KHCI->USBTRC0 |= TU_BIT(6); /* software must set this bit to 1 */ + KHCI->BDTPAGE1 = (uint8_t)((uintptr_t)_dcd.bdt >> 8); + KHCI->BDTPAGE2 = (uint8_t)((uintptr_t)_dcd.bdt >> 16); + KHCI->BDTPAGE3 = (uint8_t)((uintptr_t)_dcd.bdt >> 24); + + dcd_connect(rhport); + NVIC_ClearPendingIRQ(USB0_IRQn); +} + +void dcd_int_enable(uint8_t rhport) +{ + (void) rhport; + KHCI->INTEN = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK | + USB_INTEN_SLEEPEN_MASK | USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK; + NVIC_EnableIRQ(USB0_IRQn); +} + +void dcd_int_disable(uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ(USB0_IRQn); + KHCI->INTEN = 0; +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void) rhport; + _dcd.addr = dev_addr & 0x7F; + /* Response with status first before changing device address */ + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; + unsigned cnt = SystemCoreClock / 100; + KHCI->CTL |= USB_CTL_RESUME_MASK; + while (cnt--) __NOP(); + KHCI->CTL &= ~USB_CTL_RESUME_MASK; +} + +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + KHCI->USBCTRL = 0; + KHCI->CONTROL |= USB_CONTROL_DPPULLUPNONOTG_MASK; + KHCI->CTL |= USB_CTL_USBENSOFEN_MASK; +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + KHCI->CTL = 0; + KHCI->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK; +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) +{ + (void) rhport; + + const unsigned ep_addr = ep_desc->bEndpointAddress; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = ep_addr & TUSB_DIR_IN_MASK ? 1 : 0; + const unsigned xfer = ep_desc->bmAttributes.xfer; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + const unsigned odd = ep->odd; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; + + /* No support for control transfer */ + TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL)); + + ep->max_packet_size = ep_desc->wMaxPacketSize.size; + unsigned val = USB_ENDPT_EPCTLDIS_MASK; + val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0; + val |= dir ? USB_ENDPT_EPRXEN_MASK : USB_ENDPT_EPTXEN_MASK; + KHCI->ENDPOINT[epn].ENDPT |= val; + + if (xfer != TUSB_XFER_ISOCHRONOUS) { + bd[odd].dts = 1; + bd[odd].data = 0; + bd[odd ^ 1].dts = 1; + bd[odd ^ 1].data = 1; + } + return true; +} + +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = ep_addr & TUSB_DIR_IN_MASK ? 1 : 0; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; + + KHCI->ENDPOINT[epn].ENDPT = 0; + ep->max_packet_size = 0; + ep->length = 0; + ep->remaining = 0; + bd->head = 0; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +{ + (void) rhport; + NVIC_DisableIRQ(USB0_IRQn); + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][ep->odd]; + + if (bd->own) { + TU_LOG1("DCD XFER fail %x %d %lx %lx\r\n", ep_addr, total_bytes, ep->state, bd->head); + return false; /* The last transfer has not completed */ + } + ep->length = total_bytes; + ep->remaining = total_bytes; + + const unsigned mps = ep->max_packet_size; + if (total_bytes > mps) { + buffer_descriptor_t *next = ep->odd ? bd - 1: bd + 1; + /* When total_bytes is greater than the max packet size, + * it prepares to the next transfer to avoid NAK in advance. */ + next->bc = total_bytes >= 2 * mps ? mps: total_bytes - mps; + next->addr = buffer + mps; + next->own = 1; + } + bd->bc = total_bytes >= mps ? mps: total_bytes; + bd->addr = buffer; + __DSB(); + bd->own = 1; /* the own bit must set after addr */ + NVIC_EnableIRQ(USB0_IRQn); + return true; +} + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + const unsigned epn = ep_addr & 0xFu; + KHCI->ENDPOINT[epn].ENDPT |= USB_ENDPT_EPSTALL_MASK; +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + const unsigned epn = ep_addr & 0xFu; + KHCI->ENDPOINT[epn].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; +} + +//--------------------------------------------------------------------+ +// ISR +//--------------------------------------------------------------------+ +void dcd_int_handler(uint8_t rhport) +{ + (void) rhport; + + uint32_t is = KHCI->ISTAT; + uint32_t msk = KHCI->INTEN; + KHCI->ISTAT = is & ~msk; + is &= msk; + if (is & USB_ISTAT_ERROR_MASK) { + /* TODO: */ + uint32_t es = KHCI->ERRSTAT; + KHCI->ERRSTAT = es; + KHCI->ISTAT = is; /* discard any pending events */ + return; + } + + if (is & USB_ISTAT_USBRST_MASK) { + KHCI->ISTAT = is; /* discard any pending events */ + process_bus_reset(rhport); + return; + } + if (is & USB_ISTAT_SLEEP_MASK) { + KHCI->ISTAT = USB_ISTAT_SLEEP_MASK; + process_bus_inactive(rhport); + return; + } + if (is & USB_ISTAT_RESUME_MASK) { + KHCI->ISTAT = USB_ISTAT_RESUME_MASK; + process_bus_active(rhport); + return; + } + if (is & USB_ISTAT_SOFTOK_MASK) { + KHCI->ISTAT = USB_ISTAT_SOFTOK_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); + return; + } + if (is & USB_ISTAT_STALL_MASK) { + KHCI->ISTAT = USB_ISTAT_STALL_MASK; + process_stall(rhport); + return; + } + if (is & USB_ISTAT_TOKDNE_MASK) { + process_tokdne(rhport); + return; + } +} + +#endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 2dd2b5841..71ea7692b 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -97,6 +97,10 @@ // Dialog #define OPT_MCU_DA1469X 1000 ///< Dialog Semiconductor DA1469x +// NXP Kinetis +#define OPT_MCU_MKL25ZXX 1100 ///< NXP MKL25Zxx + + /** @} */ /** \defgroup group_supported_os Supported RTOS -- cgit v1.3.1 From 13e6afd5897ab018047fdc8e4c34f4b782ee5118 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 20 Dec 2020 22:54:55 +0100 Subject: Fix scsi_mode_sense6_t padding, which cause IAR compiler internal error. Signed-off-by: HiFiPhile --- src/class/msc/msc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/msc/msc.h b/src/class/msc/msc.h index cba8066b7..0bdc00692 100644 --- a/src/class/msc/msc.h +++ b/src/class/msc/msc.h @@ -255,7 +255,7 @@ typedef struct TU_ATTR_PACKED uint8_t : 3; uint8_t disable_block_descriptor : 1; - uint8_t : 0; + uint8_t : 4; uint8_t page_code : 6; uint8_t page_control : 2; -- cgit v1.3.1 From b3c0d417ef2b2d2ff3d00b7cdf623436ec7abf97 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 20 Dec 2020 23:06:32 +0100 Subject: Fix error if "Required Prototype" is selected. Signed-off-by: HiFiPhile --- src/class/msc/msc_device.c | 348 +++++++++++++++++++++++---------------------- src/common/tusb_compiler.h | 1 + src/device/usbd_control.c | 8 ++ 3 files changed, 184 insertions(+), 173 deletions(-) (limited to 'src') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index a4ea5f6fb..194f4d3cb 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -71,6 +71,7 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_EP_ //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ +static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize); static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc); static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc); @@ -223,179 +224,6 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t return true; } -// return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) -// In case of a failed status, sense key must be set for reason of failure -int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) -{ - (void) bufsize; // TODO refractor later - int32_t resplen; - - switch ( scsi_cmd[0] ) - { - case SCSI_CMD_TEST_UNIT_READY: - resplen = 0; - if ( !tud_msc_test_unit_ready_cb(lun) ) - { - // Failed status response - resplen = - 1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - } - break; - - case SCSI_CMD_START_STOP_UNIT: - resplen = 0; - - if (tud_msc_start_stop_cb) - { - scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; - if ( !tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject) ) - { - // Failed status response - resplen = - 1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - } - } - break; - - case SCSI_CMD_READ_CAPACITY_10: - { - uint32_t block_count; - uint32_t block_size; - uint16_t block_size_u16; - - tud_msc_capacity_cb(lun, &block_count, &block_size_u16); - block_size = (uint32_t) block_size_u16; - - // Invalid block size/count from callback, possibly unit is not ready - // stall this request, set sense key to NOT READY - if (block_count == 0 || block_size == 0) - { - resplen = -1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - }else - { - scsi_read_capacity10_resp_t read_capa10; - - read_capa10.last_lba = tu_htonl(block_count-1); - read_capa10.block_size = tu_htonl(block_size); - - resplen = sizeof(read_capa10); - memcpy(buffer, &read_capa10, resplen); - } - } - break; - - case SCSI_CMD_READ_FORMAT_CAPACITY: - { - scsi_read_format_capacity_data_t read_fmt_capa = - { - .list_length = 8, - .block_num = 0, - .descriptor_type = 2, // formatted media - .block_size_u16 = 0 - }; - - uint32_t block_count; - uint16_t block_size; - - tud_msc_capacity_cb(lun, &block_count, &block_size); - - // Invalid block size/count from callback, possibly unit is not ready - // stall this request, set sense key to NOT READY - if (block_count == 0 || block_size == 0) - { - resplen = -1; - - // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable - if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); - }else - { - read_fmt_capa.block_num = tu_htonl(block_count); - read_fmt_capa.block_size_u16 = tu_htons(block_size); - - resplen = sizeof(read_fmt_capa); - memcpy(buffer, &read_fmt_capa, resplen); - } - } - break; - - case SCSI_CMD_INQUIRY: - { - scsi_inquiry_resp_t inquiry_rsp = - { - .is_removable = 1, - .version = 2, - .response_data_format = 2, - }; - - // vendor_id, product_id, product_rev is space padded string - memset(inquiry_rsp.vendor_id , ' ', sizeof(inquiry_rsp.vendor_id)); - memset(inquiry_rsp.product_id , ' ', sizeof(inquiry_rsp.product_id)); - memset(inquiry_rsp.product_rev, ' ', sizeof(inquiry_rsp.product_rev)); - - tud_msc_inquiry_cb(lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev); - - resplen = sizeof(inquiry_rsp); - memcpy(buffer, &inquiry_rsp, resplen); - } - break; - - case SCSI_CMD_MODE_SENSE_6: - { - scsi_mode_sense6_resp_t mode_resp = - { - .data_len = 3, - .medium_type = 0, - .write_protected = false, - .reserved = 0, - .block_descriptor_len = 0 // no block descriptor are included - }; - - bool writable = true; - if (tud_msc_is_writable_cb) { - writable = tud_msc_is_writable_cb(lun); - } - mode_resp.write_protected = !writable; - - resplen = sizeof(mode_resp); - memcpy(buffer, &mode_resp, resplen); - } - break; - - case SCSI_CMD_REQUEST_SENSE: - { - scsi_sense_fixed_resp_t sense_rsp = - { - .response_code = 0x70, - .valid = 1 - }; - - sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8; - - sense_rsp.sense_key = _mscd_itf.sense_key; - sense_rsp.add_sense_code = _mscd_itf.add_sense_code; - sense_rsp.add_sense_qualifier = _mscd_itf.add_sense_qualifier; - - resplen = sizeof(sense_rsp); - memcpy(buffer, &sense_rsp, resplen); - - // Clear sense data after copy - tud_msc_set_sense(lun, 0, 0, 0); - } - break; - - default: resplen = -1; break; - } - - return resplen; -} - bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { mscd_interface_t* p_msc = &_mscd_itf; @@ -640,6 +468,180 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t /*------------------------------------------------------------------*/ /* SCSI Command Process *------------------------------------------------------------------*/ + +// return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) +// In case of a failed status, sense key must be set for reason of failure +static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) +{ + (void) bufsize; // TODO refractor later + int32_t resplen; + + switch ( scsi_cmd[0] ) + { + case SCSI_CMD_TEST_UNIT_READY: + resplen = 0; + if ( !tud_msc_test_unit_ready_cb(lun) ) + { + // Failed status response + resplen = - 1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + } + break; + + case SCSI_CMD_START_STOP_UNIT: + resplen = 0; + + if (tud_msc_start_stop_cb) + { + scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; + if ( !tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject) ) + { + // Failed status response + resplen = - 1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + } + } + break; + + case SCSI_CMD_READ_CAPACITY_10: + { + uint32_t block_count; + uint32_t block_size; + uint16_t block_size_u16; + + tud_msc_capacity_cb(lun, &block_count, &block_size_u16); + block_size = (uint32_t) block_size_u16; + + // Invalid block size/count from callback, possibly unit is not ready + // stall this request, set sense key to NOT READY + if (block_count == 0 || block_size == 0) + { + resplen = -1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + }else + { + scsi_read_capacity10_resp_t read_capa10; + + read_capa10.last_lba = tu_htonl(block_count-1); + read_capa10.block_size = tu_htonl(block_size); + + resplen = sizeof(read_capa10); + memcpy(buffer, &read_capa10, resplen); + } + } + break; + + case SCSI_CMD_READ_FORMAT_CAPACITY: + { + scsi_read_format_capacity_data_t read_fmt_capa = + { + .list_length = 8, + .block_num = 0, + .descriptor_type = 2, // formatted media + .block_size_u16 = 0 + }; + + uint32_t block_count; + uint16_t block_size; + + tud_msc_capacity_cb(lun, &block_count, &block_size); + + // Invalid block size/count from callback, possibly unit is not ready + // stall this request, set sense key to NOT READY + if (block_count == 0 || block_size == 0) + { + resplen = -1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + }else + { + read_fmt_capa.block_num = tu_htonl(block_count); + read_fmt_capa.block_size_u16 = tu_htons(block_size); + + resplen = sizeof(read_fmt_capa); + memcpy(buffer, &read_fmt_capa, resplen); + } + } + break; + + case SCSI_CMD_INQUIRY: + { + scsi_inquiry_resp_t inquiry_rsp = + { + .is_removable = 1, + .version = 2, + .response_data_format = 2, + }; + + // vendor_id, product_id, product_rev is space padded string + memset(inquiry_rsp.vendor_id , ' ', sizeof(inquiry_rsp.vendor_id)); + memset(inquiry_rsp.product_id , ' ', sizeof(inquiry_rsp.product_id)); + memset(inquiry_rsp.product_rev, ' ', sizeof(inquiry_rsp.product_rev)); + + tud_msc_inquiry_cb(lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev); + + resplen = sizeof(inquiry_rsp); + memcpy(buffer, &inquiry_rsp, resplen); + } + break; + + case SCSI_CMD_MODE_SENSE_6: + { + scsi_mode_sense6_resp_t mode_resp = + { + .data_len = 3, + .medium_type = 0, + .write_protected = false, + .reserved = 0, + .block_descriptor_len = 0 // no block descriptor are included + }; + + bool writable = true; + if (tud_msc_is_writable_cb) { + writable = tud_msc_is_writable_cb(lun); + } + mode_resp.write_protected = !writable; + + resplen = sizeof(mode_resp); + memcpy(buffer, &mode_resp, resplen); + } + break; + + case SCSI_CMD_REQUEST_SENSE: + { + scsi_sense_fixed_resp_t sense_rsp = + { + .response_code = 0x70, + .valid = 1 + }; + + sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8; + + sense_rsp.sense_key = _mscd_itf.sense_key; + sense_rsp.add_sense_code = _mscd_itf.add_sense_code; + sense_rsp.add_sense_qualifier = _mscd_itf.add_sense_qualifier; + + resplen = sizeof(sense_rsp); + memcpy(buffer, &sense_rsp, resplen); + + // Clear sense data after copy + tud_msc_set_sense(lun, 0, 0, 0); + } + break; + + default: resplen = -1; break; + } + + return resplen; +} + static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) { msc_cbw_t const * p_cbw = &p_msc->cbw; diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 505542078..22c8366ab 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -102,6 +102,7 @@ #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) #elif defined(__ICCARM__) + #include #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) #define TU_ATTR_PACKED __attribute__ ((packed)) diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index bb631320a..8ed0ad1c0 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -140,6 +140,14 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo // USBD API //--------------------------------------------------------------------+ +//--------------------------------------------------------------------+ +// Prototypes +//--------------------------------------------------------------------+ +void usbd_control_reset(void); +void usbd_control_set_request(tusb_control_request_t const *request); +void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); +bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + void usbd_control_reset(void) { tu_varclr(&_ctrl_xfer); -- cgit v1.3.1 From c8dc7f807f5f954a0f1ed12b15454018559115cc Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 18 Dec 2020 11:48:48 +0100 Subject: Fix more warnings. Signed-off-by: HiFiPhile --- src/device/usbd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 4ecc2a2f9..791d533ae 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -517,7 +517,7 @@ void tud_task (void) TU_ASSERT(driver, ); TU_LOG2(" %s xfer callback\r\n", driver->name); - driver->xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len); } } break; @@ -933,6 +933,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const break; case TUSB_DESC_STRING: + { TU_LOG2(" String[%u]\r\n", desc_index); // String Descriptor always uses the desc set from user @@ -941,6 +942,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // first byte of descriptor is its size return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]); + } break; case TUSB_DESC_DEVICE_QUALIFIER: -- cgit v1.3.1 From bdee6397ebf87ba83043fec15ca03e3542deb7a3 Mon Sep 17 00:00:00 2001 From: Yakovenko Andrey Date: Wed, 23 Dec 2020 12:52:51 +0200 Subject: Added MSC read10 and write10 function --- src/class/msc/msc_host.c | 93 ++++++++++++++++++++++++------------------------ src/class/msc/msc_host.h | 22 ++++-------- 2 files changed, 53 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 02ca81e77..9ba41d944 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -192,60 +192,59 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_ms return tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb); } -#if 0 - -tusb_error_t tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) +bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msch = &msch_data[dev_addr-1]; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - - p_msch->cbw.total_bytes = p_msch->block_size*block_count; // Number of bytes - p_msch->cbw.dir = TUSB_DIR_IN_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_read10_t); + msch_interface_t* p_msc = get_itf(dev_addr); + if ( !p_msc->mounted ){ return false;}; - //------------- SCSI command -------------// - scsi_read10_t cmd_read10 =msch_sem_hdl + msc_cbw_t cbw = { 0 }; + + //------------- Command Block Wrapper -------------// + msc_cbw_add_signature(&cbw, lun); + + cbw.total_bytes = 512*block_count; // Number of bytes + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_read10_t); + + //------------- SCSI command -------------// + scsi_read10_t cmd_read10 = { - .cmd_code = SCSI_CMD_READ_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) + .cmd_code = SCSI_CMD_READ_10, + .lba = tu_htonl(lba), + .block_count = tu_htons(block_count) }; - - memcpy(p_msch->cbw.command, &cmd_read10, p_msch->cbw.cmd_len); - - TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, p_buffer)); - - return TUSB_ERROR_NONE; + + memcpy(cbw.command, &cmd_read10, cbw.cmd_len); + + return tuh_msc_scsi_command(dev_addr, &cbw, p_buffer, complete_cb); } - -tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count) + +bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msch = &msch_data[dev_addr-1]; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - - p_msch->cbw.total_bytes = p_msch->block_size*block_count; // Number of bytes - p_msch->cbw.dir = TUSB_DIR_OUT; - p_msch->cbw.cmd_len = sizeof(scsi_write10_t); - - //------------- SCSI command -------------// - scsi_write10_t cmd_write10 = - { - .cmd_code = SCSI_CMD_WRITE_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) - }; - - memcpy(p_msch->cbw.command, &cmd_write10, p_msch->cbw.cmd_len); - - TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, (void*) p_buffer)); - - return TUSB_ERROR_NONE; + msch_interface_t* p_msc = get_itf(dev_addr); + if ( !p_msc->mounted ){ return false;}; + + msc_cbw_t cbw = { 0 }; + + //------------- Command Block Wrapper -------------// + msc_cbw_add_signature(&cbw, lun); + + cbw.total_bytes = 512*block_count; // Number of bytes + cbw.dir = TUSB_DIR_OUT; + cbw.cmd_len = sizeof(scsi_write10_t); + + //------------- SCSI command -------------// + scsi_write10_t cmd_write10 = + { + .cmd_code = SCSI_CMD_WRITE_10, + .lba = tu_htonl(lba), + .block_count = tu_htons(block_count) + }; + + memcpy(cbw.command, &cmd_write10, cbw.cmd_len); + + return tuh_msc_scsi_command(dev_addr, &cbw, p_buffer, complete_cb); } -#endif #if 0 // MSC interface Reset (not used now) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 5913350b8..016e4e21e 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -81,20 +81,16 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_ms // Carry out SCSI READ CAPACITY (10) command in non-blocking manner. bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); -#if 0 /** \brief Perform SCSI READ 10 command to read data from MassStorage device * \param[in] dev_addr device address * \param[in] lun Targeted Logical Unit - * \param[out] p_buffer Buffer used to store data read from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) + * \param[out] p_buffer Buffer used to store data read from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) * \param[in] lba Starting Logical Block Address to be read * \param[in] block_count Number of Block to be read - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function + * \retval true on success + * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by \ref complete_cb callback function */ -tusb_error_t tuh_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count); +bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); /** \brief Perform SCSI WRITE 10 command to write data to MassStorage device * \param[in] dev_addr device address @@ -102,14 +98,10 @@ tusb_error_t tuh_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uin * \param[in] p_buffer Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) * \param[in] lba Starting Logical Block Address to be written * \param[in] block_count Number of Block to be written - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function + * \retval true on success + * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by \ref complete_cb callback function */ -tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count); -#endif +bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); //------------- Application Callback -------------// -- cgit v1.3.1 From 2737166d2be7988dc3d52d34ceb7fcc6a177bd47 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Wed, 23 Dec 2020 20:32:29 +0900 Subject: fixed wrong direction to enable EP in dcd_edpt_open. fixed incorrect handling of STALL other than EP0 convert tabs to spaces removed unused symbols --- src/portable/nxp/khci/dcd_khci.c | 84 ++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c index aab847b82..8357bf2b8 100644 --- a/src/portable/nxp/khci/dcd_khci.c +++ b/src/portable/nxp/khci/dcd_khci.c @@ -49,25 +49,24 @@ typedef struct TU_ATTR_PACKED uint32_t head; struct { union { - uint16_t ctl; - struct { - uint16_t zeros : 2; - uint16_t tok_pid : 4; - uint16_t data : 1; - uint16_t own : 1; - uint16_t rsvd0 : 8; - }; - struct { - uint16_t dmy0 : 2; - uint16_t bdt_stall: 1; - uint16_t dts : 1; - uint16_t ninc : 1; - uint16_t keep : 1; - uint16_t dmy1 : 10; - }; + struct { + uint16_t : 2; + uint16_t tok_pid : 4; + uint16_t data : 1; + uint16_t own : 1; + uint16_t : 8; + }; + struct { + uint16_t : 2; + uint16_t bdt_stall: 1; + uint16_t dts : 1; + uint16_t ninc : 1; + uint16_t keep : 1; + uint16_t : 10; + }; }; uint16_t bc : 10; - uint16_t rsvd1 : 6; + uint16_t : 6; }; }; uint8_t *addr; @@ -80,10 +79,10 @@ typedef struct TU_ATTR_PACKED union { uint32_t state; struct { - uint32_t max_packet_size: 11; - uint32_t reserved0 : 5; + uint32_t max_packet_size :11; + uint32_t : 5; uint32_t odd : 1; - uint32_t reserved1 :15; + uint32_t :15; }; }; uint16_t length; @@ -128,7 +127,7 @@ static void prepare_next_setup_packet(uint8_t rhport) _dcd.bdt[0][1][in_odd].data = 1; _dcd.bdt[0][1][in_odd ^ 1].data = 0; dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), - _dcd.setup_packet, sizeof(_dcd.setup_packet)); + _dcd.setup_packet, sizeof(_dcd.setup_packet)); } static void process_stall(uint8_t rhport) @@ -137,7 +136,6 @@ static void process_stall(uint8_t rhport) /* clear stall condition of the control pipe */ prepare_next_setup_packet(rhport); KHCI->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; - KHCI->ENDPOINT[1].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; } } @@ -163,6 +161,9 @@ static void process_tokdne(uint8_t rhport) KHCI->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; return; } + if (s >> 4) { + TU_LOG1("TKDNE %x\r\n", s); + } const unsigned bc = bd->bc; const unsigned remaining = ep->remaining - bc; @@ -181,13 +182,13 @@ static void process_tokdne(uint8_t rhport) } const unsigned length = ep->length; dcd_event_xfer_complete(rhport, - ((s & USB_STAT_TX_MASK) << 4) | (s >> USB_STAT_ENDP_SHIFT), - length - remaining, XFER_RESULT_SUCCESS, true); + ((s & USB_STAT_TX_MASK) << 4) | (s >> USB_STAT_ENDP_SHIFT), + length - remaining, XFER_RESULT_SUCCESS, true); if (0 == (s & USB_STAT_ENDP_MASK) && 0 == length) { /* After completion a ZLP of control transfer, * it prepares for the next steup transfer. */ if (_dcd.addr) { - /* When the transfer was the SetAddress, + /* When the transfer was the SetAddress, * the device address should be updated here. */ KHCI->ADDR = _dcd.addr; _dcd.addr = 0; @@ -319,7 +320,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) const unsigned ep_addr = ep_desc->bEndpointAddress; const unsigned epn = ep_addr & 0xFu; - const unsigned dir = ep_addr & TUSB_DIR_IN_MASK ? 1 : 0; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; const unsigned xfer = ep_desc->bmAttributes.xfer; endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; const unsigned odd = ep->odd; @@ -331,7 +332,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) ep->max_packet_size = ep_desc->wMaxPacketSize.size; unsigned val = USB_ENDPT_EPCTLDIS_MASK; val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0; - val |= dir ? USB_ENDPT_EPRXEN_MASK : USB_ENDPT_EPTXEN_MASK; + val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; KHCI->ENDPOINT[epn].ENDPT |= val; if (xfer != TUSB_XFER_ISOCHRONOUS) { @@ -340,6 +341,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) bd[odd ^ 1].dts = 1; bd[odd ^ 1].data = 1; } + return true; } @@ -348,11 +350,11 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) (void) rhport; const unsigned epn = ep_addr & 0xFu; - const unsigned dir = ep_addr & TUSB_DIR_IN_MASK ? 1 : 0; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; - - KHCI->ENDPOINT[epn].ENDPT = 0; + const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; + KHCI->ENDPOINT[epn].ENDPT &= ~msk; ep->max_packet_size = 0; ep->length = 0; ep->remaining = 0; @@ -396,14 +398,30 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; const unsigned epn = ep_addr & 0xFu; - KHCI->ENDPOINT[epn].ENDPT |= USB_ENDPT_EPSTALL_MASK; + if (0 == epn) { + KHCI->ENDPOINT[epn].ENDPT |= USB_ENDPT_EPSTALL_MASK; + } else { + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; + bd[0].bdt_stall = 1; + bd[1].bdt_stall = 1; + } } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - const unsigned epn = ep_addr & 0xFu; - KHCI->ENDPOINT[epn].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned odd = _dcd.endpoint[epn][dir].odd; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; + + bd[odd ^ 1].own = 0; + bd[odd ^ 1].data = 1; + bd[odd ^ 1].bdt_stall = 0; + bd[odd].own = 0; + bd[odd].data = 0; + bd[odd].bdt_stall = 0; } //--------------------------------------------------------------------+ -- cgit v1.3.1 From baa5417f3eaf3f05f414c7d6ac31e08ac7b7977a Mon Sep 17 00:00:00 2001 From: HiFIPhile Date: Thu, 17 Dec 2020 22:20:56 +0100 Subject: Fix IAR error on memcpy and warnings. Signed-off-by: MasterPhi --- src/common/tusb_fifo.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 608bfd081..00f2434a7 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -30,6 +30,12 @@ #include "osal/osal.h" #include "tusb_fifo.h" +// Supress IAR warning +// Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement +#if defined(__ICCARM__) +#pragma diag_suppress = Pa082 +#endif + // implement mutex lock and unlock #if CFG_FIFO_MUTEX @@ -106,7 +112,7 @@ static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRe memcpy(f->buffer + (wRel * f->item_size), data, nLin*f->item_size); // Write data wrapped around - memcpy(f->buffer, data + nLin*f->item_size, (n - nLin) * f->item_size); + memcpy(f->buffer, ((uint8_t const*) data) + nLin*f->item_size, (n - nLin) * f->item_size); } } @@ -131,7 +137,7 @@ static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel) memcpy(p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size); // Read data wrapped part - memcpy(p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size); + memcpy((uint8_t*)p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size); } } -- cgit v1.3.1 From 56c47188d8955686f994e2809b8986bf45efd060 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 3 Jan 2021 16:11:56 +0100 Subject: Rework USB FIFO allocation scheme and allow RX FIFO size reduction --- src/portable/st/synopsys/dcd_synopsys.c | 160 ++++++++++++++++++++------------ 1 file changed, 99 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 35c814460..63b1dffa5 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -139,15 +139,6 @@ typedef struct { uint8_t interval; } xfer_ctl_t; -// EP size and transfer type report -typedef struct TU_ATTR_PACKED { - // The following format may look complicated but it is the most elegant way of addressing the required fields: EP number, EP direction, and EP transfer type. - // The codes assigned to those fields, according to the USB specification, can be neatly used as indices. - uint16_t ep_size[EP_MAX][2]; ///< dim 1: EP number, dim 2: EP direction denoted by TUSB_DIR_OUT (= 0) and TUSB_DIR_IN (= 1) - bool ep_transfer_type[EP_MAX][2][4]; ///< dim 1: EP number, dim 2: EP direction, dim 3: transfer type, where 0 = Control, 1 = Isochronous, 2 = Bulk, and 3 = Interrupt - ///< I know very well that EP0 can only be used as control EP and we waste space here but for the sake of simplicity we accept that. It is used in a non-persistent way anyway! -} ep_sz_tt_report_t; - typedef volatile uint32_t * usb_fifo_t; xfer_ctl_t xfer_status[EP_MAX][2]; @@ -156,8 +147,9 @@ xfer_ctl_t xfer_status[EP_MAX][2]; // EP0 transfers are limited to 1 packet - larger sizes has to be split static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type -// FIFO RAM allocation so far in words -static uint16_t _allocated_fifo_words; +// TX FIFO RAM allocation so far in words - RX FIFO size is readily available from usb_otg->GRXFSIZ +static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN EPs) +static bool _rx_ep_closed; // Setup the control endpoint 0. static void bus_reset(uint8_t rhport) @@ -170,6 +162,7 @@ static void bus_reset(uint8_t rhport) USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); tu_memclr(xfer_status, sizeof(xfer_status)); + _rx_ep_closed = false; for(uint8_t n = 0; n < EP_MAX; n++) { out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; @@ -182,16 +175,28 @@ static void bus_reset(uint8_t rhport) // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture // + // The FIFO is split up in a lower part where the RX FIFO is located and an upper part where the TX FIFOs start. + // We do this to allow the RX FIFO to grow dynamically which is possible since the free space is located + // between the RX and TX FIFOs. This is required by ISO OUT EPs which need a bigger FIFO than the standard + // configuration done below. + // + // Dynamically FIFO sizes are of interest only for ISO EPs since all others are usually not opened and closed. + // All EPs other than ISO are opened as soon as the driver starts up i.e. when the host sends a + // configure interface command. Hence, all IN EPs other the ISO will be located at the top. IN ISO EPs are usually + // opened when the host sends an additional command: setInterface. At this point in time + // the ISO EP will be located next to the free space and can change its size. In case more IN EPs change its size + // an additional memory + // // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO 0 | + // --------------- (320 or 1024) - 16 + // | IN FIFO 1 | + // --------------- (320 or 1024) - 16 - x + // | . . . . | + // --------------- (320 or 1024) - 16 - x - y - ... - z // | IN FIFO MAX | // --------------- - // | ... | - // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | - // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | + // | FREE | // --------------- GRXFSIZ // | OUT FIFO | // | ( Shared ) | @@ -213,24 +218,20 @@ static void bus_reset(uint8_t rhport) // NOTE: Largest-EPsize & EPOUTnum is actual used endpoints in configuration. Since DCD has no knowledge // of the overall picture yet. We will use the worst scenario: largest possible + EP_MAX // - // FIXME: for Isochronous, largest EP size can be 1023/1024 for FS/HS respectively. In addition if multiple ISO + // For Isochronous, largest EP size can be 1023/1024 for FS/HS respectively. In addition if multiple ISO // are enabled at least "2 x (Largest-EPsize/4) + 1" are recommended. Maybe provide a macro for application to // overwrite this. #if TUD_OPT_HIGH_SPEED - _allocated_fifo_words = 271 + 2*EP_MAX; + usb_otg->GRXFSIZ = 271 + 2*EP_MAX; #else - _allocated_fifo_words = 47 + 2*EP_MAX; + usb_otg->GRXFSIZ = 47 + 2*EP_MAX; #endif - usb_otg->GRXFSIZ = _allocated_fifo_words; + _allocated_fifo_words_tx += 16; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | _allocated_fifo_words; - - _allocated_fifo_words += 16; - - // TU_LOG2_INT(_allocated_fifo_words); + usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | (EP_FIFO_SIZE/4 - _allocated_fifo_words_tx); // Fixed control EP0 size to 64 bytes in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos); @@ -557,8 +558,22 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) xfer->max_size = desc_edpt->wMaxPacketSize.size; xfer->interval = desc_edpt->bInterval; + uint16_t const fifo_size = tu_max16((desc_edpt->wMaxPacketSize.size + 3) / 4, 16); // Round up to next full word, minimum value must be 16 + if(dir == TUSB_DIR_OUT) { + // Calculate required size of RX FIFO + uint16_t size_rx = 15 + 2*fifo_size + 2*EP_MAX; + + // If size_rx needs to be extended check if possible and if so enlarge it + if (usb_otg->GRXFSIZ < size_rx) + { + TU_ASSERT(size_rx + _allocated_fifo_words_tx <= EP_FIFO_SIZE/4); + + // Enlarge RX FIFO + usb_otg->GRXFSIZ = size_rx; + } + out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) | (desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos); @@ -570,16 +585,28 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture // + // The FIFO is split up in a lower part where the RX FIFO is located and an upper part where the TX FIFOs start. + // We do this to allow the RX FIFO to grow dynamically which is possible since the free space is located + // between the RX and TX FIFOs. This is required by ISO OUT EPs which need a bigger FIFO than the standard + // configuration done below. + // + // Dynamically FIFO sizes are of interest only for ISO EPs since all others are usually not opened and closed. + // All EPs other than ISO are opened as soon as the driver starts up i.e. when the host sends a + // configure interface command. Hence, all IN EPs other the ISO will be located at the top. IN ISO EPs are usually + // opened when the host sends an additional command: setInterface. At this point in time + // the ISO EP will be located next to the free space and can change its size. In case more IN EPs change its size + // an additional memory + // // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO 0 | + // --------------- (320 or 1024) - 16 + // | IN FIFO 1 | + // --------------- (320 or 1024) - 16 - x + // | . . . . | + // --------------- (320 or 1024) - 16 - x - y - ... - z // | IN FIFO MAX | // --------------- - // | ... | - // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | - // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | + // | FREE | // --------------- GRXFSIZ // | OUT FIFO | // | ( Shared ) | @@ -592,29 +619,14 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // - Interrupt is EPSize // - Bulk/ISO is max(EPSize, remaining-fifo / non-opened-EPIN) - uint16_t const fifo_remaining = EP_FIFO_SIZE/4 - _allocated_fifo_words; - uint16_t fifo_size = (desc_edpt->wMaxPacketSize.size + 3) / 4; // +3 for rounding up to next full word - - if ( desc_edpt->bmAttributes.xfer != TUSB_XFER_INTERRUPT ) - { - uint8_t opened = 0; - for(uint8_t i = 0; i < EP_MAX; i++) - { - if ( (i != epnum) && (xfer_status[i][TUSB_DIR_IN].max_size > 0) ) opened++; - } - - // EP Size or equally divided of remaining whichever is larger - fifo_size = tu_max16(fifo_size, fifo_remaining / (EP_MAX - opened)); - } + // Check if free space is available + TU_ASSERT(_allocated_fifo_words_tx + fifo_size + usb_otg->GRXFSIZ <= EP_FIFO_SIZE/4); - // FIFO overflows, we probably need a better allocating scheme - TU_ASSERT(fifo_size <= fifo_remaining); + _allocated_fifo_words_tx += fifo_size; // DIEPTXF starts at FIFO #1. // Both TXFD and TXSA are in unit of 32-bit words. - usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | _allocated_fifo_words; - - _allocated_fifo_words += fifo_size; + usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | (EP_FIFO_SIZE/4 - _allocated_fifo_words_tx); in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) | (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) | @@ -728,9 +740,17 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) { uint16_t const fifo_size = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXFD_Msk) >> USB_OTG_DIEPTXF_INEPTXFD_Pos; uint16_t const fifo_start = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXSA_Msk) >> USB_OTG_DIEPTXF_INEPTXSA_Pos; - // For now only endpoint that has FIFO at the end of FIFO memory can be closed without fuss. - TU_ASSERT(fifo_start + fifo_size == _allocated_fifo_words,); - _allocated_fifo_words -= fifo_size; + // For now only the last opened endpoint can be closed without fuss. + TU_ASSERT(fifo_start == EP_FIFO_SIZE/4 - _allocated_fifo_words_tx,); + _allocated_fifo_words_tx -= fifo_size; + } + else + { + // Update max_size + xfer_status[epnum][TUSB_DIR_OUT].max_size = 0; + + // Set flag such that RX FIFO gets reduced in size one RX FIFO is empty + _rx_ep_closed = true; } } @@ -884,6 +904,24 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ TU_BREAKPOINT(); break; } + + // If an OUT EP was closed update (reduce) the RX FIFO size if RX FIFO is empty - since this function handle_rxflvl_ints() gets looped from dcd_int_handler() until RX FIFO is empty it is guaranteed to be entered + if (_rx_ep_closed && (usb_otg->GINTSTS & USB_OTG_GINTSTS_RXFLVL)) + { + // Determine largest EP size for RX FIFO + uint16_t sz = xfer_status[0][TUSB_DIR_OUT].max_size; + + for (uint8_t cnt = 1; cnt < EP_MAX; cnt++) + { + if (sz < xfer_status[cnt][TUSB_DIR_OUT].max_size) sz = xfer_status[cnt][TUSB_DIR_OUT].max_size; + } + + // Update size of RX FIFO + usb_otg->GRXFSIZ = 15 + 2*sz/4 + 2*EP_MAX; // sz was in bytes and is now needed in words + + // Disable flag + _rx_ep_closed = false; + } } static void handle_epout_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTypeDef * out_ep) { @@ -1063,11 +1101,11 @@ void dcd_int_handler(uint8_t rhport) handle_epin_ints(rhport, dev, in_ep); } -// // Check for Incomplete isochronous IN transfer -// if(int_status & USB_OTG_GINTSTS_IISOIXFR) { -// printf(" IISOIXFR!\r\n"); -//// TU_LOG2(" IISOIXFR!\r\n"); -// } + // // Check for Incomplete isochronous IN transfer + // if(int_status & USB_OTG_GINTSTS_IISOIXFR) { + // printf(" IISOIXFR!\r\n"); + //// TU_LOG2(" IISOIXFR!\r\n"); + // } } #endif -- cgit v1.3.1 From 13b499f910d3a80886a4fd4cb20fb0b0bd46d3da Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 3 Jan 2021 17:59:50 +0100 Subject: Clean up --- src/portable/st/synopsys/dcd_synopsys.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 63b1dffa5..2ff1c2688 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -145,11 +145,11 @@ xfer_ctl_t xfer_status[EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] // EP0 transfers are limited to 1 packet - larger sizes has to be split -static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type +static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type // TX FIFO RAM allocation so far in words - RX FIFO size is readily available from usb_otg->GRXFSIZ static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN EPs) -static bool _rx_ep_closed; +static bool _rx_ep_closed; // Flag to check if RX FIFO size needs an update (reduce its size) // Setup the control endpoint 0. static void bus_reset(uint8_t rhport) @@ -563,15 +563,15 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) if(dir == TUSB_DIR_OUT) { // Calculate required size of RX FIFO - uint16_t size_rx = 15 + 2*fifo_size + 2*EP_MAX; + uint16_t const sz = 15 + 2*fifo_size + 2*EP_MAX; // If size_rx needs to be extended check if possible and if so enlarge it - if (usb_otg->GRXFSIZ < size_rx) + if (usb_otg->GRXFSIZ < sz) { - TU_ASSERT(size_rx + _allocated_fifo_words_tx <= EP_FIFO_SIZE/4); + TU_ASSERT(sz + _allocated_fifo_words_tx <= EP_FIFO_SIZE/4); // Enlarge RX FIFO - usb_otg->GRXFSIZ = size_rx; + usb_otg->GRXFSIZ = sz; } out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) | @@ -736,6 +736,10 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) uint8_t const dir = tu_edpt_dir(ep_addr); dcd_edpt_disable(rhport, ep_addr, false); + + // Update max_size + xfer_status[epnum][dir].max_size = 0; // max_size = 0 marks a disabled EP - required for changing FIFO allocation + if (dir == TUSB_DIR_IN) { uint16_t const fifo_size = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXFD_Msk) >> USB_OTG_DIEPTXF_INEPTXFD_Pos; @@ -746,11 +750,7 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) } else { - // Update max_size - xfer_status[epnum][TUSB_DIR_OUT].max_size = 0; - - // Set flag such that RX FIFO gets reduced in size one RX FIFO is empty - _rx_ep_closed = true; + _rx_ep_closed = true; // Set flag such that RX FIFO gets reduced in size once RX FIFO is empty } } -- cgit v1.3.1 From 09d8ead4b86049260dd6ee7e61d137b6bdccaa28 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 4 Jan 2021 12:02:08 +0100 Subject: Start changes - not yet finished --- src/device/usbd.c | 29 ++++++++++++++++++++++++ src/device/usbd_pvt.h | 3 +++ src/portable/st/synopsys/dcd_synopsys.c | 39 +++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 791d533ae..55e76bb66 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1188,6 +1188,35 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } +bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes); + + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); + + // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return + // and usbd task can preempt and clear the busy + _usbd_dev.ep_status[epnum][dir].busy = true; + + if ( dcd_edpt_ISO_xfer(rhport, ep_addr, ff, total_bytes) ) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + // DCD error, mark endpoint as ready to allow next transfer + _usbd_dev.ep_status[epnum][dir].busy = false; + _usbd_dev.ep_status[epnum][dir].claimed = 0; + TU_LOG2("failed\r\n"); + TU_BREAKPOINT(); + return false; + } +} + bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) { (void) rhport; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 212c3a202..de2f37281 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -72,6 +72,9 @@ 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); +// Submit a usb ISO transfer by use of a FIFO (ring buffer) +bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); + // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr); diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 35c814460..0aee6a919 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -28,6 +28,7 @@ */ #include "tusb_option.h" +#include "tusb_fifo.h" // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) // We disable SOF for now until needed later on @@ -134,6 +135,7 @@ static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2]; typedef struct { uint8_t * buffer; + tu_fifo_t * ff; uint16_t total_len; uint16_t max_size; uint8_t interval; @@ -659,6 +661,38 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } +bool dcd_edpt_ISO_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = NULL; // Indicates a FIFO shall be used + xfer->ff = ff; + xfer->total_len = total_bytes; + + // EP0 can only handle one packet + if(epnum == 0) { + ep0_pending[dir] = total_bytes; + // Schedule the first transaction for EP0 transfer + edpt_schedule_packets(rhport, epnum, dir, 1, ep0_pending[dir]); + return true; + } + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint8_t const short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if(short_packet_size > 0 || (total_bytes == 0)) { + num_packets++; + } + + // Schedule packets to be sent within interrupt + edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); + + return true; +} + static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall) { (void) rhport; @@ -849,6 +883,9 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ { xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + + // TODO: TAKE CARE OF ISO FIFO! + // Read packet off RxFIFO read_fifo_packet(rhport, xfer->buffer, bcnt); @@ -960,6 +997,8 @@ static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OT break; } + // TODO: TAKE CARE OF ISO FIFO! + // Push packet to Tx-FIFO write_fifo_packet(rhport, n, xfer->buffer, packet_size); -- cgit v1.3.1 From 37bb14678a2d3fc03b75527f223f3b16b8756fc3 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 4 Jan 2021 12:06:16 +0100 Subject: Remove too verbose comment --- src/portable/st/synopsys/dcd_synopsys.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 2ff1c2688..60d2fd604 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -585,18 +585,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // "USB Data FIFOs" section in reference manual // Peripheral FIFO architecture // - // The FIFO is split up in a lower part where the RX FIFO is located and an upper part where the TX FIFOs start. - // We do this to allow the RX FIFO to grow dynamically which is possible since the free space is located - // between the RX and TX FIFOs. This is required by ISO OUT EPs which need a bigger FIFO than the standard - // configuration done below. - // - // Dynamically FIFO sizes are of interest only for ISO EPs since all others are usually not opened and closed. - // All EPs other than ISO are opened as soon as the driver starts up i.e. when the host sends a - // configure interface command. Hence, all IN EPs other the ISO will be located at the top. IN ISO EPs are usually - // opened when the host sends an additional command: setInterface. At this point in time - // the ISO EP will be located next to the free space and can change its size. In case more IN EPs change its size - // an additional memory - // // --------------- 320 or 1024 ( 1280 or 4096 bytes ) // | IN FIFO 0 | // --------------- (320 or 1024) - 16 -- cgit v1.3.1 From 2fa500af1822e4d2d882b7b5455cfd0860aa42a5 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 4 Jan 2021 17:00:23 +0100 Subject: Minor corrections for PR - externerlize code into functions - correct comments --- src/portable/st/synopsys/dcd_synopsys.c | 63 +++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 60d2fd604..7250cf188 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -151,6 +151,36 @@ static uint16_t ep0_pending[2]; // Index determines direction static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN EPs) static bool _rx_ep_closed; // Flag to check if RX FIFO size needs an update (reduce its size) +// Calculate the RX FIFO size according to recommendations from reference manual +// ep_size in words +static inline uint16_t calc_rx_ff_size(uint16_t ep_size) +{ + return 15 + 2*ep_size + 2*EP_MAX; +} + +static inline void update_grxfsiz() +{ + // If an OUT EP was closed update (reduce) the RX FIFO size if RX FIFO is empty - since this function handle_rxflvl_ints() gets looped from dcd_int_handler() until RX FIFO is empty it is guaranteed to be entered + if (_rx_ep_closed) + { + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); + + // Determine largest EP size for RX FIFO + uint16_t sz = xfer_status[0][TUSB_DIR_OUT].max_size; + + for (uint8_t cnt = 1; cnt < EP_MAX; cnt++) + { + if (sz < xfer_status[cnt][TUSB_DIR_OUT].max_size) sz = xfer_status[cnt][TUSB_DIR_OUT].max_size; + } + + // Update size of RX FIFO + usb_otg->GRXFSIZ = calc_rx_ff_size(sz/4); // sz was in bytes and is now needed in words + + // Disable flag + _rx_ep_closed = false; + } +} + // Setup the control endpoint 0. static void bus_reset(uint8_t rhport) { @@ -223,12 +253,12 @@ static void bus_reset(uint8_t rhport) // overwrite this. #if TUD_OPT_HIGH_SPEED - usb_otg->GRXFSIZ = 271 + 2*EP_MAX; + usb_otg->GRXFSIZ = calc_rx_ff_size(128); #else - usb_otg->GRXFSIZ = 47 + 2*EP_MAX; + usb_otg->GRXFSIZ = calc_rx_ff_size(16); #endif - _allocated_fifo_words_tx += 16; + _allocated_fifo_words_tx = 16; // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | (EP_FIFO_SIZE/4 - _allocated_fifo_words_tx); @@ -563,7 +593,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) if(dir == TUSB_DIR_OUT) { // Calculate required size of RX FIFO - uint16_t const sz = 15 + 2*fifo_size + 2*EP_MAX; + uint16_t const sz = calc_rx_ff_size(fifo_size); // If size_rx needs to be extended check if possible and if so enlarge it if (usb_otg->GRXFSIZ < sz) @@ -602,10 +632,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) // // In FIFO is allocated by following rules: // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". - // - Offset: allocated so far - // - Size - // - Interrupt is EPSize - // - Bulk/ISO is max(EPSize, remaining-fifo / non-opened-EPIN) // Check if free space is available TU_ASSERT(_allocated_fifo_words_tx + fifo_size + usb_otg->GRXFSIZ <= EP_FIFO_SIZE/4); @@ -892,24 +918,6 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ TU_BREAKPOINT(); break; } - - // If an OUT EP was closed update (reduce) the RX FIFO size if RX FIFO is empty - since this function handle_rxflvl_ints() gets looped from dcd_int_handler() until RX FIFO is empty it is guaranteed to be entered - if (_rx_ep_closed && (usb_otg->GINTSTS & USB_OTG_GINTSTS_RXFLVL)) - { - // Determine largest EP size for RX FIFO - uint16_t sz = xfer_status[0][TUSB_DIR_OUT].max_size; - - for (uint8_t cnt = 1; cnt < EP_MAX; cnt++) - { - if (sz < xfer_status[cnt][TUSB_DIR_OUT].max_size) sz = xfer_status[cnt][TUSB_DIR_OUT].max_size; - } - - // Update size of RX FIFO - usb_otg->GRXFSIZ = 15 + 2*sz/4 + 2*EP_MAX; // sz was in bytes and is now needed in words - - // Disable flag - _rx_ep_closed = false; - } } static void handle_epout_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTypeDef * out_ep) { @@ -1074,6 +1082,9 @@ void dcd_int_handler(uint8_t rhport) int_status = usb_otg->GINTSTS; } while(int_status & USB_OTG_GINTSTS_RXFLVL); + // Manage RX FIFO size + update_grxfsiz(); + usb_otg->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; } -- cgit v1.3.1 From f2b4567a2b16c9e8f1af8278a9db8675d58947e2 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 4 Jan 2021 17:15:42 +0100 Subject: Correct function declaration --- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 7250cf188..32be1f2df 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -158,7 +158,7 @@ static inline uint16_t calc_rx_ff_size(uint16_t ep_size) return 15 + 2*ep_size + 2*EP_MAX; } -static inline void update_grxfsiz() +static inline void update_grxfsiz(void) { // If an OUT EP was closed update (reduce) the RX FIFO size if RX FIFO is empty - since this function handle_rxflvl_ints() gets looped from dcd_int_handler() until RX FIFO is empty it is guaranteed to be entered if (_rx_ep_closed) -- cgit v1.3.1 From 29f84b16022f9e1162dac959e65e6f7cbe2d5072 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 7 Jan 2021 11:58:05 +0700 Subject: change default CFG_TUD_HID_EP_BUFSIZE from 16 to 64 --- src/class/hid/hid_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 2d4c59d8f..456b011ba 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -46,7 +46,7 @@ #endif #ifndef CFG_TUD_HID_EP_BUFSIZE - #define CFG_TUD_HID_EP_BUFSIZE 16 + #define CFG_TUD_HID_EP_BUFSIZE 64 #endif //--------------------------------------------------------------------+ -- cgit v1.3.1 From 60620dca4286fc9ce9ddf4c2f2e6a39c062a5056 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 Jan 2021 01:21:03 +0700 Subject: walkround for samd21 setup_packet overflow increase setup packet size from 8 to 12, since USB DMA controller is suspected to overflow the buffer with 2 extra bytes --- src/portable/microchip/samd/dcd_samd.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index f1dca88a5..35fac23a8 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -37,14 +37,20 @@ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ static TU_ATTR_ALIGNED(4) UsbDeviceDescBank sram_registers[8][2]; -static TU_ATTR_ALIGNED(4) uint8_t _setup_packet[8]; + +// Setup packet is only 8 bytes in length. However under certain scenario, +// SAMD21 USB DMA controller is "suspected" to overwrite/overflow the setup_packet with 2 extra bytes. +// Which corrupt other variable and cause issue such as +// https://github.com/adafruit/circuitpython/issues/3912 (on macOS) +// Therefore we increase it to 12 bytes as walk-around until figuring out the root cause +static TU_ATTR_ALIGNED(4) uint8_t _setup_packet[8+4]; // ready for receiving SETUP packet static inline void prepare_setup(void) { // Only make sure the EP0 OUT buffer is ready sram_registers[0][0].ADDR.reg = (uint32_t) _setup_packet; - sram_registers[0][0].PCKSIZE.bit.MULTI_PACKET_SIZE = sizeof(_setup_packet); + sram_registers[0][0].PCKSIZE.bit.MULTI_PACKET_SIZE = sizeof(tusb_control_request_t); sram_registers[0][0].PCKSIZE.bit.BYTE_COUNT = 0; } -- cgit v1.3.1 From cc5dfd03cd64b1faad7374f6207cb80837134c89 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 Jan 2021 11:21:26 +0700 Subject: update comment and correct the size to 8+2 --- src/portable/microchip/samd/dcd_samd.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 35fac23a8..4806342cc 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -39,11 +39,14 @@ static TU_ATTR_ALIGNED(4) UsbDeviceDescBank sram_registers[8][2]; // Setup packet is only 8 bytes in length. However under certain scenario, -// SAMD21 USB DMA controller is "suspected" to overwrite/overflow the setup_packet with 2 extra bytes. -// Which corrupt other variable and cause issue such as -// https://github.com/adafruit/circuitpython/issues/3912 (on macOS) -// Therefore we increase it to 12 bytes as walk-around until figuring out the root cause -static TU_ATTR_ALIGNED(4) uint8_t _setup_packet[8+4]; +// USB DMA controller may decide to overwrite/overflow the buffer with +// 2 extra bytes of CRC. From datasheet's "Management of SETUP Transactions" section +// If the number of received data bytes is the maximum data payload specified by +// PCKSIZE.SIZE minus one, only the first CRC data is written to the data buffer. +// If the number of received data is equal or less than the data payload specified +// by PCKSIZE.SIZE minus two, both CRC data bytes are written to the data buffer. +// Therefore we will increase it to 10 bytes just to be safe +static TU_ATTR_ALIGNED(4) uint8_t _setup_packet[8+2]; // ready for receiving SETUP packet static inline void prepare_setup(void) -- cgit v1.3.1 From 3e1d85eed25c384cc9fe6e7e16fbfbdc491c5536 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 Jan 2021 11:43:26 +0700 Subject: comment clean up --- src/portable/microchip/samd/dcd_samd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 4806342cc..68a15672a 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -45,7 +45,7 @@ static TU_ATTR_ALIGNED(4) UsbDeviceDescBank sram_registers[8][2]; // PCKSIZE.SIZE minus one, only the first CRC data is written to the data buffer. // If the number of received data is equal or less than the data payload specified // by PCKSIZE.SIZE minus two, both CRC data bytes are written to the data buffer. -// Therefore we will increase it to 10 bytes just to be safe +// Therefore we will need to increase it to 10 bytes here. static TU_ATTR_ALIGNED(4) uint8_t _setup_packet[8+2]; // ready for receiving SETUP packet -- cgit v1.3.1 From 86c34a9a33d84eca95363f36f9ee9269d6586e3e Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 Jan 2021 16:25:30 +0700 Subject: minor clean up following pr581 --- src/portable/st/synopsys/dcd_synopsys.c | 82 +++++++++++++++++---------------- src/tusb_option.h | 12 ++--- 2 files changed, 49 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 32be1f2df..a054621a9 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -45,13 +45,13 @@ #define STM32L4_SYNOPSYS #endif -#if TUSB_OPT_DEVICE_ENABLED && \ +#if TUSB_OPT_DEVICE_ENABLED && \ ( (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_SYNOPSYS)) || \ - CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ - CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ - (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \ + CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ + CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ + (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \ ) // EP_MAX : Max number of bi-directional endpoints including EP0 @@ -115,6 +115,7 @@ #define EP_FIFO_SIZE EP_FIFO_SIZE_HS #define RHPORT_REGS_BASE USB_OTG_HS_PERIPH_BASE #define RHPORT_IRQn OTG_HS_IRQn + #endif #define GLOBAL_BASE(_port) ((USB_OTG_GlobalTypeDef*) RHPORT_REGS_BASE) @@ -152,33 +153,27 @@ static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN E static bool _rx_ep_closed; // Flag to check if RX FIFO size needs an update (reduce its size) // Calculate the RX FIFO size according to recommendations from reference manual -// ep_size in words static inline uint16_t calc_rx_ff_size(uint16_t ep_size) { - return 15 + 2*ep_size + 2*EP_MAX; + return 15 + 2*(ep_size/4) + 2*EP_MAX; } -static inline void update_grxfsiz(void) +static inline void update_grxfsiz(uint8_t rhport) { - // If an OUT EP was closed update (reduce) the RX FIFO size if RX FIFO is empty - since this function handle_rxflvl_ints() gets looped from dcd_int_handler() until RX FIFO is empty it is guaranteed to be entered - if (_rx_ep_closed) - { - USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); - - // Determine largest EP size for RX FIFO - uint16_t sz = xfer_status[0][TUSB_DIR_OUT].max_size; + (void) rhport; - for (uint8_t cnt = 1; cnt < EP_MAX; cnt++) - { - if (sz < xfer_status[cnt][TUSB_DIR_OUT].max_size) sz = xfer_status[cnt][TUSB_DIR_OUT].max_size; - } + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); - // Update size of RX FIFO - usb_otg->GRXFSIZ = calc_rx_ff_size(sz/4); // sz was in bytes and is now needed in words + // Determine largest EP size for RX FIFO + uint16_t sz = xfer_status[0][TUSB_DIR_OUT].max_size; - // Disable flag - _rx_ep_closed = false; + for (uint8_t cnt = 1; cnt < EP_MAX; cnt++) + { + if (sz < xfer_status[cnt][TUSB_DIR_OUT].max_size) sz = xfer_status[cnt][TUSB_DIR_OUT].max_size; } + + // Update size of RX FIFO + usb_otg->GRXFSIZ = calc_rx_ff_size(sz); } // Setup the control endpoint 0. @@ -252,11 +247,7 @@ static void bus_reset(uint8_t rhport) // are enabled at least "2 x (Largest-EPsize/4) + 1" are recommended. Maybe provide a macro for application to // overwrite this. -#if TUD_OPT_HIGH_SPEED - usb_otg->GRXFSIZ = calc_rx_ff_size(128); -#else - usb_otg->GRXFSIZ = calc_rx_ff_size(16); -#endif + usb_otg->GRXFSIZ = calc_rx_ff_size(TUD_OPT_HIGH_SPEED ? 512 : 64); _allocated_fifo_words_tx = 16; @@ -588,12 +579,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) xfer->max_size = desc_edpt->wMaxPacketSize.size; xfer->interval = desc_edpt->bInterval; - uint16_t const fifo_size = tu_max16((desc_edpt->wMaxPacketSize.size + 3) / 4, 16); // Round up to next full word, minimum value must be 16 + uint16_t const fifo_size = (desc_edpt->wMaxPacketSize.size + 3) / 4; // Round up to next full word if(dir == TUSB_DIR_OUT) { // Calculate required size of RX FIFO - uint16_t const sz = calc_rx_ff_size(fifo_size); + uint16_t const sz = calc_rx_ff_size(4*fifo_size); // If size_rx needs to be extended check if possible and if so enlarge it if (usb_otg->GRXFSIZ < sz) @@ -1020,13 +1011,15 @@ void dcd_int_handler(uint8_t rhport) uint32_t int_status = usb_otg->GINTSTS; - if(int_status & USB_OTG_GINTSTS_USBRST) { + if(int_status & USB_OTG_GINTSTS_USBRST) + { // USBRST is start of reset. usb_otg->GINTSTS = USB_OTG_GINTSTS_USBRST; bus_reset(rhport); } - if(int_status & USB_OTG_GINTSTS_ENUMDNE) { + if(int_status & USB_OTG_GINTSTS_ENUMDNE) + { // ENUMDNE is the end of reset where speed of the link is detected usb_otg->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; @@ -1063,39 +1056,50 @@ void dcd_int_handler(uint8_t rhport) } #if USE_SOF - if(int_status & USB_OTG_GINTSTS_SOF) { + if(int_status & USB_OTG_GINTSTS_SOF) + { usb_otg->GINTSTS = USB_OTG_GINTSTS_SOF; dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); } #endif // RxFIFO non-empty interrupt handling. - if(int_status & USB_OTG_GINTSTS_RXFLVL) { + if(int_status & USB_OTG_GINTSTS_RXFLVL) + { // RXFLVL bit is read-only // Mask out RXFLVL while reading data from FIFO usb_otg->GINTMSK &= ~USB_OTG_GINTMSK_RXFLVLM; // Loop until all available packets were handled - do { + do + { handle_rxflvl_ints(rhport, out_ep); int_status = usb_otg->GINTSTS; } while(int_status & USB_OTG_GINTSTS_RXFLVL); // Manage RX FIFO size - update_grxfsiz(); + if (_rx_ep_closed) + { + update_grxfsiz(rhport); + + // Disable flag + _rx_ep_closed = false; + } usb_otg->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; } // OUT endpoint interrupt handling. - if(int_status & USB_OTG_GINTSTS_OEPINT) { + if(int_status & USB_OTG_GINTSTS_OEPINT) + { // OEPINT is read-only handle_epout_ints(rhport, dev, out_ep); } // IN endpoint interrupt handling. - if(int_status & USB_OTG_GINTSTS_IEPINT) { + if(int_status & USB_OTG_GINTSTS_IEPINT) + { // IEPINT bit read-only handle_epin_ints(rhport, dev, in_ep); } diff --git a/src/tusb_option.h b/src/tusb_option.h index 71ea7692b..65a06bfa7 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -151,22 +151,22 @@ #define CFG_TUSB_RHPORT1_MODE OPT_MODE_NONE #endif -#if ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST ) && (CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST )) || \ - ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE) && (CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE)) +#if (((CFG_TUSB_RHPORT0_MODE) & OPT_MODE_HOST ) && ((CFG_TUSB_RHPORT1_MODE) & OPT_MODE_HOST )) || \ + (((CFG_TUSB_RHPORT0_MODE) & OPT_MODE_DEVICE) && ((CFG_TUSB_RHPORT1_MODE) & OPT_MODE_DEVICE)) #error "TinyUSB currently does not support same modes on more than 1 roothub port" #endif // Which roothub port is configured as host -#define TUH_OPT_RHPORT ( (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST) ? 0 : ((CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST) ? 1 : -1) ) +#define TUH_OPT_RHPORT ( ((CFG_TUSB_RHPORT0_MODE) & OPT_MODE_HOST) ? 0 : (((CFG_TUSB_RHPORT1_MODE) & OPT_MODE_HOST) ? 1 : -1) ) #define TUSB_OPT_HOST_ENABLED ( TUH_OPT_RHPORT >= 0 ) // Which roothub port is configured as device -#define TUD_OPT_RHPORT ( (CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE) ? 0 : ((CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE) ? 1 : -1) ) +#define TUD_OPT_RHPORT ( ((CFG_TUSB_RHPORT0_MODE) & OPT_MODE_DEVICE) ? 0 : (((CFG_TUSB_RHPORT1_MODE) & OPT_MODE_DEVICE) ? 1 : -1) ) #if TUD_OPT_RHPORT == 0 -#define TUD_OPT_HIGH_SPEED ( CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED ) +#define TUD_OPT_HIGH_SPEED ( (CFG_TUSB_RHPORT0_MODE) & OPT_MODE_HIGH_SPEED ) #else -#define TUD_OPT_HIGH_SPEED ( CFG_TUSB_RHPORT1_MODE & OPT_MODE_HIGH_SPEED ) +#define TUD_OPT_HIGH_SPEED ( (CFG_TUSB_RHPORT1_MODE) & OPT_MODE_HIGH_SPEED ) #endif #define TUSB_OPT_DEVICE_ENABLED ( TUD_OPT_RHPORT >= 0 ) -- cgit v1.3.1 From 9998e8a665cb3b14901ec9993a486f74c95d5475 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 Jan 2021 16:34:36 +0700 Subject: more minor work --- src/portable/st/synopsys/dcd_synopsys.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index a054621a9..fd845c8f4 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -150,7 +150,7 @@ static uint16_t ep0_pending[2]; // Index determines direction // TX FIFO RAM allocation so far in words - RX FIFO size is readily available from usb_otg->GRXFSIZ static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN EPs) -static bool _rx_ep_closed; // Flag to check if RX FIFO size needs an update (reduce its size) +static bool _out_ep_closed; // Flag to check if RX FIFO size needs an update (reduce its size) // Calculate the RX FIFO size according to recommendations from reference manual static inline uint16_t calc_rx_ff_size(uint16_t ep_size) @@ -165,11 +165,10 @@ static inline void update_grxfsiz(uint8_t rhport) USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); // Determine largest EP size for RX FIFO - uint16_t sz = xfer_status[0][TUSB_DIR_OUT].max_size; - - for (uint8_t cnt = 1; cnt < EP_MAX; cnt++) + uint16_t sz = 0; + for (uint8_t epnum = 0; epnum < EP_MAX; epnum++) { - if (sz < xfer_status[cnt][TUSB_DIR_OUT].max_size) sz = xfer_status[cnt][TUSB_DIR_OUT].max_size; + sz = tu_max16(sz, xfer_status[epnum][TUSB_DIR_OUT].max_size); } // Update size of RX FIFO @@ -187,7 +186,7 @@ static void bus_reset(uint8_t rhport) USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport); tu_memclr(xfer_status, sizeof(xfer_status)); - _rx_ep_closed = false; + _out_ep_closed = false; for(uint8_t n = 0; n < EP_MAX; n++) { out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; @@ -755,7 +754,7 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) } else { - _rx_ep_closed = true; // Set flag such that RX FIFO gets reduced in size once RX FIFO is empty + _out_ep_closed = true; // Set flag such that RX FIFO gets reduced in size once RX FIFO is empty } } @@ -1079,12 +1078,12 @@ void dcd_int_handler(uint8_t rhport) } while(int_status & USB_OTG_GINTSTS_RXFLVL); // Manage RX FIFO size - if (_rx_ep_closed) + if (_out_ep_closed) { update_grxfsiz(rhport); // Disable flag - _rx_ep_closed = false; + _out_ep_closed = false; } usb_otg->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; -- cgit v1.3.1 From 201ea7ca6d9634c8187c5f58938f27c4dbe33564 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 Jan 2021 16:38:41 +0700 Subject: remove inline for update_grxfsiz --- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index fd845c8f4..f00df5d55 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -158,7 +158,7 @@ static inline uint16_t calc_rx_ff_size(uint16_t ep_size) return 15 + 2*(ep_size/4) + 2*EP_MAX; } -static inline void update_grxfsiz(uint8_t rhport) +static void update_grxfsiz(uint8_t rhport) { (void) rhport; -- cgit v1.3.1 From cca27fc383a1caebf4f50c2aa27076422249aa3f Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 Jan 2021 16:54:50 +0700 Subject: another rename --- src/portable/st/synopsys/dcd_synopsys.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index f00df5d55..227c9ee61 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -165,14 +165,14 @@ static void update_grxfsiz(uint8_t rhport) USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); // Determine largest EP size for RX FIFO - uint16_t sz = 0; + uint16_t max_epsize = 0; for (uint8_t epnum = 0; epnum < EP_MAX; epnum++) { - sz = tu_max16(sz, xfer_status[epnum][TUSB_DIR_OUT].max_size); + max_epsize = tu_max16(max_epsize, xfer_status[epnum][TUSB_DIR_OUT].max_size); } // Update size of RX FIFO - usb_otg->GRXFSIZ = calc_rx_ff_size(sz); + usb_otg->GRXFSIZ = calc_rx_ff_size(max_epsize); } // Setup the control endpoint 0. -- cgit v1.3.1 From 6e6e6265e4feb797ddbd835dc1bee865d04219e6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 Jan 2021 22:34:36 +0700 Subject: use dcd_event_bus_reset() with speed to replace bus_signal --- src/device/usbd.c | 18 ++++++++++++++++++ src/portable/dialog/da146xx/dcd_da146xx.c | 7 +++---- src/portable/espressif/esp32s2/dcd_esp32s2.c | 1 - src/portable/microchip/samd/dcd_samd.c | 2 +- src/portable/microchip/samg/dcd_samg.c | 2 +- src/portable/nordic/nrf5x/dcd_nrf5x.c | 2 +- src/portable/nuvoton/nuc120/dcd_nuc120.c | 3 +-- src/portable/nuvoton/nuc121/dcd_nuc121.c | 2 +- src/portable/nxp/khci/dcd_khci.c | 2 +- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 2 +- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 4 ++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 9 --------- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 6 +++--- src/portable/valentyusb/eptri/dcd_eptri.c | 2 +- test/test/device/msc/test_msc_device.c | 2 +- test/test/support/tusb_config.h | 6 +++--- 17 files changed, 39 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 791d533ae..f6b00563d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1103,6 +1103,24 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); + if (TUSB_XFER_ISOCHRONOUS == desc_ep->bmAttributes.xfer) + { + TU_ASSERT(desc_ep->wMaxPacketSize.size <= (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023)); + } + else + { + uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 512 : 64); + + if (TUSB_XFER_BULK == desc_ep->bmAttributes.xfer) + { + // Bulk must be EXACTLY 512/64 bytes + TU_ASSERT(desc_ep->wMaxPacketSize.size == max_epsize); + }else + { + TU_ASSERT(desc_ep->wMaxPacketSize.size <= max_epsize); + } + } + return dcd_edpt_open(rhport, desc_ep); } diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 42ba867d7..59f728d08 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -664,7 +664,7 @@ static void handle_bus_reset(void) (void)USB->USB_ALTEV_REG; _dcd.in_reset = true; - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); USB->USB_DMA_CTRL_REG = 0; USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk | @@ -821,14 +821,13 @@ void dcd_disconnect(uint8_t rhport) bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { + (void)rhport; + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); uint8_t iso_mask = 0; - - (void)rhport; - TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 1023); TU_ASSERT(epnum < EP_MAX); xfer->max_packet_size = desc_edpt->wMaxPacketSize.size; diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index cd66af805..703841759 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -252,7 +252,6 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 64); TU_ASSERT(epnum < EP_MAX); xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 68a15672a..3cff92fcd 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -387,7 +387,7 @@ void dcd_int_handler (uint8_t rhport) USB->DEVICE.INTENCLR.reg = USB_DEVICE_INTFLAG_WAKEUP | USB_DEVICE_INTFLAG_SUSPEND; bus_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); } // Handle SETUP packet diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 2b64df50b..2f9f1097f 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -338,7 +338,7 @@ void dcd_int_handler(uint8_t rhport) if (intr_status & UDP_ISR_ENDBUSRES_Msk) { bus_reset(); - dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); } // SOF diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index b85d3776f..d9fe2b6ae 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -533,7 +533,7 @@ void dcd_int_handler(uint8_t rhport) if ( int_status & USBD_INTEN_USBRESET_Msk ) { bus_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); } // ISOIN: Data was moved to endpoint buffer, client will be notified in SOF diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 1a0007d8a..dc48e54cc 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -329,8 +329,7 @@ void dcd_int_handler(uint8_t rhport) USBD->ATTR |= USBD_ATTR_USB_EN_Msk | USBD_ATTR_PHY_EN_Msk; bus_reset(); - - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); } if(state & USBD_STATE_SUSPEND) diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index af7fee8b0..c9ead6de0 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -340,7 +340,7 @@ void dcd_int_handler(uint8_t rhport) bus_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); } if(state & USBD_ATTR_SUSPEND_Msk) diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c index 8357bf2b8..519b8fb7b 100644 --- a/src/portable/nxp/khci/dcd_khci.c +++ b/src/portable/nxp/khci/dcd_khci.c @@ -224,7 +224,7 @@ static void process_bus_reset(uint8_t rhport) _dcd.addr = 0; prepare_next_setup_packet(rhport); KHCI->CTL &= ~USB_CTL_ODDRST_MASK; - dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); } static void process_bus_inactive(uint8_t rhport) diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 39c5e6638..7d867aaba 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -471,7 +471,7 @@ static void bus_event_isr(uint8_t rhport) if (dev_status & SIE_DEV_STATUS_RESET_MASK) { bus_reset(); - dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); } if (dev_status & SIE_DEV_STATUS_CONNECT_CHANGE_MASK) diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 3d1420c65..e4d92458c 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -243,7 +243,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) (void) rhport; // TODO not support ISO yet - if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) return false; + TU_VERIFY(p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); //------------- Prepare Queue Head -------------// uint8_t ep_id = ep_addr2id(p_endpoint_desc->bEndpointAddress); @@ -357,7 +357,7 @@ void dcd_int_handler(uint8_t rhport) if ( cmd_stat & CMDSTAT_RESET_CHANGE_MASK) // bus reset { bus_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); } if (cmd_stat & CMDSTAT_CONNECT_CHANGE_MASK) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index dc125a758..18f0bc8e1 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -547,7 +547,7 @@ void dcd_int_handler(uint8_t rhport) { // USBRST is start of reset. clear_istr_bits(USB_ISTR_RESET); dcd_handle_bus_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); return; // Don't do the rest of the things here; perhaps they've been cleared? } diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 227c9ee61..4e385f691 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -565,15 +565,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) TU_ASSERT(epnum < EP_MAX); - if (desc_edpt->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) - { - TU_ASSERT(desc_edpt->wMaxPacketSize.size <= (get_speed(rhport) == TUSB_SPEED_HIGH ? 1024 : 1023)); - } - else - { - TU_ASSERT(desc_edpt->wMaxPacketSize.size <= (get_speed(rhport) == TUSB_SPEED_HIGH ? 512 : 64)); - } - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = desc_edpt->wMaxPacketSize.size; xfer->interval = desc_edpt->bInterval; diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index ad71e1168..e08c3536a 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -232,9 +232,9 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - // Unsupported endpoint numbers/size or type (Iso not supported. Control + // Unsupported endpoint numbers or type (Iso not supported. Control // not supported on nonzero endpoints). - if((desc_edpt->wMaxPacketSize.size > 64) || (epnum > 7) || \ + if( (epnum > 7) || \ (desc_edpt->bmAttributes.xfer == 0) || \ (desc_edpt->bmAttributes.xfer == 1)) { return false; @@ -572,7 +572,7 @@ void dcd_int_handler(uint8_t rhport) { case USBVECINT_RSTR: bus_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); break; // Clear the (hardware-enforced) NAK on EP 0 after a SETUP packet diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index d670dd38e..b68f04faa 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -332,7 +332,7 @@ static void dcd_reset(void) usb_out_ev_enable_write(1); usb_setup_ev_enable_write(3); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); } // Initializes the USB peripheral for device mode and enables it. diff --git a/test/test/device/msc/test_msc_device.c b/test/test/device/msc/test_msc_device.c index a01ef153a..00bb86ccf 100644 --- a/test/test/device/msc/test_msc_device.c +++ b/test/test/device/msc/test_msc_device.c @@ -202,7 +202,7 @@ void setUp(void) tusb_init(); } - dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, false); + dcd_event_bus_reset(rhport, TUSB_SPEED_HIGH, false); tud_task(); } diff --git a/test/test/support/tusb_config.h b/test/test/support/tusb_config.h index 8cd99eaae..d80e144da 100644 --- a/test/test/support/tusb_config.h +++ b/test/test/support/tusb_config.h @@ -86,8 +86,8 @@ //------------- CDC -------------// // FIFO size of CDC TX and RX -#define CFG_TUD_CDC_RX_BUFSIZE 64 -#define CFG_TUD_CDC_TX_BUFSIZE 64 +#define CFG_TUD_CDC_RX_BUFSIZE 512 +#define CFG_TUD_CDC_TX_BUFSIZE 512 //------------- MSC -------------// @@ -97,7 +97,7 @@ //------------- HID -------------// // Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_EP_BUFSIZE 16 +#define CFG_TUD_HID_EP_BUFSIZE 64 #ifdef __cplusplus } -- cgit v1.3.1 From d33b22d1275683cd352f3d8b729e20e6836c1ea4 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 Jan 2021 22:48:52 +0700 Subject: fix ci --- src/portable/st/synopsys/dcd_synopsys.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 4e385f691..548438b68 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -555,6 +555,8 @@ void dcd_disconnect(uint8_t rhport) bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { + (void) rhport; + USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport); -- cgit v1.3.1 From bdbcb8df394a14ac077e5210772cff91c1f76d25 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 17 Jan 2021 11:55:33 +0100 Subject: Add tu_fifo_read_n_into_other_fifo() to copy into from FIFO into another Fix overflow in tu_fifo_write_n() --- src/common/tusb_fifo.c | 163 +++++++++++++++++++++++++++++++++++++++++++------ src/common/tusb_fifo.h | 6 +- 2 files changed, 148 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 00f2434a7..a1cf0e289 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -179,7 +179,7 @@ static uint16_t get_relative_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) return _ff_mod(advance_pointer(f, p, offset), f->depth); } -// Works on local copies of w and r +// Works on local copies of w and r - return only the difference and as such can be used to determine an overflow static inline uint16_t _tu_fifo_count(tu_fifo_t* f, uint16_t wAbs, uint16_t rAbs) { uint16_t cnt = wAbs-rAbs; @@ -287,7 +287,9 @@ static inline uint16_t _tu_fifo_remaining(tu_fifo_t* f, uint16_t wAbs, uint16_t @brief Get number of items in FIFO. As this function only reads the read and write pointers once, this function is - reentrant and thus thread and ISR save without any mutexes. + reentrant and thus thread and ISR save without any mutexes. In case an + overflow occurred, this function return f.depth at maximum. Overflows are + checked and corrected for in the read functions! @param[in] f Pointer to the FIFO buffer to manipulate @@ -297,7 +299,7 @@ static inline uint16_t _tu_fifo_remaining(tu_fifo_t* f, uint16_t wAbs, uint16_t /******************************************************************************/ uint16_t tu_fifo_count(tu_fifo_t* f) { - return _tu_fifo_count(f, f->wr_idx, f->rd_idx); + return tu_min16(_tu_fifo_count(f, f->wr_idx, f->rd_idx), f->depth); } /******************************************************************************/ @@ -361,7 +363,7 @@ uint16_t tu_fifo_remaining(tu_fifo_t* f) BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS" Only one overflow is allowed for this function to work e.g. if depth = 100, you must not write more than 2*depth-1 items in one rush without updating write pointer. Otherwise - write pointer wraps and you pointer states are messed up. This can only happen if you + write pointer wraps and your pointer states are messed up. This can only happen if you use DMAs, write functions do not allow such an error. Avoid such nasty things! All reading functions (read, peek) check for overflows and correct read pointer on their own such @@ -428,24 +430,58 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) Pointer to the FIFO buffer to manipulate @param[in] buffer The pointer to data location - @param[in] count + @param[in] n Number of element that buffer can afford @returns number of items read from the FIFO */ /******************************************************************************/ -uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t count) +uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n) { tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! // Peek the data - count = _tu_fifo_peek_at_n(f, 0, buffer, count, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + n = _tu_fifo_peek_at_n(f, 0, buffer, n, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + + // Advance read pointer + f->rd_idx = advance_pointer(f, f->rd_idx, n); + + tu_fifo_unlock(f); + return n; +} + +/******************************************************************************/ +/*! + @brief This function will read n elements from the array index specified by + the read pointer and increment the read index. It copies the elements + into another FIFO and as such takes care of wraps etc. + This function checks for an overflow and corrects read pointer if required. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] f_target + Pointer to target FIFO i.e. to copy into + @param[in] offset + Position to read from in the FIFO buffer with respect to read pointer + @param[in] n + Number of items to peek + + @returns number of items read from the FIFO + */ +/******************************************************************************/ +uint16_t tu_fifo_read_n_into_other_fifo(tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n) +{ + tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! + + // Conduct copy + n = tu_fifo_peek_n_into_other_fifo(f, f_target, offset, n); // Advance read pointer - f->rd_idx = advance_pointer(f, f->rd_idx, count); + f->rd_idx = advance_pointer(f, f->rd_idx, n); tu_fifo_unlock(f); - return count; + + return n; } /******************************************************************************/ @@ -496,6 +532,95 @@ uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint1 return ret; } +/******************************************************************************/ +/*! + @brief Read n items without removing it from the FIFO and copy them into another FIFO. + This function checks for an overflow and corrects read pointer if required. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] f_target + Pointer to target FIFO i.e. to copy into + @param[in] offset + Position to read from in the FIFO buffer with respect to read pointer + @param[in] n + Number of items to peek + + @returns Number of bytes written to p_buffer + */ +/******************************************************************************/ +uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n) +{ + // Copy is only possible if both FIFOs have common element size + TU_VERIFY(f->item_size == f_target->item_size); + + // Work on local copies on case any pointer changes in between (only necessary if something is written into FIFO f in the meantime) + uint16_t f_wr_idx = f->wr_idx; + uint16_t f_rd_idx = f->rd_idx; + + uint16_t cnt = _tu_fifo_count(f, f_wr_idx, f_rd_idx); + + // Check overflow and correct if required + if (cnt > f->depth) + { + _tu_fifo_correct_read_pointer(f, f->wr_idx); + f_rd_idx = f->rd_idx; + cnt = f->depth; + } + + // Skip beginning of buffer + if (cnt == 0 || offset >= cnt) return 0; + + // Check if we can read something at and after offset - if too less is available we read what remains + cnt -= offset; + if (cnt < n) { + if (cnt == 0) return 0; + n = cnt; + } + + tu_fifo_lock(f_target); // Lock both read and write pointers - in case of an overwritable FIFO both may be modified + + uint16_t wr_rel_tgt = get_relative_pointer(f_target, f_target->wr_idx, 0); + + if (!f_target->overwritable) + { + // Not overwritable limit up to full + n = tu_min16(n, tu_fifo_remaining(f_target)); + } + + // Advance write pointer - not required for later + f_target->wr_idx = advance_pointer(f_target, f_target->wr_idx, n); + + if (n >= f_target->depth) + { + offset += n - f_target->depth; + + // We start writing at the read pointer's position since we fill the complete + // buffer and we do not want to modify the read pointer within a write function! + // This would end up in a race condition with read functions! + wr_rel_tgt = get_relative_pointer(f_target, f_target->rd_idx, 0); + + n = f_target->depth; + + // Update write pointer + f_target->wr_idx = advance_pointer(f_target, f_target->rd_idx, n); + } + + // Copy linear size + uint16_t sz = f_target->depth - wr_rel_tgt; + _tu_fifo_peek_at_n(f, offset, &f_target->buffer[wr_rel_tgt], sz, f_wr_idx, f_rd_idx); + + if (n > sz) + { + // Copy remaining, now wrapped part, into target buffer + _tu_fifo_peek_at_n(f, offset + sz, f_target->buffer, n-sz, f_wr_idx, f_rd_idx); + } + + tu_fifo_unlock(f_target); + + return n; +} + /******************************************************************************/ /*! @brief Write one element into the buffer. @@ -547,9 +672,9 @@ bool tu_fifo_write(tu_fifo_t* f, const void * data) @return Number of written elements */ /******************************************************************************/ -uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t count) +uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n) { - if ( count == 0 ) return 0; + if ( n == 0 ) return 0; tu_fifo_lock(f); @@ -559,31 +684,31 @@ uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t count) if (!f->overwritable) { // Not overwritable limit up to full - count = tu_min16(count, _tu_fifo_remaining(f, w, r)); + n = tu_min16(n, _tu_fifo_remaining(f, w, r)); } - else if (count > f->depth) + else if (n >= f->depth) { // Only copy last part - buf8 = buf8 + (count - f->depth) * f->item_size; - count = f->depth; + buf8 = buf8 + (n - f->depth) * f->item_size; + n = f->depth; // We start writing at the read pointer's position since we fill the complete // buffer and we do not want to modify the read pointer within a write function! // This would end up in a race condition with read functions! - f->wr_idx = r; + w = r; } uint16_t wRel = get_relative_pointer(f, w, 0); // Write data - _ff_push_n(f, buf8, count, wRel); + _ff_push_n(f, buf8, n, wRel); // Advance pointer - f->wr_idx = advance_pointer(f, w, count); + f->wr_idx = advance_pointer(f, w, n); tu_fifo_unlock(f); - return count; + return n; } /******************************************************************************/ diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index b965386ab..260bd4227 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -101,13 +101,15 @@ static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t mutex_hdl) #endif bool tu_fifo_write (tu_fifo_t* f, void const * p_data); -uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t count); +uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t n); bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); -uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count); +uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); +uint16_t tu_fifo_read_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n); bool tu_fifo_peek_at (tu_fifo_t* f, uint16_t pos, void * p_buffer); uint16_t tu_fifo_peek_at_n (tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n); +uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n); uint16_t tu_fifo_count (tu_fifo_t* f); bool tu_fifo_empty (tu_fifo_t* f); -- cgit v1.3.1 From 3a3ada0c57013fb64f69178a1c6299abc74e4f40 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 18 Jan 2021 17:07:15 +0100 Subject: Implement the usage of usbd_edpt_ISO_xfer() --- src/class/audio/audio_device.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8581925e4..8dd1a8fef 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -32,6 +32,8 @@ * * */ +// TODO: Rename CFG_TUD_AUDIO_EPSIZE_IN to CFG_TUD_AUDIO_EP_IN_BUFFER_SIZE + #include "tusb_option.h" #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO) @@ -129,6 +131,7 @@ typedef struct #if CFG_TUD_AUDIO_EPSIZE_IN CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) + tu_fifo_t epin_ff; #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -531,7 +534,14 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ // THIS FUNCTION IS NOT EXECUTED WITHIN AN INTERRUPT SO IT DOES NOT INTERRUPT tud_audio_n_write_ep_in_buffer()! AS LONG AS tud_audio_n_write_ep_in_buffer() IS NOT EXECUTED WITHIN AN INTERRUPT ALL IS FINE! // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, audio->epin_buf_cnt)); + // TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, audio->epin_buf_cnt)); + + + TU_VERIFY(usbd_edpt_ISO_xfer(rhport, audio->ep_in, &audio->epin_ff)); + + + + // Inform how many bytes were copied *n_bytes_copied = audio->epin_buf_cnt; @@ -631,7 +641,9 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* return true; } - nByteCount = tu_fifo_read_n(&audio->tx_ff[0], audio->epin_buf, nByteCount); + nByteCount = tu_fifo_read_n_into_other_fifo(&audio->tx_ff[0], &audio->epin_ff, 0, nByteCount); +// nByteCount = tu_fifo_read_n(&audio->tx_ff[0], audio->epin_buf, nByteCount); + audio->epin_buf_cnt = nByteCount; return true; @@ -735,6 +747,10 @@ void audiod_init(void) tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); #endif } + + // Initialize IN EP FIFO + tu_fifo_config(&audio->epin_ff, &audio->epin_buf, CFG_TUD_AUDIO_EPSIZE_IN, 1, true); + #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE @@ -765,6 +781,10 @@ void audiod_reset(uint8_t rhport) audiod_interface_t* audio = &_audiod_itf[i]; tu_memclr(audio, ITF_MEM_RESET_SIZE); +#if CFG_TUD_AUDIO_EPSIZE_IN + tu_fifo_clear(&audio->epin_ff); +#endif + #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_COUNT; cnt++) { -- cgit v1.3.1 From 84c383061f4af9e0fa66326a09c6c332920df6a7 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 18 Jan 2021 17:08:59 +0100 Subject: Add tusb_fifo.h header file to dcd.h --- src/device/dcd.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index b7e5a8da0..1b2d2b941 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -32,6 +32,7 @@ #define _TUSB_DCD_H_ #include "common/tusb_common.h" +#include "common/tusb_fifo.h" #ifdef __cplusplus extern "C" { @@ -133,6 +134,9 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Submit an ISO transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack +bool dcd_edpt_ISO_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); + // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); -- cgit v1.3.1 From 8450bc3225856fe6f32ef8a4b3d8038163bc0cb1 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 18 Jan 2021 17:12:39 +0100 Subject: Add FIFO copy modes: tu_fifo_copy_mode_t Allows to copy from/to constant pointers required for STM32 hardware FIFO copies. --- src/common/tusb_fifo.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++--- src/common/tusb_fifo.h | 30 ++++++++++++++ 2 files changed, 127 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index a1cf0e289..522fc1883 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -76,6 +76,8 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si f->max_pointer_idx = 2*depth - 1; // Limit index space to 2*depth - this allows for a fast "modulo" calculation but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable only if overflow happens once (important for unsupervised DMA applications) f->non_used_index_space = 0xFFFF - f->max_pointer_idx; + f->rd_mode = f->wr_mode = TU_FIFO_COPY_INC; // Default copy mode is incrementing addresses + f->rd_idx = f->wr_idx = 0; tu_fifo_unlock(f); @@ -91,28 +93,117 @@ static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) return idx; } +// Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address +// Code adapted from dcd_synopsis.c +static void _tu_fifo_read_from_const_src_ptr(void * dst, const void * src, uint16_t len) +{ + uint8_t * dst_u8 = (uint8_t *)dst; + volatile uint32_t * rx_fifo = (volatile uint32_t *) src; + + // Reading full available 32 bit words from FIFO + uint16_t full_words = len >> 2; + for(uint16_t i = 0; i < full_words; i++) { + uint32_t tmp = *rx_fifo; + dst_u8[0] = tmp & 0x000000FF; + dst_u8[1] = (tmp & 0x0000FF00) >> 8; + dst_u8[2] = (tmp & 0x00FF0000) >> 16; + dst_u8[3] = (tmp & 0xFF000000) >> 24; + dst_u8 += 4; + } + + // Read the remaining 1-3 bytes from FIFO + uint8_t bytes_rem = len & 0x03; + if(bytes_rem != 0) { + uint32_t tmp = *rx_fifo; + dst_u8[0] = tmp & 0x000000FF; + if(bytes_rem > 1) { + dst_u8[1] = (tmp & 0x0000FF00) >> 8; + } + if(bytes_rem > 2) { + dst_u8[2] = (tmp & 0x00FF0000) >> 16; + } + } +} + +// Intended to be used to write to hardware USB FIFO in e.g. STM32 where all data is written to a constant address +// Code adapted from dcd_synopsis.c +static void _tu_fifo_write_to_const_dst_ptr(void * dst, const void * src, uint16_t len) +{ + volatile uint32_t * tx_fifo = (volatile uint32_t *) dst; + uint8_t * src_u8 = (uint8_t *)src; + + // Pushing full available 32 bit words to FIFO + uint16_t full_words = len >> 2; + for(uint16_t i = 0; i < full_words; i++){ + *tx_fifo = (src_u8[3] << 24) | (src_u8[2] << 16) | (src_u8[1] << 8) | src_u8[0]; + src_u8 += 4; + } + + // Write the remaining 1-3 bytes into FIFO + uint8_t bytes_rem = len & 0x03; + if(bytes_rem){ + uint32_t tmp_word = 0; + tmp_word |= src_u8[0]; + if(bytes_rem > 1){ + tmp_word |= src_u8[1] << 8; + } + if(bytes_rem > 2){ + tmp_word |= src_u8[2] << 16; + } + *tx_fifo = tmp_word; + } +} + // send one item to FIFO WITHOUT updating write pointer static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t wRel) { memcpy(f->buffer + (wRel * f->item_size), data, f->item_size); } +static inline void _ff_push_copy_fct(tu_fifo_t* f, void * dst, const void * src, uint16_t len) +{ + switch (f->rd_mode) + { + case TU_FIFO_COPY_INC: + memcpy(dst, src, len); + break; + + case TU_FIFO_COPY_CST: + _tu_fifo_read_from_const_src_ptr(dst, src, len); + break; + } +} + +static inline void _ff_pull_copy_fct(tu_fifo_t* f, void * dst, const void * src, uint16_t len) +{ + switch (f->wr_mode) + { + case TU_FIFO_COPY_INC: + memcpy(dst, src, len); + break; + + case TU_FIFO_COPY_CST: + _tu_fifo_write_to_const_dst_ptr(dst, src, len); + break; + } +} + // send n items to FIFO WITHOUT updating write pointer static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRel) { if(wRel + n <= f->depth) // Linear mode only { - memcpy(f->buffer + (wRel * f->item_size), data, n*f->item_size); + _ff_push_copy_fct(f, f->buffer + (wRel * f->item_size), data, n*f->item_size); } else // Wrap around { uint16_t nLin = f->depth - wRel; // Write data to linear part of buffer - memcpy(f->buffer + (wRel * f->item_size), data, nLin*f->item_size); + _ff_push_copy_fct(f, f->buffer + (wRel * f->item_size), data, nLin*f->item_size); // Write data wrapped around - memcpy(f->buffer, ((uint8_t const*) data) + nLin*f->item_size, (n - nLin) * f->item_size); + _ff_push_copy_fct(f, f->buffer, ((uint8_t const*) data) + nLin*f->item_size, (n - nLin) * f->item_size); } } @@ -127,17 +218,17 @@ static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel) { if(rRel + n <= f->depth) // Linear mode only { - memcpy(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); + _ff_pull_copy_fct(f, p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); } else // Wrap around { uint16_t nLin = f->depth - rRel; // Read data from linear part of buffer - memcpy(p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size); + _ff_pull_copy_fct(f, p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size); // Read data wrapped part - memcpy((uint8_t*)p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size); + _ff_pull_copy_fct(f, (uint8_t*)p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size); } } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 260bd4227..2ce433718 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -55,6 +55,19 @@ extern "C" { #define tu_fifo_mutex_t osal_mutex_t #endif +/** \enum tu_fifo_copy_mode_t + * \brief Write modes intended to allow special read and write functions to be able to copy data to and from USB hardware FIFOs as needed for e.g. STM32s + */ +typedef enum +{ + TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode + TU_FIFO_COPY_CST, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO +} tu_fifo_copy_mode_t; + +//TU_FIFO_WRITE_INC_DST, ///< Write to an increasing destination address - default mode +// TU_FIFO_WRITE_CONST_DST, ///< Write to a constant destination address - required for e.g. STM32 to write into USB hardware FIFO +// TU_FIFO_READ_INC_SRC, ///< Read from an increasing source address - default mode +// TU_FIFO_READ_CONST_SRC, ///< Read from a constant source address - required for e.g. STM32 to read from USB hardware FIFO /** \struct tu_fifo_t * \brief Simple Circular FIFO @@ -72,6 +85,9 @@ typedef struct volatile uint16_t wr_idx ; ///< write pointer volatile uint16_t rd_idx ; ///< read pointer + tu_fifo_copy_mode_t wr_mode ; ///< write mode - default is TU_FIFO_COPY_INC + tu_fifo_copy_mode_t rd_mode ; ///< read mode - default is TU_FIFO_COPY_INC + #if CFG_FIFO_MUTEX tu_fifo_mutex_t mutex; #endif @@ -87,6 +103,8 @@ typedef struct .overwritable = _overwritable, \ .max_pointer_idx = 2*_depth-1, \ .non_used_index_space = 0xFFFF - 2*_depth-1, \ + .wr_mode = TU_FIFO_COPY_INC, \ + .rd_mode = TU_FIFO_COPY_INC, \ } bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); @@ -133,6 +151,18 @@ static inline uint16_t tu_fifo_depth(tu_fifo_t* f) return f->depth; } +// When writing into the FIFO by fifo_write_n(), rd_mode determines how the pointer read from is modified +static inline void tu_fifo_set_copy_mode_read(tu_fifo_t* f, tu_fifo_copy_mode_t rd_mode) +{ + f->rd_mode = rd_mode; +} + +// When reading from the FIFO by fifo_read_n() or fifo_peek_n(), wr_mode determines how the pointer written to is modified +static inline void tu_fifo_set_copy_mode_write(tu_fifo_t* f, tu_fifo_copy_mode_t wr_mode) +{ + f->wr_mode = wr_mode; +} + #ifdef __cplusplus } #endif -- cgit v1.3.1 From 51c80630f5c67cd2f67c2282a46520ef517f7234 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 18 Jan 2021 17:13:06 +0100 Subject: Clean up --- src/common/tusb_fifo.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 2ce433718..7ece30b74 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -64,11 +64,6 @@ typedef enum TU_FIFO_COPY_CST, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO } tu_fifo_copy_mode_t; -//TU_FIFO_WRITE_INC_DST, ///< Write to an increasing destination address - default mode -// TU_FIFO_WRITE_CONST_DST, ///< Write to a constant destination address - required for e.g. STM32 to write into USB hardware FIFO -// TU_FIFO_READ_INC_SRC, ///< Read from an increasing source address - default mode -// TU_FIFO_READ_CONST_SRC, ///< Read from a constant source address - required for e.g. STM32 to read from USB hardware FIFO - /** \struct tu_fifo_t * \brief Simple Circular FIFO */ -- cgit v1.3.1 From 2284db1fb5d99c91b31ef7176ea04a8a01b3206a Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 18 Jan 2021 17:14:17 +0100 Subject: Add usbd_edpt_ISO_xfer() --- src/device/usbd.c | 6 +++--- src/device/usbd_pvt.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 05acb7019..e0546ac39 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1206,12 +1206,12 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } -bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes); + TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, tu_fifo_count(ff)); // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); @@ -1220,7 +1220,7 @@ bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if ( dcd_edpt_ISO_xfer(rhport, ep_addr, ff, total_bytes) ) + if ( dcd_edpt_ISO_xfer(rhport, ep_addr, ff) ) { TU_LOG2("OK\r\n"); return true; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index de2f37281..4ae55aecc 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -72,8 +72,8 @@ 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); -// Submit a usb ISO transfer by use of a FIFO (ring buffer) -bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); +// Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted +bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. -- cgit v1.3.1 From dff588d7727f63b7e8819a89c259b5edddb079e9 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 18 Jan 2021 17:15:23 +0100 Subject: Implement dcd_edpt_ISO_xfer() and adapt transmission scheme --- src/portable/st/synopsys/dcd_synopsys.c | 55 ++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 507e5246a..49345869e 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -670,8 +670,13 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_ISO_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_ISO_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) { + // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 + TU_ASSERT(ff->item_size == 1); + + uint16_t total_bytes = tu_fifo_count(ff); + uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -680,6 +685,16 @@ bool dcd_edpt_ISO_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ xfer->ff = ff; xfer->total_len = total_bytes; + // Set copy mode to constant address - required since data copied to or from the hardware USB FIFO needs to be written at a constant address + if (dir == TUSB_DIR_IN) + { + tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_CST); + } + else + { + tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); + } + // EP0 can only handle one packet if(epnum == 0) { ep0_pending[dir] = total_bytes; @@ -692,9 +707,7 @@ bool dcd_edpt_ISO_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ uint8_t const short_packet_size = total_bytes % xfer->max_size; // Zero-size packet is special case. - if(short_packet_size > 0 || (total_bytes == 0)) { - num_packets++; - } + if(short_packet_size > 0 || (total_bytes == 0)) num_packets++; // Schedule packets to be sent within interrupt edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); @@ -900,14 +913,20 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ { xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - - // TODO: TAKE CARE OF ISO FIFO! - // Read packet off RxFIFO - read_fifo_packet(rhport, xfer->buffer, bcnt); + if (xfer->buffer) + { + // Linear buffer + read_fifo_packet(rhport, xfer->buffer, bcnt); - // Increment pointer to xfer data - xfer->buffer += bcnt; + // Increment pointer to xfer data + xfer->buffer += bcnt; + } + else + { + // Ring buffer + tu_fifo_write_n(xfer->ff, (const void *) rx_fifo, bcnt); + } // Truncate transfer length in case of short packet if(bcnt < xfer->max_size) { @@ -1014,13 +1033,19 @@ static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OT break; } - // TODO: TAKE CARE OF ISO FIFO! - // Push packet to Tx-FIFO - write_fifo_packet(rhport, n, xfer->buffer, packet_size); + if (xfer->buffer) + { + write_fifo_packet(rhport, n, xfer->buffer, packet_size); - // Increment pointer to xfer data - xfer->buffer += packet_size; + // Increment pointer to xfer data + xfer->buffer += packet_size; + } + else + { + usb_fifo_t tx_fifo = FIFO_BASE(rhport, n); + tu_fifo_read_n(xfer->ff, (void *) tx_fifo, packet_size); + } } // Turn off TXFE if all bytes are written. -- cgit v1.3.1 From 595a88b34c700bfdb5bf2db04c731de06a995f5f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 18 Jan 2021 17:38:32 +0100 Subject: Correct include path to #include "common/tusb_fifo.h" --- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 49345869e..5f9dc267b 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -28,7 +28,7 @@ */ #include "tusb_option.h" -#include "tusb_fifo.h" +#include "common/tusb_fifo.h" // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) // We disable SOF for now until needed later on -- cgit v1.3.1 From 99e6bc37207bc3239d00fc7e47e42b8d22b8adff Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 18 Jan 2021 17:54:08 +0100 Subject: Explicitly add cast to uint32_t before shifting uint8 to left --- src/common/tusb_fifo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 522fc1883..ca03864eb 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -135,7 +135,7 @@ static void _tu_fifo_write_to_const_dst_ptr(void * dst, const void * src, uint16 // Pushing full available 32 bit words to FIFO uint16_t full_words = len >> 2; for(uint16_t i = 0; i < full_words; i++){ - *tx_fifo = (src_u8[3] << 24) | (src_u8[2] << 16) | (src_u8[1] << 8) | src_u8[0]; + *tx_fifo = ((uint32_t)(src_u8[3]) << 24) | ((uint32_t)(src_u8[2]) << 16) | ((uint32_t)(src_u8[1]) << 8) | (uint32_t)src_u8[0]; src_u8 += 4; } @@ -145,10 +145,10 @@ static void _tu_fifo_write_to_const_dst_ptr(void * dst, const void * src, uint16 uint32_t tmp_word = 0; tmp_word |= src_u8[0]; if(bytes_rem > 1){ - tmp_word |= src_u8[1] << 8; + tmp_word |= (uint32_t)(src_u8[1]) << 8; } if(bytes_rem > 2){ - tmp_word |= src_u8[2] << 16; + tmp_word |= (uint32_t)(src_u8[2]) << 16; } *tx_fifo = tmp_word; } -- cgit v1.3.1 From 56edc2b2618e542b73c284a3116cf88fd70303e2 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 19 Jan 2021 10:50:19 +0100 Subject: Change names from edpt_ISO_xfer to edpt_iso_xfer --- src/class/audio/audio_device.c | 2 +- src/device/dcd.h | 2 +- src/device/usbd.c | 4 ++-- src/device/usbd_pvt.h | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8dd1a8fef..616760223 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -537,7 +537,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ // TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, audio->epin_buf_cnt)); - TU_VERIFY(usbd_edpt_ISO_xfer(rhport, audio->ep_in, &audio->epin_ff)); + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->epin_ff)); diff --git a/src/device/dcd.h b/src/device/dcd.h index 1b2d2b941..30224e16e 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -135,7 +135,7 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit an ISO transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_ISO_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index e0546ac39..c2b5b65d1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1206,7 +1206,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } -bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) +bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -1220,7 +1220,7 @@ bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if ( dcd_edpt_ISO_xfer(rhport, ep_addr, ff) ) + if ( dcd_edpt_iso_xfer(rhport, ep_addr, ff) ) { TU_LOG2("OK\r\n"); return true; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 4ae55aecc..1d24957a9 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -73,7 +73,7 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted -bool usbd_edpt_ISO_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); +bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 5f9dc267b..90fcd51e7 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -670,7 +670,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_ISO_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) { // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); -- cgit v1.3.1 From 93ec6f3735b30193f368458cf10d1af6c833c230 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 19 Jan 2021 17:10:08 +0100 Subject: Adjust #include "dcd.h" to "device/dcd.h", the same for usbd.h in usbd.c --- src/device/usbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index c2b5b65d1..4e18df757 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -29,9 +29,9 @@ #if TUSB_OPT_DEVICE_ENABLED #include "tusb.h" -#include "usbd.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" -#include "dcd.h" +#include "device/dcd.h" #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 -- cgit v1.3.1 From e0aa405d19e35dbf58cf502b8106455c1a3c2a5c Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Tue, 19 Jan 2021 19:52:07 -0600 Subject: RP2040 support --- examples/host/cdc_msc_hid/src/keyboard_helper.h | 59 +++ hw/bsp/board.h | 7 + hw/bsp/board_mcu.h | 3 + hw/bsp/raspberry_pi_pico/board_raspberry_pi_pico.c | 99 ++++ hw/mcu/microchip | 2 +- lib/lwip | 2 +- src/class/hid/hid_host.c | 6 +- src/host/usbh.c | 6 + src/host/usbh.h | 1 + src/osal/osal.h | 2 + src/osal/osal_pico.h | 192 +++++++ src/portable/raspberrypi/rp2040/dcd_rp2040.c | 482 ++++++++++++++++++ src/portable/raspberrypi/rp2040/hcd_rp2040.c | 549 +++++++++++++++++++++ src/portable/raspberrypi/rp2040/rp2040_usb.c | 279 +++++++++++ src/portable/raspberrypi/rp2040/rp2040_usb.h | 124 +++++ src/tusb_option.h | 4 + 16 files changed, 1813 insertions(+), 4 deletions(-) create mode 100644 examples/host/cdc_msc_hid/src/keyboard_helper.h create mode 100644 hw/bsp/raspberry_pi_pico/board_raspberry_pi_pico.c create mode 100644 src/osal/osal_pico.h create mode 100644 src/portable/raspberrypi/rp2040/dcd_rp2040.c create mode 100644 src/portable/raspberrypi/rp2040/hcd_rp2040.c create mode 100644 src/portable/raspberrypi/rp2040/rp2040_usb.c create mode 100644 src/portable/raspberrypi/rp2040/rp2040_usb.h (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/keyboard_helper.h b/examples/host/cdc_msc_hid/src/keyboard_helper.h new file mode 100644 index 000000000..1fde2768c --- /dev/null +++ b/examples/host/cdc_msc_hid/src/keyboard_helper.h @@ -0,0 +1,59 @@ +#ifndef KEYBOARD_HELPER_H +#define KEYBAORD_HELPER_H + +#include +#include + +#include "tusb.h" + +// look up new key in previous keys +inline bool find_key_in_report(hid_keyboard_report_t const *p_report, uint8_t keycode) +{ + for(uint8_t i = 0; i < 6; i++) + { + if (p_report->keycode[i] == keycode) return true; + } + + return false; +} + +inline uint8_t keycode_to_ascii(uint8_t modifier, uint8_t keycode) +{ + return keycode > 128 ? 0 : + hid_keycode_to_ascii_tbl [keycode][modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT) ? 1 : 0]; +} + +void print_kbd_report(hid_keyboard_report_t *prev_report, hid_keyboard_report_t const *new_report) +{ + + printf("Report: "); + uint8_t c; + + // I assume it's possible to have up to 6 keypress events per report? + for (uint8_t i = 0; i < 6; i++) + { + // Check for key presses + if (new_report->keycode[i]) + { + // If not in prev report then it is newly pressed + if ( !find_key_in_report(prev_report, new_report->keycode[i]) ) + c = keycode_to_ascii(new_report->modifier, new_report->keycode[i]); + printf("press %c ", c); + } + + // Check for key depresses (i.e. was present in prev report but not here) + if (prev_report->keycode[i]) + { + // If not present in the current report then depressed + if (!find_key_in_report(new_report, prev_report->keycode[i])) + { + c = keycode_to_ascii(prev_report->modifier, prev_report->keycode[i]); + printf("depress %c ", c); + } + } + } + + printf("\n"); +} + +#endif \ No newline at end of file diff --git a/hw/bsp/board.h b/hw/bsp/board.h index a8f973a7f..97c80e7c7 100644 --- a/hw/bsp/board.h +++ b/hw/bsp/board.h @@ -80,6 +80,13 @@ int board_uart_write(void const * buf, int len); return os_time_ticks_to_ms32( os_time_get() ); } +#elif CFG_TUSB_OS == OPT_OS_PICO +#include "pico/time.h" +static inline uint32_t board_millis(void) + { + return to_ms_since_boot(get_absolute_time()); + } + #else #error "board_millis() is not implemented for this OS" #endif diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index eedae43f7..700183414 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -117,6 +117,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_DA1469X #include "DA1469xAB.h" +#elif CFG_TUSB_MCU == OPT_MCU_RP2040 + #include "pico.h" + #else #error "Missing MCU header" #endif diff --git a/hw/bsp/raspberry_pi_pico/board_raspberry_pi_pico.c b/hw/bsp/raspberry_pi_pico/board_raspberry_pi_pico.c new file mode 100644 index 000000000..efdb54733 --- /dev/null +++ b/hw/bsp/raspberry_pi_pico/board_raspberry_pi_pico.c @@ -0,0 +1,99 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "pico/stdlib.h" +#include "../board.h" + +#ifndef LED_PIN +#define LED_PIN PICO_DEFAULT_LED_PIN +#endif + +void board_init(void) +{ + setup_default_uart(); + gpio_init(LED_PIN); + gpio_set_dir(LED_PIN, 1); + + // Button + + // todo probably set up device mode? + +#if TUSB_OPT_HOST_ENABLED + // set portfunc to host !!! +#endif +} + +////--------------------------------------------------------------------+ +//// USB Interrupt Handler +////--------------------------------------------------------------------+ +//void USB_IRQHandler(void) +//{ +//#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST +// tuh_isr(0); +//#endif +// +//#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE +// tud_int_handler(0); +//#endif +//} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + gpio_put(LED_PIN, state); +} + +uint32_t board_button_read(void) +{ + return 0; +} + +int board_uart_read(uint8_t* buf, int len) +{ + for(int i=0;iep_in = p_endpoint_desc->bEndpointAddress; p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor p_hid->itf_num = interface_number; + p_hid->valid = true; return true; } @@ -246,14 +248,14 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) usbh_driver_set_config_complete(dev_addr, itf_num); #if CFG_TUH_HID_KEYBOARD - if ( keyboardh_data[dev_addr-1].itf_num == itf_num) + if (( keyboardh_data[dev_addr-1].itf_num == itf_num) && keyboardh_data[dev_addr-1].valid) { tuh_hid_keyboard_mounted_cb(dev_addr); } #endif #if CFG_TUH_HID_MOUSE - if ( mouseh_data[dev_addr-1].ep_in == itf_num ) + if (( mouseh_data[dev_addr-1].ep_in == itf_num ) && mouseh_data[dev_addr-1].valid) { tuh_hid_mouse_mounted_cb(dev_addr); } diff --git a/src/host/usbh.c b/src/host/usbh.c index e7347ff56..bf265199d 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -151,6 +151,12 @@ tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr) return (tusb_device_state_t) _usbh_devices[dev_addr].state; } +tusb_speed_t tuh_device_get_speed (uint8_t const dev_addr) +{ + TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_DEVICE_STATE_UNPLUG); + return _usbh_devices[dev_addr].speed; +} + void osal_task_delay(uint32_t msec) { (void) msec; diff --git a/src/host/usbh.h b/src/host/usbh.h index 12c9164dd..a05010b36 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -86,6 +86,7 @@ extern void hcd_int_handler(uint8_t rhport); #define tuh_int_handler hcd_int_handler tusb_device_state_t tuh_device_get_state (uint8_t dev_addr); +tusb_speed_t tuh_device_get_speed (uint8_t dev_addr); static inline bool tuh_device_is_configured(uint8_t dev_addr) { return tuh_device_get_state(dev_addr) == TUSB_DEVICE_STATE_CONFIGURED; diff --git a/src/osal/osal.h b/src/osal/osal.h index b5057ff4c..eb3bc88d0 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -53,6 +53,8 @@ typedef void (*osal_task_func_t)( void * ); #include "osal_freertos.h" #elif CFG_TUSB_OS == OPT_OS_MYNEWT #include "osal_mynewt.h" +#elif CFG_TUSB_OS == OPT_OS_PICO + #include "osal_pico.h" #elif CFG_TUSB_OS == OPT_OS_CUSTOM #include "tusb_os_custom.h" // implemented by application #else diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h new file mode 100644 index 000000000..1788e5c8d --- /dev/null +++ b/src/osal/osal_pico.h @@ -0,0 +1,192 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_OSAL_PICO_H_ +#define _TUSB_OSAL_PICO_H_ + +#include "pico/time.h" +#include "pico/sem.h" +#include "pico/mutex.h" +#include "pico/critical_section.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// TASK API +//--------------------------------------------------------------------+ +#ifndef RP2040_USB_HOST_MODE +static inline void osal_task_delay(uint32_t msec) +{ + sleep_ms(msec); +} +#endif + +//--------------------------------------------------------------------+ +// Binary Semaphore API +//--------------------------------------------------------------------+ +typedef struct semaphore osal_semaphore_def_t, *osal_semaphore_t; + +static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) +{ + sem_init(semdef, 0, 255); + return semdef; +} + +static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) +{ + sem_release(sem_hdl); + return true; +} + +static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) +{ + return sem_acquire_timeout_ms(sem_hdl, msec); +} + +static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) +{ + sem_reset(sem_hdl, 0); +} + +//--------------------------------------------------------------------+ +// MUTEX API +// Within tinyusb, mutex is never used in ISR context +//--------------------------------------------------------------------+ +typedef struct mutex osal_mutex_def_t, *osal_mutex_t; + +static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) +{ + mutex_init(mdef); + return mdef; +} + +static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) +{ + return mutex_enter_timeout_ms(mutex_hdl, msec); +} + +static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) +{ + mutex_exit(mutex_hdl); + return true; +} + +//--------------------------------------------------------------------+ +// QUEUE API +//--------------------------------------------------------------------+ +#include "common/tusb_fifo.h" + +#if TUSB_OPT_HOST_ENABLED +extern void hcd_int_disable(uint8_t rhport); +extern void hcd_int_enable(uint8_t rhport); +#endif + +typedef struct +{ + tu_fifo_t ff; + struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section +} osal_queue_def_t; + +typedef osal_queue_def_t* osal_queue_t; + +// role device/host is used by OS NONE for mutex (disable usb isr) only +#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ + uint8_t _name##_buf[_depth*sizeof(_type)]; \ + osal_queue_def_t _name = { \ + .ff = { \ + .buffer = _name##_buf, \ + .depth = _depth, \ + .item_size = sizeof(_type), \ + .overwritable = false, \ + }\ + } + +// lock queue by disable USB interrupt +static inline void _osal_q_lock(osal_queue_t qhdl) +{ + critical_section_enter_blocking(&qhdl->critsec); +} + +// unlock queue +static inline void _osal_q_unlock(osal_queue_t qhdl) +{ + critical_section_exit(&qhdl->critsec); +} + +static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) +{ + critical_section_init(&qdef->critsec); + tu_fifo_clear(&qdef->ff); + return (osal_queue_t) qdef; +} + +static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) +{ + // TODO: revisit... docs say that mutexes are never used from IRQ context, + // however osal_queue_recieve may be. therefore my assumption is that + // the fifo mutex is not populated for queues used from an IRQ context + assert(!qhdl->ff.mutex); + + _osal_q_lock(qhdl); + bool success = tu_fifo_read(&qhdl->ff, data); + _osal_q_unlock(qhdl); + + return success; +} + +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +{ + // TODO: revisit... docs say that mutexes are never used from IRQ context, + // however osal_queue_recieve may be. therefore my assumption is that + // the fifo mutex is not populated for queues used from an IRQ context + assert(!qhdl->ff.mutex); + + _osal_q_lock(qhdl); + bool success = tu_fifo_write(&qhdl->ff, data); + _osal_q_unlock(qhdl); + + TU_ASSERT(success); + + return success; +} + +static inline bool osal_queue_empty(osal_queue_t qhdl) +{ + // TODO: revisit; whether this is true or not currently, tu_fifo_empty is a single + // volatile read. + + // Skip queue lock/unlock since this function is primarily called + // with interrupt disabled before going into low power mode + return tu_fifo_empty(&qhdl->ff); +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_OSAL_PICO_H_ */ diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c new file mode 100644 index 000000000..80e5d3c4b --- /dev/null +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -0,0 +1,482 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_RP2040 + +#include "pico.h" +#include "rp2040_usb.h" + +#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX +#include "pico/fix/rp2040_usb_device_enumeration.h" +#endif + + +#include "device/dcd.h" + +#include "pico/stdlib.h" + +/*------------------------------------------------------------------*/ +/* Low level controller + *------------------------------------------------------------------*/ + +#define usb_hw_set hw_set_alias(usb_hw) +#define usb_hw_clear hw_clear_alias(usb_hw) + +// Init these in dcd_init +static uint8_t assigned_address; +static uint8_t *next_buffer_ptr; + +// Endpoints 0-15, direction 0 for out and 1 for in. +static struct hw_endpoint hw_endpoints[16][2] = {0}; + +static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, uint8_t in) +{ + return &hw_endpoints[num][in]; +} + +static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr) +{ + uint8_t num = tu_edpt_number(ep_addr); + uint8_t in = (ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0; + return hw_endpoint_get_by_num(num, in); +} +static void _hw_endpoint_alloc(struct hw_endpoint *ep) +{ + uint size = 64; + if (ep->wMaxPacketSize > 64) + { + size = ep->wMaxPacketSize; + } + + // Assumes single buffered for now + ep->hw_data_buf = next_buffer_ptr; + next_buffer_ptr += size; + // Bits 0-5 are ignored by the controller so make sure these are 0 + if ((uintptr_t)next_buffer_ptr & 0b111111u) + { + // Round up to the next 64 + uint32_t fixptr = (uintptr_t)next_buffer_ptr; + fixptr &= ~0b111111u; + fixptr += 64; + pico_info("Rounding non 64 byte boundary buffer up from %x to %x\n", (uintptr_t)next_buffer_ptr, fixptr); + next_buffer_ptr = (uint8_t*)fixptr; + } + assert(((uintptr_t)next_buffer_ptr & 0b111111u) == 0); + uint dpram_offset = hw_data_offset(ep->hw_data_buf); + assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX); + + pico_info("Alloced %d bytes at offset 0x%x (0x%p) for ep %d %s\n", + size, + dpram_offset, + ep->hw_data_buf, + ep->num, + ep_dir_string[ep->in]); + + // Fill in endpoint control register with buffer offset + uint32_t reg = EP_CTRL_ENABLE_BITS + | EP_CTRL_INTERRUPT_PER_BUFFER + | (ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) + | dpram_offset; + + *ep->endpoint_control = reg; +} + +static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint wMaxPacketSize, uint8_t transfer_type) +{ + uint8_t num = tu_edpt_number(ep_addr); + bool in = ep_addr & TUSB_DIR_IN_MASK; + ep->ep_addr = ep_addr; + ep->in = in; + // For device, IN is a tx transfer and OUT is an rx transfer + ep->rx = in == false; + ep->num = num; + // Response to a setup packet on EP0 starts with pid of 1 + ep->next_pid = num == 0 ? 1u : 0u; + + // Add some checks around the max packet size + if (transfer_type == TUSB_XFER_ISOCHRONOUS) + { + if (wMaxPacketSize > USB_MAX_ISO_PACKET_SIZE) + { + panic("Isochronous wMaxPacketSize %d too large", wMaxPacketSize); + } + } + else + { + if (wMaxPacketSize > USB_MAX_PACKET_SIZE) + { + panic("Isochronous wMaxPacketSize %d too large", wMaxPacketSize); + } + } + + ep->wMaxPacketSize = wMaxPacketSize; + ep->transfer_type = transfer_type; + + // Every endpoint has a buffer control register in dpram + if (ep->in) + { + ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in; + } + else + { + ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].out; + } + + // Clear existing buffer control state + *ep->buffer_control = 0; + + if (ep->num == 0) + { + // EP0 has no endpoint control register because + // the buffer offsets are fixed + ep->endpoint_control = NULL; + + // Buffer offset is fixed + ep->hw_data_buf = (uint8_t*)&usb_dpram->ep0_buf_a[0]; + } + else + { + // Set the endpoint control register (starts at EP1, hence num-1) + if (in) + { + ep->endpoint_control = &usb_dpram->ep_ctrl[num-1].in; + } + else + { + ep->endpoint_control = &usb_dpram->ep_ctrl[num-1].out; + } + + // Now alloc a buffer and fill in endpoint control register + _hw_endpoint_alloc(ep); + } + + ep->configured = true; +} + +#if 0 // todo unused +static void _hw_endpoint_close(struct hw_endpoint *ep) +{ + // Clear hardware registers and then zero the struct + // Clears endpoint enable + *ep->endpoint_control = 0; + // Clears buffer available, etc + *ep->buffer_control = 0; + // Clear any endpoint state + memset(ep, 0, sizeof(struct hw_endpoint)); +} + +static void hw_endpoint_close(uint8_t ep_addr) +{ + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + _hw_endpoint_close(ep); +} +#endif + +static void hw_endpoint_init(uint8_t ep_addr, uint wMaxPacketSize, uint8_t bmAttributes) +{ + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + _hw_endpoint_init(ep, ep_addr, wMaxPacketSize, bmAttributes); +} + +static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool start) +{ + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + _hw_endpoint_xfer(ep, buffer, total_bytes, start); +} + +static void hw_handle_buff_status(void) +{ + uint32_t remaining_buffers = usb_hw->buf_status; + pico_trace("buf_status 0x%08x\n", remaining_buffers); + uint bit = 1u; + for (uint i = 0; remaining_buffers && i < USB_MAX_ENDPOINTS * 2; i++) + { + if (remaining_buffers & bit) + { + uint __unused which = (usb_hw->buf_cpu_should_handle & bit) ? 1 : 0; + // Should be single buffered + assert(which == 0); + // clear this in advance + usb_hw_clear->buf_status = bit; + // IN transfer for even i, OUT transfer for odd i + struct hw_endpoint *ep = hw_endpoint_get_by_num(i >> 1u, !(i & 1u)); + // Continue xfer + bool done = _hw_endpoint_xfer_continue(ep); + if (done) + { + // Notify + dcd_event_xfer_complete(0, ep->ep_addr, ep->len, XFER_RESULT_SUCCESS, true); + hw_endpoint_reset_transfer(ep); + } + remaining_buffers &= ~bit; + } + bit <<= 1u; + } +} + +static void reset_ep0(void) +{ + // If we have finished this transfer on EP0 set pid back to 1 for next + // setup transfer. Also clear a stall in case + uint8_t addrs[] = {0x0, 0x80}; + for (uint i = 0 ; i < count_of(addrs); i++) + { + struct hw_endpoint *ep = hw_endpoint_get_by_addr(addrs[i]); + ep->next_pid = 1u; + ep->stalled = 0; + } +} + +static void ep0_0len_status(void) +{ + // Send 0len complete response on EP0 IN + reset_ep0(); + hw_endpoint_xfer(0x80, NULL, 0, true); +} + +static void _hw_endpoint_stall(struct hw_endpoint *ep) +{ + assert(!ep->stalled); + if (ep->num == 0) + { + // A stall on EP0 has to be armed so it can be cleared on the next setup packet + usb_hw_set->ep_stall_arm = ep->in ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; + } + _hw_endpoint_buffer_control_set_mask32(ep, USB_BUF_CTRL_STALL); + ep->stalled = true; +} + +static void hw_endpoint_stall(uint8_t ep_addr) +{ + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + _hw_endpoint_stall(ep); +} + +static void _hw_endpoint_clear_stall(struct hw_endpoint *ep) +{ + if (ep->num == 0) + { + // Probably already been cleared but no harm + usb_hw_clear->ep_stall_arm = ep->in ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; + } + _hw_endpoint_buffer_control_clear_mask32(ep, USB_BUF_CTRL_STALL); + ep->stalled = false; +} + +static void hw_endpoint_clear_stall(uint8_t ep_addr) +{ + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + _hw_endpoint_clear_stall(ep); +} + +static void dcd_rp2040_irq(void) +{ + uint32_t status = usb_hw->ints; + uint32_t handled = 0; + + if (status & USB_INTS_SETUP_REQ_BITS) + { + handled |= USB_INTS_SETUP_REQ_BITS; + uint8_t const *setup = (uint8_t const *)&usb_dpram->setup_packet; + // Clear stall bits and reset pid + reset_ep0(); + // Pass setup packet to tiny usb + dcd_event_setup_received(0, setup, true); + usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS; + } + + if (status & USB_INTS_BUFF_STATUS_BITS) + { + handled |= USB_INTS_BUFF_STATUS_BITS; + hw_handle_buff_status(); + } + + if (status & USB_INTS_BUS_RESET_BITS) + { + pico_trace("BUS RESET (addr %d -> %d)\n", assigned_address, 0); + assigned_address = 0; + usb_hw->dev_addr_ctrl = assigned_address; + handled |= USB_INTS_BUS_RESET_BITS; + dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; +#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX + rp2040_usb_device_enumeration_fix(); +#endif + } + + if (status ^ handled) + { + panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled)); + } +} + +#define USB_INTS_ERROR_BITS ( \ + USB_INTS_ERROR_DATA_SEQ_BITS | \ + USB_INTS_ERROR_BIT_STUFF_BITS | \ + USB_INTS_ERROR_CRC_BITS | \ + USB_INTS_ERROR_RX_OVERFLOW_BITS | \ + USB_INTS_ERROR_RX_TIMEOUT_BITS) + +/*------------------------------------------------------------------*/ +/* Controller API + *------------------------------------------------------------------*/ +void dcd_init (uint8_t rhport) +{ + pico_trace("dcd_init %d\n", rhport); + assert(rhport == 0); + + // Reset hardware to default state + rp2040_usb_init(); + + irq_set_exclusive_handler(USBCTRL_IRQ, dcd_rp2040_irq); + memset(hw_endpoints, 0, sizeof(hw_endpoints)); + assigned_address = 0; + next_buffer_ptr = &usb_dpram->epx_data[0]; + + // EP0 always exists so init it now + // EP0 OUT + hw_endpoint_init(0x0, 64, 0); + // EP0 IN + hw_endpoint_init(0x80, 64, 0); + + // Initializes the USB peripheral for device mode and enables it. + // Don't need to enable the pull up here. Force VBUS + usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS; + + // Enable individual controller IRQS here. Processor interrupt enable will be used + // for the global interrupt enable... + usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS; + usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS; + + dcd_connect(rhport); +} + +void dcd_int_enable(uint8_t rhport) +{ + assert(rhport == 0); + irq_set_enabled(USBCTRL_IRQ, true); +} + +void dcd_int_disable(uint8_t rhport) +{ + assert(rhport == 0); + irq_set_enabled(USBCTRL_IRQ, false); +} + +void dcd_set_address (uint8_t rhport, uint8_t dev_addr) +{ + pico_trace("dcd_set_address %d %d\n", rhport, dev_addr); + assert(rhport == 0); + + // Can't set device address in hardware until status xfer has complete + assigned_address = dev_addr; + + ep0_0len_status(); +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + panic("dcd_remote_wakeup %d\n", rhport); + assert(rhport == 0); +} + +// disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + pico_info("dcd_disconnect %d\n", rhport); + assert(rhport == 0); + usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; +} + +// connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) +{ + pico_info("dcd_connect %d\n", rhport); + assert(rhport == 0); + usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; +} + +/*------------------------------------------------------------------*/ +/* DCD Endpoint port + *------------------------------------------------------------------*/ + +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + pico_trace("dcd_edpt0_status_complete %d\n", rhport); + assert(rhport == 0); + + if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && + request->bRequest == TUSB_REQ_SET_ADDRESS) + { + pico_trace("Set HW address %d\n", assigned_address); + usb_hw->dev_addr_ctrl = assigned_address; + } + + reset_ep0(); +} + +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) +{ + pico_info("dcd_edpt_open %d %02x\n", rhport, desc_edpt->bEndpointAddress); + assert(rhport == 0); + hw_endpoint_init(desc_edpt->bEndpointAddress, desc_edpt->wMaxPacketSize.size, desc_edpt->bmAttributes.xfer); + return true; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + assert(rhport == 0); + // True means start new xfer + hw_endpoint_xfer(ep_addr, buffer, total_bytes, true); + return true; +} + +void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) +{ + pico_trace("dcd_edpt_stall %d %02x\n", rhport, ep_addr); + assert(rhport == 0); + hw_endpoint_stall(ep_addr); +} + +void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) +{ + pico_trace("dcd_edpt_clear_stall %d %02x\n", rhport, ep_addr); + assert(rhport == 0); + hw_endpoint_clear_stall(ep_addr); +} + + +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) +{ + // usbd.c says: In progress transfers on this EP may be delivered after this call + pico_trace("dcd_edpt_close %d %02x\n", rhport, ep_addr); + +} + +#endif diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c new file mode 100644 index 000000000..c74578c3c --- /dev/null +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -0,0 +1,549 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_HOST_ENABLED && CFG_TUSB_MCU == OPT_MCU_RP2040 + +#include "pico.h" +#include "rp2040_usb.h" + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "osal/osal.h" + +#include "host/hcd.h" +#include "host/usbh.h" +#include "host/usbh_hcd.h" + +#define ROOT_PORT 0 + +//--------------------------------------------------------------------+ +// Low level rp2040 controller functions +//--------------------------------------------------------------------+ + +#ifndef PICO_USB_HOST_INTERRUPT_ENDPOINTS +#define PICO_USB_HOST_INTERRUPT_ENDPOINTS (USB_MAX_ENDPOINTS - 1) +#endif +static_assert(PICO_USB_HOST_INTERRUPT_ENDPOINTS <= USB_MAX_ENDPOINTS, ""); + +// Host mode uses one shared endpoint register for non-interrupt endpoint +struct hw_endpoint eps[1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS]; +#define epx (eps[0]) + +#define usb_hw_set hw_set_alias(usb_hw) +#define usb_hw_clear hw_clear_alias(usb_hw) + +// Used for hcd pipe busy. +// todo still a bit wasteful +// top bit set if valid +uint8_t dev_ep_map[CFG_TUSB_HOST_DEVICE_MAX][1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS][2]; + +// Flags we set by default in sie_ctrl (we add other bits on top) +static uint32_t sie_ctrl_base = USB_SIE_CTRL_SOF_EN_BITS | + USB_SIE_CTRL_KEEP_ALIVE_EN_BITS | + USB_SIE_CTRL_PULLDOWN_EN_BITS | + USB_SIE_CTRL_EP0_INT_1BUF_BITS; + +static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t num = tu_edpt_number(ep_addr); + if (num == 0) { + return &epx; + } + uint8_t in = (ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0; + uint mapping = dev_ep_map[dev_addr-1][num][in]; + pico_trace("Get dev addr %d ep %d = %d\n", dev_addr, ep_addr, mapping); + return mapping >= 128 ? eps + (mapping & 0x7fu) : NULL; +} + +static void set_dev_ep(uint8_t dev_addr, uint8_t ep_addr, struct hw_endpoint *ep) +{ + uint8_t num = tu_edpt_number(ep_addr); + uint8_t in = (ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0; + uint32_t index = ep - eps; + hard_assert(index < count_of(eps)); + // todo revisit why dev_addr can be 0 here + if (dev_addr) { + dev_ep_map[dev_addr-1][num][in] = 128u | index; + } + pico_trace("Set dev addr %d ep %d = %d\n", dev_addr, ep_addr, index); +} + +static inline uint8_t dev_speed(void) +{ + return (usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS) >> USB_SIE_STATUS_SPEED_LSB; +} + +static bool need_pre(uint8_t dev_addr) +{ + // If this device is different to the speed of the root device + // (i.e. is a low speed device on a full speed hub) then need pre + return hcd_port_speed_get(0) != tuh_device_get_speed(dev_addr); +} + +static void hw_xfer_complete(struct hw_endpoint *ep, xfer_result_t xfer_result) +{ + // Mark transfer as done before we tell the tinyusb stack + uint8_t dev_addr = ep->dev_addr; + uint8_t ep_addr = ep->ep_addr; + uint total_len = ep->total_len; + hw_endpoint_reset_transfer(ep); + hcd_event_xfer_complete(dev_addr, ep_addr, total_len, xfer_result, true); +} + +static void _handle_buff_status_bit(uint bit, struct hw_endpoint *ep) +{ + usb_hw_clear->buf_status = bit; + bool done = _hw_endpoint_xfer_continue(ep); + if (done) + { + hw_xfer_complete(ep, XFER_RESULT_SUCCESS); + } +} + +static void hw_handle_buff_status(void) +{ + uint32_t remaining_buffers = usb_hw->buf_status; + pico_trace("buf_status 0x%08x\n", remaining_buffers); + + // Check EPX first + uint bit = 0b1; + if (remaining_buffers & bit) + { + remaining_buffers &= ~bit; + struct hw_endpoint *ep = &epx; + _handle_buff_status_bit(bit, ep); + } + + // Check interrupt endpoints + for (uint i = 1; i <= USB_HOST_INTERRUPT_ENDPOINTS && remaining_buffers; i++) + { + // EPX is bit 0 + // IEP1 is bit 2 + // IEP2 is bit 4 + // IEP3 is bit 6 + // etc + bit = 1 << (i*2); + + if (remaining_buffers & bit) + { + remaining_buffers &= ~bit; + _handle_buff_status_bit(bit, &eps[i]); + } + } + + if (remaining_buffers) + { + panic("Unhandled buffer %d\n", remaining_buffers); + } +} + +static void hw_trans_complete(void) +{ + struct hw_endpoint *ep = &epx; + assert(ep->active); + + if (ep->sent_setup) + { + pico_trace("Sent setup packet\n"); + hw_xfer_complete(ep, XFER_RESULT_SUCCESS); + } + else + { + // Don't care. Will handle this in buff status + return; + } +} + +static void hcd_rp2040_irq(void) +{ + uint32_t status = usb_hw->ints; + uint32_t handled = 0; + + if (status & USB_INTS_HOST_CONN_DIS_BITS) + { + handled |= USB_INTS_HOST_CONN_DIS_BITS; + + if (dev_speed()) + { + hcd_event_device_attach(ROOT_PORT, true); + } + else + { + hcd_event_device_remove(ROOT_PORT, true); + } + + // Clear speed change interrupt + usb_hw_clear->sie_status = USB_SIE_STATUS_SPEED_BITS; + } + + if (status & USB_INTS_TRANS_COMPLETE_BITS) + { + handled |= USB_INTS_TRANS_COMPLETE_BITS; + usb_hw_clear->sie_status = USB_SIE_STATUS_TRANS_COMPLETE_BITS; + hw_trans_complete(); + } + + if (status & USB_INTS_BUFF_STATUS_BITS) + { + handled |= USB_INTS_BUFF_STATUS_BITS; + hw_handle_buff_status(); + } + + if (status & USB_INTS_STALL_BITS) + { + // We have rx'd a stall from the device + pico_trace("Stall REC\n"); + handled |= USB_INTS_STALL_BITS; + usb_hw_clear->sie_status = USB_SIE_STATUS_STALL_REC_BITS; + hw_xfer_complete(&epx, XFER_RESULT_STALLED); + } + + if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) + { + handled |= USB_INTS_ERROR_RX_TIMEOUT_BITS; + usb_hw_clear->sie_status = USB_SIE_STATUS_RX_TIMEOUT_BITS; + } + + if (status & USB_INTS_ERROR_DATA_SEQ_BITS) + { + usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS; + panic("Data Seq Error \n"); + } + + if (status ^ handled) + { + panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled)); + } +} + +static struct hw_endpoint *_next_free_interrupt_ep(void) +{ + struct hw_endpoint *ep = NULL; + for (uint i = 1; i < count_of(eps); i++) + { + ep = &eps[i]; + if (!ep->configured) + { + // Will be configured by _hw_endpoint_init / _hw_endpoint_allocate + ep->interrupt_num = i - 1; + return ep; + } + } + return ep; +} + +static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type) +{ + struct hw_endpoint *ep = NULL; + if (transfer_type == TUSB_XFER_INTERRUPT) + { + ep = _next_free_interrupt_ep(); + pico_info("Allocate interrupt ep %d\n", ep->interrupt_num); + assert(ep); + ep->buffer_control = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl; + ep->endpoint_control = &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; + // 0x180 for epx + // 0x1c0 for intep0 + // 0x200 for intep1 + // etc + ep->hw_data_buf = &usbh_dpram->epx_data[64 * (ep->interrupt_num + 1)]; + } + else + { + ep = &epx; + ep->buffer_control = &usbh_dpram->epx_buf_ctrl; + ep->endpoint_control = &usbh_dpram->epx_ctrl; + ep->hw_data_buf = &usbh_dpram->epx_data[0]; + } + return ep; +} + +static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep_addr, uint wMaxPacketSize, uint8_t transfer_type, uint8_t bmInterval) +{ + // Already has data buffer, endpoint control, and buffer control allocated at this point + assert(ep->endpoint_control); + assert(ep->buffer_control); + assert(ep->hw_data_buf); + + uint8_t num = tu_edpt_number(ep_addr); + bool in = ep_addr & TUSB_DIR_IN_MASK; + ep->ep_addr = ep_addr; + ep->dev_addr = dev_addr; + ep->in = in; + // For host, IN to host == RX, anything else rx == false + ep->rx = in == true; + ep->num = num; + // Response to a setup packet on EP0 starts with pid of 1 + ep->next_pid = num == 0 ? 1u : 0u; + ep->wMaxPacketSize = wMaxPacketSize; + ep->transfer_type = transfer_type; + + pico_trace("hw_endpoint_init dev %d ep %d %s xfer %d\n", ep->dev_addr, ep->num, ep_dir_string[ep->in], ep->transfer_type); + pico_trace("dev %d ep %d %s setup buffer @ 0x%p\n", ep->dev_addr, ep->num, ep_dir_string[ep->in], ep->hw_data_buf); + uint dpram_offset = hw_data_offset(ep->hw_data_buf); + // Bits 0-5 should be 0 + assert(!(dpram_offset & 0b111111)); + + // Fill in endpoint control register with buffer offset + uint32_t ep_reg = EP_CTRL_ENABLE_BITS + | EP_CTRL_INTERRUPT_PER_BUFFER + | (ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) + | dpram_offset; + ep_reg |= bmInterval ? (bmInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB : 0; + *ep->endpoint_control = ep_reg; + pico_trace("endpoint control (0x%p) <- 0x%x\n", ep->endpoint_control, ep_reg); + ep->configured = true; + + if (bmInterval) + { + // This is an interrupt endpoint + // so need to set up interrupt endpoint address control register with: + // device address + // endpoint number / direction + // preamble + uint32_t reg = dev_addr | (ep->num << USB_ADDR_ENDP1_ENDPOINT_LSB); + // Assert the interrupt endpoint is IN_TO_HOST + assert(ep->in); + + if (need_pre(dev_addr)) + { + reg |= USB_ADDR_ENDP1_INTEP_PREAMBLE_BITS; + } + usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = reg; + + // Finally, enable interrupt that endpoint + usb_hw_set->int_ep_ctrl = 1 << (ep->interrupt_num + 1); + + // If it's an interrupt endpoint we need to set up the buffer control + // register + + } +} + +static void hw_endpoint_init(uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc) +{ + // Allocated differently based on if it's an interrupt endpoint or not + struct hw_endpoint *ep = _hw_endpoint_allocate(ep_desc->bmAttributes.xfer); + _hw_endpoint_init(ep, + dev_addr, + ep_desc->bEndpointAddress, + ep_desc->wMaxPacketSize.size, + ep_desc->bmAttributes.xfer, + ep_desc->bInterval); + // Map this struct to ep@device address + set_dev_ep(dev_addr, ep_desc->bEndpointAddress, ep); +} + +//--------------------------------------------------------------------+ +// HCD API +//--------------------------------------------------------------------+ +bool hcd_init(void) +{ + pico_trace("hcd_init\n"); + + // Reset any previous state + rp2040_usb_init(); + + irq_set_exclusive_handler(USBCTRL_IRQ, hcd_rp2040_irq); + + // clear epx and interrupt eps + memset(&eps, 0, sizeof(eps)); + + // Enable in host mode with SOF / Keep alive on + usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS | USB_MAIN_CTRL_HOST_NDEVICE_BITS; + usb_hw->sie_ctrl = sie_ctrl_base; + usb_hw->inte = USB_INTE_BUFF_STATUS_BITS | + USB_INTE_HOST_CONN_DIS_BITS | + USB_INTE_HOST_RESUME_BITS | + USB_INTE_STALL_BITS | + USB_INTE_TRANS_COMPLETE_BITS | + USB_INTE_ERROR_RX_TIMEOUT_BITS | + USB_INTE_ERROR_DATA_SEQ_BITS ; + + return true; +} + +void hcd_port_reset(uint8_t rhport) +{ + pico_trace("hcd_port_reset\n"); + assert(rhport == 0); + // TODO: Nothing to do here yet. Perhaps need to reset some state? +} + +bool hcd_port_connect_status(uint8_t rhport) +{ + pico_trace("hcd_port_connect_status\n"); + assert(rhport == 0); + return usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS; +} + +tusb_speed_t hcd_port_speed_get(uint8_t rhport) +{ + pico_trace("hcd_port_speed_get\n"); + assert(rhport == 0); + // TODO: Should enumval this register + switch (dev_speed()) + { + case 1: + return TUSB_SPEED_LOW; + case 2: + return TUSB_SPEED_FULL; + default: + panic("Invalid speed\n"); + } +} + +// Close all opened endpoint belong to this device +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) +{ + pico_trace("hcd_device_close %d\n", dev_addr); +} + +void hcd_int_enable(uint8_t rhport) +{ + assert(rhport == 0); + irq_set_enabled(USBCTRL_IRQ, true); +} + +void hcd_int_disable(uint8_t rhport) +{ + // todo we should check this is disabling from the correct core; note currently this is never called + assert(rhport == 0); + irq_set_enabled(USBCTRL_IRQ, false); +} + +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) +{ + pico_info("hcd_edpt_xfer dev_addr %d, ep_addr 0x%x, len %d\n", dev_addr, ep_addr, buflen); + + // Get appropriate ep. Either EPX or interrupt endpoint + struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); + + if (ep_addr != ep->ep_addr) + { + // Direction has flipped so re init it but with same properties + _hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, ep->transfer_type, 0); + } + + // True indicates this is the start of the transfer + _hw_endpoint_xfer(ep, buffer, buflen, true); + + // If a normal transfer (non-interrupt) then initiate using + // sie ctrl registers. Otherwise interrupt ep registers should + // already be configured + if (ep == &epx) { + // That has set up buffer control, endpoint control etc + // for host we have to initiate the transfer + usb_hw->dev_addr_ctrl = dev_addr | ep->num << USB_ADDR_ENDP_ENDPOINT_LSB; + uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | sie_ctrl_base; + flags |= ep->rx ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS; + // Set pre if we are a low speed device on full speed hub + flags |= need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0; + usb_hw->sie_ctrl = flags; + } + + return true; +} + +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) +{ + pico_info("hcd_setup_send dev_addr %d\n", dev_addr); + + // Copy data into setup packet buffer + memcpy((void*)&usbh_dpram->setup_packet[0], setup_packet, 8); + + // Configure EP0 struct with setup info for the trans complete + struct hw_endpoint *ep = _hw_endpoint_allocate(0); + // EP0 out + _hw_endpoint_init(ep, dev_addr, 0x00, ep->wMaxPacketSize, 0, 0); + assert(ep->configured); + assert(ep->num == 0 && !ep->in); + ep->total_len = 8; + ep->transfer_size = 8; + ep->active = true; + ep->sent_setup = true; + + // Set device address + usb_hw->dev_addr_ctrl = dev_addr; + // Set pre if we are a low speed device on full speed hub + uint32_t flags = sie_ctrl_base | USB_SIE_CTRL_SEND_SETUP_BITS | USB_SIE_CTRL_START_TRANS_BITS; + flags |= need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0; + usb_hw->sie_ctrl = flags; + return true; +} + +uint32_t hcd_uframe_number(uint8_t rhport) +{ + // Microframe number is (125us) but we are max full speed so return miliseconds * 8 + return usb_hw->sof_rd * 8; +} + +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +{ + pico_trace("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, ep_desc->bEndpointAddress); + hw_endpoint_init(dev_addr, ep_desc); + return true; +} + +bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +{ + // EPX is shared, so multiple device addresses and endpoint addresses share that + // so if any transfer is active on epx, we are busy. Interrupt endpoints have their own + // EPX so ep->active will only be busy if there is a pending transfer on that interrupt endpoint + // on that device + pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\n", dev_addr, ep_addr); + struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); + assert(ep); + bool busy = ep->active; + pico_trace("busy == %d\n", busy); + return busy; +} + +bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) +{ + panic("hcd_pipe_stalled"); +} + +bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) +{ + panic("hcd_clear_stall"); + return true; +} + +bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) +{ + pico_trace("hcd_pipe_xfer dev_addr %d, ep_addr 0x%x, total_bytes %d, int_on_complete %d\n", + dev_addr, ep_addr, total_bytes, int_on_complete); + + // Same logic as hcd_edpt_xfer as far as I am concerned + hcd_edpt_xfer(0, dev_addr, ep_addr, buffer, total_bytes); + + return true; +} +#endif diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c new file mode 100644 index 000000000..a44607e99 --- /dev/null +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -0,0 +1,279 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include +#include "rp2040_usb.h" +#include "hardware/clocks.h" +#include "tusb_option.h" + +// Direction strings for debug +const char *ep_dir_string[] = { + "out", + "in", +}; + +static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) { + // todo add critsec as necessary to prevent issues between worker and IRQ... + // note that this is perhaps as simple as disabling IRQs because it would make + // sense to have worker and IRQ on same core, however I think using critsec is about equivalent. +} + +static inline void _hw_endpoint_update_last_buf(struct hw_endpoint *ep) +{ + ep->last_buf = ep->len + ep->transfer_size == ep->total_len; +} + +void rp2040_usb_init(void) +{ + // Reset usb controller + reset_block(RESETS_RESET_USBCTRL_BITS); + unreset_block_wait(RESETS_RESET_USBCTRL_BITS); + + // Clear any previous state just in case + memset(usb_hw, 0, sizeof(*usb_hw)); + memset(usb_dpram, 0, sizeof(*usb_dpram)); + + // Mux to phy + usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; + usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; +} + +void hw_endpoint_reset_transfer(struct hw_endpoint *ep) +{ + ep->stalled = false; + ep->active = false; + ep->sent_setup = false; + ep->total_len = 0; + ep->len = 0; + ep->transfer_size = 0; + ep->user_buf = 0; +} + +void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask) { + uint32_t value = 0; + if (and_mask) { + value = *ep->buffer_control & and_mask; + } + if (or_mask) { + value |= or_mask; + if (or_mask & USB_BUF_CTRL_AVAIL) { + if (*ep->buffer_control & USB_BUF_CTRL_AVAIL) { + panic("ep %d %s was already available", ep->num, ep_dir_string[ep->in]); + } + *ep->buffer_control = value & ~USB_BUF_CTRL_AVAIL; + // 12 cycle delay.. (should be good for 48*12Mhz = 576Mhz) + // Don't need delay in host mode as host is in charge +#ifndef RP2040_USB_HOST_MODE + __asm volatile ( + "b 1f\n" + "1: b 1f\n" + "1: b 1f\n" + "1: b 1f\n" + "1: b 1f\n" + "1: b 1f\n" + "1:\n" + : : : "memory"); +#endif + } + } + *ep->buffer_control = value; +} + +void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) +{ + // Prepare buffer control register value + uint32_t val = ep->transfer_size | USB_BUF_CTRL_AVAIL; + + if (!ep->rx) + { + // Copy data from user buffer to hw buffer + memcpy(ep->hw_data_buf, &ep->user_buf[ep->len], ep->transfer_size); + // Mark as full + val |= USB_BUF_CTRL_FULL; + } + + // PID + val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; + ep->next_pid ^= 1u; + + // Is this the last buffer? Only really matters for host mode. Will trigger + // the trans complete irq but also stop it polling. We only really care about + // trans complete for setup packets being sent + if (ep->last_buf) + { + pico_trace("Last buf (%d bytes left)\n", ep->transfer_size); + val |= USB_BUF_CTRL_LAST; + } + + // Finally, write to buffer_control which will trigger the transfer + // the next time the controller polls this dpram address + _hw_endpoint_buffer_control_set_value32(ep, val); + pico_trace("buffer control (0x%p) <- 0x%x\n", ep->buffer_control, val); +} + + +void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len) +{ + _hw_endpoint_lock_update(ep, 1); + pico_trace("Start transfer of total len %d on ep %d %s\n", total_len, ep->num, ep_dir_string[ep->in]); + if (ep->active) + { + // TODO: Is this acceptable for interrupt packets? + pico_warn("WARN: starting new transfer on already active ep %d %s\n", ep->num, ep_dir_string[ep->in]); + + hw_endpoint_reset_transfer(ep); + } + + // Fill in info now that we're kicking off the hw + ep->total_len = total_len; + ep->len = 0; + // FIXME: What if low speed + ep->transfer_size = total_len > 64 ? 64 : total_len; + ep->active = true; + ep->user_buf = buffer; + // Recalculate if this is the last buffer + _hw_endpoint_update_last_buf(ep); + ep->buf_sel = 0; + + _hw_endpoint_start_next_buffer(ep); + _hw_endpoint_lock_update(ep, -1); +} + +void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) +{ + // Update hw endpoint struct with info from hardware + // after a buff status interrupt + + // Get the buffer state and amount of bytes we have + // transferred + uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); + uint transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; + +#ifdef RP2040_USB_HOST_MODE + // tag::host_buf_sel_fix[] + if (ep->buf_sel == 1) + { + // Host can erroneously write status to top half of buf_ctrl register + buf_ctrl = buf_ctrl >> 16; + } + // Flip buf sel for host + ep->buf_sel ^= 1u; + // end::host_buf_sel_fix[] +#endif + + // We are continuing a transfer here. If we are TX, we have successfullly + // sent some data can increase the length we have sent + if (!ep->rx) + { + assert(!(buf_ctrl & USB_BUF_CTRL_FULL)); + pico_trace("tx %d bytes (buf_ctrl 0x%08x)\n", transferred_bytes, buf_ctrl); + ep->len += transferred_bytes; + } + else + { + // If we are OUT we have recieved some data, so can increase the length + // we have recieved AFTER we have copied it to the user buffer at the appropriate + // offset + pico_trace("rx %d bytes (buf_ctrl 0x%08x)\n", transferred_bytes, buf_ctrl); + assert(buf_ctrl & USB_BUF_CTRL_FULL); + memcpy(&ep->user_buf[ep->len], ep->hw_data_buf, transferred_bytes); + ep->len += transferred_bytes; + } + + // Sometimes the host will send less data than we expect... + // If this is a short out transfer update the total length of the transfer + // to be the current length + if ((ep->rx) && (transferred_bytes < ep->transfer_size)) + { + pico_trace("Short rx transfer\n"); + // Reduce total length as this is last packet + ep->total_len = ep->len; + } +} + +// Returns true if transfer is complete +bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) +{ + _hw_endpoint_lock_update(ep, 1); + // Part way through a transfer + if (!ep->active) + { + panic("Can't continue xfer on inactive ep %d %s", ep->num, ep_dir_string); + } + + // Update EP struct from hardware state + _hw_endpoint_xfer_sync(ep); + + // Now we have synced our state with the hardware. Is there more data to transfer? + uint remaining_bytes = ep->total_len - ep->len; + ep->transfer_size = remaining_bytes > 64 ? 64 : remaining_bytes; + _hw_endpoint_update_last_buf(ep); + + // Can happen because of programmer error so check for it + if (ep->len > ep->total_len) + { + panic("Transferred more data than expected"); + } + + // If we are done then notify tinyusb + if (ep->len == ep->total_len) + { + pico_trace("Completed transfer of %d bytes on ep %d %s\n", + ep->len, ep->num, ep_dir_string[ep->in]); + // Notify caller we are done so it can notify the tinyusb + // stack + _hw_endpoint_lock_update(ep, -1); + return true; + } + else + { + _hw_endpoint_start_next_buffer(ep); + } + + _hw_endpoint_lock_update(ep, -1); + // More work to do + return false; +} + +void _hw_endpoint_xfer(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len, bool start) +{ + // Trace + pico_trace("hw_endpoint_xfer ep %d %s", ep->num, ep_dir_string[ep->in]); + pico_trace(" total_len %d, start=%d\n", total_len, start); + + assert(ep->configured); + + + if (start) + { + _hw_endpoint_xfer_start(ep, buffer, total_len); + } + else + { + _hw_endpoint_xfer_continue(ep); + } +} + diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h new file mode 100644 index 000000000..7c3234e8d --- /dev/null +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -0,0 +1,124 @@ +#ifndef RP2040_COMMON_H_ +#define RP2040_COMMON_H_ + +#if defined(RP2040_USB_HOST_MODE) && defined(RP2040_USB_DEVICE_MODE) +#error TinyUSB device and host mode not supported at the same time +#endif + +#include "common/tusb_common.h" + +#include "pico.h" +#include "hardware/structs/usb.h" +#include "hardware/irq.h" +#include "hardware/resets.h" + +#if defined(PICO_RP2040_USB_DEVICE_ENUMERATION_FIX) && !defined(TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX) +#define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX +#endif + +// For memset +#include + +#if false && !defined(NDEBUG) +#define pico_trace(format,args...) printf(format, ## args) +#else +#define pico_trace(format,...) ((void)0) +#endif + +#if false && !defined(NDEBUG) +#define pico_info(format,args...) printf(format, ## args) +#else +#define pico_info(format,...) ((void)0) +#endif + +#if false && !defined(NDEBUG) +#define pico_warn(format,args...) printf(format, ## args) +#else +#define pico_warn(format,...) ((void)0) +#endif + +// Hardware information per endpoint +struct hw_endpoint +{ + // Is this a valid struct + bool configured; + // EP direction + bool in; + // EP num (not including direction) + uint8_t num; + + // Transfer direction (i.e. IN is rx for host but tx for device) + // allows us to common up transfer functions + bool rx; + + uint8_t ep_addr; + uint8_t next_pid; + + // Endpoint control register + io_rw_32 *endpoint_control; + // Buffer control register + io_rw_32 *buffer_control; + + // Buffer pointer in usb dpram + uint8_t *hw_data_buf; + + // Have we been stalled + bool stalled; + + // Current transfer information + bool active; + uint total_len; + uint len; + // Amount of data with the hardware + uint transfer_size; + // Only needed for host mode + bool last_buf; + // HOST BUG. Host will incorrect write status to top half of buffer + // control register when doing transfers > 1 packet + uint8_t buf_sel; + // User buffer in main memory + uint8_t *user_buf; + + // Data needed from EP descriptor + uint wMaxPacketSize; + // Interrupt, bulk, etc + uint8_t transfer_type; + + // Only needed for host + uint8_t dev_addr; + bool sent_setup; + // If interrupt endpoint + uint8_t interrupt_num; +}; + +void rp2040_usb_init(void); + +void hw_endpoint_reset_transfer(struct hw_endpoint *ep); +void _hw_endpoint_xfer(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len, bool start); +void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep); +void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len); +void _hw_endpoint_xfer_sync(struct hw_endpoint *ep); +bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep); +void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask); +static inline uint32_t _hw_endpoint_buffer_control_get_value32(struct hw_endpoint *ep) { + return *ep->buffer_control; +} +static inline void _hw_endpoint_buffer_control_set_value32(struct hw_endpoint *ep, uint32_t value) { + return _hw_endpoint_buffer_control_update32(ep, 0, value); +} +static inline void _hw_endpoint_buffer_control_set_mask32(struct hw_endpoint *ep, uint32_t value) { + return _hw_endpoint_buffer_control_update32(ep, ~value, value); +} +static inline void _hw_endpoint_buffer_control_clear_mask32(struct hw_endpoint *ep, uint32_t value) { + return _hw_endpoint_buffer_control_update32(ep, ~value, 0); +} + +static inline uintptr_t hw_data_offset(uint8_t *buf) +{ + // Remove usb base from buffer pointer + return (uintptr_t)buf ^ (uintptr_t)usb_dpram; +} + +extern const char *ep_dir_string[]; + +#endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 2dd2b5841..a4eeeeb7c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -97,6 +97,9 @@ // Dialog #define OPT_MCU_DA1469X 1000 ///< Dialog Semiconductor DA1469x +// Raspberry Pi +#define OPT_MCU_RP2040 1100 ///< Raspberry Pi RP2040 + /** @} */ /** \defgroup group_supported_os Supported RTOS @@ -106,6 +109,7 @@ #define OPT_OS_FREERTOS 2 ///< FreeRTOS #define OPT_OS_MYNEWT 3 ///< Mynewt OS #define OPT_OS_CUSTOM 4 ///< Custom OS is implemented by application +#define OPT_OS_PICO 5 ///< Raspberry Pi Pico SDK /** @} */ -- cgit v1.3.1 From f1551d7a5fe5faccad9c1ef3f5d374869a1874e6 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 20 Jan 2021 20:14:23 +0100 Subject: Add __restrict keyword and memore alignment to src/dst pointer of _tu_fifo_read_from_const_src_ptr() _tu_fifo_write_to_const_dst_ptr() --- src/common/tusb_fifo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index ca03864eb..ff2e2c6fd 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -95,9 +95,9 @@ static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) // Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address // Code adapted from dcd_synopsis.c -static void _tu_fifo_read_from_const_src_ptr(void * dst, const void * src, uint16_t len) +static void _tu_fifo_read_from_const_src_ptr(void * __restrict dst, const void * __restrict src, uint16_t len) { - uint8_t * dst_u8 = (uint8_t *)dst; + uint8_t CFG_TUSB_MEM_ALIGN * dst_u8 = (uint8_t *)dst; volatile uint32_t * rx_fifo = (volatile uint32_t *) src; // Reading full available 32 bit words from FIFO @@ -127,10 +127,10 @@ static void _tu_fifo_read_from_const_src_ptr(void * dst, const void * src, uint1 // Intended to be used to write to hardware USB FIFO in e.g. STM32 where all data is written to a constant address // Code adapted from dcd_synopsis.c -static void _tu_fifo_write_to_const_dst_ptr(void * dst, const void * src, uint16_t len) +static void _tu_fifo_write_to_const_dst_ptr(void * __restrict dst, const void * __restrict src, uint16_t len) { volatile uint32_t * tx_fifo = (volatile uint32_t *) dst; - uint8_t * src_u8 = (uint8_t *)src; + uint8_t CFG_TUSB_MEM_ALIGN * src_u8 = (uint8_t *)src; // Pushing full available 32 bit words to FIFO uint16_t full_words = len >> 2; -- cgit v1.3.1 From 67a9cdc35baf3767bd24c78c68e0b969d2d7c191 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 22 Jan 2021 11:33:25 +0700 Subject: fix compiler warning --- src/host/usbh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index bf265199d..10ae991f4 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -154,7 +154,7 @@ tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr) tusb_speed_t tuh_device_get_speed (uint8_t const dev_addr) { TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_DEVICE_STATE_UNPLUG); - return _usbh_devices[dev_addr].speed; + return (tusb_speed_t) _usbh_devices[dev_addr].speed; } void osal_task_delay(uint32_t msec) -- cgit v1.3.1 From 587d1b334b9368759b2afba3114bc5590e7aee09 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sat, 23 Jan 2021 20:19:10 -0600 Subject: rp2040_hcd: check pointer before using --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index c74578c3c..5ea9c7d53 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -444,6 +444,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * // Get appropriate ep. Either EPX or interrupt endpoint struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); + assert(ep); if (ep_addr != ep->ep_addr) { -- cgit v1.3.1 From edc2224118ca18d8c9dd9d6d77d66f6a6d904230 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sat, 23 Jan 2021 20:21:58 -0600 Subject: rp2040: start to adopt TU coding conventions --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 16 ++++++++-------- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 80e5d3c4b..8ad1729e5 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -38,8 +38,6 @@ #include "device/dcd.h" -#include "pico/stdlib.h" - /*------------------------------------------------------------------*/ /* Low level controller *------------------------------------------------------------------*/ @@ -67,11 +65,7 @@ static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr) } static void _hw_endpoint_alloc(struct hw_endpoint *ep) { - uint size = 64; - if (ep->wMaxPacketSize > 64) - { - size = ep->wMaxPacketSize; - } + uint size = TU_MIN(64, ep->wMaxPacketSize); // Assumes single buffered for now ep->hw_data_buf = next_buffer_ptr; @@ -244,7 +238,7 @@ static void reset_ep0(void) // If we have finished this transfer on EP0 set pid back to 1 for next // setup transfer. Also clear a stall in case uint8_t addrs[] = {0x0, 0x80}; - for (uint i = 0 ; i < count_of(addrs); i++) + for (uint i = 0 ; i < TU_ARRAY_SIZE(addrs); i++) { struct hw_endpoint *ep = hw_endpoint_get_by_addr(addrs[i]); ep->next_pid = 1u; @@ -479,4 +473,10 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) } +void dcd_int_handler(uint8_t rhport) +{ + (void) rhport; + dcd_rp2040_irq(); +} + #endif diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 5ea9c7d53..efb2bd430 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -86,7 +86,7 @@ static void set_dev_ep(uint8_t dev_addr, uint8_t ep_addr, struct hw_endpoint *ep uint8_t num = tu_edpt_number(ep_addr); uint8_t in = (ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0; uint32_t index = ep - eps; - hard_assert(index < count_of(eps)); + hard_assert(index < TU_ARRAY_SIZE(eps)); // todo revisit why dev_addr can be 0 here if (dev_addr) { dev_ep_map[dev_addr-1][num][in] = 128u | index; @@ -245,7 +245,7 @@ static void hcd_rp2040_irq(void) static struct hw_endpoint *_next_free_interrupt_ep(void) { struct hw_endpoint *ep = NULL; - for (uint i = 1; i < count_of(eps); i++) + for (uint i = 1; i < TU_ARRAY_SIZE(eps); i++) { ep = &eps[i]; if (!ep->configured) -- cgit v1.3.1 From ec458292fecbf16be425e5497722f647911de969 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 25 Jan 2021 13:25:47 +0700 Subject: fix host build --- src/common/tusb_types.h | 3 ++- src/host/usbh.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 5ab15aa3c..2b4ceb69c 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -48,7 +48,8 @@ typedef enum { TUSB_SPEED_FULL = 0, TUSB_SPEED_LOW , - TUSB_SPEED_HIGH + TUSB_SPEED_HIGH, + TUSB_SPEED_INVALID = 0xff, }tusb_speed_t; /// defined base on USB Specs Endpoint's bmAttributes diff --git a/src/host/usbh.c b/src/host/usbh.c index 10ae991f4..f278f4d94 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -153,7 +153,7 @@ tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr) tusb_speed_t tuh_device_get_speed (uint8_t const dev_addr) { - TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_DEVICE_STATE_UNPLUG); + TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_SPEED_INVALID); return (tusb_speed_t) _usbh_devices[dev_addr].speed; } -- cgit v1.3.1 From 5f999fa6a06ecb7ebec742be0b0175943cdfb774 Mon Sep 17 00:00:00 2001 From: Kamil Tomaszewski Date: Fri, 22 Jan 2021 16:03:31 +0100 Subject: Fix dcd issues on cxd56 Pass the next setup package when USB stack is ready to receive it. When the transfer is 0 on EP0 send complete to the USB stack Pass the data received after the setup package to the USB stack. --- src/portable/sony/cxd56/dcd_cxd56.c | 90 +++++++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 9269903a5..88027ccaa 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright 2019 Sony Semiconductor Solutions Corporation @@ -33,14 +33,23 @@ #include #include "device/dcd.h" +#include "osal/osal.h" #define CXD56_EPNUM (7) +#define CXD56_SETUP_QUEUE_DEPTH (4) +#define CXD56_MAX_DATA_OUT_SIZE (64) + +OSAL_QUEUE_DEF(OPT_MODE_DEVICE, _setup_queue_def, CXD56_SETUP_QUEUE_DEPTH, struct usb_ctrlreq_s); struct usbdcd_driver_s { struct usbdevclass_driver_s usbdevclass_driver; FAR struct usbdev_ep_s *ep[CXD56_EPNUM]; FAR struct usbdev_req_s *req[CXD56_EPNUM]; + osal_queue_t setup_queue; + bool setup_processed; + FAR uint8_t dataout[CXD56_MAX_DATA_OUT_SIZE]; + size_t outlen; }; static struct usbdcd_driver_s usbdcd_driver; @@ -118,14 +127,26 @@ static void _dcd_unbind(FAR struct usbdevclass_driver_s *driver, FAR struct usbd } static int _dcd_setup(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev, - FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, size_t outlen) + FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, size_t outlen) { (void) driver; (void) dev; - (void) dataout; - (void) outlen; - dcd_event_setup_received(0, (uint8_t *)ctrl, true); + if (usbdcd_driver.setup_processed) + { + usbdcd_driver.setup_processed = false; + dcd_event_setup_received(0, (uint8_t *) ctrl, true); + } + else + { + osal_queue_send(usbdcd_driver.setup_queue, ctrl, true); + } + + if (outlen > 0 && outlen <= CXD56_MAX_DATA_OUT_SIZE) + { + memcpy(usbdcd_driver.dataout, dataout, outlen); + usbdcd_driver.outlen = outlen; + } return 0; } @@ -161,6 +182,8 @@ void dcd_init(uint8_t rhport) usbdcd_driver.usbdevclass_driver.speed = USB_SPEED_HIGH; usbdcd_driver.usbdevclass_driver.ops = &g_driverops; + usbdcd_driver.setup_processed = true; + usbdcd_driver.setup_queue = osal_queue_create(&_setup_queue_def); usbdev_register(&usbdcd_driver.usbdevclass_driver); } @@ -191,7 +214,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) void dcd_remote_wakeup(uint8_t rhport) { (void) rhport; - + DEV_WAKEUP(usbdev); } @@ -277,6 +300,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to { (void) rhport; + bool ret = true; uint8_t epnum = tu_edpt_number(ep_addr); if (epnum >= CXD56_EPNUM) @@ -284,25 +308,53 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return false; } - usbdcd_driver.req[epnum]->len = total_bytes; - usbdcd_driver.req[epnum]->priv = (void *)((uint32_t)ep_addr); - usbdcd_driver.req[epnum]->flags = 0; - - if (total_bytes) + if (epnum == 0) { - usbdcd_driver.req[epnum]->buf = buffer; + if (total_bytes == 0) + { + dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, false); + } + else if (ep_addr == 0x00 && total_bytes == usbdcd_driver.outlen) + { + memcpy(buffer, usbdcd_driver.dataout, usbdcd_driver.outlen); + dcd_event_xfer_complete(0, ep_addr, total_bytes, XFER_RESULT_SUCCESS, false); + usbdcd_driver.outlen = 0; + } + else + { + usbdcd_driver.req[epnum]->len = total_bytes; + usbdcd_driver.req[epnum]->priv = (void *)((uint32_t)ep_addr); + usbdcd_driver.req[epnum]->flags = total_bytes < usbdcd_driver.ep[epnum]->maxpacket ? USBDEV_REQFLAGS_NULLPKT : 0; + usbdcd_driver.req[epnum]->buf = buffer; + + if (EP_SUBMIT(usbdcd_driver.ep[epnum], usbdcd_driver.req[epnum]) < 0) + { + ret = false; + } + } + + usbdcd_driver.setup_processed = true; + struct usb_ctrlreq_s ctrl; + + if (osal_queue_receive(usbdcd_driver.setup_queue, &ctrl)) + { + dcd_event_setup_received(0, (uint8_t *)&ctrl, false); + } } else { - return true; - } + usbdcd_driver.req[epnum]->len = total_bytes; + usbdcd_driver.req[epnum]->priv = (void *)((uint32_t)ep_addr); + usbdcd_driver.req[epnum]->flags = total_bytes < usbdcd_driver.ep[epnum]->maxpacket ? USBDEV_REQFLAGS_NULLPKT : 0; + usbdcd_driver.req[epnum]->buf = buffer; - if (EP_SUBMIT(usbdcd_driver.ep[epnum], usbdcd_driver.req[epnum]) < 0) - { - return false; + if (EP_SUBMIT(usbdcd_driver.ep[epnum], usbdcd_driver.req[epnum]) < 0) + { + ret = false; + } } - return true; + return ret; } void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) @@ -322,7 +374,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - + uint8_t epnum = tu_edpt_number(ep_addr); if (epnum >= CXD56_EPNUM) -- cgit v1.3.1 From c3c4f65fea69c7db53c9834cf426a831dc28f2eb Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 Jan 2021 13:04:38 +0700 Subject: wrap rp2040_usb around opt mcu --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index a44607e99..5c536e314 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -24,10 +24,13 @@ * This file is part of the TinyUSB stack. */ +#include "tusb_option.h" + +#if CFG_TUSB_MCU == OPT_MCU_RP2040 + #include #include "rp2040_usb.h" #include "hardware/clocks.h" -#include "tusb_option.h" // Direction strings for debug const char *ep_dir_string[] = { @@ -277,3 +280,4 @@ void _hw_endpoint_xfer(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_l } } +#endif -- cgit v1.3.1 From 1abf9eeb808d9c023352c62a486e68bdf75e1ff6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 Jan 2021 13:18:03 +0700 Subject: clean up rp2040 assigned_address, remove panic from remote_wakeup --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 11 +++-------- tools/build_family.py | 3 ++- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 80e5d3c4b..aaaa22e55 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -48,7 +48,6 @@ #define usb_hw_clear hw_clear_alias(usb_hw) // Init these in dcd_init -static uint8_t assigned_address; static uint8_t *next_buffer_ptr; // Endpoints 0-15, direction 0 for out and 1 for in. @@ -319,8 +318,7 @@ static void dcd_rp2040_irq(void) if (status & USB_INTS_BUS_RESET_BITS) { pico_trace("BUS RESET (addr %d -> %d)\n", assigned_address, 0); - assigned_address = 0; - usb_hw->dev_addr_ctrl = assigned_address; + usb_hw->dev_addr_ctrl = 0; handled |= USB_INTS_BUS_RESET_BITS; dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; @@ -355,7 +353,6 @@ void dcd_init (uint8_t rhport) irq_set_exclusive_handler(USBCTRL_IRQ, dcd_rp2040_irq); memset(hw_endpoints, 0, sizeof(hw_endpoints)); - assigned_address = 0; next_buffer_ptr = &usb_dpram->epx_data[0]; // EP0 always exists so init it now @@ -394,14 +391,12 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) assert(rhport == 0); // Can't set device address in hardware until status xfer has complete - assigned_address = dev_addr; - ep0_0len_status(); } void dcd_remote_wakeup(uint8_t rhport) { - panic("dcd_remote_wakeup %d\n", rhport); + pico_info("dcd_remote_wakeup %d is not supported yet\n", rhport); assert(rhport == 0); } @@ -435,7 +430,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re request->bRequest == TUSB_REQ_SET_ADDRESS) { pico_trace("Set HW address %d\n", assigned_address); - usb_hw->dev_addr_ctrl = assigned_address; + usb_hw->dev_addr_ctrl = (uint8_t) request->wValue; } reset_ep0(); diff --git a/tools/build_family.py b/tools/build_family.py index b178d8d41..23a08c663 100644 --- a/tools/build_family.py +++ b/tools/build_family.py @@ -49,6 +49,7 @@ def build_family(example, family): for entry in os.scandir("hw/bsp/{}/boards".format(family)): if entry.is_dir(): all_boards.append(entry.name) + filter_with_input(all_boards) all_boards.sort() for board in all_boards: @@ -83,7 +84,7 @@ def build_board(example, board): print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size)) if build_result.returncode != 0: - print(build_result.stdout.decode("utf-8")) + print(build_result.stdout.decode("utf-8")) def build_size(example, board): #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) -- cgit v1.3.1 From c4f7ea09f1e5df01eecc2b223728e066c1d8fc02 Mon Sep 17 00:00:00 2001 From: Michael Himing Date: Thu, 28 Jan 2021 20:31:11 +1100 Subject: Fix midi sysex sending bug --- src/class/midi/midi_device.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index ce4c9cafe..9fff20be2 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -192,6 +192,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u if (midi->write_buffer[0] == 0x4) { if (data == 0xf7) { midi->write_buffer[0] = 0x5; + midi->write_target_length = 2; } else { midi->write_target_length = 4; } -- cgit v1.3.1 From 2a34be2eb0654198f535afced31556d832b4bf58 Mon Sep 17 00:00:00 2001 From: Alexander Golovanov <45916903+homeodor@users.noreply.github.com> Date: Sat, 30 Jan 2021 04:11:08 +0300 Subject: A CDC-like blocking behaviour --- src/class/midi/midi_device.c | 48 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index ce4c9cafe..513f84caf 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -85,6 +85,32 @@ bool tud_midi_n_mounted (uint8_t itf) return midi->ep_in && midi->ep_out; } +static void _prep_out_transaction (midid_interface_t* p_midi) +{ + uint8_t const rhport = TUD_OPT_RHPORT; + uint16_t available = tu_fifo_remaining(&p_midi->rx_ff); + + // Prepare for incoming data but only allow what we can store in the ring buffer. + // TODO Actually we can still carry out the transfer, keeping count of received bytes + // and slowly move it to the FIFO when read(). + // This pre-check reduces endpoint claiming + TU_VERIFY(available >= sizeof(p_midi->epout_buf), ); + + // claim endpoint + TU_VERIFY(usbd_edpt_claim(rhport, p_midi->ep_out), ); + + // fifo can be changed before endpoint is claimed + available = tu_fifo_remaining(&p_midi->rx_ff); + + if ( available >= sizeof(p_midi->epout_buf) ) { + usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, sizeof(p_midi->epout_buf)); + }else + { + // Release endpoint since we don't make any transfer + usbd_edpt_release(rhport, p_midi->ep_out); + } +} + //--------------------------------------------------------------------+ // READ API //--------------------------------------------------------------------+ @@ -135,12 +161,17 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bu void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id) { (void) jack_id; - tu_fifo_clear(&_midid_itf[itf].rx_ff); + midid_interface_t* p_midi = &_midid_itf[itf]; + tu_fifo_clear(&p_midi->rx_ff); + _prep_out_transaction(p_midi); } bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]) { - return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4); + midid_interface_t* p_midi = &_midid_itf[itf]; + uint32_t num_read = tu_fifo_read_n(&p_midi->rx_ff, packet, 4); + _prep_out_transaction(p_midi); + return (num_read == 4); } void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) { @@ -274,8 +305,8 @@ void midid_init(void) midid_interface_t* midi = &_midid_itf[i]; // config fifo - tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, true); - tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, true); + tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, false); // true, true + tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); // OBVS. #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&midi->rx_ff, osal_mutex_create(&midi->rx_ff_mutex)); @@ -366,11 +397,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint } // Prepare for incoming data - if ( !usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE) ) - { - TU_LOG1_FAILED(); - TU_BREAKPOINT(); - } + _prep_out_transaction(p_midi); return drv_len; } @@ -391,6 +418,7 @@ bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; + (void) rhport; uint8_t itf; midid_interface_t* p_midi; @@ -414,7 +442,7 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 // prepare for next // TODO for now ep_out is not used by public API therefore there is no race condition, // and does not need to claim like ep_in - TU_ASSERT(usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE), false); + _prep_out_transaction(p_midi); } else if ( ep_addr == p_midi->ep_in ) { -- cgit v1.3.1 From 84406f1654ca757ecd7294f4b98b56146583be49 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 31 Jan 2021 19:08:23 +0100 Subject: Rework audio driver --- src/class/audio/audio_device.c | 410 ++++++++++++++++---------------- src/class/audio/audio_device.h | 317 +++++++++++++++--------- src/device/dcd.h | 12 +- src/device/usbd.c | 10 +- src/device/usbd_pvt.h | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 8 +- 6 files changed, 419 insertions(+), 340 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 616760223..07bfe6158 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -32,8 +32,6 @@ * * */ -// TODO: Rename CFG_TUD_AUDIO_EPSIZE_IN to CFG_TUD_AUDIO_EP_IN_BUFFER_SIZE - #include "tusb_option.h" #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO) @@ -49,30 +47,17 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -#ifndef CFG_TUD_AUDIO_TX_FIFO_COUNT -#define CFG_TUD_AUDIO_TX_FIFO_COUNT CFG_TUD_AUDIO_N_CHANNELS_TX -#endif -#endif - -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -#ifndef CFG_TUD_AUDIO_RX_FIFO_COUNT -#define CFG_TUD_AUDIO_RX_FIFO_COUNT CFG_TUD_AUDIO_N_CHANNELS_RX -#endif -#endif - typedef struct { uint8_t rhport; uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function -#if CFG_TUD_AUDIO_EPSIZE_IN - uint8_t ep_in; // Outgoing (out of uC) audio data EP. - uint16_t epin_buf_cnt; // Count filling status of EP in buffer - this is a shared state currently and is intended to be removed once EP buffers can be implemented as FIFOs! +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + uint8_t ep_in; // TX audio data EP. uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE uint8_t ep_out; // Incoming (into uC) audio data EP. uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) @@ -89,49 +74,60 @@ typedef struct #if CFG_TUD_AUDIO_N_AS_INT uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! #endif + /*------------- From this point, data is not cleared by bus reset -------------*/ // Buffer for control requests CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_AUDIO_CTRL_BUF_SIZE]; - // FIFO -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - tu_fifo_t tx_ff[CFG_TUD_AUDIO_TX_FIFO_COUNT]; - CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_TX_FIFO_COUNT][CFG_TUD_AUDIO_TX_FIFO_SIZE]; + // EP Transfer buffers and FIFOs +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + CFG_TUSB_MEM_ALIGN uint8_t ep_out_buf[CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE]; + tu_fifo_t ep_out_ff; + #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_TX_FIFO_COUNT]; + osal_mutex_def_t ep_out_ff_mutex; #endif + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). +#endif + #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - tu_fifo_t rx_ff[CFG_TUD_AUDIO_RX_FIFO_COUNT]; - CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_RX_FIFO_COUNT][CFG_TUD_AUDIO_RX_FIFO_SIZE]; +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + CFG_TUSB_MEM_ALIGN uint8_t ep_in_buf[CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE]; + tu_fifo_t ep_in_ff; + #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_RX_FIFO_COUNT]; + osal_mutex_def_t ep_in_ff_mutex; #endif + #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - tu_fifo_t int_ctr_ff; - CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; + // Support FIFOs +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE + tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; + CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t int_ctr_ff_mutex; + osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; #endif #endif - // Endpoint Transfer buffers -#if CFG_TUD_AUDIO_EPSIZE_OUT - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here) - -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE + tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; + CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; #endif - #endif -#if CFG_TUD_AUDIO_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_AUDIO_EPSIZE_IN]; // Bigger makes no sense for isochronous EP's (but technically possible here) - tu_fifo_t epin_ff; +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + tu_fifo_t int_ctr_ff; + CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; +#if CFG_FIFO_MUTEX + osal_mutex_def_t int_ctr_ff_mutex; +#endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -149,11 +145,11 @@ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; extern const uint16_t tud_audio_desc_lengths[]; -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio); #endif @@ -167,34 +163,23 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); bool tud_audio_n_mounted(uint8_t itf) { + TU_VERIFY(itf < CFG_TUD_AUDIO); audiod_interface_t* audio = &_audiod_itf[itf]; -#if CFG_TUD_AUDIO_EPSIZE_OUT - if (audio->ep_out == 0) - { - return false; - } +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + if (audio->ep_out == 0) return false; #endif -#if CFG_TUD_AUDIO_EPSIZE_IN - if (audio->ep_in == 0) - { - return false; - } +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + if (audio->ep_in == 0) return false; #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - if (audio->ep_int_ctr == 0) - { - return false; - } + if (audio->ep_int_ctr == 0) return false; #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (audio->ep_fb == 0) - { - return false; - } + if (audio->ep_fb == 0) return false; #endif return true; @@ -204,43 +189,58 @@ bool tud_audio_n_mounted(uint8_t itf) // READ API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 -uint16_t tud_audio_n_available(uint8_t itf, uint8_t channelId) +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + +uint16_t tud_audio_n_available(uint8_t itf) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + return tu_fifo_count(&_audiod_itf[itf].ep_out_ff); } -uint16_t tud_audio_n_read(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) +uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + return tu_fifo_read_n(&_audiod_itf[itf].ep_out_ff, buffer, bufsize); } -void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId) +void tud_audio_n_clear_ep_out_ff(uint8_t itf) { - TU_VERIFY(channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); - tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + return tu_fifo_clear(&_audiod_itf[itf].ep_out_ff); } -#else -uint16_t tud_audio_n_available(uint8_t itf) + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +// Delete all content in the support RX FIFOs +void tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) { - return tu_fifo_count(&_audiod_itf[itf].rx_ff[0]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); + tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); } -uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize) +uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) { - return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[0], buffer, bufsize); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); + tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); } -void tud_audio_n_read_flush (uint8_t itf) +uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { - tu_fifo_clear(&_audiod_itf[itf].rx_ff[0]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); + return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); } #endif + #endif + + + + + + + + + #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN uint16_t tud_audio_int_ctr_n_available(uint8_t itf) @@ -261,9 +261,9 @@ void tud_audio_int_ctr_n_read_flush (uint8_t itf) #endif // This function is called once something is received by USB and is responsible for decoding received stream into audio channels. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_FIFO_SIZE = 0. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE = 0. -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) { @@ -281,7 +281,7 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* { case AUDIO_DATA_FORMAT_TYPE_I_PCM: -#if CFG_TUD_AUDIO_RX_FIFO_SIZE +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); #else #error YOUR DECODING AND BUFFERING IS REQUIRED HERE! @@ -309,11 +309,11 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* return true; } -#endif //CFG_TUD_AUDIO_EPSIZE_OUT +#endif //CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -// The following functions are used in case CFG_TUD_AUDIO_RX_FIFO_SIZE != 0 -#if CFG_TUD_AUDIO_RX_FIFO_SIZE -#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 +// The following functions are used in case CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE != 0 +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_N_CHANNELS_RX > 1 static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize) { (void) rhport; @@ -365,13 +365,53 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t *a tu_fifo_write_n(&audio->rx_ff[0], buffer, bufsize); return true; } -#endif // CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 -#endif //CFG_TUD_AUDIO_RX_FIFO_SIZE +#endif // CFG_TUD_AUDIO_N_CHANNELS_RX > 1 +#endif //CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + +uint16_t tud_audio_n_write(uint8_t itf, const void * data, uint16_t len) +{ + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + return tu_fifo_write_n(&_audiod_itf[itf].ep_in_ff, data, len); +} + +void tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete all content in the EP IN FIFO +{ + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + tu_fifo_clear(&_audiod_itf[itf].ep_in_ff); +} + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into EP SW FIFO +{ + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + audiod_interface_t* audio = &_audiod_itf[itf]; + uint16_t n_bytes_copied; + TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio, &n_bytes_copied)); + return n_bytes_copied; +} + +uint16_t tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); + +uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) +{ + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX, ); + return tu_fifo_write_n(&audio->tx_ff[channelId], data, len); +} +#endif + +#endif + + + + + + /** * \brief Write data to EP in buffer * @@ -383,50 +423,28 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t *a * \param[in] len: # of array elements to copy * \return Number of bytes actually written */ -#if CFG_TUD_AUDIO_EPSIZE_IN -#if !CFG_TUD_AUDIO_TX_FIFO_SIZE -/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) { audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) { - return 0; - } - - // THIS IS A CRITICAL SECTION - audio->epin_buf_cnt MUST NOT BE MODIFIED FROM HERE - happens if audiod_tx_done_cb() is executed in between! - - // FOR SINGLE THREADED OPERATION: - // AS LONG AS THIS FUNCTION IS NOT EXECUTED WITHIN AN INTERRUPT ALL IS FINE! + if (audio->p_desc == NULL) return 0; - // Determine free space - uint16_t free = CFG_TUD_AUDIO_EPSIZE_IN - audio->epin_buf_cnt; - - // Clip length if needed - if (len > free) len = free; - - // Write data - memcpy((void *) &audio->epin_buf[audio->epin_buf_cnt], data, len); - - audio->epin_buf_cnt += len; - - // Return number of bytes written - return len; + return tu_fifo_write_n(&audio->ep_in_ff, data, len); } -*/ #else -#if CFG_TUD_AUDIO_TX_FIFO_COUNT == 1 +#if CFG_TUD_AUDIO_N_CHANNELS_TX == 1 uint16_t tud_audio_n_write(uint8_t itf, void const* data, uint16_t len) { + audiod_interface_t* audio = &_audiod_itf[itf]; + if (audio->p_desc == NULL) { - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) - { - return 0; - } - return tu_fifo_write_n(&audio->tx_ff[0], data, len); + return 0; } + return tu_fifo_write_n(&audio->tx_ff[0], data, len); } #else uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) @@ -471,11 +489,11 @@ uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_FIFO_SIZE = 0 and use tud_audio_n_write_ep_in_buffer() (NOT IMPLEMENTED SO FAR). +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE = 0 and use tud_audio_n_write_ep_in_buffer() (NOT IMPLEMENTED SO FAR). // n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. -#if CFG_TUD_AUDIO_EPSIZE_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio, uint16_t * n_bytes_copied) { uint8_t idxDriver, idxItf; uint8_t const *dummy2; @@ -488,10 +506,10 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ } // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or - // if no FIFOs are used the user may use this call back to load its data into the EP in buffer by use of tud_audio_n_write_ep_in_buffer(). + // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->altSetting[idxItf])); -#if CFG_TUD_AUDIO_TX_FIFO_SIZE +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) { case AUDIO_FORMAT_TYPE_UNDEFINED: @@ -526,30 +544,11 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ } #endif - // THIS IS A CRITICAL SECTION - audio->epin_buf_cnt MUST NOT BE MODIFIED FROM HERE - happens if tud_audio_n_write_ep_in_buffer() is executed in between! - - // THIS IS NOT SOLVED SO FAR! - - // FOR SINGLE THREADED OPERATION: - // THIS FUNCTION IS NOT EXECUTED WITHIN AN INTERRUPT SO IT DOES NOT INTERRUPT tud_audio_n_write_ep_in_buffer()! AS LONG AS tud_audio_n_write_ep_in_buffer() IS NOT EXECUTED WITHIN AN INTERRUPT ALL IS FINE! + // Inform how many bytes will be copied + *n_bytes_copied = tu_fifo_count(&audio->ep_in_ff); // Schedule transmit - // TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->epin_buf, audio->epin_buf_cnt)); - - - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->epin_ff)); - - - - - - // Inform how many bytes were copied - *n_bytes_copied = audio->epin_buf_cnt; - - // Declare EP in buffer empty - audio->epin_buf_cnt = 0; - - // TO HERE + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, *n_bytes_copied)); // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, *n_bytes_copied, idxDriver, audio->ep_in, audio->altSetting[idxItf])); @@ -557,19 +556,18 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ return true; } -#endif //CFG_TUD_AUDIO_EPSIZE_IN +#endif //CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE -#if CFG_TUD_AUDIO_TX_FIFO_SIZE -#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_N_CHANNELS_TX > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) { - // We encode directly into IN EP's buffer - abort if previous transfer not complete + // We encode directly into IN EP's FIFO - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples - uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EPSIZE_IN / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]) / CFG_TUD_AUDIO_TX_ITEMSIZE; - uint16_t nBytesToSend; uint8_t cntChannel; for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) @@ -582,58 +580,47 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* } // Check if there is enough - if (nSamplesPerChannelToSend == 0) - { - audio->epin_buf_cnt = 0; - return true; - } + if (nSamplesPerChannelToSend == 0) return true; // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! nSamplesPerChannelToSend = tu_min16(nSamplesPerChannelToSend, nEndpointSampleCapacity); - nBytesToSend = nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; // Encode uint16_t cntSample; - uint8_t * pBuff = audio->epin_buf; -#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 - uint8_t sample; -#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 - uint16_t sample; -#else - uint32_t sample; -#endif - // TODO: Big endianess handling for (cntSample = 0; cntSample < nSamplesPerChannelToSend; cntSample++) { for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { - // Get sample from buffer - tu_fifo_read_n(&audio->tx_ff[cntChannel], &sample, CFG_TUD_AUDIO_TX_ITEMSIZE); + // If 8, 16, or 32 bit values are to be copied +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == CFG_TUD_AUDIO_TX_ITEMSIZE + tu_fifo_read_n_into_other_fifo(&audio->tx_ff[cntChannel], &audio->ep_in_ff, 0, CFG_TUD_AUDIO_TX_ITEMSIZE); +#else + // TODO: Implement a left and right justified 24 to 32 and vice versa copy process from FIFO to FIFO + uint32_t sample = 0; - // Put it into EP's buffer - Let alignment problems be handled by memcpy - memcpy(pBuff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); + // Get sample from buffer + tu_fifo_read_n(&audio->tx_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); - // Advance pointer - pBuff += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + tu_fifo_write_n(&audio->ep_in_ff, &sample, CFG_TUD_AUDIO_TX_ITEMSIZE); +#endif } } - - audio->epin_buf_cnt = nBytesToSend; - return true; } #else static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) { + // TODO GET RID OF SINGLE TX_FIFO! + // We encode directly into IN EP's buffer - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples uint16_t nByteCount = tu_fifo_count(&audio->tx_ff[0]); - nByteCount = tu_min16(nByteCount, CFG_TUD_AUDIO_EPSIZE_IN); + nByteCount = tu_min16(nByteCount, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE); // Check if there is enough if (nByteCount == 0) @@ -641,20 +628,17 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* return true; } - nByteCount = tu_fifo_read_n_into_other_fifo(&audio->tx_ff[0], &audio->epin_ff, 0, nByteCount); -// nByteCount = tu_fifo_read_n(&audio->tx_ff[0], audio->epin_buf, nByteCount); - - audio->epin_buf_cnt = nByteCount; + nByteCount = tu_fifo_read_n_into_other_fifo(&audio->tx_ff[0], &audio->ep_in_ff, 0, nByteCount); return true; } -#endif // CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) +#endif // CFG_TUD_AUDIO_N_CHANNELS_TX > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) -#endif //CFG_TUD_AUDIO_TX_FIFO_SIZE +#endif //CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE // This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static bool audio_fb_send(uint8_t rhport, audiod_interface_t *audio) { uint8_t fb[4]; @@ -738,28 +722,34 @@ void audiod_init(void) { audiod_interface_t* audio = &_audiod_itf[i]; + // Initialize IN EP FIFO if required +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + // Initialize IN EP FIFO + tu_fifo_config(&audio->ep_in_ff, &audio->ep_in_buf, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE, 1, true); +#endif + // Initialize TX FIFOs if required -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_COUNT; cnt++) +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { - tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_FIFO_SIZE, 1, true); + tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); #endif } - - // Initialize IN EP FIFO - tu_fifo_config(&audio->epin_ff, &audio->epin_buf, CFG_TUD_AUDIO_EPSIZE_IN, 1, true); - #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_RX_FIFO_COUNT; cnt++) +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { - tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_FIFO_SIZE, 1, true); + tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); #endif + + // Initialize OUT EP FIFO + tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); + } #endif @@ -781,19 +771,19 @@ void audiod_reset(uint8_t rhport) audiod_interface_t* audio = &_audiod_itf[i]; tu_memclr(audio, ITF_MEM_RESET_SIZE); -#if CFG_TUD_AUDIO_EPSIZE_IN - tu_fifo_clear(&audio->epin_ff); +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + tu_fifo_clear(&audio->ep_in_ff); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_COUNT; cnt++) +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { tu_fifo_clear(&audio->tx_ff[cnt]); } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_RX_FIFO_COUNT; cnt++) +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { tu_fifo_clear(&audio->rx_ff[cnt]); } @@ -891,7 +881,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE > 0 if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) { _audiod_itf[idxDriver].ep_in_as_intf_num = 0; @@ -904,7 +894,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE if (_audiod_itf[idxDriver].ep_out_as_intf_num == itf) { _audiod_itf[idxDriver].ep_out_as_intf_num = 0; @@ -945,7 +935,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! usbd_edpt_clear_stall(rhport, ep_addr); -#if CFG_TUD_AUDIO_EPSIZE_IN > 0 +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE > 0 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP { // Save address @@ -961,7 +951,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary { @@ -973,7 +963,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Prepare for incoming data - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -1242,7 +1232,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #endif -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE // Data transmission of audio packet finished if (_audiod_itf[idxDriver].ep_in == ep_addr) @@ -1264,16 +1254,16 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 } #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE // New audio packet received if (_audiod_itf[idxDriver].ep_out == ep_addr) { // Save into buffer - do whatever has to be done - TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].epout_buf, xferred_bytes)); + TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); // prepare for next transmission - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].epout_buf, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); return true; } diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 5061501ce..fdd4c15d4 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -38,9 +38,11 @@ // Class Driver Configuration //--------------------------------------------------------------------+ +// All sizes are in bytes! + // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just waste a few bytes) #ifndef CFG_TUD_AUDIO_N_AS_INT -#define CFG_TUD_AUDIO_N_AS_INT 0 +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the descriptors! #endif // Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors @@ -48,20 +50,6 @@ #error You must define an audio class control request buffer size! #endif -// Use of TX/RX FIFOs - If sizes are not zero, audio.c implements FIFOs for RX and TX (whatever defined). -// For RX: the input stream gets decoded into its corresponding channels, where for each channel a FIFO is setup to hold its data -> see: audio_rx_done_cb(). -// For TX: the output stream is composed from CFG_TUD_AUDIO_N_CHANNELS_TX channels, where for each channel a FIFO is defined. -// Further, it implements encoding and decoding of the individual channels (parameterized by the defines below). -// If you don't use the FIFOs you need to handle encoding and decoding on your own in audio_rx_done_cb() and audio_tx_done_cb(). This, however, allows for optimizations. - -#ifndef CFG_TUD_AUDIO_TX_FIFO_SIZE -#define CFG_TUD_AUDIO_TX_FIFO_SIZE 0 // Buffer size per channel -#endif - -#ifndef CFG_TUD_AUDIO_RX_FIFO_SIZE -#define CFG_TUD_AUDIO_RX_FIFO_SIZE 0 // Buffer size per channel -#endif - // End point sizes - Limits: Full Speed <= 1023, High Speed <= 1024 #ifndef CFG_TUD_AUDIO_EPSIZE_IN #define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX @@ -71,29 +59,90 @@ #define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX #endif -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback +// Software EP FIFO buffer sizes - must be >= EP SIZEs! +#if CFG_TUD_AUDIO_EPSIZE_IN +#ifndef CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN // TX #endif - -#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE -#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#if CFG_TUD_AUDIO_EPSIZE_OUT +#ifndef CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_OUT // RX #endif #endif +// General information of number of TX and/or RX channels - is used in case support FIFOs (see below) are used and can be used for descriptor definitions #ifndef CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 +#define CFG_TUD_AUDIO_N_CHANNELS_TX 0 #endif #ifndef CFG_TUD_AUDIO_N_CHANNELS_RX -#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 +#define CFG_TUD_AUDIO_N_CHANNELS_RX 0 +#endif + +// Use of TX/RX support FIFOs + +// Support FIFOs are not mandatory for the audio driver, rather they are intended to be of use in +// - TX case: CFG_TUD_AUDIO_N_CHANNELS_TX channels need to be encoded into one USB output stream (currently PCM type I is implemented) +// - RX case: CFG_TUD_AUDIO_N_CHANNELS_RX channels need to be decoded from a single USB input stream (currently PCM type I is implemented) +// +// This encoding/decoding is done in software and thus time consuming. If you can encode/decode your stream more efficiently do not use the +// support FIFOs but write/read directly into/from the EP_X_SW_BUFFER_FIFOs using +// - tud_audio_n_write() or +// - tud_audio_n_read(). +// To write/read to/from the support FIFOs use +// - tud_audio_n_write_support_ff() or +// - tud_audio_n_read_support_ff(). +// +// The encoding/decoding format type done is defined below. +// +// The encoding/decoding starts when the private callback functions +// - audio_tx_done_cb() +// - audio_rx_done_cb() +// are invoked. If support FIFOs are used the corresponding encoding/decoding functions are called from there. +// Once encoding/decoding is done the result is put directly into the EP_X_SW_BUFFER_FIFOs. You can use the public callback functions +// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() +// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() +// if you want to get informed what happened. +// +// If you don't use the support FIFOs you may use the public callback functions +// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() +// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() +// to write/read from/into the EP_X_SW_BUFFER_FIFOs at the right time. +// +// If you need a different encoding which is not support so far implement it in the +// - audio_tx_done_cb() +// - audio_rx_done_cb() +// functions. + +// Size of support FIFOs - if size > 0 there are as many FIFOs set up as TX/RX channels defined +#ifndef CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#define CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE 0 // Buffer size per channel - minimum size: ceil(f_s/1000)*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX +#endif + +#ifndef CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#define CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE 0 // Buffer size per channel - minimum size: ceil(f_s/1000)*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX +#endif + +// Enable/disable feedback EP (required for asynchronous RX applications) +#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 #endif -// Audio data format types +// Audio interrupt control EP size - disabled if 0 +#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) +#endif + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE +#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#endif +#endif + +// Audio data format types - look in audio.h for existing types +// Used in case support FIFOs are used #ifndef CFG_TUD_AUDIO_FORMAT_TYPE_TX #define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, an encoding function has to be implemented in audio_device.c #endif @@ -110,8 +159,8 @@ #define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM #endif -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 #endif #ifndef CFG_TUD_AUDIO_TX_ITEMSIZE @@ -136,8 +185,8 @@ #define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM #endif -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 +#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize +#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 #endif #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 @@ -170,69 +219,84 @@ extern "C" { //--------------------------------------------------------------------+ bool tud_audio_n_mounted (uint8_t itf); -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 -uint16_t tud_audio_n_available (uint8_t itf, uint8_t channelId); -uint16_t tud_audio_n_read (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); -void tud_audio_n_read_flush (uint8_t itf, uint8_t channelId); -#else -uint16_t tud_audio_n_available (uint8_t itf); -uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); -void tud_audio_n_read_flush (uint8_t itf); -#endif -#endif +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + +uint16_t tud_audio_n_available (uint8_t itf); +uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); +void tud_audio_n_clear_ep_out_ff (uint8_t itf); // Delete all content in the EP OUT FIFO -/* This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers -#if CFG_TUD_AUDIO_EPSIZE_IN && !CFG_TUD_AUDIO_TX_FIFO_SIZE -uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +void tud_audio_n_clear_rx_support_ff (uint8_t itf, uint8_t channelId); // Delete all content in the support RX FIFOs +uint16_t tud_audio_n_available_support_ff (uint8_t itf, uint8_t channelId); +uint16_t tud_audio_n_read_support_ff (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); #endif -*/ -#ifndef CFG_TUD_AUDIO_TX_FIFO_COUNT -#define CFG_TUD_AUDIO_TX_FIFO_COUNT 1 #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 -uint16_t tud_audio_n_write (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); -#else -uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + +uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); +void tud_audio_n_clear_ep_in_ff (uint8_t itf); // Delete all content in the EP IN FIFO + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +uint16_t tud_audio_n_flush_tx_support_ff (uint8_t itf); // Force all content in the support TX FIFOs to be written into EP SW FIFO +uint16_t tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); +uint16_t tud_audio_n_write_support_ff (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); #endif -uint16_t tud_audio_n_write_flush(uint8_t itf); + #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -uint16_t tud_audio_int_ctr_n_available (uint8_t itf); -uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); -void tud_audio_int_ctr_n_read_flush (uint8_t itf); -uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t bufsize); +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +uint16_t tud_audio_int_ctr_n_available (uint8_t itf); +uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); +void tud_audio_int_ctr_n_clear (uint8_t itf); // Delete all content in the AUDIO_INT_CTR FIFO +uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t len); #endif //--------------------------------------------------------------------+ // Application API (Interface0) //--------------------------------------------------------------------+ -static inline bool tud_audio_mounted (void); +static inline bool tud_audio_mounted (void); + +// RX API + +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -static inline uint16_t tud_audio_available (void); -static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); -static inline void tud_audio_read_flush (void); +static inline uint16_t tud_audio_available (void); +static inline void tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO +static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +static inline void tud_audio_clear_rx_support_ff (uint8_t channelId); +static inline uint16_t tud_audio_available_support_ff (uint8_t channelId); +static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize); #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -#if CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 -static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t bufsize); -#else -static inline uint16_t tud_audio_write (uint8_t const* buffer, uint16_t bufsize); #endif + +// TX API + +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + +static inline uint16_t tud_audio_write (const void * data, uint16_t len); +static inline uint16_t tud_audio_clear_ep_in_ff (void); + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +static inline uint16_t tud_audio_flush_tx_support_ff (void); +static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId); +static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len); +#endif + #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -static inline uint32_t tud_audio_int_ctr_available (void); -static inline uint32_t tud_audio_int_ctr_read (void* buffer, uint32_t bufsize); -static inline void tud_audio_int_ctr_read_flush (void); -static inline uint32_t tud_audio_int_ctr_write (uint8_t const* buffer, uint32_t bufsize); +// INT CTR API + +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +static inline uint16_t tud_audio_int_ctr_available (void); +static inline uint16_t tud_audio_int_ctr_read (void* buffer, uint16_t bufsize); +static inline void tud_audio_int_ctr_clear (void); +static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); #endif // Buffer control EP data and schedule a transmit @@ -247,16 +311,17 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_t bufsize); +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); // User code should call this function with feedback value in 16.16 format for FS and HS. // Value will be corrected for FS to 10.14 format automatically. @@ -302,64 +367,82 @@ static inline bool tud_audio_mounted(void) return tud_audio_n_mounted(0); } -#if CFG_TUD_AUDIO_EPSIZE_IN -#if CFG_TUD_AUDIO_TX_FIFO_SIZE && CFG_TUD_AUDIO_TX_FIFO_COUNT > 1 -static inline uint16_t tud_audio_write (uint8_t channelId, uint8_t const* buffer, uint16_t n_bytes) // Short version if only one audio function is used +// RX API + +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + +static inline uint16_t tud_audio_available (void) { - return tud_audio_n_write(0, channelId, buffer, n_bytes); + return tud_audio_n_available(0); } -#else -static inline uint16_t tud_audio_write (uint8_t const* buffer, uint16_t n_bytes) // Short version if only one audio function is used + +static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize) { - return tud_audio_n_write(0, buffer, n_bytes); + return tud_audio_n_read(0, buffer, bufsize); } -#endif -static inline uint16_t tud_audio_write_flush (void) // Short version if only one audio function is used +static inline uint16_t tud_audio_clear_ep_out_ff (void) { -#if CFG_TUD_AUDIO_TX_FIFO_SIZE - return tud_audio_n_write_flush(0); -#else - return 0; -#endif + return tud_audio_n_clear_ep_out_ff(0); } -#endif // CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_FIFO_SIZE -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_FIFO_SIZE -#if CFG_TUD_AUDIO_RX_FIFO_COUNT > 1 -static inline uint16_t tud_audio_available(uint8_t channelId) +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE + +static inline void tud_audio_clear_rx_support_ff (uint8_t channelId) { - return tud_audio_n_available(0, channelId); + tud_audio_n_clear_rx_support_ff(0, channelId); } -static inline uint16_t tud_audio_read(uint8_t channelId, void* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_available_support_ff (uint8_t channelId) { - return tud_audio_n_read(0, channelId, buffer, bufsize); + return tud_audio_n_available_support_ff(0, channelId); } -static inline void tud_audio_read_flush(uint8_t channelId) +static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize) { - tud_audio_n_read_flush(0, channelId); + return tud_audio_n_read_support_ff(0, channelId, buffer, bufsize); } -#else -static inline uint16_t tud_audio_available(void) + +#endif + +#endif + +// TX API + +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + +static inline uint16_t tud_audio_write (const void * data, uint16_t len) { - return tud_audio_n_available(0); + return tud_audio_n_write(0, data, len); } -static inline uint16_t tud_audio_read(void *buffer, uint16_t bufsize) +static inline uint16_t tud_audio_clear_ep_in_ff (void) { - return tud_audio_n_read(0, buffer, bufsize); + return tud_audio_n_clear_ep_in_ff(0); } -static inline void tud_audio_read_flush(void) +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE + +static inline uint16_t tud_audio_flush_tx_support_ff (void) { - tud_audio_n_read_flush(0); + return tud_audio_n_flush_tx_support_ff(0); } + +static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId) +{ + return tud_audio_n_clear_tx_support_ff(0, channelId); +} + +static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len) +{ + return tud_audio_n_write_support_ff(0, channelId, data, len); +} + #endif + #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN static inline uint16_t tud_audio_int_ctr_available(void) { return tud_audio_int_ctr_n_available(0); @@ -370,25 +453,25 @@ static inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize) return tud_audio_int_ctr_n_read(0, buffer, bufsize); } -static inline void tud_audio_int_ctr_read_flush(void) +static inline void tud_audio_int_ctr_clear(void) { - return tud_audio_int_ctr_n_read_flush(0); + return tud_audio_int_ctr_n_clear(0); } -static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len) { - return tud_audio_int_ctr_n_write(0, buffer, bufsize); + return tud_audio_int_ctr_n_write(0, buffer, len); } #endif //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void audiod_init (void); -void audiod_reset (uint8_t rhport); -uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool audiod_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void audiod_init (void); +void audiod_reset (uint8_t rhport); +uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool audiod_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/device/dcd.h b/src/device/dcd.h index 30224e16e..f0a552434 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -125,23 +125,23 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; // Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); // Close an endpoint. // Since it is weak, caller must TU_ASSERT this function's existence before calling it. -void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; +void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit an ISO transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); // Stall endpoint -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); +void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); // clear stall, data toggle is also reset to DATA0 -void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); +void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); //--------------------------------------------------------------------+ // Event API (implemented by stack) diff --git a/src/device/usbd.c b/src/device/usbd.c index 4e18df757..2e2f9cf65 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1206,12 +1206,16 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } -bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) +// The number of bytes has to be given explicitly to allow more flexible control of how many +// bytes should be written and second to keep the return value free to give back a boolean +// success message. If total_bytes is too big, the FIFO will copy only what is available +// into the USB buffer! +bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, tu_fifo_count(ff)); + TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, count); // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); @@ -1220,7 +1224,7 @@ bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if ( dcd_edpt_iso_xfer(rhport, ep_addr, ff) ) + if (dcd_edpt_iso_xfer(rhport, ep_addr, ff, total_bytes)) { TU_LOG2("OK\r\n"); return true; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 1d24957a9..412a97a5d 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -73,7 +73,7 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted -bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff); +bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 90fcd51e7..4cb6028cc 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -670,13 +670,15 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff) +// The number of bytes has to be given explicitly to allow more flexible control of how many +// bytes should be written and second to keep the return value free to give back a boolean +// success message. If total_bytes is too big, the FIFO will copy only what is available +// into the USB buffer! +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); - uint16_t total_bytes = tu_fifo_count(ff); - uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); -- cgit v1.3.1 From bb2f93d4270cfffc16b180a870f30ac789fdae30 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Feb 2021 20:41:41 +0700 Subject: prepare for release --- changelog.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/device/usbd.h | 1 + 2 files changed, 65 insertions(+) (limited to 'src') diff --git a/changelog.md b/changelog.md index 6b17e1666..393ca24ca 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,69 @@ # TinyUSB Changelog +## 0.8.0 - 2021.02.05 + +### Device Controller Driver + +- Added new device support for Raspberry Pi RP2040 +- Added new device support for NXP Kinetis KL25ZXX +- Use dcd_event_bus_reset() with link speed to replace bus_signal +- ESP32-S2: + - Add bus suspend and wakeup support +- SAMD21: + - Fix (walkaround) samd21 setup_packet overflow by USB DMA +- STM32 Synopsys: + - Rework USB FIFO allocation scheme and allow RX FIFO size reduction +- Sony CXD56 + - Update Update Spresense SDK to 2.0.2 + - Fix dcd issues with setup packets + - Correct EP number for cdc_msc example + +### USB Device + +**UBSD** + +- Rework usbd control transfer to have additional stage parameter for setup, data, status +- Fix tusb_init() return true instead of TUSB_ERROR_NONE +- Added new API tud_connected() that return true after device got out of bus reset and received the very first setup packet + +**Class Driver** + +- CDC + - Allow to transmit data, even if the host does not support control line states i.e set DTR +- HID + - change default CFG_TUD_HID_EP_BUFSIZE from 16 to 64 +- MIDI + - Fix midi sysex sending bug +- MSC + - Invoke only scsi complete callback after status transaction is complete. + - Fix scsi_mode_sense6_t padding, which cause IAR compiler internal error. +- USBTMC + - Change interrupt endpoint example size to 8 instead of 2 for better compatibility with mcu + +**Example** + +- Support make from windows cmd.exe +- Add HID Consumer Control (media keys) to hid_composite & hid_composite_freertos examples + +### USB Host + +No noticeable changes to host stack + +### New Boards + +- NXP/Freescale Freedom FRDM-KL25Z +- Feather Double M33 express +- Raspberry Pi Pico +- Adafruit Feather RP2040 +- Adafruit Itsy Bitsy RP2040 +- Adafruit QT RP2040 +- Adfruit Feather ESP32-S2 +- Adafruit Magtag 29" Eink +- Adafruit Metro ESP32-S2 +- Adafruit PyBadge +- Adafruit PyPortal +- Great Scott Gadgets' LUNA D11 & D21 + ## 0.7.0 - 2020.11.08 ### Device Controller Driver diff --git a/src/device/usbd.h b/src/device/usbd.h index 360567743..b5f7dceba 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -57,6 +57,7 @@ extern void dcd_int_handler(uint8_t rhport); tusb_speed_t tud_speed_get(void); // Check if device is connected (may not mounted/configured yet) +// True if just got out of Bus Reset and received the very first data from host bool tud_connected(void); // Check if device is connected and configured -- cgit v1.3.1 From 465ea7a66e35725d1b5ec7443d86afe27762b586 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Feb 2021 22:37:22 +0700 Subject: increase TUSB_VERSION_ to 0.8.0 --- src/tusb_option.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/tusb_option.h b/src/tusb_option.h index a89c6db9d..5d5e50412 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -28,7 +28,7 @@ #define _TUSB_OPTION_H_ #define TUSB_VERSION_MAJOR 0 -#define TUSB_VERSION_MINOR 7 +#define TUSB_VERSION_MINOR 8 #define TUSB_VERSION_REVISION 0 #define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION) -- cgit v1.3.1 From b2019e4d719a8b4560714081e5764525308b2924 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 8 Feb 2021 16:10:13 +0700 Subject: enhance gampepad report with dpad/hat support add hid_gamepad_report_t along with GAMEPAD_BUTTON_ and GAMEPAD_HAT_ enum --- src/class/hid/hid.h | 91 ++++++++++++++++++++++++++++++++++++++++++++++ src/class/hid/hid_device.h | 44 ++++++++++++++-------- 2 files changed, 119 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 8803e4b66..cb1bd5835 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -143,6 +143,97 @@ typedef enum /** @} */ +//--------------------------------------------------------------------+ +// GAMEPAD +//--------------------------------------------------------------------+ +/** \addtogroup ClassDriver_HID_Gamepad Gamepad + * @{ */ + +/* From https://www.kernel.org/doc/html/latest/input/gamepad.html + ____________________________ __ + / [__ZL__] [__ZR__] \ | + / [__ TL __] [__ TR __] \ | Front Triggers + __/________________________________\__ __| + / _ \ | + / /\ __ (N) \ | + / || __ |MO| __ _ _ \ | Main Pad + | <===DP===> |SE| |ST| (W) -|- (E) | | + \ || ___ ___ _ / | + /\ \/ / \ / \ (S) /\ __| + / \________ | LS | ____ | RS | ________/ \ | +| / \ \___/ / \ \___/ / \ | | Control Sticks +| / \_____/ \_____/ \ | __| +| / \ | + \_____/ \_____/ + + |________|______| |______|___________| + D-Pad Left Right Action Pad + Stick Stick + + |_____________| + Menu Pad + + Most gamepads have the following features: + - Action-Pad 4 buttons in diamonds-shape (on the right side) NORTH, SOUTH, WEST and EAST. + - D-Pad (Direction-pad) 4 buttons (on the left side) that point up, down, left and right. + - Menu-Pad Different constellations, but most-times 2 buttons: SELECT - START. + - Analog-Sticks provide freely moveable sticks to control directions, Analog-sticks may also + provide a digital button if you press them. + - Triggers are located on the upper-side of the pad in vertical direction. The upper buttons + are normally named Left- and Right-Triggers, the lower buttons Z-Left and Z-Right. + - Rumble Many devices provide force-feedback features. But are mostly just simple rumble motors. + */ + +/// HID Gamepad Protocol Report. +typedef struct TU_ATTR_PACKED +{ + int8_t x; ///< Delta x movement of left analog-stick + int8_t y; ///< Delta y movement of left analog-stick + int8_t z; ///< Delta z movement of right analog-joystick + int8_t rz; ///< Delta Rz movement of right analog-joystick + int8_t rx; ///< Delta Rx movement of analog left trigger + int8_t ry; ///< Delta Ry movement of analog right trigger + uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat + uint16_t buttons; ///< Buttons mask for currently pressed buttons +}hid_gamepad_report_t; + +/// Standard Gamepad Buttons Bitmap (from Linux input event codes) +typedef enum +{ + GAMEPAD_BUTTON_A = TU_BIT(0), ///< A/South button + GAMEPAD_BUTTON_B = TU_BIT(1), ///< B/East button + GAMEPAD_BUTTON_C = TU_BIT(2), ///< C button + GAMEPAD_BUTTON_X = TU_BIT(3), ///< X/North button + GAMEPAD_BUTTON_Y = TU_BIT(4), ///< Y/West button + GAMEPAD_BUTTON_Z = TU_BIT(5), ///< Z button + GAMEPAD_BUTTON_TL = TU_BIT(6), ///< L1 button + GAMEPAD_BUTTON_TR = TU_BIT(7), ///< R1 button + GAMEPAD_BUTTON_TL2 = TU_BIT(8), ///< L2 button + GAMEPAD_BUTTON_TR2 = TU_BIT(9), ///< R2 button + GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button + GAMEPAD_BUTTON_START = TU_BIT(11), ///< Start button + GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button + GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button + GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button +//GAMEPAD_BUTTON_ = TU_BIT(15), ///< Undefined button +}hid_gamepad_button_bm_t; + +/// Standard Gamepad HAT/DPAD Buttons Bitmap (from Linux input event codes) +typedef enum +{ + GAMEPAD_HAT_CENTERED = 0, ///< DPAD_CENTERED + GAMEPAD_HAT_UP = 1, ///< DPAD_UP + GAMEPAD_HAT_UP_RIGHT = 2, ///< DPAD_UP_RIGHT + GAMEPAD_HAT_RIGHT = 3, ///< DPAD_RIGHT + GAMEPAD_HAT_DOWN_RIGHT = 4, ///< DPAD_DOWN_RIGHT + GAMEPAD_HAT_DOWN = 5, ///< DPAD_DOWN + GAMEPAD_HAT_DOWN_LEFT = 6, ///< DPAD_DOWN_LEFT + GAMEPAD_HAT_LEFT = 7, ///< DPAD_LEFT + GAMEPAD_HAT_UP_LEFT = 8, ///< DPAD_UP_LEFT +}hid_gamepad_hat_bm_t; + +/// @} + //--------------------------------------------------------------------+ // MOUSE //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 456b011ba..f429d8b9a 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -301,14 +301,37 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 HID_COLLECTION_END \ // Gamepad Report Descriptor Template -// with 16 buttons and 2 joysticks with following layout -// | Button Map (2 bytes) | X | Y | Z | Rz +// with 16 buttons, 2 joysticks and 1 hat/dpad with following layout +// | X | Y | Z | Rz | Rx | Ry (1 byte each) | hat/DPAD (1 byte) | Button Map (2 bytes) | #define TUD_HID_REPORT_DESC_GAMEPAD(...) \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ) ,\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ) ,\ + HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ /* Report ID if any */\ __VA_ARGS__ \ + /* 8 bit X, Y, Z, Rz, Rx, Ry (min -127, max 127 ) */ \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_RX ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_RY ) ,\ + HID_LOGICAL_MIN ( 0x81 ) ,\ + HID_LOGICAL_MAX ( 0x7f ) ,\ + HID_REPORT_COUNT ( 6 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* 8 bit DPad/Hat Button Map */ \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_HAT_SWITCH ) ,\ + HID_LOGICAL_MIN ( 1 ) ,\ + HID_LOGICAL_MAX ( 8 ) ,\ + HID_PHYSICAL_MIN ( 0 ) ,\ + HID_PHYSICAL_MAX_N ( 315, 2 ) ,\ + HID_REPORT_COUNT ( 1 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ /* 16 bit Button Map */ \ HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ HID_USAGE_MIN ( 1 ) ,\ @@ -318,17 +341,6 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 HID_REPORT_COUNT ( 16 ) ,\ HID_REPORT_SIZE ( 1 ) ,\ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ - /* X, Y, Z, Rz (min -127, max 127 ) */ \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ - HID_LOGICAL_MIN ( 0x81 ) ,\ - HID_LOGICAL_MAX ( 0x7f ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\ - HID_REPORT_COUNT ( 4 ) ,\ - HID_REPORT_SIZE ( 8 ) ,\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ HID_COLLECTION_END \ // HID Generic Input & Output -- cgit v1.3.1 From 72bcc0685c142c512f1d04ff18eaa13b99f62e93 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 8 Feb 2021 19:08:16 +0700 Subject: add tud_hid_n_gamepad_report() helper for gamepad report - Add gamepad to hid_composite example. Though it needs a bit of extra work but it will come later as separated PR. --- examples/device/hid_composite/src/main.c | 29 ++++++++++++++++++++++ .../device/hid_composite/src/usb_descriptors.c | 3 ++- .../device/hid_composite/src/usb_descriptors.h | 1 + .../hid_multiple_interface/src/usb_descriptors.c | 10 ++++---- src/class/hid/hid.h | 4 +-- src/class/hid/hid_device.c | 27 ++++++++++++++------ src/class/hid/hid_device.h | 6 +++++ 7 files changed, 65 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 6a9b6445d..45b8ba674 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -183,6 +183,35 @@ void hid_task(void) if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2); has_consumer_key = false; } + + // delay a bit before sending next report + board_delay(10); + } + + /*------------- Gamepad -------------*/ + if ( tud_hid_ready() ) + { + // use to avoid send multiple consecutive zero report for keyboard + static bool has_gamepad_key = false; + + hid_gamepad_report_t report = + { + .x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0, + .hat = 0, .buttons = 0 + }; + + if ( btn ) + { + report.hat = GAMEPAD_HAT_UP; + tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + + has_gamepad_key = true; + }else + { + report.hat = GAMEPAD_HAT_CENTERED; + if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + has_gamepad_key = false; + } } } diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index 67ea34c08..fbe0e2550 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -75,7 +75,8 @@ 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 )), - TUD_HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(REPORT_ID_CONSUMER_CONTROL )) + TUD_HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(REPORT_ID_CONSUMER_CONTROL )), + TUD_HID_REPORT_DESC_GAMEPAD ( HID_REPORT_ID(REPORT_ID_GAMEPAD )) }; // Invoked when received GET HID REPORT DESCRIPTOR diff --git a/examples/device/hid_composite/src/usb_descriptors.h b/examples/device/hid_composite/src/usb_descriptors.h index feda83dcd..7894719fd 100644 --- a/examples/device/hid_composite/src/usb_descriptors.h +++ b/examples/device/hid_composite/src/usb_descriptors.h @@ -30,6 +30,7 @@ enum REPORT_ID_KEYBOARD = 1, REPORT_ID_MOUSE, REPORT_ID_CONSUMER_CONTROL, + REPORT_ID_GAMEPAD }; #endif /* USB_DESCRIPTORS_H_ */ diff --git a/examples/device/hid_multiple_interface/src/usb_descriptors.c b/examples/device/hid_multiple_interface/src/usb_descriptors.c index 2354e5c1f..a28e57a2b 100644 --- a/examples/device/hid_multiple_interface/src/usb_descriptors.c +++ b/examples/device/hid_multiple_interface/src/usb_descriptors.c @@ -140,11 +140,11 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) char const* string_desc_arr [] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - "123456", // 3: Serials, should use chip ID - "Keyboard Interface", // 4: Interface 1 String - "Mouse Interface", // 5: Interface 2 String + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + "123456", // 3: Serials, should use chip ID + "Keyboard Interface", // 4: Interface 1 String + "Mouse Interface", // 5: Interface 2 String }; static uint16_t _desc_str[32]; diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index cb1bd5835..a7db087a7 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -218,7 +218,7 @@ typedef enum //GAMEPAD_BUTTON_ = TU_BIT(15), ///< Undefined button }hid_gamepad_button_bm_t; -/// Standard Gamepad HAT/DPAD Buttons Bitmap (from Linux input event codes) +/// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) typedef enum { GAMEPAD_HAT_CENTERED = 0, ///< DPAD_CENTERED @@ -230,7 +230,7 @@ typedef enum GAMEPAD_HAT_DOWN_LEFT = 6, ///< DPAD_DOWN_LEFT GAMEPAD_HAT_LEFT = 7, ///< DPAD_LEFT GAMEPAD_HAT_UP_LEFT = 8, ///< DPAD_UP_LEFT -}hid_gamepad_hat_bm_t; +}hid_gamepad_hat_t; /// @} diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 1f03f8862..5b9735071 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -107,9 +107,6 @@ bool tud_hid_n_boot_mode(uint8_t itf) return _hidd_itf[itf].boot_mode; } -//--------------------------------------------------------------------+ -// KEYBOARD API -//--------------------------------------------------------------------+ bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) { hid_keyboard_report_t report; @@ -127,10 +124,8 @@ bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, return tud_hid_n_report(itf, report_id, &report, sizeof(report)); } -//--------------------------------------------------------------------+ -// MOUSE APPLICATION API -//--------------------------------------------------------------------+ -bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) +bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, + uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) { hid_mouse_report_t report = { @@ -144,6 +139,24 @@ bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int return tud_hid_n_report(itf, report_id, &report, sizeof(report)); } +bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, + int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) +{ + hid_gamepad_report_t report = + { + .x = x, + .y = y, + .z = z, + .rz = rz, + .rx = rx, + .ry = ry, + .hat = hat, + .buttons = buttons, + }; + + return tud_hid_n_report(itf, report_id, &report, sizeof(report)); +} + //--------------------------------------------------------------------+ // USBD-CLASS API //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index f429d8b9a..a92dc14e0 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -71,6 +71,10 @@ bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, // use template layout report as defined by hid_mouse_report_t bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +// Gamepad: convenient helper to send mouse report if application +// use template layout report TUD_HID_REPORT_DESC_GAMEPAD +bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); + //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ @@ -119,6 +123,8 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); #endif +// TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, ); + //--------------------------------------------------------------------+ // Inline Functions -- cgit v1.3.1 From 1b678eccf55a808cde2e9fa450b76fe5e95539ba Mon Sep 17 00:00:00 2001 From: tfx2001 <2479727366@qq.com> Date: Sun, 7 Feb 2021 22:44:49 +0800 Subject: add basic support for rt-thread --- hw/bsp/board.h | 5 ++ src/osal/osal.h | 2 + src/osal/osal_rtthread.h | 130 +++++++++++++++++++++++++++++++++++++++++++++++ src/tusb_option.h | 1 + 4 files changed, 138 insertions(+) create mode 100644 src/osal/osal_rtthread.h (limited to 'src') diff --git a/hw/bsp/board.h b/hw/bsp/board.h index 97c80e7c7..7b77def50 100644 --- a/hw/bsp/board.h +++ b/hw/bsp/board.h @@ -86,6 +86,11 @@ static inline uint32_t board_millis(void) { return to_ms_since_boot(get_absolute_time()); } +#elif CFG_TUSB_OS == OPT_OS_RTTHREAD + static inline uint32_t board_millis(void) + { + return (((uint64_t)rt_tick_get()) * 1000 / RT_TICK_PER_SECOND); + } #else #error "board_millis() is not implemented for this OS" diff --git a/src/osal/osal.h b/src/osal/osal.h index eb3bc88d0..02e3e0a06 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -55,6 +55,8 @@ typedef void (*osal_task_func_t)( void * ); #include "osal_mynewt.h" #elif CFG_TUSB_OS == OPT_OS_PICO #include "osal_pico.h" +#elif CFG_TUSB_OS == OPT_OS_RTTHREAD + #include "osal_rtthread.h" #elif CFG_TUSB_OS == OPT_OS_CUSTOM #include "tusb_os_custom.h" // implemented by application #else diff --git a/src/osal/osal_rtthread.h b/src/osal/osal_rtthread.h new file mode 100644 index 000000000..d5c062ac1 --- /dev/null +++ b/src/osal/osal_rtthread.h @@ -0,0 +1,130 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 tfx2001 (2479727366@qq.com) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_OSAL_RTTHREAD_H_ +#define _TUSB_OSAL_RTTHREAD_H_ + +// RT-Thread Headers +#include "rtthread.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------+ +// TASK API +//--------------------------------------------------------------------+ +static inline void osal_task_delay(uint32_t msec) { + rt_thread_mdelay(msec); +} + +//--------------------------------------------------------------------+ +// Semaphore API +//--------------------------------------------------------------------+ +typedef struct rt_semaphore osal_semaphore_def_t; +typedef rt_sem_t osal_semaphore_t; + +static inline osal_semaphore_t +osal_semaphore_create(osal_semaphore_def_t *semdef) { + rt_sem_init(semdef, "tusb", 0, RT_IPC_FLAG_FIFO); + return semdef; +} + +static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { + (void) in_isr; + return rt_sem_release(sem_hdl) == RT_EOK; +} + +static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) { + return rt_sem_take(sem_hdl, rt_tick_from_millisecond(msec)) == RT_EOK; +} + +static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { + // TODO: implement +} + +//--------------------------------------------------------------------+ +// MUTEX API (priority inheritance) +//--------------------------------------------------------------------+ +typedef struct rt_mutex osal_mutex_def_t; +typedef rt_mutex_t osal_mutex_t; + +static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) { + rt_mutex_init(mdef, "tusb", RT_IPC_FLAG_FIFO); + return mdef; +} + +static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) { + return rt_mutex_take(mutex_hdl, rt_tick_from_millisecond(msec)) == RT_EOK; +} + +static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { + return rt_mutex_release(mutex_hdl) == RT_EOK; +} + +//--------------------------------------------------------------------+ +// QUEUE API +//--------------------------------------------------------------------+ + +// role device/host is used by OS NONE for mutex (disable usb isr) only +#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ + static _type _name##_##buf[_depth]; \ + osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf }; + +typedef struct { + uint16_t depth; + uint16_t item_sz; + void *buf; + + struct rt_messagequeue sq; +} osal_queue_def_t; + +typedef rt_mq_t osal_queue_t; + +static inline osal_queue_t osal_queue_create(osal_queue_def_t *qdef) { + rt_mq_init(&(qdef->sq), "tusb", qdef->buf, qdef->item_sz, + qdef->item_sz * qdef->depth, RT_IPC_FLAG_FIFO); + return &(qdef->sq); +} + +static inline bool osal_queue_receive(osal_queue_t qhdl, void *data) { + return rt_mq_recv(qhdl, data, qhdl->msg_size, RT_WAITING_FOREVER) == RT_EOK; +} + +static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) { + (void) in_isr; + return rt_mq_send(qhdl, (void *)data, qhdl->msg_size) == RT_EOK; +} + +static inline bool osal_queue_empty(osal_queue_t qhdl) { + return (qhdl->entry) == 0; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_OSAL_RTTHREAD_H_ */ diff --git a/src/tusb_option.h b/src/tusb_option.h index 5d5e50412..73daf8592 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -113,6 +113,7 @@ #define OPT_OS_MYNEWT 3 ///< Mynewt OS #define OPT_OS_CUSTOM 4 ///< Custom OS is implemented by application #define OPT_OS_PICO 5 ///< Raspberry Pi Pico SDK +#define OPT_OS_RTTHREAD 6 ///< RT-Thread /** @} */ -- cgit v1.3.1 From d2b8e591f6f939f87c28aaa8b12f67a5072d2b06 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 9 Feb 2021 15:57:29 +0700 Subject: tud_hid_report_complete_cb() API update hid composite to make use of tud_hid_report_complete_cb() for sending reports when possible. --- changelog.md | 6 + examples/device/hid_composite/src/main.c | 189 ++++++++++++--------- .../device/hid_composite/src/usb_descriptors.c | 2 +- .../device/hid_composite/src/usb_descriptors.h | 3 +- src/class/hid/hid_device.c | 20 ++- src/class/hid/hid_device.h | 5 +- 6 files changed, 133 insertions(+), 92 deletions(-) (limited to 'src') diff --git a/changelog.md b/changelog.md index 393ca24ca..d645b4fbf 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ # TinyUSB Changelog +## WIP + +- Fix dropping MIDI sysex message when fifo is full +- Add DPad/Hat support for HID Gamepad +- Add tud_hid_report_complete_cb() API + ## 0.8.0 - 2021.02.05 ### Device Controller Driver diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 45b8ba674..9fb2de88d 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -104,114 +104,135 @@ void tud_resume_cb(void) // USB HID //--------------------------------------------------------------------+ -void hid_task(void) +static void send_hid_report(uint8_t report_id, uint32_t btn) { - // Poll every 10ms - const uint32_t interval_ms = 10; - static uint32_t start_ms = 0; - - if ( board_millis() - start_ms < interval_ms) return; // not enough time - start_ms += interval_ms; + // skip if hid is not ready yet + if ( !tud_hid_ready() ) return; - uint32_t const btn = board_button_read(); - - // Remote wakeup - if ( tud_suspended() && btn ) + switch(report_id) { - // Wake up host if we are in suspend mode - // and REMOTE_WAKEUP feature is enabled by host - tud_remote_wakeup(); - } + case REPORT_ID_KEYBOARD: + { + // use to avoid send multiple consecutive zero report for keyboard + static bool has_keyboard_key = false; + + if ( btn ) + { + uint8_t keycode[6] = { 0 }; + keycode[0] = HID_KEY_A; + + tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode); + has_keyboard_key = true; + }else + { + // send empty key report if previously has key pressed + if (has_keyboard_key) tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL); + has_keyboard_key = false; + } + } + break; - /*------------- Mouse -------------*/ - if ( tud_hid_ready() ) - { - if ( btn ) + case REPORT_ID_MOUSE: { int8_t const delta = 5; - // no button, right + down, no scroll pan + // no button, right + down, no scroll, no pan tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0); - - // delay a bit before sending keyboard report - board_delay(10); } - } + break; - /*------------- Keyboard -------------*/ - if ( tud_hid_ready() ) - { - // use to avoid send multiple consecutive zero report for keyboard - static bool has_key = false; - - if ( btn ) + case REPORT_ID_CONSUMER_CONTROL: { - uint8_t keycode[6] = { 0 }; - keycode[0] = HID_KEY_A; - - tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode); + // use to avoid send multiple consecutive zero report + static bool has_consumer_key = false; + + if ( btn ) + { + // volume down + uint16_t volume_down = HID_USAGE_CONSUMER_VOLUME_DECREMENT; + tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &volume_down, 2); + has_consumer_key = true; + }else + { + // send empty key report (release key) if previously has key pressed + uint16_t empty_key = 0; + if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2); + has_consumer_key = false; + } + } + break; - has_key = true; - }else + case REPORT_ID_GAMEPAD: { - // send empty key report if previously has key pressed - if (has_key) tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL); - has_key = false; + // use to avoid send multiple consecutive zero report for keyboard + static bool has_gamepad_key = false; + + hid_gamepad_report_t report = + { + .x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0, + .hat = 0, .buttons = 0 + }; + + if ( btn ) + { + report.hat = GAMEPAD_HAT_UP; + report.buttons = GAMEPAD_BUTTON_A; + tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + + has_gamepad_key = true; + }else + { + report.hat = GAMEPAD_HAT_CENTERED; + report.buttons = 0; + if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + has_gamepad_key = false; + } } + break; - // delay a bit before sending consumer report - board_delay(10); + default: break; } +} - /*------------- Consume Control -------------*/ - if ( tud_hid_ready() ) - { - // use to avoid send multiple consecutive zero report - static bool has_consumer_key = false; - - if ( btn ) - { - // volume down - uint16_t volume_down = HID_USAGE_CONSUMER_VOLUME_DECREMENT; - tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &volume_down, 2); +// Every 10ms, we will sent 1 report for each HID profile (keyboard, mouse etc ..) +// tud_hid_report_complete_cb() is used to send the next report after previous one is complete +void hid_task(void) +{ + // Poll every 10ms + const uint32_t interval_ms = 10; + static uint32_t start_ms = 0; - has_consumer_key = true; - }else - { - // send empty key report (release key) if previously has key pressed - uint16_t empty_key = 0; - if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2); - has_consumer_key = false; - } + if ( board_millis() - start_ms < interval_ms) return; // not enough time + start_ms += interval_ms; - // delay a bit before sending next report - board_delay(10); - } + uint32_t const btn = board_button_read(); - /*------------- Gamepad -------------*/ - if ( tud_hid_ready() ) + // Remote wakeup + if ( tud_suspended() && btn ) { - // use to avoid send multiple consecutive zero report for keyboard - static bool has_gamepad_key = false; + // Wake up host if we are in suspend mode + // and REMOTE_WAKEUP feature is enabled by host + tud_remote_wakeup(); + }else + { + // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb() + send_hid_report(REPORT_ID_KEYBOARD, btn); + } +} - hid_gamepad_report_t report = - { - .x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0, - .hat = 0, .buttons = 0 - }; +// Invoked when sent REPORT successfully to host +// Application can use this to send the next report +// Note: For composite reports, report[0] is report ID +void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len) +{ + (void) itf; + (void) len; - if ( btn ) - { - report.hat = GAMEPAD_HAT_UP; - tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + uint8_t next_report_id = report[0] + 1; - has_gamepad_key = true; - }else - { - report.hat = GAMEPAD_HAT_CENTERED; - if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); - has_gamepad_key = false; - } + if (next_report_id < REPORT_ID_COUNT) + { + send_hid_report(next_report_id, board_button_read()); } } diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index fbe0e2550..e5f1ea703 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -107,7 +107,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 2) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_composite/src/usb_descriptors.h b/examples/device/hid_composite/src/usb_descriptors.h index 7894719fd..ca8925ad9 100644 --- a/examples/device/hid_composite/src/usb_descriptors.h +++ b/examples/device/hid_composite/src/usb_descriptors.h @@ -30,7 +30,8 @@ enum REPORT_ID_KEYBOARD = 1, REPORT_ID_MOUSE, REPORT_ID_CONSUMER_CONTROL, - REPORT_ID_GAMEPAD + REPORT_ID_GAMEPAD, + REPORT_ID_COUNT }; #endif /* USB_DESCRIPTORS_H_ */ diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 5b9735071..4cdcecc9e 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -381,14 +381,24 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ uint8_t itf = 0; hidd_interface_t * p_hid = _hidd_itf; - for ( ; ; itf++, p_hid++) + // Identify which interface to use + for (itf = 0; itf < CFG_TUD_HID; itf++) { - if (itf >= TU_ARRAY_SIZE(_hidd_itf)) return false; - - if ( ep_addr == p_hid->ep_out ) break; + p_hid = &_hidd_itf[itf]; + if ( (ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in) ) break; } + TU_ASSERT(itf < CFG_TUD_HID); - if (ep_addr == p_hid->ep_out) + // Sent report successfully + if (ep_addr == p_hid->ep_in) + { + if (tud_hid_report_complete_cb) + { + tud_hid_report_complete_cb(itf, p_hid->epin_buf, (uint8_t) xferred_bytes); + } + } + // Received report + else if (ep_addr == p_hid->ep_out) { tud_hid_set_report_cb( #if CFG_TUD_HID > 1 diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index a92dc14e0..d5de53221 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -123,7 +123,10 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); #endif -// TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, ); +// Invoked when sent REPORT successfully to host +// Application can use this to send the next report +// Note: For composite reports, report[0] is report ID +TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len); //--------------------------------------------------------------------+ -- cgit v1.3.1 From 49bc97b0caf65f4e850846f03c8693bb49198172 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Feb 2021 11:22:02 +0700 Subject: remove the requirement of std SET/CLEAR_FEATURE must not return zlp status --- src/device/usbd.c | 75 ++++++++++++++++++++++++++--------------------- src/device/usbd_control.c | 18 +++--------- 2 files changed, 46 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index f6b00563d..d871a53d4 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -485,6 +485,12 @@ void tud_task (void) // But it is easier to set it every time instead of wasting time to check then set _usbd_dev.connected = 1; + // mark both in & out control as free + _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = false; + _usbd_dev.ep_status[0][TUSB_DIR_OUT].claimed = 0; + _usbd_dev.ep_status[0][TUSB_DIR_IN ].busy = false; + _usbd_dev.ep_status[0][TUSB_DIR_IN ].claimed = 0; + // Process control request if ( !process_control_request(event.rhport, &event.setup_received) ) { @@ -605,6 +611,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // forward to class driver: "non-STD request to Interface" return invoke_class_control(rhport, driver, p_request); } + if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { // Non standard request is not supported @@ -712,14 +719,17 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) ); - bool ret = false; + usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]); - // Handle STD request to endpoint - if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ) + if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { - // force return true for standard request - ret = true; - + // Forward class request to its driver + TU_VERIFY(driver); + return invoke_class_control(rhport, driver, p_request); + } + else + { + // Handle STD request to endpoint switch ( p_request->bRequest ) { case TUSB_REQ_GET_STATUS: @@ -730,40 +740,39 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const break; case TUSB_REQ_CLEAR_FEATURE: - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) usbd_edpt_clear_stall(rhport, ep_addr); - tud_control_status(rhport, p_request); - break; - case TUSB_REQ_SET_FEATURE: - if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) usbd_edpt_stall(rhport, ep_addr); - tud_control_status(rhport, p_request); + { + if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) + { + if ( TUSB_REQ_CLEAR_FEATURE == p_request->bRequest ) + { + usbd_edpt_clear_stall(rhport, ep_addr); + }else + { + usbd_edpt_stall(rhport, ep_addr); + } + } + + if (driver) + { + // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request + // We will also forward std request targeted endpoint to class drivers as well + + // STD request must always be ACKed regardless of driver returned value + // Also clear complete callback if driver set since it can also stall the request. + (void) invoke_class_control(rhport, driver, p_request); + usbd_control_set_complete_callback(NULL); + + // skip ZLP status if driver already did that + if ( !_usbd_dev.ep_status[0][TUSB_DIR_IN].busy ) tud_control_status(rhport, p_request); + } + } break; // Unknown/Unsupported request default: TU_BREAKPOINT(); return false; } } - - usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]); - - if (driver) - { - // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request - // We will forward all request targeted endpoint to class drivers after - // - For class-type requests: driver is fully responsible to reply to host - // - For std-type requests : driver init/re-init internal variable/buffer only, and - // must not call tud_control_status(), driver's return value will have no effect. - // EP state has already affected (stalled/cleared) - if ( invoke_class_control(rhport, driver, p_request) ) ret = true; - } - - if ( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ) - { - // Set complete callback = NULL since it can also stall the request. - usbd_control_set_complete_callback(NULL); - } - - return ret; } break; diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 8ed0ad1c0..d15380199 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -67,12 +67,7 @@ static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t con { // Opposite to endpoint in Data Phase uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; - - TU_LOG2(" Queue EP %02X with zlp Status\r\n", ep_addr); - - // status direction is reversed to one in the setup packet - // Note: Status must always be DATA1 - return dcd_edpt_xfer(rhport, ep_addr, NULL, 0); + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); } // Status phase @@ -101,9 +96,7 @@ static bool _data_stage_xact(uint8_t rhport) if ( xact_len ) memcpy(_usbd_ctrl_buf, _ctrl_xfer.buffer, xact_len); } - TU_LOG2(" Queue EP %02X with %u bytes\r\n", ep_addr, xact_len); - - return dcd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); + return usbd_edpt_xfer(rhport, ep_addr, xact_len ? _usbd_ctrl_buf : NULL, xact_len); } // Transmit data to/from the control endpoint. @@ -140,9 +133,6 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo // USBD API //--------------------------------------------------------------------+ -//--------------------------------------------------------------------+ -// Prototypes -//--------------------------------------------------------------------+ void usbd_control_reset(void); void usbd_control_set_request(tusb_control_request_t const *request); void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ); @@ -153,13 +143,13 @@ void usbd_control_reset(void) tu_varclr(&_ctrl_xfer); } -// TODO may find a better way +// Set complete callback void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp ) { _ctrl_xfer.complete_cb = fp; } -// useful for dcd_set_address where DCD is responsible for status response +// for dcd_set_address where DCD is responsible for status response void usbd_control_set_request(tusb_control_request_t const *request) { _ctrl_xfer.request = (*request); -- cgit v1.3.1 From 919bb9ce38e2c2c7afc3f9c763cc76c0c47f3a85 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Feb 2021 11:45:24 +0700 Subject: more epsize checking per type --- src/device/usbd.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index f6b00563d..10fd4612d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1103,22 +1103,36 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); - if (TUSB_XFER_ISOCHRONOUS == desc_ep->bmAttributes.xfer) + switch (desc_ep->bmAttributes.xfer) { - TU_ASSERT(desc_ep->wMaxPacketSize.size <= (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023)); - } - else - { - uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 512 : 64); - - if (TUSB_XFER_BULK == desc_ep->bmAttributes.xfer) + case TUSB_XFER_ISOCHRONOUS: { - // Bulk must be EXACTLY 512/64 bytes - TU_ASSERT(desc_ep->wMaxPacketSize.size == max_epsize); - }else + uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023); + TU_ASSERT(desc_ep->wMaxPacketSize.size <= max_epsize); + } + break; + + case TUSB_XFER_BULK: + + if (_usbd_dev.speed == TUSB_SPEED_HIGH) + { + // Bulk highspeed must be EXACTLY 512 + TU_ASSERT(desc_ep->wMaxPacketSize.size == 512); + }else + { + // TODO Bulk fullspeed can only be 8, 16, 32, 64 + TU_ASSERT(desc_ep->wMaxPacketSize.size <= 64); + } + break; + + case TUSB_XFER_INTERRUPT: { + uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 64); TU_ASSERT(desc_ep->wMaxPacketSize.size <= max_epsize); } + break; + + default: return false; } return dcd_edpt_open(rhport, desc_ep); -- cgit v1.3.1 From 9812cfc6c6ab98e600a1dd812d62e465ea3b99b4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Feb 2021 11:48:34 +0700 Subject: clean up --- src/device/usbd.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 10fd4612d..0c2d7b2ea 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1113,7 +1113,6 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) break; case TUSB_XFER_BULK: - if (_usbd_dev.speed == TUSB_SPEED_HIGH) { // Bulk highspeed must be EXACTLY 512 -- cgit v1.3.1 From e12c25ec2c6d1cb0dd3c02bdc1947ae351ccad54 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Feb 2021 12:05:22 +0700 Subject: rename dfu_rt to dfu_runtime for easy reading also rename tud_dfu_rt_reboot_to_dfu to tud_dfu_runtime_reboot_to_dfu_cb --- examples/device/dfu_rt/src/main.c | 2 +- examples/device/dfu_rt/src/tusb_config.h | 2 +- src/class/dfu/dfu_rt_device.c | 4 ++-- src/class/dfu/dfu_rt_device.h | 2 +- src/device/usbd.c | 4 ++-- src/tusb.h | 2 +- src/tusb_option.h | 4 ++-- 7 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/examples/device/dfu_rt/src/main.c b/examples/device/dfu_rt/src/main.c index 029ff7312..823c71ae5 100644 --- a/examples/device/dfu_rt/src/main.c +++ b/examples/device/dfu_rt/src/main.c @@ -112,7 +112,7 @@ void tud_resume_cb(void) } // Invoked on DFU_DETACH request to reboot to the bootloader -void tud_dfu_rt_reboot_to_dfu(void) +void tud_dfu_runtime_reboot_to_dfu_cb(void) { blink_interval_ms = BLINK_DFU_MODE; } diff --git a/examples/device/dfu_rt/src/tusb_config.h b/examples/device/dfu_rt/src/tusb_config.h index abdbe7526..bdae1d2e9 100644 --- a/examples/device/dfu_rt/src/tusb_config.h +++ b/examples/device/dfu_rt/src/tusb_config.h @@ -78,7 +78,7 @@ //------------- CLASS -------------// -#define CFG_TUD_DFU_RT 1 +#define CFG_TUD_DFU_RUNTIME 1 #ifdef __cplusplus } diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 38644615a..5700615be 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RT) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) #include "dfu_rt_device.h" #include "device/usbd_pvt.h" @@ -110,7 +110,7 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request { case DFU_REQUEST_DETACH: tud_control_status(rhport, request); - tud_dfu_rt_reboot_to_dfu(); + tud_dfu_runtime_reboot_to_dfu_cb(); break; case DFU_REQUEST_GETSTATUS: diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 643e25d8f..cff43d035 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); // TODO rename to _cb convention +TU_ATTR_WEAK void tud_dfu_runtime_reboot_to_dfu_cb(void); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/device/usbd.c b/src/device/usbd.c index d871a53d4..f4e4e08f3 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -175,9 +175,9 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif - #if CFG_TUD_DFU_RT + #if CFG_TUD_DFU_RUNTIME { - DRIVER_NAME("DFU-RT") + DRIVER_NAME("DFU-RUNTIME") .init = dfu_rtd_init, .reset = dfu_rtd_reset, .open = dfu_rtd_open, diff --git a/src/tusb.h b/src/tusb.h index 8b0dd103c..cc82c440d 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -92,7 +92,7 @@ #include "class/usbtmc/usbtmc_device.h" #endif - #if CFG_TUD_DFU_RT + #if CFG_TUD_DFU_RUNTIME #include "class/dfu/dfu_rt_device.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 73daf8592..6cbdefbf1 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -233,8 +233,8 @@ #define CFG_TUD_USBTMC 0 #endif -#ifndef CFG_TUD_DFU_RT - #define CFG_TUD_DFU_RT 0 +#ifndef CFG_TUD_DFU_RUNTIME + #define CFG_TUD_DFU_RUNTIME 0 #endif #ifndef CFG_TUD_NET -- cgit v1.3.1 From 09868434cd9f53394350cce682333ada97f796c3 Mon Sep 17 00:00:00 2001 From: ndinsmore <45537276+ndinsmore@users.noreply.github.com> Date: Fri, 12 Feb 2021 03:16:46 -0500 Subject: Fixes RP2040 buffer reallocation overrun problem (#642) Fix running out of memory on a device that repeatedly closes and opens an endpoint. This is a workaround at the moment. A better solution would be to implement reclaiming usb buffer memory when closing an endpoint (i.e. implement dcd_edpt_close). --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index a54f579b8..95b0963a3 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -164,8 +164,12 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint wMax ep->endpoint_control = &usb_dpram->ep_ctrl[num-1].out; } - // Now alloc a buffer and fill in endpoint control register - _hw_endpoint_alloc(ep); + // Now if it hasn't already been done + //alloc a buffer and fill in endpoint control register + if(!(ep->configured)) + { + _hw_endpoint_alloc(ep); + } } ep->configured = true; -- cgit v1.3.1 From a9fd0a454a96c599cb42f741c2e3e893b6c7306c Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 12 Feb 2021 16:28:41 +0100 Subject: Complete redesign of audio driver. --- examples/device/audio_test/src/main.c | 12 +- examples/device/audio_test/src/tusb_config.h | 7 +- examples/device/audio_test/src/usb_descriptors.c | 2 +- examples/device/uac2_headset/src/tusb_config.h | 14 +- src/class/audio/audio_device.c | 524 +++++++++-------------- src/class/audio/audio_device.h | 61 ++- src/portable/st/synopsys/dcd_synopsys.c | 8 - 7 files changed, 235 insertions(+), 393 deletions(-) (limited to 'src') diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 7f0ce3652..c63e64934 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -59,7 +59,7 @@ audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_N_CHANNELS_TX+1]; // Vol audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state // Audio test data -uint16_t test_buffer_audio[CFG_TUD_AUDIO_TX_FIFO_SIZE/2]; +uint16_t test_buffer_audio[CFG_TUD_AUDIO_EPSIZE_IN/2]; uint16_t startVal = 0; void led_blinking_task(void); @@ -73,12 +73,12 @@ int main(void) tusb_init(); // Init values - sampFreq = 44100; + sampFreq = 48000; clkValid = 1; sampleFreqRng.wNumSubRanges = 1; - sampleFreqRng.subrange[0].bMin = 44100; - sampleFreqRng.subrange[0].bMax = 44100; + sampleFreqRng.subrange[0].bMin = 48000; + sampleFreqRng.subrange[0].bMax = 48000; sampleFreqRng.subrange[0].bRes = 0; while (1) @@ -375,7 +375,7 @@ bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, u (void) ep_in; (void) cur_alt_setting; - tud_audio_write ((uint8_t *)test_buffer_audio, CFG_TUD_AUDIO_TX_FIFO_SIZE); + tud_audio_write ((uint8_t *)test_buffer_audio, CFG_TUD_AUDIO_EPSIZE_IN); return true; } @@ -388,7 +388,7 @@ bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uin (void) ep_in; (void) cur_alt_setting; - for (size_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_SIZE/2; cnt++) + for (size_t cnt = 0; cnt < CFG_TUD_AUDIO_EPSIZE_IN/2; cnt++) { test_buffer_audio[cnt] = startVal++; } diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index 5d94858ea..0744afdf0 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -90,7 +90,6 @@ extern "C" { //-------------------------------------------------------------------- // Audio format type -#define CFG_TUD_AUDIO_USE_TX_FIFO 1 #define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_I #define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED @@ -100,11 +99,11 @@ extern "C" { #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 2 // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_EPSIZE_IN 48*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX*CFG_TUD_AUDIO_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x 1 Channels -#define CFG_TUD_AUDIO_TX_FIFO_SIZE 48*2 // 48 Samples (48 kHz) x 2 Bytes/Sample (1/2 word) +#define CFG_TUD_AUDIO_EPSIZE_IN 48*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX*CFG_TUD_AUDIO_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x 1 Channels +#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN + 1; // Just for safety one sample more space // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) -#define CFG_TUD_AUDIO_N_AS_INT 1 +#define CFG_TUD_AUDIO_N_AS_INT 1 // Size of control request buffer #define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 diff --git a/examples/device/audio_test/src/usb_descriptors.c b/examples/device/audio_test/src/usb_descriptors.c index 02d018823..d4869a940 100644 --- a/examples/device/audio_test/src/usb_descriptors.c +++ b/examples/device/audio_test/src/usb_descriptors.c @@ -102,7 +102,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_MIC_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ 3, /*_nBitsUsedPerSample*/ 24, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ 48*4) + TUD_AUDIO_MIC_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ 16, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EPSIZE_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index d19feeb86..2ecfd59f6 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -112,20 +112,18 @@ extern "C" { #define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_EPSIZE_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels -#define CFG_TUD_AUDIO_TX_FIFO_COUNT (CFG_TUD_AUDIO_IN_PATH * 1) -#define CFG_TUD_AUDIO_TX_FIFO_SIZE (CFG_TUD_AUDIO_IN_PATH ? ((CFG_TUD_AUDIO_EPSIZE_IN)) : 0) +#define CFG_TUD_AUDIO_EPSIZE_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_EPSIZE_OUT (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels -#define CFG_TUD_AUDIO_RX_FIFO_COUNT (CFG_TUD_AUDIO_OUT_PATH * 1) -#define CFG_TUD_AUDIO_RX_FIFO_SIZE (CFG_TUD_AUDIO_OUT_PATH ? (3 * (CFG_TUD_AUDIO_EPSIZE_OUT / CFG_TUD_AUDIO_RX_FIFO_COUNT)) : 0) +#define CFG_TUD_AUDIO_EPSIZE_OUT (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_OUT*3 // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) -#define CFG_TUD_AUDIO_N_AS_INT 1 +#define CFG_TUD_AUDIO_N_AS_INT 1 // Size of control request buffer -#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 +#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 #ifdef __cplusplus } diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 07bfe6158..d1666056f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -103,6 +103,11 @@ typedef struct osal_mutex_def_t ep_in_ff_mutex; #endif +#endif + + // Audio control interrupt buffer - no FIFO +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN + CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; #endif // Support FIFOs @@ -122,18 +127,6 @@ typedef struct #endif #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - tu_fifo_t int_ctr_ff; - CFG_TUSB_MEM_ALIGN uint8_t int_ctr_ff_buf[CFG_TUD_AUDIO_INT_CTR_BUFSIZE]; -#if CFG_FIFO_MUTEX - osal_mutex_def_t int_ctr_ff_mutex; -#endif -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN]; -#endif - } audiod_interface_t; #define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ctrl_buf) @@ -146,11 +139,19 @@ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; extern const uint16_t tud_audio_desc_lengths[]; #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize); +static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio); +#endif + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); #endif #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE -static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio); +static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio); +#endif + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +static bool audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); #endif static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); @@ -193,80 +194,70 @@ bool tud_audio_n_mounted(uint8_t itf) uint16_t tud_audio_n_available(uint8_t itf) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); return tu_fifo_count(&_audiod_itf[itf].ep_out_ff); } uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); return tu_fifo_read_n(&_audiod_itf[itf].ep_out_ff, buffer, bufsize); } -void tud_audio_n_clear_ep_out_ff(uint8_t itf) +bool tud_audio_n_clear_ep_out_ff(uint8_t itf) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); return tu_fifo_clear(&_audiod_itf[itf].ep_out_ff); } #if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE // Delete all content in the support RX FIFOs -void tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) +bool tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); - tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + return tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); } uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); - tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + return tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); } uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX, ); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); } #endif #endif +// This function is called once an audio packet is received by the USB and is responsible for decoding received stream into audio channels. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE = 0. +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE - - - - - - - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - -uint16_t tud_audio_int_ctr_n_available(uint8_t itf) -{ - return tu_fifo_count(&_audiod_itf[itf].int_ctr_ff); -} - -uint16_t tud_audio_int_ctr_n_read(uint8_t itf, void* buffer, uint16_t bufsize) +static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) { - return tu_fifo_read_n(&_audiod_itf[itf].int_ctr_ff, buffer, bufsize); -} + uint8_t idxDriver, idxItf; + uint8_t const *dummy2; -void tud_audio_int_ctr_n_read_flush (uint8_t itf) -{ - tu_fifo_clear(&_audiod_itf[itf].int_ctr_ff); -} + // If a callback is used determine current alternate setting of + if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) + { + // Find index of audio streaming interface and index of interface + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); + } -#endif + // Get number of bytes in EP OUT SW FIFO + uint16_t n_bytes_received = tu_fifo_count(&audio->ep_out_ff); -// This function is called once something is received by USB and is responsible for decoding received stream into audio channels. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE = 0. + // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now decoded into support RX software FIFO + if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* buffer, uint16_t bufsize) -{ switch (CFG_TUD_AUDIO_FORMAT_TYPE_RX) { case AUDIO_FORMAT_TYPE_UNDEFINED: @@ -280,12 +271,7 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) { case AUDIO_DATA_FORMAT_TYPE_I_PCM: - -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - TU_VERIFY(audio_rx_done_type_I_pcm_ff_cb(rhport, audio, buffer, bufsize)); -#else -#error YOUR DECODING AND BUFFERING IS REQUIRED HERE! -#endif + TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio)); break; default: @@ -303,8 +289,13 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* break; } - // Call a weak callback here - a possibility for user to get informed RX was completed - if (tud_audio_rx_done_cb) TU_VERIFY(tud_audio_rx_done_cb(rhport, buffer, bufsize)); +#endif + + // Prepare for next transmission + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); + + // Call a weak callback here - a possibility for user to get informed decoding was completed + if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); return true; } @@ -313,59 +304,42 @@ static bool audio_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t* // The following functions are used in case CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE != 0 #if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -#if CFG_TUD_AUDIO_N_CHANNELS_RX > 1 -static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio, uint8_t * buffer, uint16_t bufsize) +static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { (void) rhport; - // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel - if (bufsize % (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX) != 0) - { - return false; - } + // We assume there is always the correct number of samples available for decoding - extra checks make no sense here - uint8_t chId = 0; - uint16_t cnt; -#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 - uint8_t sample = 0; -#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 2 - uint16_t sample = 0; -#else - uint32_t sample = 0; -#endif + uint16_t const n_bytes = tu_fifo_count(&audio->ep_out_ff); - for(cnt = 0; cnt < bufsize; cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) - { - // Let alignment problems be handled by memcpy - memcpy(&sample, &buffer[cnt], CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX); - if(tu_fifo_write_n(&audio->rx_ff[chId++], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE) != CFG_TUD_AUDIO_RX_ITEMSIZE) - { - // Buffer overflow - return false; - } + uint16_t cnt = CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; - if (chId == CFG_TUD_AUDIO_N_CHANNELS_RX) - { - chId = 0; - } - } - return true; -} + while (cnt <= n_bytes) + { + for (uint8_t cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_RX; cntChannel++) + { + // If 8, 16, or 32 bit values are to be copied +#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == CFG_TUD_AUDIO_RX_ITEMSIZE + // If this aborts then the target buffer is full + TU_VERIFY(tu_fifo_read_n_into_other_fifo(&audio->ep_out_ff, &audio->rx_ff[cntChannel], 0, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); #else -static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t *audio, uint8_t *buffer, uint16_t bufsize) -{ - (void) rhport; + // TODO: Implement a left and right justified 24 to 32 and vice versa copy process from FIFO to FIFO + uint32_t sample = 0; - // We expect to get a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX per channel - if (bufsize % (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX) != 0) - { - return false; + // Get sample from buffer + TU_VERIFY(tu_fifo_read_n(&audio->ep_out_ff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); + TU_VERIFY(tu_fifo_write_n(&audio->rx_ff[cntChannel], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE)); +#endif + } + + cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; } - tu_fifo_write_n(&audio->rx_ff[0], buffer, bufsize); + // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it + // TU_VERIFY(cnt != n_bytes); + return true; } -#endif // CFG_TUD_AUDIO_N_CHANNELS_RX > 1 #endif //CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE //--------------------------------------------------------------------+ @@ -374,126 +348,89 @@ static bool audio_rx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t *a #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +/** + * \brief Write data to EP in buffer + * + * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). + * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. + * + * \param[in] itf: Index of audio function interface + * \param[in] data: Pointer to data array to be copied from + * \param[in] len: # of array elements to copy + * \return Number of bytes actually written + */ uint16_t tud_audio_n_write(uint8_t itf, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); return tu_fifo_write_n(&_audiod_itf[itf].ep_in_ff, data, len); } -void tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete all content in the EP IN FIFO +bool tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete all content in the EP IN FIFO { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); - tu_fifo_clear(&_audiod_itf[itf].ep_in_ff); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); + return tu_fifo_clear(&_audiod_itf[itf].ep_in_ff); } #if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into EP SW FIFO { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, ); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); audiod_interface_t* audio = &_audiod_itf[itf]; - uint16_t n_bytes_copied; - TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio, &n_bytes_copied)); - return n_bytes_copied; -} - -uint16_t tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); - -uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) -{ - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX, ); - return tu_fifo_write_n(&audio->tx_ff[channelId], data, len); -} -#endif - -#endif - + uint16_t n_bytes_copied = tu_fifo_count(&audio->ep_in_ff); + TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio)); + n_bytes_copied -= tu_fifo_count(&audio->ep_in_ff); + n_bytes_copied = n_bytes_copied*audio->ep_in_ff.item_size; + return n_bytes_copied; +} -/** - * \brief Write data to EP in buffer - * - * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). - * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. - * - * \param[in] itf: Index of audio function interface - * \param[in] data: Pointer to data array to be copied from - * \param[in] len: # of array elements to copy - * \return Number of bytes actually written - */ -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE -#if !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -This function is intended for later use once EP buffers (at least for ISO EPs) are implemented as ring buffers -uint16_t tud_audio_n_write_ep_in_buffer(uint8_t itf, const void * data, uint16_t len) +bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) { - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) return 0; - - return tu_fifo_write_n(&audio->ep_in_ff, data, len); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); + return tu_fifo_clear(&_audiod_itf[itf].tx_ff[channelId]); } -#else - -#if CFG_TUD_AUDIO_N_CHANNELS_TX == 1 -uint16_t tud_audio_n_write(uint8_t itf, void const* data, uint16_t len) +uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) - { - return 0; - } - return tu_fifo_write_n(&audio->tx_ff[0], data, len); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); + return tu_fifo_write_n(&_audiod_itf[itf].tx_ff[channelId], data, len); } -#else -uint16_t tud_audio_n_write(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) -{ - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) { - return 0; - } +#endif - return tu_fifo_write_n(&audio->tx_ff[channelId], data, len); -} #endif -static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied); +#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -uint16_t tud_audio_n_write_flush(uint8_t itf) +// If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user +uint16_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint16_t len) { - audiod_interface_t *audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) { - return 0; - } + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - uint16_t n_bytes_copied; - TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio, &n_bytes_copied)); - return n_bytes_copied; -} + // We write directly into the EP's buffer - abort if previous transfer not complete + TU_VERIFY(!usbd_edpt_busy(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_int_ctr)); -#endif -#endif + // Check length + TU_VERIFY(len <= CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE); -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 -uint32_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint32_t bufsize) -{ - audiod_interface_t* audio = &_audiod_itf[itf]; - if (audio->p_desc == NULL) { - return 0; - } + memcpy(_audiod_itf[itf].ep_int_ctr_buf, buffer, len); - return tu_fifo_write_n(&audio->int_ctr_ff, buffer, bufsize); + // Schedule transmit + TU_VERIFY(usbd_edpt_xfer(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_int_ctr, _audiod_itf[itf].ep_int_ctr_buf, len)); + + return true; } #endif // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE = 0 and use tud_audio_n_write_ep_in_buffer() (NOT IMPLEMENTED SO FAR). +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE = 0 and use tud_audio_n_write. // n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE -static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio, uint16_t * n_bytes_copied) +static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) { uint8_t idxDriver, idxItf; uint8_t const *dummy2; @@ -524,7 +461,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio, uint16 { case AUDIO_DATA_FORMAT_TYPE_I_PCM: - TU_VERIFY(audiod_tx_done_type_I_pcm_ff_cb(rhport, audio)); + TU_VERIFY(audiod_encode_type_I_pcm(rhport, audio)); break; @@ -544,14 +481,14 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio, uint16 } #endif - // Inform how many bytes will be copied - *n_bytes_copied = tu_fifo_count(&audio->ep_in_ff); + // Send everything in ISO EP FIFO + uint16_t n_bytes_tx = tu_fifo_count(&audio->ep_in_ff); // Schedule transmit - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, *n_bytes_copied)); + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, *n_bytes_copied, idxDriver, audio->ep_in, audio->altSetting[idxItf])); + if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->altSetting[idxItf])); return true; } @@ -559,26 +496,29 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio, uint16 #endif //CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE #if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -#if CFG_TUD_AUDIO_N_CHANNELS_TX > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) -static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) +// Take samples from the support buffer and encode them into the IN EP software FIFO +static bool audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { // We encode directly into IN EP's FIFO - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]) / CFG_TUD_AUDIO_TX_ITEMSIZE; + uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]); // We first look for the minimum number of bytes and afterwards convert it to sample size uint8_t cntChannel; for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { uint16_t const count = tu_fifo_count(&audio->tx_ff[cntChannel]); - if (count / CFG_TUD_AUDIO_TX_ITEMSIZE < nSamplesPerChannelToSend) + if (count < nSamplesPerChannelToSend) { - nSamplesPerChannelToSend = count * CFG_TUD_AUDIO_TX_ITEMSIZE; + nSamplesPerChannelToSend = count; } } + // Convert to sample size + nSamplesPerChannelToSend = nSamplesPerChannelToSend / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + // Check if there is enough if (nSamplesPerChannelToSend == 0) return true; @@ -608,106 +548,14 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* } return true; } - -#else -static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t* audio) -{ - // TODO GET RID OF SINGLE TX_FIFO! - - // We encode directly into IN EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); - - // Determine amount of samples - uint16_t nByteCount = tu_fifo_count(&audio->tx_ff[0]); - - nByteCount = tu_min16(nByteCount, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE); - - // Check if there is enough - if (nByteCount == 0) - { - return true; - } - - nByteCount = tu_fifo_read_n_into_other_fifo(&audio->tx_ff[0], &audio->ep_in_ff, 0, nByteCount); - - return true; -} -#endif // CFG_TUD_AUDIO_N_CHANNELS_TX > 1 || (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX != CFG_TUD_AUDIO_TX_ITEMSIZE) - #endif //CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -// This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent +// This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static bool audio_fb_send(uint8_t rhport, audiod_interface_t *audio) -{ - uint8_t fb[4]; - uint16_t len; - - if (audio->fb_val == 0) - { - len = 0; - return true; - } - else - { - len = 4; - // Here we need to return the feedback value - if (rhport == 0) - { - // For FS format is 10.14 - fb[0] = (audio->fb_val >> 2) & 0xFF; - fb[1] = (audio->fb_val >> 10) & 0xFF; - fb[2] = (audio->fb_val >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - fb[3] = 0; - } - else - { - // For HS format is 16.16 - fb[0] = (audio->fb_val >> 0) & 0xFF; - fb[1] = (audio->fb_val >> 8) & 0xFF; - fb[2] = (audio->fb_val >> 16) & 0xFF; - fb[3] = (audio->fb_val >> 24) & 0xFF; - } - return usbd_edpt_xfer(rhport, audio->ep_fb, fb, len); - } - -} - -//static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio) -//{ -// (void) rhport; -// (void) audio; -// -// if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); -// return 0; -//} - -#endif - -// This function is called once a transmit of an interrupt control packet was successfully completed. Here, we get the remaining bytes to send - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static bool audio_int_ctr_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t * n_bytes_copied) +static inline bool audiod_fb_send(uint8_t rhport, audiod_interface_t *audio) { - // We write directly into the EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_int_ctr)); - - // TODO: Big endianess handling - uint16_t cnt = tu_fifo_read_n(audio->int_ctr_ff, audio->ep_int_ctr_buf, CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN); - - if (cnt > 0) - { - // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_int_ctr, audio->ep_int_ctr_buf, cnt)); - } - - *n_bytes_copied = cnt; - - if (tud_audio_int_ctr_done_cb) TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, n_bytes_copied)); - - return true; + return usbd_edpt_xfer(rhport, audio->ep_fb, (uint8_t *) &audio->fb_val, 4); } #endif @@ -724,11 +572,21 @@ void audiod_init(void) // Initialize IN EP FIFO if required #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE - // Initialize IN EP FIFO tu_fifo_config(&audio->ep_in_ff, &audio->ep_in_buf, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex)); +#endif #endif - // Initialize TX FIFOs if required + // Initialize OUT EP FIFO if required +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_out_ff, osal_mutex_create(&audio->ep_out_ff_mutex)); +#endif +#endif + + // Initialize TX support FIFOs if required #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { @@ -739,6 +597,7 @@ void audiod_init(void) } #endif + // Initialize RX support FIFOs if required #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { @@ -746,18 +605,7 @@ void audiod_init(void) #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); #endif - - // Initialize OUT EP FIFO - tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); - } -#endif - -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0 - tu_fifo_config(&audio->int_ctr_ff, &audio->int_ctr_ff_buf, CFG_TUD_AUDIO_INT_CTR_BUFSIZE, 1, true); -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->int_ctr_ff, osal_mutex_create(&audio->int_ctr_ff_mutex)); -#endif #endif } } @@ -775,6 +623,10 @@ void audiod_reset(uint8_t rhport) tu_fifo_clear(&audio->ep_in_ff); #endif +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + tu_fifo_clear(&audio->ep_out_ff); +#endif + #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { @@ -881,7 +733,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE > 0 +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) { _audiod_itf[idxDriver].ep_in_as_intf_num = 0; @@ -932,10 +784,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - // We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! + //TODO: We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! usbd_edpt_clear_stall(rhport, ep_addr); -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE > 0 +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP { // Save address @@ -946,8 +798,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Schedule first transmit - in case no sample data is available a ZLP is loaded - uint16_t n_bytes_copied; - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); + // It is necessary to trigger this here since the refill is done with an TX FIFO empty interrupt which can only trigger if something was in there + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver])); } #endif @@ -963,7 +815,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Prepare for incoming data - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); + TU_VERIFY(usbd_edpt_iso_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].ep_out_ff, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -1218,16 +1070,10 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? // In case of an erroneous transmission a retransmission is conducted - this is taken care of by PHY ??? - // Load new data - uint16 *n_bytes_copied; - TU_VERIFY(audio_int_ctr_done_cb(rhport, &_audiod_itf[idxDriver], n_bytes_copied)); + // I assume here, that things above are handled by PHY + // All transmission is done - what remains to do is to inform job was completed - if (*n_bytes_copied == 0 && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN))) - { - // There is no data left to send, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); - } + if (tud_audio_int_ctr_done_cb) TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, (uint16_t) xferred_bytes)); } #endif @@ -1246,8 +1092,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // This is the only place where we can fill something into the EPs buffer! // Load new data - uint16_t n_bytes_copied; - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver], &n_bytes_copied)); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver])); // Transmission of ZLP is done by audiod_tx_done_cb() return true; @@ -1260,10 +1105,8 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 if (_audiod_itf[idxDriver].ep_out == ep_addr) { // Save into buffer - do whatever has to be done - TU_VERIFY(audio_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); - - // prepare for next transmission - TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, _audiod_itf[idxDriver].ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); +// TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver])); return true; } @@ -1275,14 +1118,14 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 { if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); - return audio_fb_send(rhport, &_audiod_itf[idxDriver]); + // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent + return audiod_fb_send(rhport, &_audiod_itf[idxDriver]); } #endif #endif } return false; - } bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len) @@ -1458,14 +1301,37 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback) -{ - audiod_interface_t *audio = &_audiod_itf[0]; - - audio->fb_val = feedback; - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_fb), true); - return audio_fb_send(rhport, audio); +// Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically +bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback) +{ + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); + + // Format the feedback value + if (_audiod_itf[itf].rhport == 0) + { + uint8_t * fb = (uint8_t *) &_audiod_itf[itf].fb_val; + + // For FS format is 10.14 + *(fb++) = (feedback >> 2) & 0xFF; + *(fb++) = (feedback >> 10) & 0xFF; + *(fb++) = (feedback >> 18) & 0xFF; + // 4th byte is needed to work correctly with MS Windows + *fb = 0; + } + else + { + // For HS format is 16.16 as originally demanded + _audiod_itf[itf].fb_val = feedback; + } + + // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value + if (!usbd_edpt_busy(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_fb)) + { + return audiod_fb_send(_audiod_itf[itf].rhport, &_audiod_itf[itf]); + } + + return true; } #endif diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index fdd4c15d4..6e0b3308e 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -136,8 +136,8 @@ #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#ifndef CFG_TUD_AUDIO_INT_CTR_BUFSIZE -#define CFG_TUD_AUDIO_INT_CTR_BUFSIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE +#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) #endif #endif @@ -223,10 +223,10 @@ bool tud_audio_n_mounted (uint8_t itf); uint16_t tud_audio_n_available (uint8_t itf); uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); -void tud_audio_n_clear_ep_out_ff (uint8_t itf); // Delete all content in the EP OUT FIFO +bool tud_audio_n_clear_ep_out_ff (uint8_t itf); // Delete all content in the EP OUT FIFO #if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -void tud_audio_n_clear_rx_support_ff (uint8_t itf, uint8_t channelId); // Delete all content in the support RX FIFOs +bool tud_audio_n_clear_rx_support_ff (uint8_t itf, uint8_t channelId); // Delete all content in the support RX FIFOs uint16_t tud_audio_n_available_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_read_support_ff (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); #endif @@ -236,20 +236,17 @@ uint16_t tud_audio_n_read_support_ff (uint8_t itf, uint8_t channelI #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); -void tud_audio_n_clear_ep_in_ff (uint8_t itf); // Delete all content in the EP IN FIFO +bool tud_audio_n_clear_ep_in_ff (uint8_t itf); // Delete all content in the EP IN FIFO #if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE uint16_t tud_audio_n_flush_tx_support_ff (uint8_t itf); // Force all content in the support TX FIFOs to be written into EP SW FIFO -uint16_t tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); +bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_write_support_ff (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); #endif #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -uint16_t tud_audio_int_ctr_n_available (uint8_t itf); -uint16_t tud_audio_int_ctr_n_read (uint8_t itf, void* buffer, uint16_t bufsize); -void tud_audio_int_ctr_n_clear (uint8_t itf); // Delete all content in the AUDIO_INT_CTR FIFO uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t len); #endif @@ -264,11 +261,11 @@ static inline bool tud_audio_mounted (void); #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE static inline uint16_t tud_audio_available (void); -static inline void tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO +static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); #if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -static inline void tud_audio_clear_rx_support_ff (uint8_t channelId); +static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId); static inline uint16_t tud_audio_available_support_ff (uint8_t channelId); static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize); #endif @@ -280,7 +277,7 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE static inline uint16_t tud_audio_write (const void * data, uint16_t len); -static inline uint16_t tud_audio_clear_ep_in_ff (void); +static inline bool tud_audio_clear_ep_in_ff (void); #if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE static inline uint16_t tud_audio_flush_tx_support_ff (void); @@ -293,9 +290,6 @@ static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, // INT CTR API #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_available (void); -static inline uint16_t tud_audio_int_ctr_read (void* buffer, uint16_t bufsize); -static inline void tud_audio_int_ctr_clear (void); static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); #endif @@ -317,8 +311,8 @@ TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_byte #endif #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -327,11 +321,12 @@ TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); // Value will be corrected for FS to 10.14 format automatically. // (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). // Feedback value will be sent at FB endpoint interval till it's changed. -bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback); +bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback); +static inline bool tud_audio_fb_set(uint32_t feedback); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t * n_bytes_copied); +TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t n_bytes_copied); #endif // Invoked when audio set interface request received @@ -381,16 +376,16 @@ static inline uint16_t tud_audio_read (void* buffer, uint1 return tud_audio_n_read(0, buffer, bufsize); } -static inline uint16_t tud_audio_clear_ep_out_ff (void) +static inline bool tud_audio_clear_ep_out_ff (void) { return tud_audio_n_clear_ep_out_ff(0); } #if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -static inline void tud_audio_clear_rx_support_ff (uint8_t channelId) +static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId) { - tud_audio_n_clear_rx_support_ff(0, channelId); + return tud_audio_n_clear_rx_support_ff(0, channelId); } static inline uint16_t tud_audio_available_support_ff (uint8_t channelId) @@ -416,7 +411,7 @@ static inline uint16_t tud_audio_write (const void * data, return tud_audio_n_write(0, data, len); } -static inline uint16_t tud_audio_clear_ep_in_ff (void) +static inline bool tud_audio_clear_ep_in_ff (void) { return tud_audio_n_clear_ep_in_ff(0); } @@ -443,24 +438,16 @@ static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_available(void) -{ - return tud_audio_int_ctr_n_available(0); -} - -static inline uint16_t tud_audio_int_ctr_read(void* buffer, uint16_t bufsize) -{ - return tud_audio_int_ctr_n_read(0, buffer, bufsize); -} - -static inline void tud_audio_int_ctr_clear(void) +static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len) { - return tud_audio_int_ctr_n_clear(0); + return tud_audio_int_ctr_n_write(0, buffer, len); } +#endif -static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len) +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +static inline bool tud_audio_fb_set(uint32_t feedback) { - return tud_audio_int_ctr_n_write(0, buffer, len); + return tud_audio_n_fb_set(0, feedback); } #endif diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 4cb6028cc..b6dacd927 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -697,14 +697,6 @@ bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); } - // EP0 can only handle one packet - if(epnum == 0) { - ep0_pending[dir] = total_bytes; - // Schedule the first transaction for EP0 transfer - edpt_schedule_packets(rhport, epnum, dir, 1, ep0_pending[dir]); - return true; - } - uint16_t num_packets = (total_bytes / xfer->max_size); uint8_t const short_packet_size = total_bytes % xfer->max_size; -- cgit v1.3.1 From 185414721ff549058a199ade40966015e6260996 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 12 Feb 2021 18:04:45 +0100 Subject: Formating --- src/class/audio/audio.h | 10 ++-- src/class/audio/audio_device.c | 116 ++++++++++++++++++++--------------------- src/class/audio/audio_device.h | 2 +- 3 files changed, 64 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 05e61f8df..af0e86e21 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -901,7 +901,7 @@ typedef struct TU_ATTR_PACKED { } subrange[numSubRanges] ; \ } - /// 5.2.3.2 2-byte Control RANGE Parameter Block +/// 5.2.3.2 2-byte Control RANGE Parameter Block #define audio_control_range_2_n_t(numSubRanges) \ struct TU_ATTR_PACKED { \ uint16_t wNumSubRanges; \ @@ -912,7 +912,7 @@ typedef struct TU_ATTR_PACKED { } subrange[numSubRanges]; \ } - // 5.2.3.3 4-byte Control RANGE Parameter Block +// 5.2.3.3 4-byte Control RANGE Parameter Block #define audio_control_range_4_n_t(numSubRanges) \ struct TU_ATTR_PACKED { \ uint16_t wNumSubRanges; \ @@ -923,12 +923,12 @@ typedef struct TU_ATTR_PACKED { } subrange[numSubRanges]; \ } - /** @} */ +/** @} */ #ifdef __cplusplus - } +} #endif #endif - /** @} */ +/** @} */ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index d1666056f..622e6d113 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -240,21 +240,21 @@ uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffe static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) { - uint8_t idxDriver, idxItf; - uint8_t const *dummy2; + uint8_t idxDriver, idxItf; + uint8_t const *dummy2; - // If a callback is used determine current alternate setting of - if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) - { - // Find index of audio streaming interface and index of interface - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); - } + // If a callback is used determine current alternate setting of + if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) + { + // Find index of audio streaming interface and index of interface + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); + } - // Get number of bytes in EP OUT SW FIFO - uint16_t n_bytes_received = tu_fifo_count(&audio->ep_out_ff); + // Get number of bytes in EP OUT SW FIFO + uint16_t n_bytes_received = tu_fifo_count(&audio->ep_out_ff); - // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now decoded into support RX software FIFO - if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); + // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now decoded into support RX software FIFO + if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); #if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE @@ -316,23 +316,23 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) while (cnt <= n_bytes) { - for (uint8_t cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_RX; cntChannel++) - { - // If 8, 16, or 32 bit values are to be copied + for (uint8_t cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_RX; cntChannel++) + { + // If 8, 16, or 32 bit values are to be copied #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == CFG_TUD_AUDIO_RX_ITEMSIZE - // If this aborts then the target buffer is full - TU_VERIFY(tu_fifo_read_n_into_other_fifo(&audio->ep_out_ff, &audio->rx_ff[cntChannel], 0, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); + // If this aborts then the target buffer is full + TU_VERIFY(tu_fifo_read_n_into_other_fifo(&audio->ep_out_ff, &audio->rx_ff[cntChannel], 0, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); #else - // TODO: Implement a left and right justified 24 to 32 and vice versa copy process from FIFO to FIFO - uint32_t sample = 0; + // TODO: Implement a left and right justified 24 to 32 and vice versa copy process from FIFO to FIFO + uint32_t sample = 0; - // Get sample from buffer - TU_VERIFY(tu_fifo_read_n(&audio->ep_out_ff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); - TU_VERIFY(tu_fifo_write_n(&audio->rx_ff[cntChannel], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE)); + // Get sample from buffer + TU_VERIFY(tu_fifo_read_n(&audio->ep_out_ff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); + TU_VERIFY(tu_fifo_write_n(&audio->rx_ff[cntChannel], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE)); #endif - } + } - cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; + cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; } // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it @@ -389,8 +389,8 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force a bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); - return tu_fifo_clear(&_audiod_itf[itf].tx_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); + return tu_fifo_clear(&_audiod_itf[itf].tx_ff[channelId]); } uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) @@ -574,15 +574,15 @@ void audiod_init(void) #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE tu_fifo_config(&audio->ep_in_ff, &audio->ep_in_buf, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex)); + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex)); #endif #endif // Initialize OUT EP FIFO if required #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE - tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); + tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, osal_mutex_create(&audio->ep_out_ff_mutex)); + tu_fifo_config_mutex(&audio->ep_out_ff, osal_mutex_create(&audio->ep_out_ff_mutex)); #endif #endif @@ -1105,8 +1105,8 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 if (_audiod_itf[idxDriver].ep_out == ep_addr) { // Save into buffer - do whatever has to be done -// TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); - TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver])); + // TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver])); return true; } @@ -1305,33 +1305,33 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) // Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - - // Format the feedback value - if (_audiod_itf[itf].rhport == 0) - { - uint8_t * fb = (uint8_t *) &_audiod_itf[itf].fb_val; - - // For FS format is 10.14 - *(fb++) = (feedback >> 2) & 0xFF; - *(fb++) = (feedback >> 10) & 0xFF; - *(fb++) = (feedback >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - *fb = 0; - } - else - { - // For HS format is 16.16 as originally demanded - _audiod_itf[itf].fb_val = feedback; - } - - // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_fb)) - { - return audiod_fb_send(_audiod_itf[itf].rhport, &_audiod_itf[itf]); - } - - return true; + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); + + // Format the feedback value + if (_audiod_itf[itf].rhport == 0) + { + uint8_t * fb = (uint8_t *) &_audiod_itf[itf].fb_val; + + // For FS format is 10.14 + *(fb++) = (feedback >> 2) & 0xFF; + *(fb++) = (feedback >> 10) & 0xFF; + *(fb++) = (feedback >> 18) & 0xFF; + // 4th byte is needed to work correctly with MS Windows + *fb = 0; + } + else + { + // For HS format is 16.16 as originally demanded + _audiod_itf[itf].fb_val = feedback; + } + + // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value + if (!usbd_edpt_busy(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_fb)) + { + return audiod_fb_send(_audiod_itf[itf].rhport, &_audiod_itf[itf]); + } + + return true; } #endif diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 6e0b3308e..34ba5bb55 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -447,7 +447,7 @@ static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t l #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static inline bool tud_audio_fb_set(uint32_t feedback) { - return tud_audio_n_fb_set(0, feedback); + return tud_audio_n_fb_set(0, feedback); } #endif -- cgit v1.3.1 From 9e2a1d2e6a22fb1cfb952a62f501403d372bbb45 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 12 Feb 2021 18:31:54 +0100 Subject: Fix CFG_TUD_AUDIO_EP_IN/OUT_SW_BUFFER_SIZE to be defined anyway --- src/class/audio/audio_device.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 34ba5bb55..d1d1157eb 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -64,21 +64,25 @@ #ifndef CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE #define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN // TX #endif +#else +#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE 0 #endif #if CFG_TUD_AUDIO_EPSIZE_OUT #ifndef CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE #define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_OUT // RX #endif +#else +#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE 0 #endif // General information of number of TX and/or RX channels - is used in case support FIFOs (see below) are used and can be used for descriptor definitions #ifndef CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_N_CHANNELS_TX 0 +#define CFG_TUD_AUDIO_N_CHANNELS_TX 0 #endif #ifndef CFG_TUD_AUDIO_N_CHANNELS_RX -#define CFG_TUD_AUDIO_N_CHANNELS_RX 0 +#define CFG_TUD_AUDIO_N_CHANNELS_RX 0 #endif // Use of TX/RX support FIFOs -- cgit v1.3.1 From 59d6ed9ea409525899d398789b255ffb7f96660a Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 13 Feb 2021 12:13:10 +0100 Subject: Implement dcd_edpt_iso_xfer() for dcd_esp32s2.c --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 184 +++++++++++++++++++-------- 1 file changed, 131 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 703841759..72fb4ba48 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -27,6 +27,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if CFG_TUSB_MCU == OPT_MCU_ESP32S2 && TUSB_OPT_DEVICE_ENABLED @@ -59,6 +60,7 @@ typedef struct { uint8_t *buffer; + tu_fifo_t * ff; uint16_t total_len; uint16_t queued_len; uint16_t max_size; @@ -354,6 +356,64 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void)rhport; + + // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 + TU_ASSERT(ff->item_size == 1); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->short_packet = false; + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint8_t short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if (short_packet_size > 0 || (total_bytes == 0)) { + num_packets++; + } + + // Set copy mode to constant address - required since data copied to or from the hardware USB FIFO needs to be written at a constant address + if (dir == TUSB_DIR_IN) + { + tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_CST); + } + else + { + tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); + } + + ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", + epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), + num_packets, total_bytes); + + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them + // here. + if (dir == TUSB_DIR_IN) { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; + USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK + + // Enable fifo empty interrupt only if there are something to put in the fifo. + if(total_bytes != 0) { + USB0.dtknqr4_fifoemptymsk |= (1 << epnum); + } + } else { + // Each complete packet for OUT xfers triggers XFRC. + USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; + } + return true; +} + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; @@ -462,36 +522,46 @@ static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; } - uint8_t to_recv_rem = to_recv_size % 4; - uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; - - // Do not assume xfer buffer is aligned. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to collect. - if (to_recv_size >= 4) { - for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { - uint32_t tmp = (*rx_fifo); - base[i] = tmp & 0x000000FF; - base[i + 1] = (tmp & 0x0000FF00) >> 8; - base[i + 2] = (tmp & 0x00FF0000) >> 16; - base[i + 3] = (tmp & 0xFF000000) >> 24; + // Common buffer read + if (xfer->buffer) + { + uint8_t to_recv_rem = to_recv_size % 4; + uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; + + // Do not assume xfer buffer is aligned. + uint8_t *base = (xfer->buffer + xfer->queued_len); + + // This for loop always runs at least once- skip if less than 4 bytes + // to collect. + if (to_recv_size >= 4) { + for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { + uint32_t tmp = (*rx_fifo); + base[i] = tmp & 0x000000FF; + base[i + 1] = (tmp & 0x0000FF00) >> 8; + base[i + 2] = (tmp & 0x00FF0000) >> 16; + base[i + 3] = (tmp & 0xFF000000) >> 24; + } } - } - // Do not read invalid bytes from RX FIFO. - if (to_recv_rem != 0) { - uint32_t tmp = (*rx_fifo); - uint8_t *last_32b_bound = base + to_recv_size_aligned; + // Do not read invalid bytes from RX FIFO. + if (to_recv_rem != 0) { + uint32_t tmp = (*rx_fifo); + uint8_t *last_32b_bound = base + to_recv_size_aligned; - last_32b_bound[0] = tmp & 0x000000FF; - if (to_recv_rem > 1) { - last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; - } - if (to_recv_rem > 2) { - last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; + last_32b_bound[0] = tmp & 0x000000FF; + if (to_recv_rem > 1) { + last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; + } + if (to_recv_rem > 2) { + last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; + } } + + } + else + { + // Ring buffer + tu_fifo_write_n(xfer->ff, (const void *) rx_fifo, to_recv_size); } xfer->queued_len += xfer_size; @@ -510,37 +580,45 @@ static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, xfer->queued_len = xfer->total_len - remaining; uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; - uint8_t to_xfer_rem = to_xfer_size % 4; - uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; - - // Buffer might not be aligned to 32b, so we need to force alignment - // by copying to a temp var. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to send off. - if (to_xfer_size >= 4) { - for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { - uint32_t tmp = base[i] | (base[i + 1] << 8) | - (base[i + 2] << 16) | (base[i + 3] << 24); - (*tx_fifo) = tmp; + + if (xfer->buffer) + { + uint8_t to_xfer_rem = to_xfer_size % 4; + uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; + + // Buffer might not be aligned to 32b, so we need to force alignment + // by copying to a temp var. + uint8_t *base = (xfer->buffer + xfer->queued_len); + + // This for loop always runs at least once- skip if less than 4 bytes + // to send off. + if (to_xfer_size >= 4) { + for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { + uint32_t tmp = base[i] | (base[i + 1] << 8) | + (base[i + 2] << 16) | (base[i + 3] << 24); + (*tx_fifo) = tmp; + } } - } - // Do not read beyond end of buffer if not divisible by 4. - if (to_xfer_rem != 0) { - uint32_t tmp = 0; - uint8_t *last_32b_bound = base + to_xfer_size_aligned; + // Do not read beyond end of buffer if not divisible by 4. + if (to_xfer_rem != 0) { + uint32_t tmp = 0; + uint8_t *last_32b_bound = base + to_xfer_size_aligned; - tmp |= last_32b_bound[0]; - if (to_xfer_rem > 1) { - tmp |= (last_32b_bound[1] << 8); - } - if (to_xfer_rem > 2) { - tmp |= (last_32b_bound[2] << 16); - } + tmp |= last_32b_bound[0]; + if (to_xfer_rem > 1) { + tmp |= (last_32b_bound[1] << 8); + } + if (to_xfer_rem > 2) { + tmp |= (last_32b_bound[2] << 16); + } - (*tx_fifo) = tmp; + (*tx_fifo) = tmp; + } + } + else + { + tu_fifo_read_n(xfer->ff, (void *) tx_fifo, to_xfer_size); } } -- cgit v1.3.1 From 7ab389db210fdab67bdcc68b5d245606b5146a03 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 13 Feb 2021 16:36:32 +0100 Subject: Implement dcd_edpt_iso_xfer() for dcd_samg.c. NOTE: ISO EP not supported --- src/portable/microchip/samg/dcd_samg.c | 53 ++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 2f9f1097f..465f6419e 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -25,6 +25,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if CFG_TUSB_MCU == OPT_MCU_SAMG @@ -43,6 +44,7 @@ typedef struct { uint8_t* buffer; + tu_fifo_t* ff; uint16_t total_len; volatile uint16_t actual_len; uint16_t epsize; @@ -293,6 +295,38 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_desc_t* xfer = &_dcd_xfer[epnum]; + xfer->total_len = total_bytes; + xfer->actual_len = 0; + xfer->buffer = NULL; // Indicates a FIFO shall be used + xfer->ff = ff; + + if (dir == TUSB_DIR_OUT) + { + tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); + + // Enable interrupt when starting OUT transfer + if (epnum != 0) UDP->UDP_IER |= (1 << epnum); + } + else + { + tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_CST); + tu_fifo_read_n(ff, (void *) &UDP->UDP_FDR[epnum], xfer_packet_len(xfer)); + + // TX ready for transfer + csr_set(epnum, UDP_CSR_TXPKTRDY_Msk); + } + + return true; +} + // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { @@ -402,7 +436,14 @@ void dcd_int_handler(uint8_t rhport) if (xact_len) { // write to EP fifo - xact_ep_write(epnum, xfer->buffer, xact_len); + if (xfer->buffer) + { + xact_ep_write(epnum, xfer->buffer, xact_len); + } + else + { + tu_fifo_read_n(ff, (void *) &UDP->UDP_FDR[epnum], xact_len); + } // TX ready for transfer csr_set(epnum, UDP_CSR_TXPKTRDY_Msk); @@ -428,7 +469,15 @@ void dcd_int_handler(uint8_t rhport) uint16_t const xact_len = (uint16_t) ((UDP->UDP_CSR[epnum] & UDP_CSR_RXBYTECNT_Msk) >> UDP_CSR_RXBYTECNT_Pos); // Read from EP fifo - xact_ep_read(epnum, xfer->buffer, xact_len); + if (xfer->buffer) + { + xact_ep_read(epnum, xfer->buffer, xact_len); + } + else + { + tu_fifo_write_n(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len); + } + xfer_packet_done(xfer); if ( 0 == xfer_packet_len(xfer) ) -- cgit v1.3.1 From e6816784021959223ce740ed6946b62136778fec Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 13 Feb 2021 17:06:27 +0100 Subject: Implement dcd_edpt_iso_xfer() for dcd_nuc120.c --- src/portable/nuvoton/nuc120/dcd_nuc120.c | 58 +++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index dc48e54cc..0c3bd9a6b 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -34,6 +34,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC120) @@ -76,6 +77,7 @@ static bool active_ep0_xfer; static struct xfer_ctl_t { uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */ + tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_iso_xfer() */ union { uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */ uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */ @@ -142,7 +144,15 @@ static void dcd_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) { uint16_t bytes_now = tu_min16(xfer->in_remaining_bytes, xfer->max_packet_size); - memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); + if (xfer->data_ptr) + { + memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); + } + else + { + tu_fifo_read_n(xfer->ff, (void *) (USBD_BUF_BASE + ep->BUFSEG), bytes_now); + } + ep->MXPLD = bytes_now; } @@ -286,6 +296,36 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + + /* mine the data for the information we need */ + tusb_dir_t dir = tu_edpt_dir(ep_addr); + USBD_EP_T *ep = ep_entry(ep_addr, false); + struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; + + /* store away the information we'll needing now and later */ + xfer->data_ptr = NULL; // Indicates a FIFO shall be used + xfer->ff = ff; + xfer->in_remaining_bytes = total_bytes; + xfer->total_bytes = total_bytes; + + if (TUSB_DIR_IN == dir) + { + tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_INC); // For the PHY in nuc120 the source and destination pointer have to be incremented! + dcd_in_xfer(xfer, ep); + } + else + { + tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_INC); // For the PHY in nuc120 the source and destination pointer have to be incremented! + xfer->out_bytes_so_far = 0; + ep->MXPLD = xfer->max_packet_size; + } + + return true; +} + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; @@ -389,9 +429,17 @@ void dcd_int_handler(uint8_t rhport) if (out_ep) { /* copy the data from the PC to the previously provided buffer */ - memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); + if (xfer->data_ptr) + { + memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); + xfer->data_ptr += available_bytes; + } + else + { + tu_fifo_write_n(xfer->ff, (const void *) (USBD_BUF_BASE + ep->BUFSEG), available_bytes); + } + xfer->out_bytes_so_far += available_bytes; - xfer->data_ptr += available_bytes; /* when the transfer is finished, alert TinyUSB; otherwise, accept more data */ if ( (xfer->total_bytes == xfer->out_bytes_so_far) || (available_bytes < xfer->max_packet_size) ) @@ -403,7 +451,9 @@ void dcd_int_handler(uint8_t rhport) { /* update the bookkeeping to reflect the data that has now been sent to the PC */ xfer->in_remaining_bytes -= available_bytes; - xfer->data_ptr += available_bytes; + + /* increment only if xfer->data_ptr != NULL - if xfer->data_ptr == NULL then a FIFO is used for which xfer->data_ptr MUST STAY ZERO! */ + if (xfer->data_ptr) xfer->data_ptr += available_bytes; /* if more data to send, send it; otherwise, alert TinyUSB that we've finished */ if (xfer->in_remaining_bytes) -- cgit v1.3.1 From 126e46e38ae1f839262160e8e56cd99936c7451d Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 13 Feb 2021 17:37:13 +0100 Subject: Fix not increment xfer->buffer if xfer->buffer == NULL in dcd_samg.c --- src/portable/microchip/samg/dcd_samg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 465f6419e..6e7e84a99 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -82,7 +82,7 @@ void xfer_packet_done(xfer_desc_t* xfer) { uint16_t const xact_len = xfer_packet_len(xfer); - xfer->buffer += xact_len; + if (xfer->buffer) xfer->buffer += xact_len; xfer->actual_len += xact_len; } -- cgit v1.3.1 From 0c3dc8f99bc3bdce40164904d6705f7112b80d9d Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 13 Feb 2021 17:44:59 +0100 Subject: Implement dcd_edpt_iso_xfer() for dcd_nuc121.c --- src/portable/nuvoton/nuc121/dcd_nuc121.c | 54 +++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index c9ead6de0..1560d5642 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -144,7 +144,15 @@ static void dcd_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) { uint16_t bytes_now = tu_min16(xfer->in_remaining_bytes, xfer->max_packet_size); - memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); + if (xfer->data_ptr) + { + memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); + } + else + { + tu_fifo_read_n(xfer->ff, (void *) (USBD_BUF_BASE + ep->BUFSEG), bytes_now); + } + ep->MXPLD = bytes_now; } @@ -292,6 +300,36 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + + /* mine the data for the information we need */ + tusb_dir_t dir = tu_edpt_dir(ep_addr); + USBD_EP_T *ep = ep_entry(ep_addr, false); + struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; + + /* store away the information we'll needing now and later */ + xfer->data_ptr = NULL; // Indicates a FIFO shall be used + xfer->ff = ff; + xfer->in_remaining_bytes = total_bytes; + xfer->total_bytes = total_bytes; + + if (TUSB_DIR_IN == dir) + { + tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_INC); // For the PHY in nuc120 the source and destination pointer have to be incremented! + dcd_in_xfer(xfer, ep); + } + else + { + tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_INC); // For the PHY in nuc120 the source and destination pointer have to be incremented! + xfer->out_bytes_so_far = 0; + ep->MXPLD = xfer->max_packet_size; + } + + return true; +} + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; @@ -400,9 +438,17 @@ void dcd_int_handler(uint8_t rhport) if (out_ep) { /* copy the data from the PC to the previously provided buffer */ - memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); + if (xfer->data_ptr) + { + memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); + xfer->data_ptr += available_bytes; + } + else + { + tu_fifo_write_n(xfer->ff, (const void *) (USBD_BUF_BASE + ep->BUFSEG), available_bytes); + } + xfer->out_bytes_so_far += available_bytes; - xfer->data_ptr += available_bytes; /* when the transfer is finished, alert TinyUSB; otherwise, accept more data */ if ( (xfer->total_bytes == xfer->out_bytes_so_far) || (available_bytes < xfer->max_packet_size) ) @@ -414,7 +460,7 @@ void dcd_int_handler(uint8_t rhport) { /* update the bookkeeping to reflect the data that has now been sent to the PC */ xfer->in_remaining_bytes -= available_bytes; - xfer->data_ptr += available_bytes; + if (xfer->data_ptr) xfer->data_ptr += available_bytes; /* if more data to send, send it; otherwise, alert TinyUSB that we've finished */ if (xfer->in_remaining_bytes) -- cgit v1.3.1 From b634b5958b92fc2352ea20e279e010d8bf4f2df2 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 13 Feb 2021 21:00:55 +0100 Subject: Implement dcd_edpt_iso_xfer() for INTERRUPT driven dcd_nuc505 --- src/portable/nuvoton/nuc505/dcd_nuc505.c | 68 +++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index a7961a687..92656488d 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -34,6 +34,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC505) @@ -94,6 +95,7 @@ static uint32_t bufseg_addr; static struct xfer_ctl_t { uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */ + tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_iso_xfer() */ union { uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */ uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */ @@ -164,7 +166,6 @@ static USBD_EP_T *ep_entry(uint8_t ep_addr, bool add) static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) { uint16_t bytes_now = tu_min16(xfer->in_remaining_bytes, xfer->max_packet_size); - uint16_t countdown = bytes_now; /* precompute what amount of data will be left */ xfer->in_remaining_bytes -= bytes_now; @@ -180,16 +181,24 @@ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) } /* provided buffers are thankfully 32-bit aligned, allowing most data to be transfered as 32-bit */ - while (countdown > 3) + if (xfer->data_ptr) { - uint32_t u32; - memcpy(&u32, xfer->data_ptr, 4); + uint16_t countdown = bytes_now; + while (countdown > 3) + { + uint32_t u32; + memcpy(&u32, xfer->data_ptr, 4); - ep->EPDAT = u32; - xfer->data_ptr += 4; countdown -= 4; + ep->EPDAT = u32; + xfer->data_ptr += 4; countdown -= 4; + } + while (countdown--) + ep->EPDAT_BYTE = *xfer->data_ptr++; + } + else + { + tu_fifo_read_n(xfer->ff, (void *) (ep->EPDAT_BYTE), bytes_now); } - while (countdown--) - ep->EPDAT_BYTE = *xfer->data_ptr++; /* for short packets, we must nudge the peripheral to say 'that's all folks' */ if (bytes_now != xfer->max_packet_size) @@ -402,6 +411,38 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + + TU_ASSERT(0x80 != ep_addr && 0x00 != ep_addr); // Must not be used for control stuff + + /* mine the data for the information we need */ + tusb_dir_t dir = tu_edpt_dir(ep_addr); + USBD_EP_T *ep = ep_entry(ep_addr, false); + struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; + + /* store away the information we'll needing now and later */ + xfer->data_ptr = NULL; // Indicates a FIFO shall be used + xfer->ff = ff; + xfer->in_remaining_bytes = total_bytes; + xfer->total_bytes = total_bytes; + + if (TUSB_DIR_IN == dir) + { + tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_CST); // For the PHY in nuc505 the source and destination pointer have to be constant! + ep->EPINTEN = USBD_EPINTEN_BUFEMPTYIEN_Msk; + } + else + { + tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); // For the PHY in nuc505 the source and destination pointer have to be constant! + xfer->out_bytes_so_far = 0; + ep->EPINTEN = USBD_EPINTEN_RXPKIEN_Msk; + } + + return true; +} + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; @@ -615,8 +656,15 @@ void dcd_int_handler(uint8_t rhport) #else uint16_t const available_bytes = ep->EPDATCNT & USBD_EPDATCNT_DATCNT_Msk; /* copy the data from the PC to the previously provided buffer */ - for (int count = 0; (count < available_bytes) && (xfer->out_bytes_so_far < xfer->total_bytes); count++, xfer->out_bytes_so_far++) - *xfer->data_ptr++ = ep->EPDAT_BYTE; + if (xfer->data_ptr) + { + for (int count = 0; (count < available_bytes) && (xfer->out_bytes_so_far < xfer->total_bytes); count++, xfer->out_bytes_so_far++) + *xfer->data_ptr++ = ep->EPDAT_BYTE; + } + else + { + tu_fifo_write_n(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far)); + } /* when the transfer is finished, alert TinyUSB; otherwise, continue accepting more data */ if ( (xfer->total_bytes == xfer->out_bytes_so_far) || (available_bytes < xfer->max_packet_size) ) -- cgit v1.3.1 From 893f997dcb09ffef872ab7cb9a5c0a74839f5715 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Feb 2021 09:25:34 +0100 Subject: Change FIFO use indication to ff == NULL to avoid future errors. This way people don't need to pay attention for the buffer pointer --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 24 ++++++++++++------------ src/portable/microchip/samg/dcd_samg.c | 16 +++++++++------- src/portable/nuvoton/nuc120/dcd_nuc120.c | 18 +++++++++--------- src/portable/nuvoton/nuc121/dcd_nuc121.c | 17 +++++++++-------- src/portable/nuvoton/nuc505/dcd_nuc505.c | 20 +++++++++++--------- src/portable/st/synopsys/dcd_synopsys.c | 25 +++++++++++++------------ 6 files changed, 63 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 72fb4ba48..25e54418f 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -321,6 +321,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->buffer = buffer; + xfer->ff = NULL; xfer->total_len = total_bytes; xfer->queued_len = 0; xfer->short_packet = false; @@ -523,7 +524,12 @@ static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ } // Common buffer read - if (xfer->buffer) + if (xfer->ff) + { + // Ring buffer + tu_fifo_write_n(xfer->ff, (const void *) rx_fifo, to_recv_size); + } + else { uint8_t to_recv_rem = to_recv_size % 4; uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; @@ -556,12 +562,6 @@ static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; } } - - } - else - { - // Ring buffer - tu_fifo_write_n(xfer->ff, (const void *) rx_fifo, to_recv_size); } xfer->queued_len += xfer_size; @@ -581,7 +581,11 @@ static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; - if (xfer->buffer) + if (xfer->ff) + { + tu_fifo_read_n(xfer->ff, (void *) tx_fifo, to_xfer_size); + } + else { uint8_t to_xfer_rem = to_xfer_size % 4; uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; @@ -616,10 +620,6 @@ static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, (*tx_fifo) = tmp; } } - else - { - tu_fifo_read_n(xfer->ff, (void *) tx_fifo, to_xfer_size); - } } static void read_rx_fifo(void) diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 6e7e84a99..12b2633a0 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -61,6 +61,7 @@ void xfer_epsize_set(xfer_desc_t* xfer, uint16_t epsize) void xfer_begin(xfer_desc_t* xfer, uint8_t * buffer, uint16_t total_bytes) { xfer->buffer = buffer; + xfer->ff = NULL; xfer->total_len = total_bytes; xfer->actual_len = 0; } @@ -68,6 +69,7 @@ void xfer_begin(xfer_desc_t* xfer, uint8_t * buffer, uint16_t total_bytes) void xfer_end(xfer_desc_t* xfer) { xfer->buffer = NULL; + xfer->ff = NULL; xfer->total_len = 0; xfer->actual_len = 0; } @@ -82,7 +84,7 @@ void xfer_packet_done(xfer_desc_t* xfer) { uint16_t const xact_len = xfer_packet_len(xfer); - if (xfer->buffer) xfer->buffer += xact_len; + xfer->buffer += xact_len; xfer->actual_len += xact_len; } @@ -436,13 +438,13 @@ void dcd_int_handler(uint8_t rhport) if (xact_len) { // write to EP fifo - if (xfer->buffer) + if (xfer->ff) { - xact_ep_write(epnum, xfer->buffer, xact_len); + tu_fifo_read_n(ff, (void *) &UDP->UDP_FDR[epnum], xact_len); } else { - tu_fifo_read_n(ff, (void *) &UDP->UDP_FDR[epnum], xact_len); + xact_ep_write(epnum, xfer->buffer, xact_len); } // TX ready for transfer @@ -469,13 +471,13 @@ void dcd_int_handler(uint8_t rhport) uint16_t const xact_len = (uint16_t) ((UDP->UDP_CSR[epnum] & UDP_CSR_RXBYTECNT_Msk) >> UDP_CSR_RXBYTECNT_Pos); // Read from EP fifo - if (xfer->buffer) + if (xfer->ff) { - xact_ep_read(epnum, xfer->buffer, xact_len); + tu_fifo_write_n(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len); } else { - tu_fifo_write_n(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len); + xact_ep_read(epnum, xfer->buffer, xact_len); } xfer_packet_done(xfer); diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 0c3bd9a6b..9ff34e760 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -144,13 +144,13 @@ static void dcd_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) { uint16_t bytes_now = tu_min16(xfer->in_remaining_bytes, xfer->max_packet_size); - if (xfer->data_ptr) + if (xfer->ff) { - memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); + tu_fifo_read_n(xfer->ff, (void *) (USBD_BUF_BASE + ep->BUFSEG), bytes_now); } else { - tu_fifo_read_n(xfer->ff, (void *) (USBD_BUF_BASE + ep->BUFSEG), bytes_now); + memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); } ep->MXPLD = bytes_now; @@ -277,6 +277,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to /* store away the information we'll needing now and later */ xfer->data_ptr = buffer; + xfer->ff = NULL; xfer->in_remaining_bytes = total_bytes; xfer->total_bytes = total_bytes; @@ -429,14 +430,14 @@ void dcd_int_handler(uint8_t rhport) if (out_ep) { /* copy the data from the PC to the previously provided buffer */ - if (xfer->data_ptr) + if (xfer->ff) { - memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); - xfer->data_ptr += available_bytes; + tu_fifo_write_n(xfer->ff, (const void *) (USBD_BUF_BASE + ep->BUFSEG), available_bytes); } else { - tu_fifo_write_n(xfer->ff, (const void *) (USBD_BUF_BASE + ep->BUFSEG), available_bytes); + memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); + xfer->data_ptr += available_bytes; } xfer->out_bytes_so_far += available_bytes; @@ -452,8 +453,7 @@ void dcd_int_handler(uint8_t rhport) /* update the bookkeeping to reflect the data that has now been sent to the PC */ xfer->in_remaining_bytes -= available_bytes; - /* increment only if xfer->data_ptr != NULL - if xfer->data_ptr == NULL then a FIFO is used for which xfer->data_ptr MUST STAY ZERO! */ - if (xfer->data_ptr) xfer->data_ptr += available_bytes; + xfer->data_ptr += available_bytes; /* if more data to send, send it; otherwise, alert TinyUSB that we've finished */ if (xfer->in_remaining_bytes) diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 1560d5642..a689470d6 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -144,13 +144,13 @@ static void dcd_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) { uint16_t bytes_now = tu_min16(xfer->in_remaining_bytes, xfer->max_packet_size); - if (xfer->data_ptr) + if (xfer->ff) { - memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); + tu_fifo_read_n(xfer->ff, (void *) (USBD_BUF_BASE + ep->BUFSEG), bytes_now); } else { - tu_fifo_read_n(xfer->ff, (void *) (USBD_BUF_BASE + ep->BUFSEG), bytes_now); + memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); } ep->MXPLD = bytes_now; @@ -281,6 +281,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to /* store away the information we'll needing now and later */ xfer->data_ptr = buffer; + xfer->ff = NULL; xfer->in_remaining_bytes = total_bytes; xfer->total_bytes = total_bytes; @@ -438,14 +439,14 @@ void dcd_int_handler(uint8_t rhport) if (out_ep) { /* copy the data from the PC to the previously provided buffer */ - if (xfer->data_ptr) + if (xfer->ff) { - memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); - xfer->data_ptr += available_bytes; + tu_fifo_write_n(xfer->ff, (const void *) (USBD_BUF_BASE + ep->BUFSEG), available_bytes); } else { - tu_fifo_write_n(xfer->ff, (const void *) (USBD_BUF_BASE + ep->BUFSEG), available_bytes); + memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); + xfer->data_ptr += available_bytes; } xfer->out_bytes_so_far += available_bytes; @@ -460,7 +461,7 @@ void dcd_int_handler(uint8_t rhport) { /* update the bookkeeping to reflect the data that has now been sent to the PC */ xfer->in_remaining_bytes -= available_bytes; - if (xfer->data_ptr) xfer->data_ptr += available_bytes; + xfer->data_ptr += available_bytes; /* if more data to send, send it; otherwise, alert TinyUSB that we've finished */ if (xfer->in_remaining_bytes) diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 92656488d..3641b7047 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -181,7 +181,11 @@ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) } /* provided buffers are thankfully 32-bit aligned, allowing most data to be transfered as 32-bit */ - if (xfer->data_ptr) + if (xfer->ff) + { + tu_fifo_read_n(xfer->ff, (void *) (ep->EPDAT_BYTE), bytes_now); + } + else { uint16_t countdown = bytes_now; while (countdown > 3) @@ -195,10 +199,6 @@ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) while (countdown--) ep->EPDAT_BYTE = *xfer->data_ptr++; } - else - { - tu_fifo_read_n(xfer->ff, (void *) (ep->EPDAT_BYTE), bytes_now); - } /* for short packets, we must nudge the peripheral to say 'that's all folks' */ if (bytes_now != xfer->max_packet_size) @@ -394,6 +394,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to /* store away the information we'll needing now and later */ xfer->data_ptr = buffer; + xfer->ff = NULL; xfer->in_remaining_bytes = total_bytes; xfer->total_bytes = total_bytes; @@ -656,14 +657,15 @@ void dcd_int_handler(uint8_t rhport) #else uint16_t const available_bytes = ep->EPDATCNT & USBD_EPDATCNT_DATCNT_Msk; /* copy the data from the PC to the previously provided buffer */ - if (xfer->data_ptr) + if (xfer->ff) { - for (int count = 0; (count < available_bytes) && (xfer->out_bytes_so_far < xfer->total_bytes); count++, xfer->out_bytes_so_far++) - *xfer->data_ptr++ = ep->EPDAT_BYTE; + tu_fifo_write_n(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far)); } else { - tu_fifo_write_n(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far)); + for (int count = 0; (count < available_bytes) && (xfer->out_bytes_so_far < xfer->total_bytes); count++, xfer->out_bytes_so_far++) + *xfer->data_ptr++ = ep->EPDAT_BYTE; + } /* when the transfer is finished, alert TinyUSB; otherwise, continue accepting more data */ diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index b6dacd927..5f8c44638 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -646,6 +646,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->buffer = buffer; + xfer->ff = NULL; xfer->total_len = total_bytes; // EP0 can only handle one packet @@ -908,7 +909,12 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); // Read packet off RxFIFO - if (xfer->buffer) + if (xfer->ff) + { + // Ring buffer + tu_fifo_write_n(xfer->ff, (const void *) rx_fifo, bcnt); + } + else { // Linear buffer read_fifo_packet(rhport, xfer->buffer, bcnt); @@ -916,11 +922,6 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ // Increment pointer to xfer data xfer->buffer += bcnt; } - else - { - // Ring buffer - tu_fifo_write_n(xfer->ff, (const void *) rx_fifo, bcnt); - } // Truncate transfer length in case of short packet if(bcnt < xfer->max_size) { @@ -1028,18 +1029,18 @@ static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OT } // Push packet to Tx-FIFO - if (xfer->buffer) + if (xfer->ff) + { + usb_fifo_t tx_fifo = FIFO_BASE(rhport, n); + tu_fifo_read_n(xfer->ff, (void *) tx_fifo, packet_size); + } + else { write_fifo_packet(rhport, n, xfer->buffer, packet_size); // Increment pointer to xfer data xfer->buffer += packet_size; } - else - { - usb_fifo_t tx_fifo = FIFO_BASE(rhport, n); - tu_fifo_read_n(xfer->ff, (void *) tx_fifo, packet_size); - } } // Turn off TXFE if all bytes are written. -- cgit v1.3.1 From a5d7b6266dca8a4f79178f5978401b680ddfa637 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Feb 2021 14:05:15 +0100 Subject: Implement dcd_edpt_iso_xfer() for msp430 --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 77 +++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index e08c3536a..61cbe1cf7 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -26,6 +26,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MSP430x5xx ) @@ -48,6 +49,7 @@ uint8_t _setup_packet[8]; typedef struct { uint8_t * buffer; + tu_fifo_t * ff; uint16_t total_len; uint16_t queued_len; uint16_t max_size; @@ -306,6 +308,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->buffer = buffer; + xfer->ff = NULL; xfer->total_len = total_bytes; xfer->queued_len = 0; xfer->short_packet = false; @@ -344,6 +347,36 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->short_packet = false; + + ep_regs_t ep_regs = EP_REGS(epnum, dir); + + if(dir == TUSB_DIR_OUT) + { + tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_INC); // For the PHY in msp430 the source and destination pointer have to be incremented! + ep_regs[BCTX] &= ~NAK; + } + else + { + tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_INC); // For the PHY in msp430 the source and destination pointer have to be incremented! + USBIEPIFG |= (1 << epnum); + } + + return true; +} + void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; @@ -443,22 +476,30 @@ static void receive_packet(uint8_t ep_num) to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; } - uint8_t * base = (xfer->buffer + xfer->queued_len); - - if(ep_num == 0) + if (xfer->ff) { - volatile uint8_t * ep0out_buf = &USBOEP0BUF; - for(uint16_t i = 0; i < to_recv_size; i++) - { - base[i] = ep0out_buf[i]; - } + volatile uint8_t * ep_buf = &USBSTABUFF + (ep_regs[BBAX] << 3); + tu_fifo_write_n(xfer->ff, (const void *) ep_buf, to_recv_size); } else { - volatile uint8_t * ep_buf = &USBSTABUFF + (ep_regs[BBAX] << 3); - for(uint16_t i = 0; i < to_recv_size ; i++) + uint8_t * base = (xfer->buffer + xfer->queued_len); + + if(ep_num == 0) { - base[i] = ep_buf[i]; + volatile uint8_t * ep0out_buf = &USBOEP0BUF; + for(uint16_t i = 0; i < to_recv_size; i++) + { + base[i] = ep0out_buf[i]; + } + } + else + { + volatile uint8_t * ep_buf = &USBSTABUFF + (ep_regs[BBAX] << 3); + for(uint16_t i = 0; i < to_recv_size ; i++) + { + base[i] = ep_buf[i]; + } } } @@ -499,7 +540,6 @@ static void transmit_packet(uint8_t ep_num) } // Then actually commit to transmit a packet. - uint8_t * base = (xfer->buffer + xfer->queued_len); uint16_t remaining = xfer->total_len - xfer->queued_len; uint8_t xfer_size = (xfer->max_size < xfer->total_len) ? xfer->max_size : remaining; @@ -513,6 +553,7 @@ static void transmit_packet(uint8_t ep_num) if(ep_num == 0) { volatile uint8_t * ep0in_buf = &USBIEP0BUF; + uint8_t * base = (xfer->buffer + xfer->queued_len); for(uint16_t i = 0; i < xfer_size; i++) { ep0in_buf[i] = base[i]; @@ -526,9 +567,17 @@ static void transmit_packet(uint8_t ep_num) ep_regs_t ep_regs = EP_REGS(ep_num, TUSB_DIR_IN); volatile uint8_t * ep_buf = &USBSTABUFF + (ep_regs[BBAX] << 3); - for(int i = 0; i < xfer_size; i++) + if (xfer->ff) + { + tu_fifo_read_n(xfer->ff, (void *) ep_buf, xfer_size); + } + else { - ep_buf[i] = base[i]; + uint8_t * base = (xfer->buffer + xfer->queued_len); + for(int i = 0; i < xfer_size; i++) + { + ep_buf[i] = base[i]; + } } ep_regs[BCTX] = (ep_regs[BCTX] & 0x80) + (xfer_size & 0x7F); -- cgit v1.3.1 From f8fbc0930bd17b263ca702c0beb9f83af4429d0a Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Tue, 16 Feb 2021 10:40:06 -0500 Subject: Add alternate bitfield padding option Adds configuration option CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT, which substitutes bitfield variable " : 0" padding syntax with an unused variable of size equal to the remaining number of bits. This change resolves aligned access issues for some platforms. Default behavior is original if the option is not explicitly enabled. --- src/class/cdc/cdc.h | 22 +++++++++++++++++++++- src/common/tusb_types.h | 6 +++++- src/host/ehci/ehci.h | 13 ++++++++++--- src/host/hub.h | 8 ++++++-- src/host/ohci/ohci.h | 12 ++++++++++-- src/tusb_option.h | 4 ++++ 6 files changed, 56 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 2c044ac7f..ec31ee4cf 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -277,7 +277,11 @@ typedef struct TU_ATTR_PACKED struct { uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface. uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself. +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint8_t unused : 6; +#else uint8_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ } bmCapabilities; uint8_t bDataInterface; @@ -290,7 +294,11 @@ typedef struct TU_ATTR_PACKED uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State. uint8_t support_send_break : 1; ///< Device supports the request Send_Break uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection. +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint8_t unused : 4; +#else uint8_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ }cdc_acm_capability_t; TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); @@ -316,7 +324,11 @@ typedef struct TU_ATTR_PACKED uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit. uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State. uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time. +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint8_t unused : 5; +#else uint8_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ } bmCapabilities; }cdc_desc_func_direct_line_management_t; @@ -344,7 +356,11 @@ typedef struct TU_ATTR_PACKED uint8_t simple_mode : 1; uint8_t standalone_mode : 1; uint8_t computer_centric_mode : 1; +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint8_t unused : 5; +#else uint8_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ } bmCapabilities; }cdc_desc_func_telephone_operational_modes_t; @@ -363,7 +379,11 @@ typedef struct TU_ATTR_PACKED uint32_t incoming_distinctive : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns. uint32_t dual_tone_multi_freq : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line. uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint32_t unused : 26; +#else uint32_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ } bmCapabilities; }cdc_desc_func_telephone_call_state_reporting_capabilities_t; diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 2b4ceb69c..e57dc26f5 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -342,7 +342,11 @@ typedef struct TU_ATTR_PACKED struct TU_ATTR_PACKED { uint16_t size : 11; ///< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. \n For isochronous endpoints, this value is used to reserve the bus time in the schedule, required for the per-(micro)frame data payloads. The pipe may, on an ongoing basis, actually use less bandwidth than that reserved. The device reports, if necessary, the actual bandwidth used via its normal, non-USB defined mechanisms. \n For all endpoints, bits 10..0 specify the maximum packet size (in bytes). \n For high-speed isochronous and interrupt endpoints: \n Bits 12..11 specify the number of additional transaction opportunities per microframe: \n- 00 = None (1 transaction per microframe) \n- 01 = 1 additional (2 per microframe) \n- 10 = 2 additional (3 per microframe) \n- 11 = Reserved \n Bits 15..13 are reserved and must be set to zero. uint16_t hs_period_mult : 2; +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint16_t unused : 3; +#else uint16_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ }wMaxPacketSize; uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. diff --git a/src/host/ehci/ehci.h b/src/host/ehci/ehci.h index a6342b2d2..acaf545c1 100644 --- a/src/host/ehci/ehci.h +++ b/src/host/ehci/ehci.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -231,7 +231,11 @@ typedef struct TU_ATTR_ALIGNED(32) uint32_t : 1; ///< reserved uint32_t port_number : 7; ///< This field is the port number of the recipient transaction translator. uint32_t direction : 1; ///< 0 = OUT; 1 = IN. This field encodes whether the full-speed transaction should be an IN or OUT. - uint32_t : 0; // padding to the end of current storage unit +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + ///< All 32 bits are used +#else + uint32_t : 0; // padding to the end of current storage unit +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ // Word 2: Micro-frame Schedule Control uint8_t int_smask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute complete-split transactions @@ -423,7 +427,11 @@ typedef volatile struct uint32_t nxp_port_force_fullspeed : 1; ///< NXP customized: Writing this bit to a 1 will force the port to only connect at Full Speed. It disables the chirp sequence that allowsthe port to identify itself as High Speed. This is useful for testing FS configurations with a HS host, hub or device. uint32_t : 1; uint32_t nxp_port_speed : 2; ///< NXP customized: This register field indicates the speed atwhich the port is operating. For HS mode operation in the host controllerand HS/FS operation in the device controller the port routing steers data to the Protocol engine. For FS and LS mode operation in the host controller, the port routing steers data to the Protocol Engine w/ Embedded Transaction Translator. 0x0: Fullspeed, 0x1: Lowspeed, 0x2: Highspeed +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint32_t unused : 4; ///< padding +#else uint32_t : 0; // padding to the boundary of storage unit +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ }portsc_bm; }; }ehci_registers_t; @@ -461,4 +469,3 @@ typedef struct /** @} */ /** @} */ - diff --git a/src/host/hub.h b/src/host/hub.h index 35d8ad629..0e3292274 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -163,7 +163,11 @@ typedef struct { uint16_t high_speed : 1; uint16_t port_test_mode : 1; uint16_t port_indicator_control : 1; - uint16_t : 0; +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint16_t unused : 3; +#else + uint16_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ }; uint16_t value; diff --git a/src/host/ohci/ohci.h b/src/host/ohci/ohci.h index bfcdaf9a3..76d6fff61 100644 --- a/src/host/ohci/ohci.h +++ b/src/host/ohci/ohci.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -208,7 +208,11 @@ typedef volatile struct uint32_t interrupt_routing : 1; uint32_t remote_wakeup_connected : 1; uint32_t remote_wakeup_enale : 1; - uint32_t : 0; +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint32_t unused : 21; +#else + uint32_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ }control_bit; }; @@ -276,7 +280,11 @@ typedef volatile struct uint32_t port_suspend_status_change : 1; uint32_t port_over_current_indicator_change : 1; uint32_t port_reset_status_change : 1; +#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + uint32_t unused : 11; +#else uint32_t : 0; +#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ }rhport_status_bit[2]; }; }ohci_registers_t; diff --git a/src/tusb_option.h b/src/tusb_option.h index 6cbdefbf1..b5504d29c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -197,6 +197,10 @@ #define CFG_TUSB_OS OPT_OS_NONE #endif +#ifndef CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT + #define CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT 0 +#endif + //-------------------------------------------------------------------- // DEVICE OPTIONS //-------------------------------------------------------------------- -- cgit v1.3.1 From b7ec66e33af1e24b763d855545d921ec5957f61a Mon Sep 17 00:00:00 2001 From: Nicholas R Dinsmore Date: Tue, 16 Feb 2021 23:08:08 -0500 Subject: This fixes the overflow mathmatic in the fifo --- src/common/tusb_fifo.c | 2 +- src/common/tusb_fifo.h | 2 +- src/osal/osal_pico.h | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 00f2434a7..e3c4d74c7 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -74,7 +74,7 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si f->overwritable = overwritable; f->max_pointer_idx = 2*depth - 1; // Limit index space to 2*depth - this allows for a fast "modulo" calculation but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable only if overflow happens once (important for unsupervised DMA applications) - f->non_used_index_space = 0xFFFF - f->max_pointer_idx; + f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; f->rd_idx = f->wr_idx = 0; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index b965386ab..c35b85a49 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -86,7 +86,7 @@ typedef struct .item_size = sizeof(_type), \ .overwritable = _overwritable, \ .max_pointer_idx = 2*_depth-1, \ - .non_used_index_space = 0xFFFF - 2*_depth-1, \ + .non_used_index_space = UINT16_MAX - (2*_depth-1), \ } bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index 1788e5c8d..79054ddfa 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -123,6 +123,8 @@ typedef osal_queue_def_t* osal_queue_t; .depth = _depth, \ .item_size = sizeof(_type), \ .overwritable = false, \ + .max_pointer_idx = 2*_depth-1, \ + .non_used_index_space = UINT16_MAX - (2*_depth-1), \ }\ } -- cgit v1.3.1 From 79b360f0a6b980cb8b4826bbad0d2d6a4c9dae4b Mon Sep 17 00:00:00 2001 From: Nicholas R Dinsmore Date: Wed, 17 Feb 2021 13:22:34 -0500 Subject: Enable iso buffers per rp2040 spec --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 5c536e314..036b52196 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -154,6 +154,14 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t ep->total_len = total_len; ep->len = 0; // FIXME: What if low speed + if(ep->transfer_type == TUSB_XFER_ISOCHRONOUS) + { + ep->transfer_size = total_len; //There is an assumption that the max buffer size of 1023 or 1024 was checked before this + } + else + { + ep->transfer_size = total_len > 64 ? 64 : total_len; + } ep->transfer_size = total_len > 64 ? 64 : total_len; ep->active = true; ep->user_buf = buffer; -- cgit v1.3.1 From c87357c0257251f2cecfe83a29035648c5a47662 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 20:44:26 +0100 Subject: Improve tu_fifo capabilites Added tu_fifo_get_linear_write_info(), tu_fifo_backward_write_pointer(), and tu_fifo_backward_read_pointer() --- src/common/tusb_fifo.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++-- src/common/tusb_fifo.h | 11 ++- 2 files changed, 204 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index ff2e2c6fd..f6def94ab 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -354,10 +354,7 @@ static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffe // Check if we can read something at and after offset - if too less is available we read what remains cnt -= offset; - if (cnt < n) { - if (cnt == 0) return 0; - n = cnt; - } + if (cnt < n) n = cnt; uint16_t rRel = get_relative_pointer(f, rAbs, offset); @@ -664,10 +661,7 @@ uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint // Check if we can read something at and after offset - if too less is available we read what remains cnt -= offset; - if (cnt < n) { - if (cnt == 0) return 0; - n = cnt; - } + if (cnt < n) n = cnt; tu_fifo_lock(f_target); // Lock both read and write pointers - in case of an overwritable FIFO both may be modified @@ -881,3 +875,195 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) { f->rd_idx = advance_pointer(f, f->rd_idx, n); } + +/******************************************************************************/ +/*! + @brief Move back write pointer - intended to be used in combination with DMA. + It is possible to fill the FIFO by use of a DMA in circular mode. Within + DMA ISRs you may update the write pointer to be able to read from the FIFO. + As long as the DMA is the only process writing into the FIFO this is safe + to use. + + USE WITH CARE - WE DO NOT CONDUCT SAFTY CHECKS HERE! + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] n + Number of items the write pointer moves backward + */ +/******************************************************************************/ +void tu_fifo_backward_write_pointer(tu_fifo_t *f, uint16_t n) +{ + f->wr_idx = backward_pointer(f, f->wr_idx, n); +} + +/******************************************************************************/ +/*! + @brief Move back read pointer - intended to be used in combination with DMA. + It is possible to read from the FIFO by use of a DMA in linear mode. Within + DMA ISRs you may update the read pointer to be able to again write into the + FIFO. As long as the DMA is the only process reading from the FIFO this is + safe to use. + + USE WITH CARE - WE DO NOT CONDUCT SAFTY CHECKS HERE! + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] n + Number of items the read pointer moves backward + */ +/******************************************************************************/ +void tu_fifo_backward_read_pointer(tu_fifo_t *f, uint16_t n) +{ + f->rd_idx = backward_pointer(f, f->rd_idx, n); +} + +/******************************************************************************/ +/*! + @brief Get linear read info + + Returns the length and pointer from which bytes can be read in a linear manner. + This is of major interest for DMA transmissions. If returned length is zero the + corresponding pointer is invalid. The returned length is limited to the number + of BYTES n which the user wants to write into the buffer. + The write pointer does NOT get advanced, use tu_fifo_advance_read_pointer() to + do so! If the length returned is less than n i.e. lenwr_idx, r = f->rd_idx; + + uint16_t cnt = _tu_fifo_count(f, w, r); + + // Check overflow and correct if required + if (cnt > f->depth) + { + tu_fifo_lock(f); + _tu_fifo_correct_read_pointer(f, w); + tu_fifo_unlock(f); + r = f->rd_idx; + cnt = f->depth; + } + + // Convert to bytes + cnt = cnt * f->item_size; + + // Skip beginning of buffer + if (cnt == 0 || offset >= cnt) return 0; + + // Check if we can read something at and after offset - if too less is available we read what remains + cnt -= offset; + if (cnt < n) n = cnt; + + // Get relative pointers + w = get_relative_pointer(f, w, 0); + r = get_relative_pointer(f, r, offset); + + // Check if there is a wrap around necessary + uint16_t len; + + if (w >= r) { + len = w - r; + } + else + { + len = f->depth - r; + } + + len = len * f->item_size; + + // Limit to required length + len = tu_min16(n, len); + + // Copy pointer to buffer to start reading from + *ptr = &f->buffer[r]; + + return len; +} + +/******************************************************************************/ +/*! + @brief Get linear write info + + Returns the length and pointer from which bytes can be written into buffer array in a linear manner. + This is of major interest for DMA transmissions not using circular mode. If returned length is zero the + corresponding pointer is invalid. The returned length is limited to the number of BYTES n which the user + wants to write into the buffer. + The write pointer does NOT get advanced, use tu_fifo_advance_write_pointer() to do so! If the length + returned is less than n i.e. lenwr_idx, r = f->rd_idx; + uint16_t free = _tu_fifo_remaining(f, w, r) * f->item_size; + + if (!f->overwritable) + { + // Not overwritable limit up to full + n = tu_min16(n, free); + } + else if (n >= f->depth * f->item_size) + { + // If overwrite is allowed it must be less than or equal to 2 x buffer length, otherwise the overflow can not be resolved by the read functions + TU_VERIFY(n <= 2*f->depth * f->item_size); + + n = f->depth * f->item_size; + // We start writing at the read pointer's position since we fill the complete + // buffer and we do not want to modify the read pointer within a write function! + // This would end up in a race condition with read functions! + w = r; + } + + // Check if there is room to write to + if (free == 0 || offset >= free) return 0; + + // Get relative pointers + w = get_relative_pointer(f, w, offset); + r = get_relative_pointer(f, r, 0); + uint16_t len; + + if (w < r) + { + len = r-w; + } + else + { + len = f->depth - w; + } + + len = len * f->item_size; + + // Limit to required length + len = tu_min16(n, len); + + // Copy pointer to buffer to start reading from + *ptr = &f->buffer[w]; + + return len; +} diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 7ece30b74..833b3eead 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -128,13 +128,22 @@ uint16_t tu_fifo_count (tu_fifo_t* f); bool tu_fifo_empty (tu_fifo_t* f); bool tu_fifo_full (tu_fifo_t* f); uint16_t tu_fifo_remaining (tu_fifo_t* f); -bool tu_fifo_overflowed (tu_fifo_t* f); +bool tu_fifo_overflowed (tu_fifo_t* f); void tu_fifo_correct_read_pointer (tu_fifo_t* f); // Pointer modifications intended to be used in combinations with DMAs. // USE WITH CARE - NO SAFTY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED! void tu_fifo_advance_write_pointer (tu_fifo_t *f, uint16_t n); +void tu_fifo_backward_write_pointer (tu_fifo_t *f, uint16_t n); void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); +void tu_fifo_backward_read_pointer (tu_fifo_t *f, uint16_t n); + +// If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies to handle a possible wrapping part +// This functions deliver a pointer to start reading/writing from/to and a valid linear length along which no wrap occurs. +// In case not all of your data is available within one read/write, update the read/write pointer by +// tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation +uint16_t tu_fifo_get_linear_read_info (tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n); +uint16_t tu_fifo_get_linear_write_info (tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n); static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { -- cgit v1.3.1 From 2d7b61972c669040c494899509b02bde49728a65 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 20:46:31 +0100 Subject: Implement dcd_edpt_iso_xfer() for dcd_stm32_fsdev Implemented a special copy strategy to copy directly from the FIFO. This function, however, is untested and should be regarded as unreliable until somebody was able to test it --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 148 +++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 18f0bc8e1..9d813d4a5 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -102,6 +102,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if defined(STM32F102x6) || defined(STM32F102xB) || \ defined(STM32F103x6) || defined(STM32F103xB) || \ @@ -165,6 +166,7 @@ TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligne typedef struct { uint8_t * buffer; + tu_fifo_t * ff; uint16_t total_len; uint16_t queued_len; uint16_t pma_ptr; @@ -195,7 +197,9 @@ 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_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wNBytes); static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes); +static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNBytes); // Using a function due to better type checks // This seems better than having to do type casts everywhere else @@ -476,8 +480,16 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) if (count != 0U) { - dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]), - *pcd_ep_rx_address_ptr(USB,EPindex), count); + if (xfer->ff) + { + dcd_read_packet_memory_ff(xfer->ff, *pcd_ep_rx_address_ptr(USB,EPindex), count); + } + else + { + dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]), + *pcd_ep_rx_address_ptr(USB,EPindex), count); + } + xfer->queued_len = (uint16_t)(xfer->queued_len + count); } @@ -804,7 +816,14 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix) len = xfer->max_packet_size; } uint16_t oldAddr = *pcd_ep_tx_address_ptr(USB,ep_ix); - dcd_write_packet_memory(oldAddr, &(xfer->buffer[xfer->queued_len]), len); + if (xfer->ff) + { + dcd_write_packet_memory_ff(xfer->ff, oldAddr, len); + } + else + { + dcd_write_packet_memory(oldAddr, &(xfer->buffer[xfer->queued_len]), len); + } xfer->queued_len = (uint16_t)(xfer->queued_len + len); pcd_set_ep_tx_cnt(USB,ep_ix,len); @@ -821,6 +840,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_ctl_t * xfer = xfer_ctl_ptr(epnum,dir); xfer->buffer = buffer; + xfer->ff = NULL; xfer->total_len = total_bytes; xfer->queued_len = 0; @@ -847,6 +867,37 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = xfer_ctl_ptr(epnum,dir); + + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + + if ( dir == TUSB_DIR_OUT ) + { + if(total_bytes > xfer->max_packet_size) + { + pcd_set_ep_rx_cnt(USB,epnum,xfer->max_packet_size); + } else { + pcd_set_ep_rx_cnt(USB,epnum,total_bytes); + } + pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_VALID); + } + else // IN + { + dcd_transmit_packet(xfer,epnum); + } + return true; +} + void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void)rhport; @@ -921,7 +972,52 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, si } /** - * @brief Copy a buffer from user memory area to packet memory area (PMA). + * @brief Copy from FIFO to packet memory area (PMA). + * Uses byte-access of system memory and 16-bit access of packet memory + * @param wNBytes no. of bytes to be copied. + * @retval None + */ + +// THIS FUNCTION IS UNTESTED + +static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wNBytes) +{ + // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies + // Check for first linear part + void *__restrict src; + uint16_t len = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes); // We want to read from the FIFO + TU_VERIFY(len && dcd_write_packet_memory(dst, src, len)); // and write it into the PMA + tu_fifo_advance_read_pointer(ff, len); + + // Check for wrapped part + if (len < wNBytes) + { + // Get remaining wrapped length + uint16_t len2 = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes - len); + TU_VERIFY(len2); + + // Update destination pointer + dst += len; + + // Since PMA is accessed 16-bit wise we need to handle the case when a 16 bit value was split + if (len % 2) // If len is uneven there is a byte left to copy + { + // Since PMA can accessed only 16 bit-wise we copy the last byte again + tu_fifo_backward_read_pointer(ff, 1); // Move one byte back and copy two bytes for the PMA + pma[PMA_STRIDE*(dst>>1)] = tu_fifo_read_n(ff, 2); // Since EP FIFOs must be of item size 1 this is safe to do + dst++; + len2--; + } + + TU_VERIFY(dcd_write_packet_memory(dst, src, len2)); + tu_fifo_advance_write_pointer(ff, len2); + } + + return true; +} + +/** + * @brief Copy a buffer from packet memory area (PMA) to user memory area. * Uses byte-access of system memory and 16-bit access of packet memory * @param wNBytes no. of bytes to be copied. * @retval None @@ -955,5 +1051,49 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN return true; } +/** + * @brief Copy a buffer from user packet memory area (PMA) to FIFO. + * Uses byte-access of system memory and 16-bit access of packet memory + * @param wNBytes no. of bytes to be copied. + * @retval None + */ + +// THIS FUNCTION IS UNTESTED + +static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNBytes) +{ + // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies + // Check for first linear part + void *__restrict dst; + uint16_t len = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes); + TU_VERIFY(len && dcd_read_packet_memory(dst, src, len)); + tu_fifo_advance_write_pointer(ff, len); + + // Check for wrapped part + if (len < wNBytes) + { + // Get remaining wrapped length + uint16_t len2 = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes - len); + TU_VERIFY(len2); + + // Update source pointer + src += len; + + // Since PMA is accessed 16-bit wise we need to handle the case when a 16 bit value was split + if (len % 2) // If len is uneven there is a byte left to copy + { + uint32_t temp = pma[PMA_STRIDE*(src>>1)]; + *((uint8_t *)dst++) = ((temp >> 8) & 0xFF); + src++; + len2--; + } + + TU_VERIFY(dcd_read_packet_memory(dst, src, len2)); + tu_fifo_advance_write_pointer(ff, len2); + } + + return true; +} + #endif -- cgit v1.3.1 From 189b357b54614a770232ac9fa95d56d173efe302 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 21:42:44 +0100 Subject: Implement an evasion linear buffer for MCUs not capable for EP FIFO Also MCUs using DMAs are within this list, however, these can use an EP FIFO. There is just no time for implementation --- src/class/audio/audio_device.c | 55 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 622e6d113..7b7c61750 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -125,6 +125,41 @@ typedef struct #if CFG_FIFO_MUTEX osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; #endif +#endif + + // Evasion buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically +#if ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || /* Intermediate software buffer required */ \ + CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ + CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ + CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_RP2040) || /* Don't want to change driver */ \ + CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI || /* Intermediate software buffer required */ \ + CFG_TUSB_MCU == OPT_MCU_CXD56 || /* No clue how driver works */ \ + CFG_TUSB_MCU == OPT_MCU_DA1469X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ + CFG_TUSB_MCU == OPT_MCU_NRF5X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ + CFG_TUSB_MCU == OPT_MCU_LPC11UXX || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ + CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC15XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC51UXX || \ + CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ + CFG_TUSB_MCU == OPT_MCU_LPC55XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ + CFG_TUSB_MCU == OPT_MCU_LPC40XX) + +#define USE_EVADE_BUFFER 1 + +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + CFG_TUSB_MEM_ALIGN uint8_t evasion_buf_out[CFG_TUD_AUDIO_EPSIZE_OUT]; +#endif + +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE + CFG_TUSB_MEM_ALIGN uint8_t evasion_buf_in[CFG_TUD_AUDIO_EPSIZE_IN]; +#endif + +#endif + +#ifndef USE_EVADE_BUFFER +#define USE_EVADE_BUFFER 0 #endif } audiod_interface_t; @@ -292,7 +327,11 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) #endif // Prepare for next transmission +#if USE_EVADE_BUFFER + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, &audio->evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); +#else TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); +#endif // Call a weak callback here - a possibility for user to get informed decoding was completed if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); @@ -485,7 +524,12 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) uint16_t n_bytes_tx = tu_fifo_count(&audio->ep_in_ff); // Schedule transmit +#if USE_EVADE_BUFFER + tu_fifo_write_n(&audio->ep_in_ff, &audio->evasion_buf_in, n_bytes_tx); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, &audio->evasion_buf_in, n_bytes_tx)); +#else TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); +#endif // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->altSetting[idxItf])); @@ -815,7 +859,11 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Prepare for incoming data - TU_VERIFY(usbd_edpt_iso_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].ep_out_ff, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); +#if USE_EVADE_BUFFER + TU_VERIFY(usbd_edpt_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); +#else + TU_VERIFY(usbd_edpt_iso_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].ep_out_ff, CFG_TUD_AUDIO_EPSIZE_OUT), false); +#endif } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -1106,6 +1154,11 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 { // Save into buffer - do whatever has to be done // TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); + +#if USE_EVADE_BUFFER + TU_VERIFY(tu_fifo_write_n(&_audiod_itf[idxDriver].ep_out_ff, &_audiod_itf[idxDriver].evasion_buf_out, (uint16_t) xferred_bytes)); // Copy data into FIFO +#endif + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver])); return true; -- cgit v1.3.1 From e407ce463d007231f0d24e55768c1d0ab3b2c049 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 21:47:01 +0100 Subject: Add SAMD MCUs to buffer evasion list --- src/class/audio/audio_device.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 7b7c61750..c93de9380 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -144,7 +144,11 @@ typedef struct CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ CFG_TUSB_MCU == OPT_MCU_LPC55XX || \ CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ - CFG_TUSB_MCU == OPT_MCU_LPC40XX) + CFG_TUSB_MCU == OPT_MCU_LPC40XX || \ + CFG_TUSB_MCU == OPT_MCU_SAMD11 || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ + CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ + CFG_TUSB_MCU == OPT_MCU_SAMD51 || \ + CFG_TUSB_MCU == OPT_MCU_SAME5X) #define USE_EVADE_BUFFER 1 -- cgit v1.3.1 From eee47493a336eb334fdd7f1713903e2131a86650 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 21:59:32 +0100 Subject: Fix bug in evasion buffer list --- src/class/audio/audio_device.c | 4 ++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index c93de9380..9dd2ee704 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -132,7 +132,7 @@ typedef struct CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_RP2040) || /* Don't want to change driver */ \ + CFG_TUSB_MCU == OPT_MCU_RP2040 || /* Don't want to change driver */ \ CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI || /* Intermediate software buffer required */ \ CFG_TUSB_MCU == OPT_MCU_CXD56 || /* No clue how driver works */ \ CFG_TUSB_MCU == OPT_MCU_DA1469X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ @@ -148,7 +148,7 @@ typedef struct CFG_TUSB_MCU == OPT_MCU_SAMD11 || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ CFG_TUSB_MCU == OPT_MCU_SAMD51 || \ - CFG_TUSB_MCU == OPT_MCU_SAME5X) + CFG_TUSB_MCU == OPT_MCU_SAME5X ) #define USE_EVADE_BUFFER 1 diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 9d813d4a5..0d25cceb8 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -984,7 +984,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN { // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part - void *__restrict src; + void * src; uint16_t len = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes); // We want to read from the FIFO TU_VERIFY(len && dcd_write_packet_memory(dst, src, len)); // and write it into the PMA tu_fifo_advance_read_pointer(ff, len); @@ -1064,7 +1064,7 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB { // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part - void *__restrict dst; + void * dst; uint16_t len = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes); TU_VERIFY(len && dcd_read_packet_memory(dst, src, len)); tu_fifo_advance_write_pointer(ff, len); -- cgit v1.3.1 From 53a796a92ea853ea5af16431ba2a6bed8a3c7b5a Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 22:29:40 +0100 Subject: Fix wrong pointer type. --- src/class/audio/audio_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 9dd2ee704..2db1e8b58 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -332,7 +332,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) // Prepare for next transmission #if USE_EVADE_BUFFER - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, &audio->evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); #else TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); #endif @@ -529,8 +529,8 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) // Schedule transmit #if USE_EVADE_BUFFER - tu_fifo_write_n(&audio->ep_in_ff, &audio->evasion_buf_in, n_bytes_tx); - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, &audio->evasion_buf_in, n_bytes_tx)); + tu_fifo_write_n(&audio->ep_in_ff, audio->evasion_buf_in, n_bytes_tx); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->evasion_buf_in, n_bytes_tx)); #else TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); #endif -- cgit v1.3.1 From 94bf4f54dae23f0b0fcd660f0afae374f8e141d5 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 22:29:51 +0100 Subject: Fix missing FIFO definitions --- src/portable/nuvoton/nuc121/dcd_nuc121.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index a689470d6..8aa97ad10 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -34,6 +34,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && ( (CFG_TUSB_MCU == OPT_MCU_NUC121) || (CFG_TUSB_MCU == OPT_MCU_NUC126) ) @@ -78,6 +79,7 @@ static bool active_ep0_xfer; static struct xfer_ctl_t { uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */ + tu_fifo_t * ff; union { uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */ uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */ -- cgit v1.3.1 From 402005c9e0804ef71606edd0490b3f853ca85593 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 22:49:10 +0100 Subject: Fix missing pointer operator in dcd_nuc505.c --- src/portable/nuvoton/nuc505/dcd_nuc505.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 3641b7047..0a690d84d 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -183,7 +183,7 @@ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) /* provided buffers are thankfully 32-bit aligned, allowing most data to be transfered as 32-bit */ if (xfer->ff) { - tu_fifo_read_n(xfer->ff, (void *) (ep->EPDAT_BYTE), bytes_now); + tu_fifo_read_n(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now); } else { -- cgit v1.3.1 From 666e0fad358dfdbda01fadc2c04dee5de5a527c0 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 22:50:49 +0100 Subject: Fix wrong tu_fifo_read_n() call in dcd_stm32_fsdev.c --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 0d25cceb8..42d34f498 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -1004,7 +1004,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN { // Since PMA can accessed only 16 bit-wise we copy the last byte again tu_fifo_backward_read_pointer(ff, 1); // Move one byte back and copy two bytes for the PMA - pma[PMA_STRIDE*(dst>>1)] = tu_fifo_read_n(ff, 2); // Since EP FIFOs must be of item size 1 this is safe to do + tu_fifo_read_n(ff, &pma[PMA_STRIDE*(dst>>1)], 2); // Since EP FIFOs must be of item size 1 this is safe to do dst++; len2--; } -- cgit v1.3.1 From d8481ac7e40a2458a7df9394f487218ea35f6c2d Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 22:52:59 +0100 Subject: Fix wrong pointer call in dcd_samg.c --- src/portable/microchip/samg/dcd_samg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 12b2633a0..1edbba629 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -440,7 +440,7 @@ void dcd_int_handler(uint8_t rhport) // write to EP fifo if (xfer->ff) { - tu_fifo_read_n(ff, (void *) &UDP->UDP_FDR[epnum], xact_len); + tu_fifo_read_n(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len); } else { -- cgit v1.3.1 From 6cb9a6ebb15c2bfacc15c7e4e6e13ec333067693 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 17 Feb 2021 23:04:19 +0100 Subject: Add (void *) for pointer cast. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 42d34f498..e2fd48d74 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -1004,7 +1004,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN { // Since PMA can accessed only 16 bit-wise we copy the last byte again tu_fifo_backward_read_pointer(ff, 1); // Move one byte back and copy two bytes for the PMA - tu_fifo_read_n(ff, &pma[PMA_STRIDE*(dst>>1)], 2); // Since EP FIFOs must be of item size 1 this is safe to do + tu_fifo_read_n(ff, (void *) &pma[PMA_STRIDE*(dst>>1)], 2); // Since EP FIFOs must be of item size 1 this is safe to do dst++; len2--; } -- cgit v1.3.1 From 27f4b6f5a4e122ba0413315472ff663e5b8417be Mon Sep 17 00:00:00 2001 From: Nicholas R Dinsmore Date: Wed, 17 Feb 2021 18:22:24 -0500 Subject: Included size check for ISO buffers --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 036b52196..d3cbb2a21 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -156,13 +156,12 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t // FIXME: What if low speed if(ep->transfer_type == TUSB_XFER_ISOCHRONOUS) { - ep->transfer_size = total_len; //There is an assumption that the max buffer size of 1023 or 1024 was checked before this + ep->transfer_size = total_len > ep->wMaxPacketSize ? ep->wMaxPacketSize : total_len; } else { ep->transfer_size = total_len > 64 ? 64 : total_len; } - ep->transfer_size = total_len > 64 ? 64 : total_len; ep->active = true; ep->user_buf = buffer; // Recalculate if this is the last buffer @@ -240,7 +239,16 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) // Now we have synced our state with the hardware. Is there more data to transfer? uint remaining_bytes = ep->total_len - ep->len; - ep->transfer_size = remaining_bytes > 64 ? 64 : remaining_bytes; + // ep->transfer_size = remaining_bytes > 64 ? 64 : remaining_bytes; + + if(ep->transfer_type == TUSB_XFER_ISOCHRONOUS) + { + ep->transfer_size = remaining_bytes > ep->wMaxPacketSize ? ep->wMaxPacketSize : remaining_bytes; + } + else + { + ep->transfer_size = remaining_bytes > 64 ? 64 : remaining_bytes; + } _hw_endpoint_update_last_buf(ep); // Can happen because of programmer error so check for it -- cgit v1.3.1 From 681cfd0bf21cc0e977cb3e5294c7a1edbb4f0928 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 18 Feb 2021 11:12:16 +0100 Subject: Correct for wrong pointer type in audio_device.c --- src/class/audio/audio_device.c | 4 ++-- src/common/tusb_fifo.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 2db1e8b58..527aecc0d 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -864,7 +864,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Prepare for incoming data #if USE_EVADE_BUFFER - TU_VERIFY(usbd_edpt_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, _audiod_itf[idxDriver].ep_out, _audiod_itf[idxDriver].evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); #else TU_VERIFY(usbd_edpt_iso_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].ep_out_ff, CFG_TUD_AUDIO_EPSIZE_OUT), false); #endif @@ -1160,7 +1160,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); #if USE_EVADE_BUFFER - TU_VERIFY(tu_fifo_write_n(&_audiod_itf[idxDriver].ep_out_ff, &_audiod_itf[idxDriver].evasion_buf_out, (uint16_t) xferred_bytes)); // Copy data into FIFO + TU_VERIFY(tu_fifo_write_n(&_audiod_itf[idxDriver].ep_out_ff, _audiod_itf[idxDriver].evasion_buf_out, (uint16_t) xferred_bytes)); // Copy data into FIFO #endif TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver])); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 19f120a33..eb88538ef 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2020 Reinhard Panhuber - rework to unmasked pointers * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal -- cgit v1.3.1 From ac87a4547d520fd41815ccb5155ed6680de46ce0 Mon Sep 17 00:00:00 2001 From: ndinsmore <45537276+ndinsmore@users.noreply.github.com> Date: Thu, 18 Feb 2021 08:25:04 -0500 Subject: Change to using tu_min32 This was a github edit, not tested --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index d3cbb2a21..9bf359525 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -156,11 +156,11 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t // FIXME: What if low speed if(ep->transfer_type == TUSB_XFER_ISOCHRONOUS) { - ep->transfer_size = total_len > ep->wMaxPacketSize ? ep->wMaxPacketSize : total_len; + ep->transfer_size = tu_min32(total_len, ep->wMaxPacketSize); } else { - ep->transfer_size = total_len > 64 ? 64 : total_len; + ep->transfer_size = tu_min32(total_len, 64); } ep->active = true; ep->user_buf = buffer; @@ -243,11 +243,11 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) if(ep->transfer_type == TUSB_XFER_ISOCHRONOUS) { - ep->transfer_size = remaining_bytes > ep->wMaxPacketSize ? ep->wMaxPacketSize : remaining_bytes; + ep->transfer_size = tu_min32(remaining_bytes,ep->wMaxPacketSize); } else { - ep->transfer_size = remaining_bytes > 64 ? 64 : remaining_bytes; + ep->transfer_size = tu_min32(remaining_bytes, 64); } _hw_endpoint_update_last_buf(ep); -- cgit v1.3.1 From c098da9803a091c4b2402057ece370975850ef53 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 18 Feb 2021 19:25:08 +0100 Subject: Implement left and right justifications for 24 to 32 bit PCM encoding --- src/class/audio/audio_device.c | 10 ++++++++-- src/class/audio/audio_device.h | 12 ++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 527aecc0d..c71ad6b8e 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -366,11 +366,15 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) // If this aborts then the target buffer is full TU_VERIFY(tu_fifo_read_n_into_other_fifo(&audio->ep_out_ff, &audio->rx_ff[cntChannel], 0, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); #else - // TODO: Implement a left and right justified 24 to 32 and vice versa copy process from FIFO to FIFO uint32_t sample = 0; // Get sample from buffer TU_VERIFY(tu_fifo_read_n(&audio->ep_out_ff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); + +#if CFG_TUD_AUDIO_JUSTIFICATION_RX == CFG_TUD_AUDIO_LEFT_JUSTIFIED + sample = sample << 8; +#endif + TU_VERIFY(tu_fifo_write_n(&audio->rx_ff[cntChannel], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE)); #endif } @@ -584,12 +588,14 @@ static bool audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == CFG_TUD_AUDIO_TX_ITEMSIZE tu_fifo_read_n_into_other_fifo(&audio->tx_ff[cntChannel], &audio->ep_in_ff, 0, CFG_TUD_AUDIO_TX_ITEMSIZE); #else - // TODO: Implement a left and right justified 24 to 32 and vice versa copy process from FIFO to FIFO uint32_t sample = 0; // Get sample from buffer tu_fifo_read_n(&audio->tx_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); +#if CFG_TUD_AUDIO_JUSTIFICATION_TX == CFG_TUD_AUDIO_LEFT_JUSTIFIED + sample = sample << 8; +#endif tu_fifo_write_n(&audio->ep_in_ff, &sample, CFG_TUD_AUDIO_TX_ITEMSIZE); #endif } diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index d1d1157eb..38495f72d 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -203,6 +203,18 @@ #endif +// In case PCM encoding/decoding of 24 into 32 bits, the adjustment needs to be defined +#define CFG_TUD_AUDIO_LEFT_JUSTIFIED +#define CFG_TUD_AUDIO_RIGHT_JUSTIFIED + +#ifndef CFG_TUD_AUDIO_JUSTIFICATION_RX +#define CFG_TUD_AUDIO_JUSTIFICATION_RX CFG_TUD_AUDIO_LEFT_JUSTIFIED +#endif + +#ifndef CFG_TUD_AUDIO_JUSTIFICATION_TX +#define CFG_TUD_AUDIO_JUSTIFICATION_TX CFG_TUD_AUDIO_LEFT_JUSTIFIED +#endif + //static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); // Supported types of this driver: -- cgit v1.3.1 From 21f1cd4ec7e2104ac88b26be5c06e81e385cd660 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 18 Feb 2021 13:26:03 -0500 Subject: Implement requested PR changes Removes CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT, and makes the manual padding behavior standard. Replaced unused variable name with TU_RESERVED. --- src/class/cdc/cdc.h | 30 +++++------------------------- src/common/tusb_types.h | 6 +----- src/host/ehci/ehci.h | 11 +---------- src/host/hub.h | 6 +----- src/host/ohci/ohci.h | 12 ++---------- src/tusb_option.h | 4 ---- 6 files changed, 10 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index ec31ee4cf..f59bf0f1a 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -277,11 +277,7 @@ typedef struct TU_ATTR_PACKED struct { uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface. uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself. -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint8_t unused : 6; -#else - uint8_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint8_t TU_RESERVED : 6; } bmCapabilities; uint8_t bDataInterface; @@ -294,11 +290,7 @@ typedef struct TU_ATTR_PACKED uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State. uint8_t support_send_break : 1; ///< Device supports the request Send_Break uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection. -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint8_t unused : 4; -#else - uint8_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint8_t TU_RESERVED : 4; }cdc_acm_capability_t; TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); @@ -324,11 +316,7 @@ typedef struct TU_ATTR_PACKED uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit. uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State. uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time. -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint8_t unused : 5; -#else - uint8_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint8_t TU_RESERVED : 5; } bmCapabilities; }cdc_desc_func_direct_line_management_t; @@ -356,11 +344,7 @@ typedef struct TU_ATTR_PACKED uint8_t simple_mode : 1; uint8_t standalone_mode : 1; uint8_t computer_centric_mode : 1; -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint8_t unused : 5; -#else - uint8_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint8_t TU_RESERVED : 5; } bmCapabilities; }cdc_desc_func_telephone_operational_modes_t; @@ -379,11 +363,7 @@ typedef struct TU_ATTR_PACKED uint32_t incoming_distinctive : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns. uint32_t dual_tone_multi_freq : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line. uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint32_t unused : 26; -#else - uint32_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint32_t TU_RESERVED : 26; } bmCapabilities; }cdc_desc_func_telephone_call_state_reporting_capabilities_t; diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index e57dc26f5..ba3fe2c41 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -342,11 +342,7 @@ typedef struct TU_ATTR_PACKED struct TU_ATTR_PACKED { uint16_t size : 11; ///< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. \n For isochronous endpoints, this value is used to reserve the bus time in the schedule, required for the per-(micro)frame data payloads. The pipe may, on an ongoing basis, actually use less bandwidth than that reserved. The device reports, if necessary, the actual bandwidth used via its normal, non-USB defined mechanisms. \n For all endpoints, bits 10..0 specify the maximum packet size (in bytes). \n For high-speed isochronous and interrupt endpoints: \n Bits 12..11 specify the number of additional transaction opportunities per microframe: \n- 00 = None (1 transaction per microframe) \n- 01 = 1 additional (2 per microframe) \n- 10 = 2 additional (3 per microframe) \n- 11 = Reserved \n Bits 15..13 are reserved and must be set to zero. uint16_t hs_period_mult : 2; -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint16_t unused : 3; -#else - uint16_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint16_t TU_RESERVED : 3; }wMaxPacketSize; uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. diff --git a/src/host/ehci/ehci.h b/src/host/ehci/ehci.h index acaf545c1..d8218a5fd 100644 --- a/src/host/ehci/ehci.h +++ b/src/host/ehci/ehci.h @@ -231,11 +231,6 @@ typedef struct TU_ATTR_ALIGNED(32) uint32_t : 1; ///< reserved uint32_t port_number : 7; ///< This field is the port number of the recipient transaction translator. uint32_t direction : 1; ///< 0 = OUT; 1 = IN. This field encodes whether the full-speed transaction should be an IN or OUT. -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - ///< All 32 bits are used -#else - uint32_t : 0; // padding to the end of current storage unit -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ // Word 2: Micro-frame Schedule Control uint8_t int_smask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute complete-split transactions @@ -427,11 +422,7 @@ typedef volatile struct uint32_t nxp_port_force_fullspeed : 1; ///< NXP customized: Writing this bit to a 1 will force the port to only connect at Full Speed. It disables the chirp sequence that allowsthe port to identify itself as High Speed. This is useful for testing FS configurations with a HS host, hub or device. uint32_t : 1; uint32_t nxp_port_speed : 2; ///< NXP customized: This register field indicates the speed atwhich the port is operating. For HS mode operation in the host controllerand HS/FS operation in the device controller the port routing steers data to the Protocol engine. For FS and LS mode operation in the host controller, the port routing steers data to the Protocol Engine w/ Embedded Transaction Translator. 0x0: Fullspeed, 0x1: Lowspeed, 0x2: Highspeed -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint32_t unused : 4; ///< padding -#else - uint32_t : 0; // padding to the boundary of storage unit -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint32_t TU_RESERVED : 4; }portsc_bm; }; }ehci_registers_t; diff --git a/src/host/hub.h b/src/host/hub.h index 0e3292274..851bb8e66 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -163,11 +163,7 @@ typedef struct { uint16_t high_speed : 1; uint16_t port_test_mode : 1; uint16_t port_indicator_control : 1; -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint16_t unused : 3; -#else - uint16_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint16_t TU_RESERVED : 3; }; uint16_t value; diff --git a/src/host/ohci/ohci.h b/src/host/ohci/ohci.h index 76d6fff61..2915f8b00 100644 --- a/src/host/ohci/ohci.h +++ b/src/host/ohci/ohci.h @@ -208,11 +208,7 @@ typedef volatile struct uint32_t interrupt_routing : 1; uint32_t remote_wakeup_connected : 1; uint32_t remote_wakeup_enale : 1; -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint32_t unused : 21; -#else - uint32_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint32_t TU_RESERVED : 21; }control_bit; }; @@ -280,11 +276,7 @@ typedef volatile struct uint32_t port_suspend_status_change : 1; uint32_t port_over_current_indicator_change : 1; uint32_t port_reset_status_change : 1; -#if CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - uint32_t unused : 11; -#else - uint32_t : 0; -#endif /* CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT */ + uint32_t TU_RESERVED : 11; }rhport_status_bit[2]; }; }ohci_registers_t; diff --git a/src/tusb_option.h b/src/tusb_option.h index b5504d29c..6cbdefbf1 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -197,10 +197,6 @@ #define CFG_TUSB_OS OPT_OS_NONE #endif -#ifndef CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT - #define CFG_TUSB_ALT_BIT_PACKING_ALIGNMENT 0 -#endif - //-------------------------------------------------------------------- // DEVICE OPTIONS //-------------------------------------------------------------------- -- cgit v1.3.1 From 31bf73517e91b4c25c34b8651064602f5adbef3e Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 18 Feb 2021 20:16:57 +0100 Subject: Add #include "osal/osal.h" in tu_fifo.h --- src/common/tusb_fifo.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index eb88538ef..e56bcb844 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -47,6 +47,7 @@ #include #include +#include "osal/osal.h" #ifdef __cplusplus extern "C" { -- cgit v1.3.1 From 8904874f76ba4a476aefcbadfe74d70a6bfb692a Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 18 Feb 2021 20:52:57 +0100 Subject: Exclude #include "osal/osal.h" for OPT_OS_NONE --- src/common/tusb_fifo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index e56bcb844..585ea17d3 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -47,13 +47,13 @@ #include #include -#include "osal/osal.h" #ifdef __cplusplus extern "C" { #endif #if CFG_FIFO_MUTEX +#include "osal/osal.h" #define tu_fifo_mutex_t osal_mutex_t #endif -- cgit v1.3.1 From fff6283bf751ecf8e2ef33745e03d45eb13b354e Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 18 Feb 2021 21:22:11 +0100 Subject: Update .non_used_index_space = UINT16_MAX - (2*_depth-1) in osal_none.h --- src/osal/osal_none.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 1d170d2fa..11726c95f 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -140,7 +140,7 @@ typedef osal_queue_def_t* osal_queue_t; .item_size = sizeof(_type), \ .overwritable = false, \ .max_pointer_idx = (2*(_depth))-1, \ - .non_used_index_space = 0xFFFF-((2*(_depth))-1),\ + .non_used_index_space = UINT16_MAX - (2*_depth-1),\ }\ } -- cgit v1.3.1 From aa850991715e2a6dcaa33a370b0ae702a33c1d54 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Feb 2021 10:51:47 +0700 Subject: fix tud_midi_write24 typo rename jack_id to cable_num in function argument --- src/class/midi/midi_device.c | 18 +++++++++--------- src/class/midi/midi_device.h | 26 +++++++++++++------------- 2 files changed, 22 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index b9d6b2efc..325fc4669 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -114,15 +114,15 @@ static void _prep_out_transaction (midid_interface_t* p_midi) //--------------------------------------------------------------------+ // READ API //--------------------------------------------------------------------+ -uint32_t tud_midi_n_available(uint8_t itf, uint8_t jack_id) +uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) { - (void) jack_id; + (void) cable_num; return tu_fifo_count(&_midid_itf[itf].rx_ff); } -uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize) +uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) { - (void) jack_id; + (void) cable_num; midid_interface_t* midi = &_midid_itf[itf]; // Fill empty buffer @@ -158,9 +158,9 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bu return n; } -void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id) +void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num) { - (void) jack_id; + (void) cable_num; midid_interface_t* p_midi = &_midid_itf[itf]; tu_fifo_clear(&p_midi->rx_ff); _prep_out_transaction(p_midi); @@ -205,7 +205,7 @@ static uint32_t write_flush(midid_interface_t* midi) } } -uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize) +uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { midid_interface_t* midi = &_midid_itf[itf]; if (midi->itf_num == 0) { @@ -228,7 +228,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u midi->write_target_length = 4; } } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { - midi->write_buffer[0] = jack_id << 4 | msg; + midi->write_buffer[0] = cable_num << 4 | msg; midi->write_target_length = 4; } else if (msg == 0xf) { if (data == 0xf0) { @@ -246,7 +246,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u } } else { // Pack individual bytes if we don't support packing them into words. - midi->write_buffer[0] = jack_id << 4 | 0xf; + midi->write_buffer[0] = cable_num << 4 | 0xf; midi->write_buffer[2] = 0; midi->write_buffer[3] = 0; midi->write_buffer_length = 2; diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 9235448f2..5e7df80ae 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -60,13 +60,13 @@ // CFG_TUD_MIDI > 1 //--------------------------------------------------------------------+ bool tud_midi_n_mounted (uint8_t itf); -uint32_t tud_midi_n_available (uint8_t itf, uint8_t jack_id); -uint32_t tud_midi_n_read (uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize); -void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id); -uint32_t tud_midi_n_write (uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize); +uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); +uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); +void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num); +uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); static inline -uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3); +uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]); bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]); @@ -78,8 +78,8 @@ static inline bool tud_midi_mounted (void); static inline uint32_t tud_midi_available (void); static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); static inline void tud_midi_read_flush (void); -static inline uint32_t tud_midi_write (uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize); -static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3); +static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); +static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); static inline bool tud_midi_receive (uint8_t packet[4]); static inline bool tud_midi_send (uint8_t const packet[4]); @@ -92,10 +92,10 @@ TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf); // Inline Functions //--------------------------------------------------------------------+ -static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3) +static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3) { uint8_t msg[3] = { b1, b2, b3 }; - return tud_midi_n_write(itf, jack_id, msg, 3); + return tud_midi_n_write(itf, cable_num, msg, 3); } static inline bool tud_midi_mounted (void) @@ -118,15 +118,15 @@ static inline void tud_midi_read_flush (void) tud_midi_n_read_flush(0, 0); } -static inline uint32_t tud_midi_write (uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize) +static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { - return tud_midi_n_write(0, jack_id, buffer, bufsize); + return tud_midi_n_write(0, cable_num, buffer, bufsize); } -static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3) +static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3) { uint8_t msg[3] = { b1, b2, b3 }; - return tud_midi_write(jack_id, msg, 3); + return tud_midi_write(cable_num, msg, 3); } static inline bool tud_midi_receive (uint8_t packet[4]) -- cgit v1.3.1 From 2a04ee68b82d8857fc02974eab2c0557826d9f49 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Feb 2021 11:57:56 +0700 Subject: add TU_FIFO_INIT() to help with tu_fifo declaration tu_fifo_clear() also reset max_pointer_idx and non_used_index_space --- src/common/tusb_fifo.c | 2 ++ src/common/tusb_fifo.h | 25 ++++++++++++++----------- src/osal/osal_none.h | 17 +++++------------ src/osal/osal_pico.h | 15 ++++----------- 4 files changed, 25 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index e3c4d74c7..30629af71 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -598,6 +598,8 @@ bool tu_fifo_clear(tu_fifo_t *f) { tu_fifo_lock(f); f->rd_idx = f->wr_idx = 0; + f->max_pointer_idx = 2*f->depth-1; + f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; tu_fifo_unlock(f); return true; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index c35b85a49..294378496 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -66,8 +66,8 @@ typedef struct uint16_t item_size ; ///< size of each item bool overwritable ; - uint16_t non_used_index_space ; ///< required for non-power-of-two buffer length uint16_t max_pointer_idx ; ///< maximum absolute pointer index + uint16_t non_used_index_space ; ///< required for non-power-of-two buffer length volatile uint16_t wr_idx ; ///< write pointer volatile uint16_t rd_idx ; ///< read pointer @@ -78,16 +78,19 @@ typedef struct } tu_fifo_t; -#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - tu_fifo_t _name = { \ - .buffer = _name##_buf, \ - .depth = _depth, \ - .item_size = sizeof(_type), \ - .overwritable = _overwritable, \ - .max_pointer_idx = 2*_depth-1, \ - .non_used_index_space = UINT16_MAX - (2*_depth-1), \ - } +#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ +{ \ + .buffer = _buffer, \ + .depth = _depth, \ + .item_size = sizeof(_type), \ + .overwritable = _overwritable, \ + .max_pointer_idx = 2*(_depth)-1, \ + .non_used_index_space = UINT16_MAX - (2*(_depth)-1) \ +} + +#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ + uint8_t _name##_buf[_depth*sizeof(_type)]; \ + tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _type, _overwritable) bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); bool tu_fifo_clear(tu_fifo_t *f); diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 1d170d2fa..ea6818621 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -130,18 +130,11 @@ typedef struct typedef osal_queue_def_t* osal_queue_t; // role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - osal_queue_def_t _name = { \ - .role = _role, \ - .ff = { \ - .buffer = _name##_buf, \ - .depth = _depth, \ - .item_size = sizeof(_type), \ - .overwritable = false, \ - .max_pointer_idx = (2*(_depth))-1, \ - .non_used_index_space = 0xFFFF-((2*(_depth))-1),\ - }\ +#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ + uint8_t _name##_buf[_depth*sizeof(_type)]; \ + osal_queue_def_t _name = { \ + .role = _role, \ + .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ } // lock queue by disable USB interrupt diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index 79054ddfa..de964a7a0 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -115,17 +115,10 @@ typedef struct typedef osal_queue_def_t* osal_queue_t; // role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - osal_queue_def_t _name = { \ - .ff = { \ - .buffer = _name##_buf, \ - .depth = _depth, \ - .item_size = sizeof(_type), \ - .overwritable = false, \ - .max_pointer_idx = 2*_depth-1, \ - .non_used_index_space = UINT16_MAX - (2*_depth-1), \ - }\ +#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ + uint8_t _name##_buf[_depth*sizeof(_type)]; \ + osal_queue_def_t _name = { \ + .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ } // lock queue by disable USB interrupt -- cgit v1.3.1 From cb5b9eb2f671a6d1a00205e0df01b0d68725ec60 Mon Sep 17 00:00:00 2001 From: ndinsmore <45537276+ndinsmore@users.noreply.github.com> Date: Fri, 19 Feb 2021 08:33:06 -0500 Subject: Remove stray. commented out line --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 9bf359525..a6e0ed560 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -239,7 +239,6 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) // Now we have synced our state with the hardware. Is there more data to transfer? uint remaining_bytes = ep->total_len - ep->len; - // ep->transfer_size = remaining_bytes > 64 ? 64 : remaining_bytes; if(ep->transfer_type == TUSB_XFER_ISOCHRONOUS) { -- cgit v1.3.1 From 43ca6267748e697a70db4c8c085c837addadff2e Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 22 Feb 2021 12:27:02 +0700 Subject: merge iso and cbi transaction size to max ep size --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index a6e0ed560..339297ad6 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -153,15 +153,7 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t // Fill in info now that we're kicking off the hw ep->total_len = total_len; ep->len = 0; - // FIXME: What if low speed - if(ep->transfer_type == TUSB_XFER_ISOCHRONOUS) - { - ep->transfer_size = tu_min32(total_len, ep->wMaxPacketSize); - } - else - { - ep->transfer_size = tu_min32(total_len, 64); - } + ep->transfer_size = tu_min32(total_len, ep->wMaxPacketSize); ep->active = true; ep->user_buf = buffer; // Recalculate if this is the last buffer @@ -239,15 +231,7 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) // Now we have synced our state with the hardware. Is there more data to transfer? uint remaining_bytes = ep->total_len - ep->len; - - if(ep->transfer_type == TUSB_XFER_ISOCHRONOUS) - { - ep->transfer_size = tu_min32(remaining_bytes,ep->wMaxPacketSize); - } - else - { - ep->transfer_size = tu_min32(remaining_bytes, 64); - } + ep->transfer_size = tu_min32(remaining_bytes, ep->wMaxPacketSize); _hw_endpoint_update_last_buf(ep); // Can happen because of programmer error so check for it -- cgit v1.3.1 From 00b4b74e8276691dfc4a20163b472c7bd15f4f51 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 22 Feb 2021 17:15:06 +0700 Subject: rename hcd_lpc18_43 to hcd_transdimension --- examples/host/cdc_msc_hid/Makefile | 2 +- src/portable/nxp/lpc18_43/hcd_lpc18_43.c | 50 ---------------------- .../nxp/transdimension/hcd_transdimension.c | 50 ++++++++++++++++++++++ 3 files changed, 51 insertions(+), 51 deletions(-) delete mode 100644 src/portable/nxp/lpc18_43/hcd_lpc18_43.c create mode 100644 src/portable/nxp/transdimension/hcd_transdimension.c (limited to 'src') diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index b49c4c75c..3a0e94d73 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -21,7 +21,7 @@ SRC_C += \ src/host/usbh_control.c \ src/host/ehci/ehci.c \ src/host/ohci/ohci.c \ - src/portable/nxp/lpc18_43/hcd_lpc18_43.c \ + src/portable/nxp/transdimension/hcd_transdimension.c \ src/portable/nxp/lpc17_40/hcd_lpc17_40.c include ../../rules.mk diff --git a/src/portable/nxp/lpc18_43/hcd_lpc18_43.c b/src/portable/nxp/lpc18_43/hcd_lpc18_43.c deleted file mode 100644 index cb509e7a2..000000000 --- a/src/portable/nxp/lpc18_43/hcd_lpc18_43.c +++ /dev/null @@ -1,50 +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. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if TUSB_OPT_HOST_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX) - -#include "chip.h" - -// LPC18xx and 43xx use EHCI driver - -void hcd_int_enable(uint8_t rhport) -{ - NVIC_EnableIRQ(rhport ? USB1_IRQn : USB0_IRQn); -} - -void hcd_int_disable(uint8_t rhport) -{ - NVIC_DisableIRQ(rhport ? USB1_IRQn : USB0_IRQn); -} - -uint32_t hcd_ehci_register_addr(uint8_t rhport) -{ - return (uint32_t) (rhport ? &LPC_USB1->USBCMD_H : &LPC_USB0->USBCMD_H ); -} - -#endif diff --git a/src/portable/nxp/transdimension/hcd_transdimension.c b/src/portable/nxp/transdimension/hcd_transdimension.c new file mode 100644 index 000000000..cb509e7a2 --- /dev/null +++ b/src/portable/nxp/transdimension/hcd_transdimension.c @@ -0,0 +1,50 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_HOST_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX) + +#include "chip.h" + +// LPC18xx and 43xx use EHCI driver + +void hcd_int_enable(uint8_t rhport) +{ + NVIC_EnableIRQ(rhport ? USB1_IRQn : USB0_IRQn); +} + +void hcd_int_disable(uint8_t rhport) +{ + NVIC_DisableIRQ(rhport ? USB1_IRQn : USB0_IRQn); +} + +uint32_t hcd_ehci_register_addr(uint8_t rhport) +{ + return (uint32_t) (rhport ? &LPC_USB1->USBCMD_H : &LPC_USB0->USBCMD_H ); +} + +#endif -- cgit v1.3.1 From b591a66b3d38bc199aaa5ac1b32d0a1221b8b983 Mon Sep 17 00:00:00 2001 From: Kamil Tomaszewski Date: Mon, 22 Feb 2021 11:24:16 +0100 Subject: Pass the correct speed on Spresense --- src/portable/sony/cxd56/dcd_cxd56.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 88027ccaa..904176ba1 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -155,7 +155,24 @@ static void _dcd_disconnect(FAR struct usbdevclass_driver_s *driver, FAR struct { (void) driver; - tusb_speed_t speed = (dev->speed == 3) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL; + tusb_speed_t speed; + + switch (dev->speed) + { + case USB_SPEED_LOW: + speed = TUSB_SPEED_LOW; + break; + case USB_SPEED_FULL: + speed = TUSB_SPEED_FULL; + break; + case USB_SPEED_HIGH: + speed = TUSB_SPEED_HIGH; + break; + default: + speed = TUSB_SPEED_HIGH; + break; + } + dcd_event_bus_reset(0, speed, true); DEV_CONNECT(dev); } -- cgit v1.3.1 From 8a2e4c79fd6a5b7927ae07bececc30ca79d9edf2 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 22 Feb 2021 18:02:52 +0700 Subject: make hcd tdi more generic --- src/host/ehci/ehci.c | 5 ++- .../nxp/transdimension/dcd_transdimension.c | 5 +-- .../nxp/transdimension/hcd_transdimension.c | 45 +++++++++++++++++++--- 3 files changed, 45 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 23c8ea9ee..f3a5cf9cd 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -26,7 +26,10 @@ #include "common/tusb_common.h" -#if TUSB_OPT_HOST_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX) +#if TUSB_OPT_HOST_ENABLED && \ + (CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ + CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX ) + //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 755e7635e..6f1923ec9 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -26,9 +26,8 @@ #include "tusb_option.h" -#if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ - CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX) +#if TUSB_OPT_DEVICE_ENABLED && \ + (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX) //--------------------------------------------------------------------+ // INCLUDE diff --git a/src/portable/nxp/transdimension/hcd_transdimension.c b/src/portable/nxp/transdimension/hcd_transdimension.c index cb509e7a2..f8ad7c719 100644 --- a/src/portable/nxp/transdimension/hcd_transdimension.c +++ b/src/portable/nxp/transdimension/hcd_transdimension.c @@ -26,25 +26,58 @@ #include "tusb_option.h" -#if TUSB_OPT_HOST_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX) +// NXP Trans-Dimension USB IP implement EHCI for host functionality -#include "chip.h" +#if TUSB_OPT_HOST_ENABLED && \ + (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX) + +#if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX + #include "fsl_device_registers.h" +#else + // LPCOpen for 18xx & 43xx + #include "chip.h" +#endif + +typedef struct +{ + uint32_t regs_addr; // registers base + const IRQn_Type irqnum; // IRQ number +}hcd_controller_t; + +#if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX + static const hcd_controller_t _hcd_controller[] = + { + // RT1010 and RT1020 only has 1 USB controller + #if FSL_FEATURE_SOC_USBHS_COUNT == 1 + { .regs_addr = (uint32_t) &USB->USBCMD , .irqnum = USB_OTG1_IRQn } + #else + { .regs_addr = (uint32_t) &USB1->USBCMD, .irqnum = USB_OTG1_IRQn }, + { .regs_addr = (uint32_t) &USB2->USBCMD, .irqnum = USB_OTG2_IRQn } + #endif + }; + +#else + static const hcd_controller_t _hcd_controller[] = + { + { .regs_addr = (uint32_t) &LPC_USB0->USBCMD_H, .irqnum = USB0_IRQn }, + { .regs_addr = (uint32_t) &LPC_USB1->USBCMD_H, .irqnum = USB1_IRQn } + }; +#endif -// LPC18xx and 43xx use EHCI driver void hcd_int_enable(uint8_t rhport) { - NVIC_EnableIRQ(rhport ? USB1_IRQn : USB0_IRQn); + NVIC_EnableIRQ(_hcd_controller[rhport].irqnum); } void hcd_int_disable(uint8_t rhport) { - NVIC_DisableIRQ(rhport ? USB1_IRQn : USB0_IRQn); + NVIC_DisableIRQ(_hcd_controller[rhport].irqnum); } uint32_t hcd_ehci_register_addr(uint8_t rhport) { - return (uint32_t) (rhport ? &LPC_USB1->USBCMD_H : &LPC_USB0->USBCMD_H ); + return _hcd_controller[rhport].regs_addr; } #endif -- cgit v1.3.1 From 1e07fc024c91453cd71d357698b05d40eb571431 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 22 Feb 2021 22:32:56 +0700 Subject: add rhport to hcd_init() --- src/host/ehci/ehci.c | 4 ++-- src/host/hcd.h | 2 +- src/host/usbh.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index f3a5cf9cd..b5f872c81 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -105,10 +105,10 @@ static bool ehci_init (uint8_t rhport); //--------------------------------------------------------------------+ // HCD API //--------------------------------------------------------------------+ -bool hcd_init(void) +bool hcd_init(uint8_t rhport) { tu_memclr(&ehci_data, sizeof(ehci_data_t)); - return ehci_init(TUH_OPT_RHPORT); + return ehci_init(rhport); } uint32_t hcd_uframe_number(uint8_t rhport) diff --git a/src/host/hcd.h b/src/host/hcd.h index db98f6110..4810ef8da 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -98,7 +98,7 @@ enum { //--------------------------------------------------------------------+ // Controller & Port API //--------------------------------------------------------------------+ -bool hcd_init(void); +bool hcd_init(uint8_t rhport); void hcd_int_handler(uint8_t rhport); void hcd_int_enable (uint8_t rhport); void hcd_int_disable(uint8_t rhport); diff --git a/src/host/usbh.c b/src/host/usbh.c index f278f4d94..0bc6378b2 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -197,7 +197,7 @@ bool tuh_init(void) usbh_class_drivers[drv_id].init(); } - TU_ASSERT(hcd_init()); + TU_ASSERT(hcd_init(TUH_OPT_RHPORT)); hcd_int_enable(TUH_OPT_RHPORT); return true; -- cgit v1.3.1 From c5b8980398a8e79f6501af1f1b1e17e0a599fabf Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 22 Feb 2021 22:40:51 +0700 Subject: separate hcd_init from ehci --- src/host/ehci/ehci.c | 12 ++++-------- src/portable/nxp/transdimension/hcd_transdimension.c | 8 ++++++++ 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index b5f872c81..5626abcc8 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -51,6 +51,7 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data; // EHCI portable uint32_t hcd_ehci_register_addr(uint8_t rhport); +bool hcd_ehci_init (uint8_t rhport); // TODO move later //--------------------------------------------------------------------+ // PROTOTYPE @@ -100,16 +101,9 @@ static void qtd_init (ehci_qtd_t* p_qtd, void* buffer, uint16_t total_bytes); static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type); static inline ehci_link_t* list_next (ehci_link_t *p_link_pointer); -static bool ehci_init (uint8_t rhport); - //--------------------------------------------------------------------+ // HCD API //--------------------------------------------------------------------+ -bool hcd_init(uint8_t rhport) -{ - tu_memclr(&ehci_data, sizeof(ehci_data_t)); - return ehci_init(rhport); -} uint32_t hcd_uframe_number(uint8_t rhport) { @@ -206,8 +200,10 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) } // EHCI controller init -static bool ehci_init(uint8_t rhport) +bool hcd_ehci_init(uint8_t rhport) { + tu_memclr(&ehci_data, sizeof(ehci_data_t)); + ehci_data.regs = (ehci_registers_t* ) hcd_ehci_register_addr(rhport); ehci_registers_t* regs = ehci_data.regs; diff --git a/src/portable/nxp/transdimension/hcd_transdimension.c b/src/portable/nxp/transdimension/hcd_transdimension.c index f8ad7c719..62b14364d 100644 --- a/src/portable/nxp/transdimension/hcd_transdimension.c +++ b/src/portable/nxp/transdimension/hcd_transdimension.c @@ -65,6 +65,14 @@ typedef struct #endif +// TODO better prototype later +extern bool hcd_ehci_init (uint8_t rhport); // from ehci.c + +bool hcd_init(uint8_t rhport) +{ + return hcd_ehci_init(rhport); +} + void hcd_int_enable(uint8_t rhport) { NVIC_EnableIRQ(_hcd_controller[rhport].irqnum); -- cgit v1.3.1 From de955852586eb88cac4c107cfa0ace267ce079d1 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Feb 2021 01:27:52 +0700 Subject: nxp tdi: hcd_init() reset and set host mode --- hw/bsp/mcb1800/mcb1800.c | 39 ------ .../nxp/transdimension/common_transdimension.h | 136 +++++++++++++++++++++ .../nxp/transdimension/dcd_transdimension.c | 108 +--------------- .../nxp/transdimension/hcd_transdimension.c | 52 ++++++-- 4 files changed, 185 insertions(+), 150 deletions(-) create mode 100644 src/portable/nxp/transdimension/common_transdimension.h (limited to 'src') diff --git a/hw/bsp/mcb1800/mcb1800.c b/hw/bsp/mcb1800/mcb1800.c index 569d33834..5256501ed 100644 --- a/hw/bsp/mcb1800/mcb1800.c +++ b/hw/bsp/mcb1800/mcb1800.c @@ -157,51 +157,12 @@ void board_init(void) Chip_UART_TXEnable(UART_DEV); //------------- USB -------------// - enum { - USBMODE_DEVICE = 2, - USBMODE_HOST = 3 - }; - - enum { - USBMODE_VBUS_LOW = 0, - USBMODE_VBUS_HIGH = 1 - }; - - // USB0 #if CFG_TUSB_RHPORT0_MODE Chip_USB0_Init(); - - // Host/Device mode can only be set right after controller reset - LPC_USB0->USBCMD_D |= 0x02; - while( LPC_USB0->USBCMD_D & 0x02 ) {} - - // Set mode - #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST - LPC_USB0->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5); - LPC_USB0->PORTSC1_H |= (1<<24); // FIXME force full speed for debugging - #else // TODO OTG - LPC_USB0->USBMODE_D = USBMODE_DEVICE; - LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/; - #endif #endif - // USB1 #if CFG_TUSB_RHPORT1_MODE Chip_USB1_Init(); - -// // Reset controller -// LPC_USB1->USBCMD_D |= 0x02; -// while( LPC_USB1->USBCMD_D & 0x02 ) {} -// -// // Set mode -// #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST -// LPC_USB1->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5); -// #else // TODO OTG -// LPC_USB1->USBMODE_D = USBMODE_DEVICE; -// #endif -// -// // USB1 as fullspeed -// LPC_USB1->PORTSC1_D |= (1<<24); #endif } diff --git a/src/portable/nxp/transdimension/common_transdimension.h b/src/portable/nxp/transdimension/common_transdimension.h new file mode 100644 index 000000000..7b94dac34 --- /dev/null +++ b/src/portable/nxp/transdimension/common_transdimension.h @@ -0,0 +1,136 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef COMMON_TRANSDIMENSION_H_ +#define COMMON_TRANSDIMENSION_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// USBCMD +enum { + USBCMD_RUN_STOP = TU_BIT(0), + USBCMD_RESET = TU_BIT(1), + USBCMD_SETUP_TRIPWIRE = TU_BIT(13), + USBCMD_ADD_QTD_TRIPWIRE = TU_BIT(14) ///< This bit is used as a semaphore to ensure the to proper addition of a new dTD to an active (primed) endpoint’s linked list. This bit is set and cleared by software during the process of adding a new dTD +// Interrupt Threshold bit 23:16 +}; + +// PORTSC1 +#define PORTSC1_PORT_SPEED_POS 26 + +enum { + PORTSC1_CURRENT_CONNECT_STATUS = TU_BIT(0), + PORTSC1_FORCE_PORT_RESUME = TU_BIT(6), + PORTSC1_SUSPEND = TU_BIT(7), + PORTSC1_FORCE_FULL_SPEED = TU_BIT(24), + PORTSC1_PORT_SPEED = TU_BIT(26) | TU_BIT(27) +}; + +// OTGSC +enum { + OTGSC_VBUS_DISCHARGE = TU_BIT(0), + OTGSC_VBUS_CHARGE = TU_BIT(1), +// OTGSC_HWASSIST_AUTORESET = TU_BIT(2), + OTGSC_OTG_TERMINATION = TU_BIT(3), ///< Must set to 1 when OTG go to device mode + OTGSC_DATA_PULSING = TU_BIT(4), + OTGSC_ID_PULLUP = TU_BIT(5), +// OTGSC_HWASSIT_DATA_PULSE = TU_BIT(6), +// OTGSC_HWASSIT_BDIS_ACONN = TU_BIT(7), + OTGSC_ID = TU_BIT(8), ///< 0 = A device, 1 = B Device + OTGSC_A_VBUS_VALID = TU_BIT(9), + OTGSC_A_SESSION_VALID = TU_BIT(10), + OTGSC_B_SESSION_VALID = TU_BIT(11), + OTGSC_B_SESSION_END = TU_BIT(12), + OTGSC_1MS_TOGGLE = TU_BIT(13), + OTGSC_DATA_BUS_PULSING_STATUS = TU_BIT(14), +}; + +// USBMode +enum { + USBMODE_CM_DEVICE = 2, + USBMODE_CM_HOST = 3, + + USBMODE_SLOM = TU_BIT(3), + USBMODE_SDIS = TU_BIT(4), + + USBMODE_VBUS_POWER_SELECT = TU_BIT(5), // Need to be enabled for LPC18XX/43XX in host mode +}; + +// Device Registers +typedef struct +{ + //------------- ID + HW Parameter Registers-------------// + __I uint32_t TU_RESERVED[64]; ///< For iMX RT10xx, but not used by LPC18XX/LPC43XX + + //------------- Capability Registers-------------// + __I uint8_t CAPLENGTH; ///< Capability Registers Length + __I uint8_t TU_RESERVED[1]; + __I uint16_t HCIVERSION; ///< Host Controller Interface Version + + __I uint32_t HCSPARAMS; ///< Host Controller Structural Parameters + __I uint32_t HCCPARAMS; ///< Host Controller Capability Parameters + __I uint32_t TU_RESERVED[5]; + + __I uint16_t DCIVERSION; ///< Device Controller Interface Version + __I uint8_t TU_RESERVED[2]; + + __I uint32_t DCCPARAMS; ///< Device Controller Capability Parameters + __I uint32_t TU_RESERVED[6]; + + //------------- Operational Registers -------------// + __IO uint32_t USBCMD; ///< USB Command Register + __IO uint32_t USBSTS; ///< USB Status Register + __IO uint32_t USBINTR; ///< Interrupt Enable Register + __IO uint32_t FRINDEX; ///< USB Frame Index + __I uint32_t TU_RESERVED; + __IO uint32_t DEVICEADDR; ///< Device Address + __IO uint32_t ENDPTLISTADDR; ///< Endpoint List Address + __I uint32_t TU_RESERVED; + __IO uint32_t BURSTSIZE; ///< Programmable Burst Size + __IO uint32_t TXFILLTUNING; ///< TX FIFO Fill Tuning + uint32_t TU_RESERVED[4]; + __IO uint32_t ENDPTNAK; ///< Endpoint NAK + __IO uint32_t ENDPTNAKEN; ///< Endpoint NAK Enable + __I uint32_t TU_RESERVED; + __IO uint32_t PORTSC1; ///< Port Status & Control + __I uint32_t TU_RESERVED[7]; + __IO uint32_t OTGSC; ///< On-The-Go Status & control + __IO uint32_t USBMODE; ///< USB Device Mode + __IO uint32_t ENDPTSETUPSTAT; ///< Endpoint Setup Status + __IO uint32_t ENDPTPRIME; ///< Endpoint Prime + __IO uint32_t ENDPTFLUSH; ///< Endpoint Flush + __I uint32_t ENDPTSTAT; ///< Endpoint Status + __IO uint32_t ENDPTCOMPLETE; ///< Endpoint Complete + __IO uint32_t ENDPTCTRL[8]; ///< Endpoint Control 0 - 7 +} dcd_registers_t; + +#ifdef __cplusplus + } +#endif + +#endif /* COMMON_TRANSDIMENSION_H_ */ diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 6f1923ec9..afc7184a0 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -32,9 +32,6 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ -#include "common/tusb_common.h" -#include "device/dcd.h" - #if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX #include "fsl_device_registers.h" #else @@ -42,6 +39,10 @@ #include "chip.h" #endif +#include "common/tusb_common.h" +#include "device/dcd.h" +#include "common_transdimension.h" + #if defined(__CORTEX_M) && __CORTEX_M == 7 && __DCACHE_PRESENT == 1 #define CleanInvalidateDCache_by_Addr SCB_CleanInvalidateDCache_by_Addr #else @@ -60,15 +61,6 @@ enum { ENDPTCTRL_ENABLE = TU_BIT(7) }; -// USBCMD -enum { - USBCMD_RUN_STOP = TU_BIT(0), - USBCMD_RESET = TU_BIT(1), - USBCMD_SETUP_TRIPWIRE = TU_BIT(13), - USBCMD_ADD_QTD_TRIPWIRE = TU_BIT(14) ///< This bit is used as a semaphore to ensure the to proper addition of a new dTD to an active (primed) endpoint’s linked list. This bit is set and cleared by software during the process of adding a new dTD -}; -// Interrupt Threshold bit 23:16 - // USBSTS, USBINTR enum { INTR_USB = TU_BIT(0), @@ -80,96 +72,6 @@ enum { INTR_NAK = TU_BIT(16) }; -// PORTSC1 -#define PORTSC1_PORT_SPEED_POS 26 - -enum { - PORTSC1_CURRENT_CONNECT_STATUS = TU_BIT(0), - PORTSC1_FORCE_PORT_RESUME = TU_BIT(6), - PORTSC1_SUSPEND = TU_BIT(7), - PORTSC1_FORCE_FULL_SPEED = TU_BIT(24), - PORTSC1_PORT_SPEED = TU_BIT(26) | TU_BIT(27) -}; - -// OTGSC -enum { - OTGSC_VBUS_DISCHARGE = TU_BIT(0), - OTGSC_VBUS_CHARGE = TU_BIT(1), -// OTGSC_HWASSIST_AUTORESET = TU_BIT(2), - OTGSC_OTG_TERMINATION = TU_BIT(3), ///< Must set to 1 when OTG go to device mode - OTGSC_DATA_PULSING = TU_BIT(4), - OTGSC_ID_PULLUP = TU_BIT(5), -// OTGSC_HWASSIT_DATA_PULSE = TU_BIT(6), -// OTGSC_HWASSIT_BDIS_ACONN = TU_BIT(7), - OTGSC_ID = TU_BIT(8), ///< 0 = A device, 1 = B Device - OTGSC_A_VBUS_VALID = TU_BIT(9), - OTGSC_A_SESSION_VALID = TU_BIT(10), - OTGSC_B_SESSION_VALID = TU_BIT(11), - OTGSC_B_SESSION_END = TU_BIT(12), - OTGSC_1MS_TOGGLE = TU_BIT(13), - OTGSC_DATA_BUS_PULSING_STATUS = TU_BIT(14), -}; - -// USBMode -enum { - USBMODE_CM_DEVICE = 2, - USBMODE_CM_HOST = 3, - - USBMODE_SLOM = TU_BIT(3), - USBMODE_SDIS = TU_BIT(4), - - USBMODE_VBUS_POWER_SELCT = TU_BIT(5), // Enable for LPC18XX/43XX in host most only -}; - -// Device Registers -typedef struct -{ - //------------- ID + HW Parameter Registers-------------// - __I uint32_t TU_RESERVED[64]; ///< For iMX RT10xx, but not used by LPC18XX/LPC43XX - - //------------- Capability Registers-------------// - __I uint8_t CAPLENGTH; ///< Capability Registers Length - __I uint8_t TU_RESERVED[1]; - __I uint16_t HCIVERSION; ///< Host Controller Interface Version - - __I uint32_t HCSPARAMS; ///< Host Controller Structural Parameters - __I uint32_t HCCPARAMS; ///< Host Controller Capability Parameters - __I uint32_t TU_RESERVED[5]; - - __I uint16_t DCIVERSION; ///< Device Controller Interface Version - __I uint8_t TU_RESERVED[2]; - - __I uint32_t DCCPARAMS; ///< Device Controller Capability Parameters - __I uint32_t TU_RESERVED[6]; - - //------------- Operational Registers -------------// - __IO uint32_t USBCMD; ///< USB Command Register - __IO uint32_t USBSTS; ///< USB Status Register - __IO uint32_t USBINTR; ///< Interrupt Enable Register - __IO uint32_t FRINDEX; ///< USB Frame Index - __I uint32_t TU_RESERVED; - __IO uint32_t DEVICEADDR; ///< Device Address - __IO uint32_t ENDPTLISTADDR; ///< Endpoint List Address - __I uint32_t TU_RESERVED; - __IO uint32_t BURSTSIZE; ///< Programmable Burst Size - __IO uint32_t TXFILLTUNING; ///< TX FIFO Fill Tuning - uint32_t TU_RESERVED[4]; - __IO uint32_t ENDPTNAK; ///< Endpoint NAK - __IO uint32_t ENDPTNAKEN; ///< Endpoint NAK Enable - __I uint32_t TU_RESERVED; - __IO uint32_t PORTSC1; ///< Port Status & Control - __I uint32_t TU_RESERVED[7]; - __IO uint32_t OTGSC; ///< On-The-Go Status & control - __IO uint32_t USBMODE; ///< USB Device Mode - __IO uint32_t ENDPTSETUPSTAT; ///< Endpoint Setup Status - __IO uint32_t ENDPTPRIME; ///< Endpoint Prime - __IO uint32_t ENDPTFLUSH; ///< Endpoint Flush - __I uint32_t ENDPTSTAT; ///< Endpoint Status - __IO uint32_t ENDPTCOMPLETE; ///< Endpoint Complete - __IO uint32_t ENDPTCTRL[8]; ///< Endpoint Control 0 - 7 -} dcd_registers_t; - - // Queue Transfer Descriptor typedef struct { @@ -279,7 +181,7 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(2048) static dcd_data_t _dcd_data; //--------------------------------------------------------------------+ -// CONTROLLER API +// Controller API //--------------------------------------------------------------------+ /// follows LPC43xx User Manual 23.10.3 diff --git a/src/portable/nxp/transdimension/hcd_transdimension.c b/src/portable/nxp/transdimension/hcd_transdimension.c index 62b14364d..e6b7afe8f 100644 --- a/src/portable/nxp/transdimension/hcd_transdimension.c +++ b/src/portable/nxp/transdimension/hcd_transdimension.c @@ -31,6 +31,9 @@ #if TUSB_OPT_HOST_ENABLED && \ (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX) +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ #if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX #include "fsl_device_registers.h" #else @@ -38,9 +41,17 @@ #include "chip.h" #endif +#include "common/tusb_common.h" +#include "common_transdimension.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +// TODO can be merged with dcd_controller_t typedef struct { - uint32_t regs_addr; // registers base + uint32_t regs_base; // registers base const IRQn_Type irqnum; // IRQ number }hcd_controller_t; @@ -49,27 +60,49 @@ typedef struct { // RT1010 and RT1020 only has 1 USB controller #if FSL_FEATURE_SOC_USBHS_COUNT == 1 - { .regs_addr = (uint32_t) &USB->USBCMD , .irqnum = USB_OTG1_IRQn } + { .regs_base = USB_BASE , .irqnum = USB_OTG1_IRQn } #else - { .regs_addr = (uint32_t) &USB1->USBCMD, .irqnum = USB_OTG1_IRQn }, - { .regs_addr = (uint32_t) &USB2->USBCMD, .irqnum = USB_OTG2_IRQn } + { .regs_base = USB1_BASE, .irqnum = USB_OTG1_IRQn }, + { .regs_base = USB2_BASE, .irqnum = USB_OTG2_IRQn } #endif }; #else static const hcd_controller_t _hcd_controller[] = { - { .regs_addr = (uint32_t) &LPC_USB0->USBCMD_H, .irqnum = USB0_IRQn }, - { .regs_addr = (uint32_t) &LPC_USB1->USBCMD_H, .irqnum = USB1_IRQn } + { .regs_base = LPC_USB0_BASE, .irqnum = USB0_IRQn }, + { .regs_base = LPC_USB1_BASE, .irqnum = USB1_IRQn } }; #endif - // TODO better prototype later extern bool hcd_ehci_init (uint8_t rhport); // from ehci.c +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ + bool hcd_init(uint8_t rhport) { + dcd_registers_t* dcd_reg = (dcd_registers_t*) _hcd_controller[rhport].regs_base; + + // Reset controller + dcd_reg->USBCMD |= USBCMD_RESET; + while( dcd_reg->USBCMD & USBCMD_RESET ) {} + + // Set mode to device, must be set immediately after reset +#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX + // LPC18XX/43XX need to set VBUS Power Select to HIGH + // RHPORT1 is fullspeed only (need external PHY for Highspeed) + dcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT; + if (rhport == 1) dcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; +#else + dcd_reg->USBMODE = USBMODE_CM_HOST; +#endif + + // FIXME force full speed, still have issue with Highspeed enumeration + dcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; + return hcd_ehci_init(rhport); } @@ -85,7 +118,10 @@ void hcd_int_disable(uint8_t rhport) uint32_t hcd_ehci_register_addr(uint8_t rhport) { - return _hcd_controller[rhport].regs_addr; + dcd_registers_t* hcd_reg = (dcd_registers_t*) _hcd_controller[rhport].regs_base; + + // EHCI USBCMD has same address within dcd_register_t + return (uint32_t) &hcd_reg->USBCMD; } #endif -- cgit v1.3.1 From 592d047936544af03e7704ad7a88acef88fd6aee Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Mon, 22 Feb 2021 20:53:16 -0600 Subject: rp2040: correctly size variables to reduce RAM usage --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 10 +++++----- src/portable/raspberrypi/rp2040/rp2040_usb.c | 9 ++++----- src/portable/raspberrypi/rp2040/rp2040_usb.h | 12 ++++++++---- 3 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 95b0963a3..d329d40c3 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -48,8 +48,8 @@ // Init these in dcd_init static uint8_t *next_buffer_ptr; -// Endpoints 0-15, direction 0 for out and 1 for in. -static struct hw_endpoint hw_endpoints[16][2] = {0}; +// Endpoints 0-TUD_OPT_RP2040_USB_MAX_ENDPOINTS, direction 0 for out and 1 for in. +static struct hw_endpoint hw_endpoints[TUD_OPT_RP2040_USB_MAX_ENDPOINTS][2] = {0}; static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, uint8_t in) { @@ -64,7 +64,7 @@ static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr) } static void _hw_endpoint_alloc(struct hw_endpoint *ep) { - uint size = TU_MIN(64, ep->wMaxPacketSize); + uint16_t size = TU_MIN(64, ep->wMaxPacketSize); // Assumes single buffered for now ep->hw_data_buf = next_buffer_ptr; @@ -99,7 +99,7 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep) *ep->endpoint_control = reg; } -static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint wMaxPacketSize, uint8_t transfer_type) +static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { uint8_t num = tu_edpt_number(ep_addr); bool in = ep_addr & TUSB_DIR_IN_MASK; @@ -194,7 +194,7 @@ static void hw_endpoint_close(uint8_t ep_addr) } #endif -static void hw_endpoint_init(uint8_t ep_addr, uint wMaxPacketSize, uint8_t bmAttributes) +static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t bmAttributes) { struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); _hw_endpoint_init(ep, ep_addr, wMaxPacketSize, bmAttributes); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 339297ad6..ecd474695 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -30,7 +30,6 @@ #include #include "rp2040_usb.h" -#include "hardware/clocks.h" // Direction strings for debug const char *ep_dir_string[] = { @@ -153,7 +152,7 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t // Fill in info now that we're kicking off the hw ep->total_len = total_len; ep->len = 0; - ep->transfer_size = tu_min32(total_len, ep->wMaxPacketSize); + ep->transfer_size = tu_min16(total_len, ep->wMaxPacketSize); ep->active = true; ep->user_buf = buffer; // Recalculate if this is the last buffer @@ -172,7 +171,7 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) // Get the buffer state and amount of bytes we have // transferred uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); - uint transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; + uint16_t transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; #ifdef RP2040_USB_HOST_MODE // tag::host_buf_sel_fix[] @@ -230,8 +229,8 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) _hw_endpoint_xfer_sync(ep); // Now we have synced our state with the hardware. Is there more data to transfer? - uint remaining_bytes = ep->total_len - ep->len; - ep->transfer_size = tu_min32(remaining_bytes, ep->wMaxPacketSize); + uint16_t remaining_bytes = ep->total_len - ep->len; + ep->transfer_size = tu_min16(remaining_bytes, ep->wMaxPacketSize); _hw_endpoint_update_last_buf(ep); // Can happen because of programmer error so check for it diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 7c3234e8d..be9b507c2 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -16,6 +16,10 @@ #define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX #endif +#if !defined(TUD_OPT_RP2040_USB_MAX_ENDPOINTS) +#define TUD_OPT_RP2040_USB_MAX_ENDPOINTS 16 +#endif + // For memset #include @@ -67,10 +71,10 @@ struct hw_endpoint // Current transfer information bool active; - uint total_len; - uint len; + uint16_t total_len; + uint16_t len; // Amount of data with the hardware - uint transfer_size; + uint16_t transfer_size; // Only needed for host mode bool last_buf; // HOST BUG. Host will incorrect write status to top half of buffer @@ -80,7 +84,7 @@ struct hw_endpoint uint8_t *user_buf; // Data needed from EP descriptor - uint wMaxPacketSize; + uint16_t wMaxPacketSize; // Interrupt, bulk, etc uint8_t transfer_type; -- cgit v1.3.1 From f2ed2ae09a480835eacf049d8959b3c904713be7 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Feb 2021 11:14:19 +0700 Subject: rename tuh_msc_scsi_inquiry() to tuh_msc_inquiry() --- examples/host/cdc_msc_hid/src/msc_app.c | 2 +- src/class/msc/msc_host.c | 2 +- src/class/msc/msc_host.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index a45fba737..5e2ea308a 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -82,7 +82,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr) block_size = block_count = 0; uint8_t const lun = 0; - tuh_msc_scsi_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb); + tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb); // // //------------- file system (only 1 LUN support) -------------// // uint8_t phy_disk = dev_addr-1; diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 02ca81e77..9a44d0632 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -139,7 +139,7 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb); } -bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) +bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) { msc_cbw_t cbw = { 0 }; diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 5913350b8..61f6e6a21 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -70,7 +70,7 @@ uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); // Carry out SCSI INQUIRY command in non-blocking manner. -bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); +bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); // Carry out SCSI REQUEST SENSE (10) command in non-blocking manner. bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); -- cgit v1.3.1 From ade4bf74ea7343bcebff4c1b2bbd1ebaac9009c0 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Feb 2021 11:38:15 +0700 Subject: update function comment --- src/class/msc/msc_host.h | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 61f6e6a21..3d1963701 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -51,34 +51,27 @@ typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, ms // This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb() bool tuh_msc_mounted(uint8_t dev_addr); -/** \brief Check if the interface is currently busy or not - * \param[in] dev_addr device address - * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device - * \retval false if the interface is not busy meaning the stack successfully transferred data from/to device - * \note This function is used to check if previous transfer is complete (success or error), so that the next transfer - * can be scheduled. User needs to make sure the corresponding interface is mounted (by \ref tuh_msc_is_mounted) - * before calling this function - */ -bool tuh_msc_is_busy(uint8_t dev_addr); +// Check if the interface is currently busy transferring data +bool tuh_msc_is_busy(uint8_t dev_addr); // Get Max Lun uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); -// Carry out a full SCSI command (cbw, data, csw) in non-blocking manner. +// Perform a full SCSI command (cbw, data, csw) in non-blocking manner. // `complete_cb` callback is invoked when SCSI op is complete. // return true if success, false if there is already pending operation. bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); -// Carry out SCSI INQUIRY command in non-blocking manner. +// Perform SCSI Inquiry command bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); -// Carry out SCSI REQUEST SENSE (10) command in non-blocking manner. +// Perform SCSI Test Unit Ready command bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); -// Carry out SCSI REQUEST SENSE (10) command in non-blocking manner. +// Perform SCSI Request Sense (10) command bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); -// Carry out SCSI READ CAPACITY (10) command in non-blocking manner. +// Perform SCSI Read Capacity (10) command bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); #if 0 -- cgit v1.3.1 From 386a386345fbaa1a9c63a4346c2d946fe015da72 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Feb 2021 12:20:30 +0700 Subject: clean up host msc --- src/class/msc/msc_host.c | 91 +++++++++++++++++++++++------------------------- src/class/msc/msc_host.h | 38 ++++++++------------ 2 files changed, 57 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index ce3693dcb..943dc541f 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -99,11 +99,12 @@ bool tuh_msc_is_busy(uint8_t dev_addr) //--------------------------------------------------------------------+ // PUBLIC API: SCSI COMMAND //--------------------------------------------------------------------+ -static inline void msc_cbw_add_signature(msc_cbw_t *p_cbw, uint8_t lun) +static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun) { - p_cbw->signature = MSC_CBW_SIGNATURE; - p_cbw->tag = 0x54555342; // TUSB - p_cbw->lun = lun; + tu_memclr(cbw, sizeof(msc_cbw_t)); + cbw->signature = MSC_CBW_SIGNATURE; + cbw->tag = 0x54555342; // TUSB + cbw->lun = lun; } bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb) @@ -126,11 +127,11 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb) { msch_interface_t* p_msc = get_itf(dev_addr); - if ( !p_msc->mounted ) return false; + TU_VERIFY(p_msc->mounted); - msc_cbw_t cbw = { 0 }; + msc_cbw_t cbw; + cbw_init(&cbw, lun); - msc_cbw_add_signature(&cbw, lun); cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); cbw.dir = TUSB_DIR_IN_MASK; cbw.cmd_len = sizeof(scsi_read_capacity10_t); @@ -141,9 +142,9 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) { - msc_cbw_t cbw = { 0 }; + msc_cbw_t cbw; + cbw_init(&cbw, lun); - msc_cbw_add_signature(&cbw, lun); cbw.total_bytes = sizeof(scsi_inquiry_resp_t); cbw.dir = TUSB_DIR_IN_MASK; cbw.cmd_len = sizeof(scsi_inquiry_t); @@ -160,8 +161,8 @@ bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* respons bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) { - msc_cbw_t cbw = { 0 }; - msc_cbw_add_signature(&cbw, lun); + msc_cbw_t cbw; + cbw_init(&cbw, lun); cbw.total_bytes = 0; // Number of bytes cbw.dir = TUSB_DIR_OUT; @@ -174,8 +175,8 @@ bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb) { - msc_cbw_t cbw = { 0 }; - msc_cbw_add_signature(&cbw, lun); + msc_cbw_t cbw; + cbw_init(&cbw, lun); cbw.total_bytes = 18; // TODO sense response cbw.dir = TUSB_DIR_IN_MASK; @@ -192,58 +193,52 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_ms return tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb); } -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) +bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) { msch_interface_t* p_msc = get_itf(dev_addr); - if ( !p_msc->mounted ){ return false;}; + TU_VERIFY(p_msc->mounted); - msc_cbw_t cbw = { 0 }; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&cbw, lun); + msc_cbw_t cbw; + cbw_init(&cbw, lun); - cbw.total_bytes = 512*block_count; // Number of bytes + cbw.total_bytes = 512*block_count; // Number of bytes TODO get block size from READ CAPACITY 10 cbw.dir = TUSB_DIR_IN_MASK; cbw.cmd_len = sizeof(scsi_read10_t); - //------------- SCSI command -------------// scsi_read10_t cmd_read10 = { - .cmd_code = SCSI_CMD_READ_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) + .cmd_code = SCSI_CMD_READ_10, + .lba = tu_htonl(lba), + .block_count = tu_htons(block_count) }; memcpy(cbw.command, &cmd_read10, cbw.cmd_len); - return tuh_msc_scsi_command(dev_addr, &cbw, p_buffer, complete_cb); + return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb); } -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) +bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msc = get_itf(dev_addr); - if ( !p_msc->mounted ){ return false;}; - - msc_cbw_t cbw = { 0 }; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&cbw, lun); - - cbw.total_bytes = 512*block_count; // Number of bytes - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_write10_t); + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->mounted); - //------------- SCSI command -------------// - scsi_write10_t cmd_write10 = - { - .cmd_code = SCSI_CMD_WRITE_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) - }; - - memcpy(cbw.command, &cmd_write10, cbw.cmd_len); - - return tuh_msc_scsi_command(dev_addr, &cbw, p_buffer, complete_cb); + msc_cbw_t cbw; + cbw_init(&cbw, lun); + + cbw.total_bytes = 512*block_count; // Number of bytes TODO get block size from READ CAPACITY 10 + cbw.dir = TUSB_DIR_OUT; + cbw.cmd_len = sizeof(scsi_write10_t); + + scsi_write10_t cmd_write10 = + { + .cmd_code = SCSI_CMD_WRITE_10, + .lba = tu_htonl(lba), + .block_count = tu_htons(block_count) + }; + + memcpy(cbw.command, &cmd_write10, cbw.cmd_len); + + return tuh_msc_scsi_command(dev_addr, &cbw, (void*) buffer, complete_cb); } #if 0 diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index d80e3e44d..b6ead28c5 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -58,43 +58,33 @@ bool tuh_msc_is_busy(uint8_t dev_addr); uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); // Perform a full SCSI command (cbw, data, csw) in non-blocking manner. -// `complete_cb` callback is invoked when SCSI op is complete. +// Complete callback is invoked when SCSI op is complete. // return true if success, false if there is already pending operation. bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); // Perform SCSI Inquiry command +// Complete callback is invoked when SCSI op is complete. bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); // Perform SCSI Test Unit Ready command +// Complete callback is invoked when SCSI op is complete. bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb); -// Perform SCSI Request Sense (10) command +// Perform SCSI Request Sense 10 command +// Complete callback is invoked when SCSI op is complete. bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); -// Perform SCSI Read Capacity (10) command +// Perform SCSI Read Capacity 10 command +// Complete callback is invoked when SCSI op is complete. bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); -/** \brief Perform SCSI READ 10 command to read data from MassStorage device - * \param[in] dev_addr device address - * \param[in] lun Targeted Logical Unit - * \param[out] p_buffer Buffer used to store data read from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) - * \param[in] lba Starting Logical Block Address to be read - * \param[in] block_count Number of Block to be read - * \retval true on success - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by \ref complete_cb callback function - */ -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); - -/** \brief Perform SCSI WRITE 10 command to write data to MassStorage device - * \param[in] dev_addr device address - * \param[in] lun Targeted Logical Unit - * \param[in] p_buffer Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION) - * \param[in] lba Starting Logical Block Address to be written - * \param[in] block_count Number of Block to be written - * \retval true on success - * \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by \ref complete_cb callback function - */ -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); +// Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer +// Complete callback is invoked when SCSI op is complete. +bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); + +// Perform SCSI Write 10 command. Write n blocks starting from LBA to device +// Complete callback is invoked when SCSI op is complete. +bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); //------------- Application Callback -------------// -- cgit v1.3.1 From 5108d7613600449c50af9e8ce373571d56bed3cc Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Feb 2021 19:41:11 +0700 Subject: host msc: call read_capacity as part of enumeration - add tuh_msc_get_block_count(), tuh_msc_get_block_size() - rename tuh_msc_mounted_cb/tuh_msc_unmounted_cb to tuh_msc_mount_cb/tuh_msc_unmount_cb to match device stack naming - change tuh_msc_is_busy() to tuh_msc_ready() - add CFG_TUH_MSC_MAXLUN (default to 4) to hold lun capacities - add host msc configured to for state check. --- examples/host/cdc_msc_hid/src/msc_app.c | 46 ++--------- examples/obsolete/host/src/msc_host_app.c | 4 +- lib/fatfs/diskio.c | 2 +- src/class/msc/msc_host.c | 133 ++++++++++++++++++++---------- src/class/msc/msc_host.h | 33 ++++++-- 5 files changed, 125 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 5e2ea308a..623141eaa 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -31,31 +31,6 @@ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ static scsi_inquiry_resp_t inquiry_resp; -static scsi_read_capacity10_resp_t capacity_resp; - -uint32_t block_size; -uint32_t block_count; - -bool capacity_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) -{ - (void) dev_addr; - (void) cbw; - - if (csw->status != 0) - { - printf("Read Capacity (10) failed\r\n"); - return false; - } - - // Capacity response field: Block size and Last LBA are both Big-Endian - block_count = tu_ntohl(capacity_resp.last_lba) + 1; - block_size = tu_ntohl(capacity_resp.block_size); - - printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size)); - printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size); - - return true; -} bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) { @@ -68,19 +43,21 @@ bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const // Print out Vendor ID, Product ID and Rev printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev); - // Read capacity of device - tuh_msc_read_capacity(dev_addr, cbw->lun, &capacity_resp, capacity_complete_cb); + // Get capacity of device + uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun); + uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun); + + printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size)); + printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size); return true; } //------------- IMPLEMENTATION -------------// -void tuh_msc_mounted_cb(uint8_t dev_addr) +void tuh_msc_mount_cb(uint8_t dev_addr) { printf("A MassStorage device is mounted\r\n"); - block_size = block_count = 0; - uint8_t const lun = 0; tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb); // @@ -110,7 +87,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr) // } } -void tuh_msc_unmounted_cb(uint8_t dev_addr) +void tuh_msc_unmount_cb(uint8_t dev_addr) { (void) dev_addr; printf("A MassStorage device is unmounted\r\n"); @@ -133,11 +110,4 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr) // } } -//void tuh_msc_scsi_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) -//{ -// (void) dev_addr; -// (void) cbw; -// (void) csw; -//} - #endif diff --git a/examples/obsolete/host/src/msc_host_app.c b/examples/obsolete/host/src/msc_host_app.c index 8afb6ede8..5399e6620 100644 --- a/examples/obsolete/host/src/msc_host_app.c +++ b/examples/obsolete/host/src/msc_host_app.c @@ -48,7 +48,7 @@ CFG_TUSB_MEM_SECTION static FATFS fatfs[CFG_TUSB_HOST_DEVICE_MAX]; //--------------------------------------------------------------------+ // tinyusb callbacks //--------------------------------------------------------------------+ -void tuh_msc_mounted_cb(uint8_t dev_addr) +void tuh_msc_mount_cb(uint8_t dev_addr) { puts("\na MassStorage device is mounted"); @@ -94,7 +94,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr) } } -void tuh_msc_unmounted_cb(uint8_t dev_addr) +void tuh_msc_unmount_cb(uint8_t dev_addr) { puts("\na MassStorage device is unmounted"); diff --git a/lib/fatfs/diskio.c b/lib/fatfs/diskio.c index 38503148d..401f583a2 100644 --- a/lib/fatfs/diskio.c +++ b/lib/fatfs/diskio.c @@ -48,7 +48,7 @@ static DSTATUS disk_state[CFG_TUSB_HOST_DEVICE_MAX]; static DRESULT wait_for_io_complete(uint8_t usb_addr) { // TODO with RTOS, this should use semaphore instead of blocking - while ( tuh_msc_is_busy(usb_addr) ) + while ( !tuh_msc_ready(usb_addr) ) { // TODO should have timeout here #if CFG_TUSB_OS != OPT_OS_NONE diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 943dc541f..34dbec2e3 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -47,14 +47,21 @@ enum typedef struct { - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; - uint8_t max_lun; + uint8_t max_lun; - volatile bool mounted; + volatile bool configured; // Receive SET_CONFIGURE + volatile bool mounted; // Enumeration is complete + struct { + uint32_t block_size; + uint32_t block_count; + } capacity[CFG_TUH_MSC_MAXLUN]; + + //------------- SCSI -------------// uint8_t stage; void* buffer; tuh_msc_complete_cb_t complete_cb; @@ -63,14 +70,15 @@ typedef struct msc_csw_t csw; }msch_interface_t; -CFG_TUSB_MEM_SECTION static msch_interface_t msch_data[CFG_TUSB_HOST_DEVICE_MAX]; +CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUSB_HOST_DEVICE_MAX]; -// buffer used to read scsi information when mounted, largest response data currently is inquiry -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msch_buffer[sizeof(scsi_inquiry_resp_t)]; +// buffer used to read scsi information when mounted +// largest response data currently is inquiry TODO Inquiry is not part of enum anymore +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; static inline msch_interface_t* get_itf(uint8_t dev_addr) { - return &msch_data[dev_addr-1]; + return &_msch_itf[dev_addr-1]; } //--------------------------------------------------------------------+ @@ -82,18 +90,28 @@ uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) return p_msc->max_lun; } -bool tuh_msc_mounted(uint8_t dev_addr) +uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun) { msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->capacity[lun].block_count; +} - // is configured can be omitted - return tuh_device_is_configured(dev_addr) && p_msc->mounted; +uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->capacity[lun].block_size; +} + +bool tuh_msc_mounted(uint8_t dev_addr) +{ + msch_interface_t* p_msc = get_itf(dev_addr); + return p_msc->mounted; } -bool tuh_msc_is_busy(uint8_t dev_addr) +bool tuh_msc_ready(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted && hcd_edpt_busy(dev_addr, p_msc->ep_in); + return p_msc->mounted && !hcd_edpt_busy(dev_addr, p_msc->ep_in); } //--------------------------------------------------------------------+ @@ -110,7 +128,7 @@ static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun) bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb) { msch_interface_t* p_msc = get_itf(dev_addr); - // TU_VERIFY(p_msc->mounted); // TODO part of the enumeration also use scsi command + TU_VERIFY(p_msc->configured); // TODO claim endpoint @@ -126,8 +144,8 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->mounted); + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->configured); msc_cbw_t cbw; cbw_init(&cbw, lun); @@ -142,6 +160,9 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) { + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->mounted); + msc_cbw_t cbw; cbw_init(&cbw, lun); @@ -161,14 +182,17 @@ bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* respons bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) { + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->configured); + msc_cbw_t cbw; cbw_init(&cbw, lun); - cbw.total_bytes = 0; // Number of bytes - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_test_unit_ready_t); - cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; - cbw.command[1] = lun; // according to wiki TODO need verification + cbw.total_bytes = 0; + cbw.dir = TUSB_DIR_OUT; + cbw.cmd_len = sizeof(scsi_test_unit_ready_t); + cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; + cbw.command[1] = lun; // according to wiki TODO need verification return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb); } @@ -179,8 +203,8 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_ms cbw_init(&cbw, lun); cbw.total_bytes = 18; // TODO sense response - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_request_sense_t); + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_request_sense_t); scsi_request_sense_t const cmd_request_sense = { @@ -201,11 +225,11 @@ bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, msc_cbw_t cbw; cbw_init(&cbw, lun); - cbw.total_bytes = 512*block_count; // Number of bytes TODO get block size from READ CAPACITY 10 - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_read10_t); + cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_read10_t); - scsi_read10_t cmd_read10 = + scsi_read10_t const cmd_read10 = { .cmd_code = SCSI_CMD_READ_10, .lba = tu_htonl(lba), @@ -225,11 +249,11 @@ bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_ msc_cbw_t cbw; cbw_init(&cbw, lun); - cbw.total_bytes = 512*block_count; // Number of bytes TODO get block size from READ CAPACITY 10 - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_write10_t); + cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; + cbw.dir = TUSB_DIR_OUT; + cbw.cmd_len = sizeof(scsi_write10_t); - scsi_write10_t cmd_write10 = + scsi_write10_t const cmd_write10 = { .cmd_code = SCSI_CMD_WRITE_10, .lba = tu_htonl(lba), @@ -267,14 +291,14 @@ bool tuh_msc_reset(uint8_t dev_addr) //--------------------------------------------------------------------+ void msch_init(void) { - tu_memclr(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(_msch_itf, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); } void msch_close(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); tu_memclr(p_msc, sizeof(msch_interface_t)); - tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback + tuh_msc_unmount_cb(dev_addr); // invoke Application Callback } bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) @@ -331,6 +355,7 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); +static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) { @@ -369,6 +394,8 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) msch_interface_t* p_msc = get_itf(dev_addr); TU_ASSERT(p_msc->itf_num == itf_num); + p_msc->configured = true; + //------------- Get Max Lun -------------// TU_LOG2("MSC Get Max Lun\r\n"); tusb_control_request_t request = @@ -396,12 +423,13 @@ static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t msch_interface_t* p_msc = get_itf(dev_addr); // STALL means zero - p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? msch_buffer[0] : 0; + p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? _msch_buffer[0] : 0; p_msc->max_lun++; // MAX LUN is minus 1 by specs // TODO multiple LUN support TU_LOG2("SCSI Test Unit Ready\r\n"); - tuh_msc_test_unit_ready(dev_addr, 0, config_test_unit_ready_complete); + uint8_t const lun = 0; + tuh_msc_test_unit_ready(dev_addr, lun, config_test_unit_ready_complete); return true; } @@ -410,19 +438,16 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c { if (csw->status == 0) { - msch_interface_t* p_msc = get_itf(dev_addr); - - usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); - - // Unit is ready, Enumeration is complete - p_msc->mounted = true; - tuh_msc_mounted_cb(dev_addr); + // Unit is ready, read its capacity + TU_LOG2("SCSI Read Capacity\r\n"); + tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) _msch_buffer, config_read_capacity_complete); }else { // Note: During enumeration, some device fails Test Unit Ready and require a few retries // with Request Sense to start working !! // TODO limit number of retries - TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, msch_buffer, config_request_sense_complete)); + TU_LOG2("SCSI Request Sense\r\n"); + TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, _msch_buffer, config_request_sense_complete)); } return true; @@ -435,4 +460,24 @@ static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw return true; } +static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +{ + TU_ASSERT(csw->status == 0); + + msch_interface_t* p_msc = get_itf(dev_addr); + + // Capacity response field: Block size and Last LBA are both Big-Endian + scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) _msch_buffer; + p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1; + p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size); + + // Mark enumeration is complete + p_msc->mounted = true; + tuh_msc_mount_cb(dev_addr); + + usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); + + return true; +} + #endif diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index b6ead28c5..8116e729f 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -35,6 +35,15 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUH_MSC_MAXLUN +#define CFG_TUH_MSC_MAXLUN 4 +#endif + + /** \addtogroup ClassDriver_MSC * @{ * \defgroup MSC_Host Host @@ -51,12 +60,18 @@ typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, ms // This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb() bool tuh_msc_mounted(uint8_t dev_addr); -// Check if the interface is currently busy transferring data -bool tuh_msc_is_busy(uint8_t dev_addr); +// Check if the interface is currently ready or busy transferring data +bool tuh_msc_ready(uint8_t dev_addr); // Get Max Lun uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); +// Get number of block +uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun); + +// Get block size in bytes +uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun); + // Perform a full SCSI command (cbw, data, csw) in non-blocking manner. // Complete callback is invoked when SCSI op is complete. // return true if success, false if there is already pending operation. @@ -74,10 +89,6 @@ bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_ // Complete callback is invoked when SCSI op is complete. bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb); -// Perform SCSI Read Capacity 10 command -// Complete callback is invoked when SCSI op is complete. -bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); - // Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer // Complete callback is invoked when SCSI op is complete. bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); @@ -86,13 +97,19 @@ bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, // Complete callback is invoked when SCSI op is complete. bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb); +// Perform SCSI Read Capacity 10 command +// Complete callback is invoked when SCSI op is complete. +// Note: during enumeration, host stack already carried out this request. Application can retrieve capacity by +// simply call tuh_msc_get_block_count() and tuh_msc_get_block_size() +bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); + //------------- Application Callback -------------// // Invoked when a device with MassStorage interface is mounted -void tuh_msc_mounted_cb(uint8_t dev_addr); +void tuh_msc_mount_cb(uint8_t dev_addr); // Invoked when a device with MassStorage interface is unmounted -void tuh_msc_unmounted_cb(uint8_t dev_addr); +void tuh_msc_unmount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API -- cgit v1.3.1 From 0de6a05d73ca79974bc45f5cfa94b2246113c1f1 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Feb 2021 19:45:53 +0700 Subject: fix ohci hcd_init() signature change --- src/host/ohci/ohci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index d9bbfc8c6..44acebf72 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -141,8 +141,10 @@ static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr); // USBH-HCD API //--------------------------------------------------------------------+ // Initialization according to 5.1.1.4 -bool hcd_init(void) +bool hcd_init(uint8_t rhport) { + (void) rhport; + //------------- Data Structure init -------------// tu_memclr(&ohci_data, sizeof(ohci_data_t)); for(uint8_t i=0; i<32; i++) -- cgit v1.3.1 From 5a8ae31316ed30937e910e376dc6f62e8e4e3433 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Tue, 23 Feb 2021 10:08:38 -0600 Subject: rp2040: leverage existing macro for capping endpoints in pico-sdk --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 4 ++-- src/portable/raspberrypi/rp2040/rp2040_usb.h | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index d329d40c3..9c43b6fdb 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -48,8 +48,8 @@ // Init these in dcd_init static uint8_t *next_buffer_ptr; -// Endpoints 0-TUD_OPT_RP2040_USB_MAX_ENDPOINTS, direction 0 for out and 1 for in. -static struct hw_endpoint hw_endpoints[TUD_OPT_RP2040_USB_MAX_ENDPOINTS][2] = {0}; +// USB_MAX_ENDPOINTS Endpoints, direction 0 for out and 1 for in. +static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2] = {0}; static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, uint8_t in) { diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index be9b507c2..522d7d701 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -16,10 +16,6 @@ #define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX #endif -#if !defined(TUD_OPT_RP2040_USB_MAX_ENDPOINTS) -#define TUD_OPT_RP2040_USB_MAX_ENDPOINTS 16 -#endif - // For memset #include -- cgit v1.3.1 From 451650fa32b245f2dc02c366b25fa802b75fbb1b Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Feb 2021 23:09:48 +0700 Subject: move ehci and ohci to portable folder --- examples/host/cdc_msc_hid/Makefile | 4 +- examples/host/cdc_msc_hid/src/msc_app.c | 7 - src/host/ehci/ehci.c | 901 -------------------------------- src/host/ehci/ehci.h | 462 ---------------- src/host/ohci/ohci.c | 686 ------------------------ src/host/ohci/ohci.h | 293 ----------- src/portable/ehci/ehci.c | 901 ++++++++++++++++++++++++++++++++ src/portable/ehci/ehci.h | 460 ++++++++++++++++ src/portable/ohci/ohci.c | 688 ++++++++++++++++++++++++ src/portable/ohci/ohci.h | 291 +++++++++++ 10 files changed, 2342 insertions(+), 2351 deletions(-) delete mode 100644 src/host/ehci/ehci.c delete mode 100644 src/host/ehci/ehci.h delete mode 100644 src/host/ohci/ohci.c delete mode 100644 src/host/ohci/ohci.h create mode 100644 src/portable/ehci/ehci.c create mode 100644 src/portable/ehci/ehci.h create mode 100644 src/portable/ohci/ohci.c create mode 100644 src/portable/ohci/ohci.h (limited to 'src') diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index 3a0e94d73..6a2b4d902 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -19,8 +19,8 @@ SRC_C += \ src/host/hub.c \ src/host/usbh.c \ src/host/usbh_control.c \ - src/host/ehci/ehci.c \ - src/host/ohci/ohci.c \ + src/portable/ehci/ehci.c \ + src/portable/ohci/ohci.c \ src/portable/nxp/transdimension/hcd_transdimension.c \ src/portable/nxp/lpc17_40/hcd_lpc17_40.c diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 623141eaa..3a8ef3a07 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -73,13 +73,6 @@ void tuh_msc_mount_cb(uint8_t dev_addr) // return; // } // -// puts("---------------------------------------------------------------------"); -// puts("- MASSSTORAGE CLASS CLI IS A IMMATURE CODE. DISK-WRITING COMMANDS"); -// puts("- SUCH AS cp(COPY), mkdir(MAKE DIRECTORY) ARE POTENTIAL TO DAMAGE"); -// puts("- YOUR USB THUMBDRIVE. USING THOSE COMMANDS ARE AT YOUR OWN RISK."); -// puts("- THE AUTHOR HAS NO RESPONSIBILITY WITH YOUR DEVICE NOR ITS DATA"); -// puts("---------------------------------------------------------------------"); -// // f_chdrive(phy_disk); // change to newly mounted drive // f_chdir("/"); // root as current dir // diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c deleted file mode 100644 index 5626abcc8..000000000 --- a/src/host/ehci/ehci.c +++ /dev/null @@ -1,901 +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. - * - * This file is part of the TinyUSB stack. - */ - -#include "common/tusb_common.h" - -#if TUSB_OPT_HOST_ENABLED && \ - (CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ - CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX ) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "osal/osal.h" - -#include "../hcd.h" -#include "../usbh_hcd.h" -#include "ehci.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -// Periodic frame list must be 4K alignment -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data; - -// EHCI portable -uint32_t hcd_ehci_register_addr(uint8_t rhport); -bool hcd_ehci_init (uint8_t rhport); // TODO move later - -//--------------------------------------------------------------------+ -// PROTOTYPE -//--------------------------------------------------------------------+ -static inline ehci_link_t* get_period_head(uint8_t rhport, uint8_t interval_ms) -{ - (void) rhport; - return (ehci_link_t*) &ehci_data.period_head_arr[ tu_log2( tu_min8(EHCI_FRAMELIST_SIZE, interval_ms) ) ]; -} - -static inline ehci_qhd_t* qhd_control(uint8_t dev_addr) -{ - return &ehci_data.control[dev_addr].qhd; -} - -static inline ehci_qhd_t* qhd_async_head(uint8_t rhport) -{ - (void) rhport; - return qhd_control(0); // control qhd of dev0 is used as async head -} - -static inline ehci_qtd_t* qtd_control(uint8_t dev_addr) -{ - return &ehci_data.control[dev_addr].qtd; -} - - -static inline ehci_qhd_t* qhd_next (ehci_qhd_t const * p_qhd); -static inline ehci_qhd_t* qhd_find_free (void); -static inline ehci_qhd_t* qhd_get_from_addr (uint8_t dev_addr, uint8_t ep_addr); - -// determine if a queue head has bus-related error -static inline bool qhd_has_xact_error (ehci_qhd_t * p_qhd) -{ - return (p_qhd->qtd_overlay.buffer_err || p_qhd->qtd_overlay.babble_err || p_qhd->qtd_overlay.xact_err); - //p_qhd->qtd_overlay.non_hs_period_missed_uframe || p_qhd->qtd_overlay.pingstate_err TODO split transaction error -} - -static void qhd_init (ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); - -static inline ehci_qtd_t* qtd_find_free (void); -static inline ehci_qtd_t* qtd_next (ehci_qtd_t const * p_qtd); -static inline void qtd_insert_to_qhd (ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new); -static inline void qtd_remove_1st_from_qhd (ehci_qhd_t *p_qhd); -static void qtd_init (ehci_qtd_t* p_qtd, void* buffer, uint16_t total_bytes); - -static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type); -static inline ehci_link_t* list_next (ehci_link_t *p_link_pointer); - -//--------------------------------------------------------------------+ -// HCD API -//--------------------------------------------------------------------+ - -uint32_t hcd_uframe_number(uint8_t rhport) -{ - (void) rhport; - return ehci_data.uframe_number + ehci_data.regs->frame_index; -} - -void hcd_port_reset(uint8_t rhport) -{ - (void) rhport; - - ehci_registers_t* regs = ehci_data.regs; - -// regs->portsc_bm.port_enabled = 0; // disable port before reset -// regs->portsc_bm.port_reset = 1; - - uint32_t portsc = regs->portsc; - - portsc &= ~(EHCI_PORTSC_MASK_PORT_EANBLED); - portsc |= EHCI_PORTSC_MASK_PORT_RESET; - - regs->portsc = portsc; -} - -#if 0 -void hcd_port_reset_end(uint8_t rhport) -{ - (void) rhport; - - ehci_registers_t* regs = ehci_data.regs; - regs->portsc_bm.port_reset = 0; -} -#endif - -bool hcd_port_connect_status(uint8_t rhport) -{ - (void) rhport; - return ehci_data.regs->portsc_bm.current_connect_status; -} - -tusb_speed_t hcd_port_speed_get(uint8_t rhport) -{ - (void) rhport; - return (tusb_speed_t) ehci_data.regs->portsc_bm.nxp_port_speed; // NXP specific port speed -} - -static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr) -{ - for(ehci_link_t* prev = list_head; - !prev->terminate && (tu_align32(prev->address) != (uint32_t) list_head); - prev = list_next(prev) ) - { - // TODO check type for ISO iTD and siTD - ehci_qhd_t* qhd = (ehci_qhd_t*) list_next(prev); - if ( qhd->dev_addr == dev_addr ) - { - // TODO deactive all TD, wait for QHD to inactive before removal - prev->address = qhd->next.address; - - // EHCI 4.8.2 link the removed qhd to async head (which always reachable by Host Controller) - qhd->next.address = ((uint32_t) list_head) | (EHCI_QTYPE_QHD << 1); - - if ( qhd->int_smask ) - { - // period list queue element is guarantee to be free in the next frame (1 ms) - qhd->used = 0; - }else - { - // async list use async advance handshake - // mark as removing, will completely re-usable when async advance isr occurs - qhd->removing = 1; - } - } - } -} - -// Close all opened endpoint belong to this device -void hcd_device_close(uint8_t rhport, uint8_t dev_addr) -{ - // skip dev0 - if (dev_addr == 0) return; - - // Remove from async list - list_remove_qhd_by_addr( (ehci_link_t*) qhd_async_head(rhport), dev_addr ); - - // Remove from all interval period list - for(uint8_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++) - { - list_remove_qhd_by_addr( (ehci_link_t*) &ehci_data.period_head_arr[i], dev_addr); - } - - // Async doorbell (EHCI 4.8.2 for operational details) - ehci_data.regs->command_bm.async_adv_doorbell = 1; -} - -// EHCI controller init -bool hcd_ehci_init(uint8_t rhport) -{ - tu_memclr(&ehci_data, sizeof(ehci_data_t)); - - ehci_data.regs = (ehci_registers_t* ) hcd_ehci_register_addr(rhport); - - ehci_registers_t* regs = ehci_data.regs; - - //------------- CTRLDSSEGMENT Register (skip) -------------// - //------------- USB INT Register -------------// - regs->inten = 0; // 1. disable all the interrupt - regs->status = EHCI_INT_MASK_ALL; // 2. clear all status - - regs->inten = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE | EHCI_INT_MASK_ASYNC_ADVANCE | - EHCI_INT_MASK_NXP_PERIODIC | EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_FRAMELIST_ROLLOVER; - - //------------- Asynchronous List -------------// - ehci_qhd_t * const async_head = qhd_async_head(rhport); - tu_memclr(async_head, sizeof(ehci_qhd_t)); - - async_head->next.address = (uint32_t) async_head; // circular list, next is itself - async_head->next.type = EHCI_QTYPE_QHD; - async_head->head_list_flag = 1; - async_head->qtd_overlay.halted = 1; // inactive most of time - async_head->qtd_overlay.next.terminate = 1; // TODO removed if verified - - regs->async_list_addr = (uint32_t) async_head; - - //------------- Periodic List -------------// - // Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only - for(uint32_t i=0; i<4; i++) - { - ehci_data.period_head_arr[i].int_smask = 1; // queue head in period list must have smask non-zero - ehci_data.period_head_arr[i].qtd_overlay.halted = 1; // dummy node, always inactive - } - - ehci_link_t * const framelist = ehci_data.period_framelist; - ehci_link_t * const period_1ms = get_period_head(rhport, 1); - // all links --> period_head_arr[0] (1ms) - // 0, 2, 4, 6 etc --> period_head_arr[1] (2ms) - // 1, 5 --> period_head_arr[2] (4ms) - // 3 --> period_head_arr[3] (8ms) - - // TODO EHCI_FRAMELIST_SIZE with other size than 8 - for(uint32_t i=0; iterminate = 1; - - regs->periodic_list_base = (uint32_t) framelist; - - //------------- TT Control (NXP only) -------------// - regs->nxp_tt_control = 0; - - //------------- USB CMD Register -------------// - regs->command |= TU_BIT(EHCI_USBCMD_POS_RUN_STOP) | TU_BIT(EHCI_USBCMD_POS_ASYNC_ENABLE) - | TU_BIT(EHCI_USBCMD_POS_PERIOD_ENABLE) // TODO enable period list only there is int/iso endpoint - | ((EHCI_CFG_FRAMELIST_SIZE_BITS & TU_BIN8(011)) << EHCI_USBCMD_POS_FRAMELIST_SZIE) - | ((EHCI_CFG_FRAMELIST_SIZE_BITS >> 2) << EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB); - - //------------- ConfigFlag Register (skip) -------------// - regs->portsc_bm.port_power = 1; // enable port power - - return true; -} - -#if 0 -static void ehci_stop(uint8_t rhport) -{ - (void) rhport; - - ehci_registers_t* regs = ehci_data.regs; - - regs->command_bm.run_stop = 0; - - // USB Spec: controller has to stop within 16 uframe = 2 frames - while( regs->status_bm.hc_halted == 0 ) {} -} -#endif - -//--------------------------------------------------------------------+ -// CONTROL PIPE API -//--------------------------------------------------------------------+ -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) -{ - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - // FIXME control only for now - if ( epnum == 0 ) - { - ehci_qhd_t* qhd = qhd_control(dev_addr); - ehci_qtd_t* qtd = qtd_control(dev_addr); - - qtd_init(qtd, buffer, buflen); - - // first first data toggle is always 1 (data & setup stage) - qtd->data_toggle = 1; - qtd->pid = dir ? EHCI_PID_IN : EHCI_PID_OUT; - qtd->int_on_complete = 1; - qtd->next.terminate = 1; - - // sw region - qhd->p_qtd_list_head = qtd; - qhd->p_qtd_list_tail = qtd; - - // attach TD - qhd->qtd_overlay.next.address = (uint32_t) qtd; - }else - { - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - ehci_qtd_t *p_qtd = qtd_find_free(); - TU_ASSERT(p_qtd); - - qtd_init(p_qtd, buffer, buflen); - p_qtd->pid = p_qhd->pid; - - // Insert TD to QH - qtd_insert_to_qhd(p_qhd, p_qtd); - - p_qhd->p_qtd_list_tail->int_on_complete = 1; - - // attach head QTD to QHD start transferring - p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; - } - - return true; -} - -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) -{ - (void) rhport; - - ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd; - ehci_qtd_t* td = &ehci_data.control[dev_addr].qtd; - - qtd_init(td, (void*) setup_packet, 8); - td->pid = EHCI_PID_SETUP; - td->int_on_complete = 1; - td->next.terminate = 1; - - // sw region - qhd->p_qtd_list_head = td; - qhd->p_qtd_list_tail = td; - - // attach TD - qhd->qtd_overlay.next.address = (uint32_t) td; - - return true; -} - -//--------------------------------------------------------------------+ -// BULK/INT/ISO PIPE API -//--------------------------------------------------------------------+ -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; - - // TODO not support ISO yet - TU_ASSERT (ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); - - //------------- Prepare Queue Head -------------// - ehci_qhd_t * p_qhd; - - if ( ep_desc->bEndpointAddress == 0 ) - { - p_qhd = qhd_control(dev_addr); - }else - { - p_qhd = qhd_find_free(); - } - TU_ASSERT(p_qhd); - - qhd_init(p_qhd, dev_addr, ep_desc); - - // control of dev0 is always present as async head - if ( dev_addr == 0 ) return true; - - // Insert to list - ehci_link_t * list_head = NULL; - - switch (ep_desc->bmAttributes.xfer) - { - case TUSB_XFER_CONTROL: - case TUSB_XFER_BULK: - list_head = (ehci_link_t*) qhd_async_head(rhport); - break; - - case TUSB_XFER_INTERRUPT: - list_head = get_period_head(rhport, p_qhd->interval_ms); - break; - - case TUSB_XFER_ISOCHRONOUS: - // TODO iso is not supported - break; - - default: break; - } - - TU_ASSERT(list_head); - - // TODO might need to disable async/period list - list_insert(list_head, (ehci_link_t*) p_qhd, EHCI_QTYPE_QHD); - - return true; -} - -bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes) -{ - //------------- set up QTD -------------// - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - ehci_qtd_t *p_qtd = qtd_find_free(); - - TU_ASSERT(p_qtd); - - qtd_init(p_qtd, buffer, total_bytes); - p_qtd->pid = p_qhd->pid; - - //------------- insert TD to TD list -------------// - qtd_insert_to_qhd(p_qhd, p_qtd); - - return true; -} - -bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) -{ - TU_ASSERT ( hcd_pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes) ); - - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - - if ( int_on_complete ) - { // the just added qtd is pointed by list_tail - p_qhd->p_qtd_list_tail->int_on_complete = 1; - } - p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; // attach head QTD to QHD start transferring - - return true; -} - -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - return !p_qhd->qtd_overlay.halted && (p_qhd->p_qtd_list_head != NULL); -} - -bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) -{ - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - return p_qhd->qtd_overlay.halted && !qhd_has_xact_error(p_qhd); -} - -bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) -{ - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - p_qhd->qtd_overlay.halted = 0; - // TODO reset data toggle ? - return true; -} - -//--------------------------------------------------------------------+ -// EHCI Interrupt Handler -//--------------------------------------------------------------------+ - -// async_advance is handshake between usb stack & ehci controller. -// This isr mean it is safe to modify previously removed queue head from async list. -// In tinyusb, queue head is only removed when device is unplugged. -static void async_advance_isr(uint8_t rhport) -{ - (void) rhport; - - ehci_qhd_t* qhd_pool = ehci_data.qhd_pool; - for(uint32_t i = 0; i < HCD_MAX_ENDPOINT; i++) - { - if ( qhd_pool[i].removing ) - { - qhd_pool[i].removing = 0; - qhd_pool[i].used = 0; - } - } -} - -static void port_connect_status_change_isr(uint8_t hostid) -{ - // NOTE There is an sequence plug->unplug->…..-> plug if device is powering with pre-plugged device - if (ehci_data.regs->portsc_bm.current_connect_status) - { - hcd_port_reset(hostid); - hcd_event_device_attach(hostid, true); - }else // device unplugged - { - hcd_event_device_remove(hostid, true); - } -} - -static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) -{ - // free all TDs from the head td to the first active TD - while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active) - { - // TD need to be freed and removed from qhd, before invoking callback - bool is_ioc = (p_qhd->p_qtd_list_head->int_on_complete != 0); - p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; - - p_qhd->p_qtd_list_head->used = 0; // free QTD - qtd_remove_1st_from_qhd(p_qhd); - - if (is_ioc) - { - // end of request - // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), p_qhd->total_xferred_bytes, XFER_RESULT_SUCCESS, true); - p_qhd->total_xferred_bytes = 0; - } - } -} - -static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head) -{ - ehci_qhd_t *p_qhd = async_head; - do - { - if ( !p_qhd->qtd_overlay.halted ) // halted or error is processed in error isr - { - qhd_xfer_complete_isr(p_qhd); - } - p_qhd = qhd_next(p_qhd); - }while(p_qhd != async_head); // async list traversal, stop if loop around -} - -static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms) -{ - uint16_t max_loop = 0; - uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1); - ehci_link_t next_item = * get_period_head(hostid, interval_ms); - - // TODO abstract max loop guard for period - while( !next_item.terminate && - !(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) && - max_loop < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUSB_HOST_DEVICE_MAX) - { - switch ( next_item.type ) - { - case EHCI_QTYPE_QHD: - { - ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) tu_align32(next_item.address); - if ( !p_qhd_int->qtd_overlay.halted ) - { - qhd_xfer_complete_isr(p_qhd_int); - } - } - break; - - case EHCI_QTYPE_ITD: // TODO support hs/fs ISO - case EHCI_QTYPE_SITD: - case EHCI_QTYPE_FSTN: - - default: break; - } - - next_item = *list_next(&next_item); - max_loop++; - } -} - -static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) -{ - if ( (p_qhd->dev_addr != 0 && p_qhd->qtd_overlay.halted) || // addr0 cannot be protocol STALL - qhd_has_xact_error(p_qhd) ) - { - // current qhd has error in transaction - xfer_result_t error_event; - - // no error bits are set, endpoint is halted due to STALL - error_event = qhd_has_xact_error(p_qhd) ? XFER_RESULT_FAILED : XFER_RESULT_STALLED; - - p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; - -// if ( XFER_RESULT_FAILED == error_event ) TU_BREAKPOINT(); // TODO skip unplugged device - - p_qhd->p_qtd_list_head->used = 0; // free QTD - qtd_remove_1st_from_qhd(p_qhd); - - if ( 0 == p_qhd->ep_number ) - { - // control cannot be halted --> clear all qtd list - p_qhd->p_qtd_list_head = NULL; - p_qhd->p_qtd_list_tail = NULL; - - p_qhd->qtd_overlay.next.terminate = 1; - p_qhd->qtd_overlay.alternate.terminate = 1; - p_qhd->qtd_overlay.halted = 0; - - ehci_qtd_t *p_setup = qtd_control(p_qhd->dev_addr); - p_setup->used = 0; - } - - // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), p_qhd->total_xferred_bytes, error_event, true); - - p_qhd->total_xferred_bytes = 0; - } -} - -static void xfer_error_isr(uint8_t hostid) -{ - //------------- async list -------------// - ehci_qhd_t * const async_head = qhd_async_head(hostid); - ehci_qhd_t *p_qhd = async_head; - do - { - qhd_xfer_error_isr( p_qhd ); - p_qhd = qhd_next(p_qhd); - }while(p_qhd != async_head); // async list traversal, stop if loop around - - //------------- TODO refractor period list -------------// - uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1); - for (uint8_t interval_ms=1; interval_ms <= EHCI_FRAMELIST_SIZE; interval_ms *= 2) - { - ehci_link_t next_item = * get_period_head(hostid, interval_ms); - - // TODO abstract max loop guard for period - while( !next_item.terminate && - !(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) ) - { - switch ( next_item.type ) - { - case EHCI_QTYPE_QHD: - { - ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) tu_align32(next_item.address); - qhd_xfer_error_isr(p_qhd_int); - } - break; - - // TODO support hs/fs ISO - case EHCI_QTYPE_ITD: - case EHCI_QTYPE_SITD: - case EHCI_QTYPE_FSTN: - default: break; - } - - next_item = *list_next(&next_item); - } - } -} - -//------------- Host Controller Driver's Interrupt Handler -------------// -void hcd_int_handler(uint8_t rhport) -{ - ehci_registers_t* regs = ehci_data.regs; - - uint32_t int_status = regs->status; - int_status &= regs->inten; - - regs->status |= int_status; // Acknowledge handled interrupt - - if (int_status == 0) return; - - if (int_status & EHCI_INT_MASK_FRAMELIST_ROLLOVER) - { - ehci_data.uframe_number += (EHCI_FRAMELIST_SIZE << 3); - } - - if (int_status & EHCI_INT_MASK_PORT_CHANGE) - { - uint32_t port_status = regs->portsc & EHCI_PORTSC_MASK_ALL; - - if (regs->portsc_bm.connect_status_change) - { - port_connect_status_change_isr(rhport); - } - - regs->portsc |= port_status; // Acknowledge change bits in portsc - } - - if (int_status & EHCI_INT_MASK_ERROR) - { - xfer_error_isr(rhport); - } - - //------------- some QTD/SITD/ITD with IOC set is completed -------------// - if (int_status & EHCI_INT_MASK_NXP_ASYNC) - { - async_list_xfer_complete_isr( qhd_async_head(rhport) ); - } - - if (int_status & EHCI_INT_MASK_NXP_PERIODIC) - { - for (uint8_t i=1; i <= EHCI_FRAMELIST_SIZE; i *= 2) - { - period_list_xfer_complete_isr( rhport, i ); - } - } - - //------------- There is some removed async previously -------------// - if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) // need to place after EHCI_INT_MASK_NXP_ASYNC - { - async_advance_isr(rhport); - } -} - -//--------------------------------------------------------------------+ -// HELPER -//--------------------------------------------------------------------+ - - -//------------- queue head helper -------------// -static inline ehci_qhd_t* qhd_find_free (void) -{ - for (uint32_t i=0; inext.address); -} - -static inline ehci_qhd_t* qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) -{ - ehci_qhd_t* qhd_pool = ehci_data.qhd_pool; - - for(uint32_t i=0; inext.address); -} - -static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd) -{ - if (p_qhd->p_qtd_list_head == p_qhd->p_qtd_list_tail) // last TD --> make it NULL - { - p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = NULL; - }else - { - p_qhd->p_qtd_list_head = qtd_next( p_qhd->p_qtd_list_head ); - } -} - -static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new) -{ - if (p_qhd->p_qtd_list_head == NULL) // empty list - { - p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = p_qtd_new; - }else - { - p_qhd->p_qtd_list_tail->next.address = (uint32_t) p_qtd_new; - p_qhd->p_qtd_list_tail = p_qtd_new; - } -} - -static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) -{ - // address 0 is used as async head, which always on the list --> cannot be cleared (ehci halted otherwise) - if (dev_addr != 0) - { - tu_memclr(p_qhd, sizeof(ehci_qhd_t)); - } - - uint8_t const xfer_type = ep_desc->bmAttributes.xfer; - uint8_t const interval = ep_desc->bInterval; - - p_qhd->dev_addr = dev_addr; - p_qhd->fl_inactive_next_xact = 0; - p_qhd->ep_number = tu_edpt_number(ep_desc->bEndpointAddress); - p_qhd->ep_speed = _usbh_devices[dev_addr].speed; - p_qhd->data_toggle_control= (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0; - p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static asyn list head - p_qhd->max_packet_size = ep_desc->wMaxPacketSize.size; - p_qhd->fl_ctrl_ep_flag = ((xfer_type == TUSB_XFER_CONTROL) && (p_qhd->ep_speed != TUSB_SPEED_HIGH)) ? 1 : 0; - p_qhd->nak_reload = 0; - - // Bulk/Control -> smask = cmask = 0 - // TODO Isochronous - if (TUSB_XFER_INTERRUPT == xfer_type) - { - if (TUSB_SPEED_HIGH == p_qhd->ep_speed) - { - TU_ASSERT( interval <= 16, ); - if ( interval < 4) // sub milisecond interval - { - p_qhd->interval_ms = 0; - p_qhd->int_smask = (interval == 1) ? TU_BIN8(11111111) : - (interval == 2) ? TU_BIN8(10101010) : TU_BIN8(01000100); - }else - { - p_qhd->interval_ms = (uint8_t) tu_min16( 1 << (interval-4), 255 ); - p_qhd->int_smask = TU_BIT(interval % 8); - } - }else - { - TU_ASSERT( 0 != interval, ); - // Full/Low: 4.12.2.1 (EHCI) case 1 schedule start split at 1 us & complete split at 2,3,4 uframes - p_qhd->int_smask = 0x01; - p_qhd->fl_int_cmask = TU_BIN8(11100); - p_qhd->interval_ms = interval; - } - }else - { - p_qhd->int_smask = p_qhd->fl_int_cmask = 0; - } - - p_qhd->fl_hub_addr = _usbh_devices[dev_addr].hub_addr; - p_qhd->fl_hub_port = _usbh_devices[dev_addr].hub_port; - p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet - - //------------- HCD Management Data -------------// - p_qhd->used = 1; - p_qhd->removing = 0; - p_qhd->p_qtd_list_head = NULL; - p_qhd->p_qtd_list_tail = NULL; - p_qhd->pid = tu_edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint - - //------------- active, but no TD list -------------// - p_qhd->qtd_overlay.halted = 0; - p_qhd->qtd_overlay.next.terminate = 1; - p_qhd->qtd_overlay.alternate.terminate = 1; - if (TUSB_XFER_BULK == xfer_type && p_qhd->ep_speed == TUSB_SPEED_HIGH && p_qhd->pid == EHCI_PID_OUT) - { - p_qhd->qtd_overlay.ping_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11 - } -} - -static void qtd_init(ehci_qtd_t* p_qtd, void* buffer, uint16_t total_bytes) -{ - tu_memclr(p_qtd, sizeof(ehci_qtd_t)); - - p_qtd->used = 1; - - p_qtd->next.terminate = 1; // init to null - p_qtd->alternate.terminate = 1; // not used, always set to terminated - p_qtd->active = 1; - p_qtd->err_count = 3; // TODO 3 consecutive errors tolerance - p_qtd->data_toggle = 0; - p_qtd->total_bytes = total_bytes; - p_qtd->expected_bytes = total_bytes; - - p_qtd->buffer[0] = (uint32_t) buffer; - for(uint8_t i=1; i<5; i++) - { - p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096; - } -} - -//------------- List Managing Helper -------------// -static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type) -{ - new->address = current->address; - current->address = ((uint32_t) new) | (new_type << 1); -} - -static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer) -{ - return (ehci_link_t*) tu_align32(p_link_pointer->address); -} - -#endif diff --git a/src/host/ehci/ehci.h b/src/host/ehci/ehci.h deleted file mode 100644 index d8218a5fd..000000000 --- a/src/host/ehci/ehci.h +++ /dev/null @@ -1,462 +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. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup Group_HCD - * @{ - * \defgroup EHCI - * \brief EHCI driver. All documents sources mentioned here (eg section 3.5) is referring to EHCI Specs unless state otherwise - * @{ */ - -#ifndef _TUSB_EHCI_H_ -#define _TUSB_EHCI_H_ - -#include "common/tusb_common.h" -#include "../hcd.h" - -/* Abbreviation - * HC: Host Controller - * HCD: Host Controller Driver - * QHD: Queue Head for non-ISO transfer - * QTD: Queue Transfer Descriptor for non-ISO transfer - * ITD: Iso Transfer Descriptor for highspeed - * SITD: Split ISO Transfer Descriptor for full-speed - * SMASK: Start Split mask for Slipt Transaction - * CMASK: Complete Split mask for Slipt Transaction -*/ - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// EHCI CONFIGURATION & CONSTANTS -//--------------------------------------------------------------------+ -#define EHCI_CFG_FRAMELIST_SIZE_BITS 7 /// Framelist Size (NXP specific) (0:1024) - (1:512) - (2:256) - (3:128) - (4:64) - (5:32) - (6:16) - (7:8) -#define EHCI_FRAMELIST_SIZE (1024 >> EHCI_CFG_FRAMELIST_SIZE_BITS) - -// TODO merge OHCI with EHCI -enum { - EHCI_MAX_ITD = 4, - EHCI_MAX_SITD = 16 -}; - -//------------- Validation -------------// -TU_VERIFY_STATIC(EHCI_CFG_FRAMELIST_SIZE_BITS <= 7, "incorrect value"); - -//--------------------------------------------------------------------+ -// EHCI Data Structure -//--------------------------------------------------------------------+ -enum -{ - EHCI_QTYPE_ITD = 0 , - EHCI_QTYPE_QHD , - EHCI_QTYPE_SITD , - EHCI_QTYPE_FSTN -}; - -/// EHCI PID -enum -{ - EHCI_PID_OUT = 0 , - EHCI_PID_IN , - EHCI_PID_SETUP -}; - -/// Link pointer -typedef union { - uint32_t address; - struct { - uint32_t terminate : 1; - uint32_t type : 2; - }; -}ehci_link_t; - -/// Queue Element Transfer Descriptor -/// Qtd is used to declare overlay in ehci_qhd_t -> cannot be declared with TU_ATTR_ALIGNED(32) -typedef struct -{ - // Word 0: Next QTD Pointer - ehci_link_t next; - - // Word 1: Alternate Next QTD Pointer (not used) - union{ - ehci_link_t alternate; - struct { - uint32_t : 5; - uint32_t used : 1; - uint32_t : 10; - uint32_t expected_bytes : 16; - }; - }; - - // Word 2: qTQ Token - volatile uint32_t ping_err : 1 ; ///< For Highspeed: 0 Out, 1 Ping. Full/Slow used as error indicator - volatile uint32_t non_hs_split_state : 1 ; ///< Used by HC to track the state of slipt transaction - volatile uint32_t non_hs_missed_uframe : 1 ; ///< HC misses a complete slip transaction - volatile uint32_t xact_err : 1 ; ///< Error (Timeout, CRC, Bad PID ... ) - volatile uint32_t babble_err : 1 ; ///< Babble detected, also set Halted bit to 1 - volatile uint32_t buffer_err : 1 ; ///< Data overrun/underrun error - volatile uint32_t halted : 1 ; ///< Serious error or STALL received - volatile uint32_t active : 1 ; ///< Start transfer, clear by HC when complete - - uint32_t pid : 2 ; ///< 0: OUT, 1: IN, 2 Setup - volatile uint32_t err_count : 2 ; ///< Error Counter of consecutive errors - volatile uint32_t current_page : 3 ; ///< Index into the qTD buffer pointer list - uint32_t int_on_complete : 1 ; ///< Interrupt on complete - volatile uint32_t total_bytes : 15 ; ///< Transfer bytes, decreased during transaction - volatile uint32_t data_toggle : 1 ; ///< Data Toogle bit - - - /// Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page - uint32_t buffer[5]; -} ehci_qtd_t; - -TU_VERIFY_STATIC( sizeof(ehci_qtd_t) == 32, "size is not correct" ); - -/// Queue Head -typedef struct TU_ATTR_ALIGNED(32) -{ - // Word 0: Next QHD - ehci_link_t next; - - // Word 1: Endpoint Characteristics - uint32_t dev_addr : 7 ; ///< device address - uint32_t fl_inactive_next_xact : 1 ; ///< Only valid for Periodic with Full/Slow speed - uint32_t ep_number : 4 ; ///< EP number - uint32_t ep_speed : 2 ; ///< 0: Full, 1: Low, 2: High - uint32_t data_toggle_control : 1 ; ///< 0: use DT in qHD, 1: use DT in qTD - uint32_t head_list_flag : 1 ; ///< Head of the queue - uint32_t max_packet_size : 11 ; ///< Max packet size - uint32_t fl_ctrl_ep_flag : 1 ; ///< 1 if is Full/Low speed control endpoint - uint32_t nak_reload : 4 ; ///< Used by HC - - // Word 2: Endpoint Capabilities - uint32_t int_smask : 8 ; ///< Interrupt Schedule Mask - uint32_t fl_int_cmask : 8 ; ///< Split Completion Mask for Full/Slow speed - uint32_t fl_hub_addr : 7 ; ///< Hub Address for Full/Slow speed - uint32_t fl_hub_port : 7 ; ///< Hub Port for Full/Slow speed - uint32_t mult : 2 ; ///< Transaction per micro frame - - // Word 3: Current qTD Pointer - volatile uint32_t qtd_addr; - - // Word 4-11: Transfer Overlay - volatile ehci_qtd_t qtd_overlay; - - //--------------------------------------------------------------------+ - /// Due to the fact QHD is 32 bytes aligned but occupies only 48 bytes - /// thus there are 16 bytes padding free that we can make use of. - //--------------------------------------------------------------------+ - uint8_t used; - uint8_t removing; // removed from asyn list, waiting for async advance - uint8_t pid; - uint8_t interval_ms; // polling interval in frames (or milisecond) - - uint16_t total_xferred_bytes; // number of bytes xferred until a qtd with ioc bit set - uint8_t reserved2[2]; - - ehci_qtd_t * volatile p_qtd_list_head; // head of the scheduled TD list - ehci_qtd_t * volatile p_qtd_list_tail; // tail of the scheduled TD list -} ehci_qhd_t; - -TU_VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" ); - -/// Highspeed Isochronous Transfer Descriptor (section 3.3) -typedef struct TU_ATTR_ALIGNED(32) { - // Word 0: Next Link Pointer - ehci_link_t next; - - // Word 1-8: iTD Transaction Status and Control List - struct { - // iTD Control - volatile uint32_t offset : 12 ; ///< This field is a value that is an offset, expressed in bytes, from the beginning of a buffer. - volatile uint32_t page_select : 3 ; ///< These bits are set by software to indicate which of the buffer page pointers the offset field in this slot should be concatenated to produce the starting memory address for this transaction. The valid range of values for this field is 0 to 6 - uint32_t int_on_complete : 1 ; ///< If this bit is set to a one, it specifies that when this transaction completes, the Host Controller should issue an interrupt at the next interrupt threshold - volatile uint32_t length : 12 ; ///< For an OUT, this field is the number of data bytes the host controller will send during the transaction. The host controller is not required to update this field to reflect the actual number of bytes transferred during the transfer - ///< For an IN, the initial value of the field is the number of bytes the host expects the endpoint to deliver. During the status update, the host controller writes back the number of bytes successfully received. The value in this register is the actual byte count - // iTD Status - volatile uint32_t error : 1 ; ///< Set to a one by the Host Controller during status update in the case where the host did not receive a valid response from the device (Timeout, CRC, Bad PID, etc.). This bit may only be set for isochronous IN transactions. - volatile uint32_t babble_err : 1 ; ///< Set to a 1 by the Host Controller during status update when a babble is detected during the transaction - volatile uint32_t buffer_err : 1 ; ///< Set to a 1 by the Host Controller during status update to indicate that the Host Controller is unable to keep up with the reception of incoming data (overrun) or is unable to supply data fast enough during transmission (underrun). - volatile uint32_t active : 1 ; ///< Set to 1 by software to enable the execution of an isochronous transaction by the Host Controller - } xact[8]; - - // Word 9-15 Buffer Page Pointer List (Plus) - uint32_t BufferPointer[7]; - -// // FIXME: Store meta data into buffer pointer reserved for saving memory -// /*---------- HCD Area ----------*/ -// uint32_t used; -// uint32_t IhdIdx; -// uint32_t reserved[6]; -} ehci_itd_t; - -TU_VERIFY_STATIC( sizeof(ehci_itd_t) == 64, "size is not correct" ); - -/// Split (Full-Speed) Isochronous Transfer Descriptor -typedef struct TU_ATTR_ALIGNED(32) -{ - // Word 0: Next Link Pointer - ehci_link_t next; - - // Word 1: siTD Endpoint Characteristics - uint32_t dev_addr : 7; ///< This field selects the specific device serving as the data source or sink. - uint32_t : 1; ///< reserved - uint32_t ep_number : 4; ///< This 4-bit field selects the particular endpoint number on the device serving as the data source or sink. - uint32_t : 4; ///< This field is reserved and should be set to zero. - uint32_t hub_addr : 7; ///< This field holds the device address of the transaction translators’ hub. - uint32_t : 1; ///< reserved - uint32_t port_number : 7; ///< This field is the port number of the recipient transaction translator. - uint32_t direction : 1; ///< 0 = OUT; 1 = IN. This field encodes whether the full-speed transaction should be an IN or OUT. - - // Word 2: Micro-frame Schedule Control - uint8_t int_smask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute complete-split transactions - uint8_t fl_int_cmask; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute start-split transactions. - uint16_t reserved ; ///< reserved - - // Word 3: siTD Transfer Status and Control - // Status [7:0] TODO indentical to qTD Token'status --> refractor later - volatile uint32_t : 1 ; // reserved - volatile uint32_t split_state : 1 ; - volatile uint32_t missed_uframe : 1 ; - volatile uint32_t xact_err : 1 ; - volatile uint32_t babble_err : 1 ; - volatile uint32_t buffer_err : 1 ; - volatile uint32_t error : 1 ; - volatile uint32_t active : 1 ; - // Micro-frame Schedule Control - volatile uint32_t cmask_progress : 8 ; ///< This field is used by the host controller to record which split-completes have been executed. See Section 4.12.3.3.2 for behavioral requirements. - volatile uint32_t total_bytes : 10 ; ///< This field is initialized by software to the total number of bytes expected in this transfer. Maximum value is 1023 - volatile uint32_t : 4 ; ///< reserved - volatile uint32_t page_select : 1 ; ///< Used to indicate which data page pointer should be concatenated with the CurrentOffsetfield to construct a data buffer pointer - uint32_t int_on_complete : 1 ; ///< Do not interrupt when transaction is complete. 1 = Do interrupt when transaction is complete - uint32_t : 0 ; // padding to the end of current storage unit - - /// Word 4-5: Buffer Pointer List - uint32_t buffer[2]; // buffer[1] TP: Transaction Position - T-Count: Transaction Count - -// union{ -// uint32_t BufferPointer1; -// struct { -// volatile uint32_t TCount : 3; -// volatile uint32_t TPosition : 2; -// }; -// }; - - /*---------- Word 6 ----------*/ - ehci_link_t back; - - /// SITD is 32-byte aligned but occupies only 28 --> 4 bytes for storing extra data - uint8_t used; - uint8_t ihd_idx; - uint8_t reserved2[2]; -} ehci_sitd_t; - -TU_VERIFY_STATIC( sizeof(ehci_sitd_t) == 32, "size is not correct" ); - -//--------------------------------------------------------------------+ -// EHCI Operational Register -//--------------------------------------------------------------------+ -enum ehci_interrupt_mask_{ - EHCI_INT_MASK_USB = TU_BIT(0), - EHCI_INT_MASK_ERROR = TU_BIT(1), - EHCI_INT_MASK_PORT_CHANGE = TU_BIT(2), - - EHCI_INT_MASK_FRAMELIST_ROLLOVER = TU_BIT(3), - EHCI_INT_MASK_PCI_HOST_SYSTEM_ERROR = TU_BIT(4), - EHCI_INT_MASK_ASYNC_ADVANCE = TU_BIT(5), - EHCI_INT_MASK_NXP_SOF = TU_BIT(7), - - EHCI_INT_MASK_NXP_ASYNC = TU_BIT(18), - EHCI_INT_MASK_NXP_PERIODIC = TU_BIT(19), - - EHCI_INT_MASK_ALL = - EHCI_INT_MASK_USB | EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE | - EHCI_INT_MASK_FRAMELIST_ROLLOVER | EHCI_INT_MASK_PCI_HOST_SYSTEM_ERROR | - EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_NXP_SOF | - EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_NXP_PERIODIC -}; - -enum ehci_usbcmd_pos_ { - EHCI_USBCMD_POS_RUN_STOP = 0, - EHCI_USBCMD_POS_FRAMELIST_SZIE = 2, - EHCI_USBCMD_POS_PERIOD_ENABLE = 4, - EHCI_USBCMD_POS_ASYNC_ENABLE = 5, - EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB = 15, - EHCI_USBCMD_POS_INTERRUPT_THRESHOLD = 16 -}; - -enum ehci_portsc_change_mask_{ - EHCI_PORTSC_MASK_CURRENT_CONNECT_STATUS = TU_BIT(0), - EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE = TU_BIT(1), - EHCI_PORTSC_MASK_PORT_EANBLED = TU_BIT(2), - EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE = TU_BIT(3), - EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE = TU_BIT(5), - - EHCI_PORTSC_MASK_PORT_RESET = TU_BIT(8), - - EHCI_PORTSC_MASK_ALL = - EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE | - EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE | - EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE -}; - -typedef volatile struct -{ - union { - uint32_t command; - - struct { - uint32_t run_stop : 1 ; ///< 1=Run. 0=Stop - uint32_t reset : 1 ; ///< SW write 1 to reset HC, clear by HC when complete - uint32_t framelist_size : 2 ; ///< Frame List size 0: 1024, 1: 512, 2: 256 - uint32_t periodic_enable : 1 ; ///< This bit controls whether the host controller skips processing the Periodic Schedule. Values mean: 0b Do not process the Periodic Schedule 1b Use the PERIODICLISTBASE register to access the Periodic Schedule. - uint32_t async_enable : 1 ; ///< This bit controls whether the host controller skips processing the Asynchronous Schedule. Values mean: 0b Do not process the Asynchronous Schedule 1b Use the ASYNCLISTADDR register to access the Asynchronous Schedule. - uint32_t async_adv_doorbell : 1 ; ///< Tell HC to interrupt next time it advances async list. Clear by HC - uint32_t light_reset : 1 ; ///< Reset HC without affecting ports state - uint32_t async_park_count : 2 ; ///< not used by tinyusb - uint32_t : 1 ; - uint32_t async_park_enable : 1 ; ///< Enable park mode, not used by tinyusb - uint32_t : 3 ; - uint32_t nxp_framelist_size_msb : 1 ; ///< NXP customized : Bit 2 of the Frame List Size bits \n 011b: 128 elements \n 100b: 64 elements \n 101b: 32 elements \n 110b: 16 elements \n 111b: 8 elements - uint32_t int_threshold : 8 ; ///< Default 08h. Interrupt rate in unit of micro frame - }command_bm; - }; - - union { - uint32_t status; - - struct { - uint32_t usb : 1 ; ///< qTD with IOC is retired - uint32_t usb_error : 1 ; ///< qTD retired due to error - uint32_t port_change_detect : 1 ; ///< Set when PortOwner or ForcePortResume change from 0 -> 1 - uint32_t framelist_rollover : 1 ; ///< R/WC The Host Controller sets this bit to a one when the Frame List Index(see Section 2.3.4) rolls over from its maximum value to zero. The exact value at which the rollover occurs depends on the frame list size. For example, if the frame list size (as programmed in the Frame List Sizefield of the USBCMD register) is 1024, the Frame Index Registerrolls over every time FRINDEX[13] toggles. Similarly, if the size is 512, the Host Controller sets this bit to a one every time FRINDEX[12] toggles. - uint32_t pci_host_system_error : 1 ; ///< R/WC (not used by NXP) The Host Controller sets this bit to 1 when a serious error occurs during a host system access involving the Host Controller module. In a PCI system, conditions that set this bit to 1 include PCI Parity error, PCI Master Abort, and PCI Target Abort. When this error occurs, the Host Controller clears the Run/Stop bit in the Command register to prevent further execution of the scheduled TDs. - uint32_t async_adv : 1 ; ///< Async Advance interrupt - uint32_t : 1 ; - uint32_t nxp_int_sof : 1 ; ///< NXP customized: this bit will be set every 125us and can be used by host controller driver as a time base. - uint32_t : 4 ; - uint32_t hc_halted : 1 ; ///< Opposite value to run_stop bit. - uint32_t reclamation : 1 ; ///< Used to detect empty async shecudle - uint32_t periodic_status : 1 ; ///< Periodic schedule status - uint32_t async_status : 1 ; ///< Async schedule status - uint32_t : 2 ; - uint32_t nxp_int_async : 1 ; ///< NXP customized: This bit is set by the Host Controller when the cause of an interrupt is a completion of a USB transaction where the Transfer Descriptor (TD) has an interrupt on complete (IOC) bit set andthe TD was from the asynchronous schedule. This bit is also set by the Host when a short packet is detected andthe packet is on the asynchronous schedule. - uint32_t nxp_int_period : 1 ; ///< NXP customized: This bit is set by the Host Controller when the cause of an interrupt is a completion of a USB transaction where the Transfer Descriptor (TD) has an interrupt on complete (IOC) bit set andthe TD was from the periodic schedule. - uint32_t : 12 ; - }status_bm; - }; - - union{ - uint32_t inten; - - struct { - uint32_t usb : 1 ; - uint32_t usb_error : 1 ; - uint32_t port_change_detect : 1 ; - uint32_t framelist_rollover : 1 ; - uint32_t pci_host_system_error : 1 ; - uint32_t async_adv : 1 ; - uint32_t : 1 ; - uint32_t nxp_int_sof : 1 ; - uint32_t : 10 ; - uint32_t nxp_int_async : 1 ; - uint32_t nxp_int_period : 1 ; - uint32_t : 12 ; - }inten_bm; - }; - - uint32_t frame_index ; ///< Micro frame counter - uint32_t ctrl_ds_seg ; ///< Control Data Structure Segment - uint32_t periodic_list_base ; ///< Beginning address of perodic frame list - uint32_t async_list_addr ; ///< Address of next async QHD to be executed - uint32_t nxp_tt_control ; ///< nxp embedded transaction translator (reserved by EHCI specs) - uint32_t reserved[8] ; - uint32_t config_flag ; ///< not used by NXP - - union { - uint32_t portsc ; ///< port status and control - struct { - uint32_t current_connect_status : 1; ///< 0: No device, 1: Device is present on port - uint32_t connect_status_change : 1; ///< Change in Current Connect Status - uint32_t port_enabled : 1; ///< Ports can only be enabled by HC as a part of the reset and enable. SW can write 0 to disable - uint32_t port_enable_change : 1; ///< Port Enabled has changed - uint32_t over_current_active : 1; ///< Port has an over-current condition - uint32_t over_current_change : 1; ///< Change to Over-current Active - uint32_t force_port_resume : 1; ///< Resume detected/driven on port. This functionality defined for manipulating this bit depends on the value of the Suspend bit. - uint32_t suspend : 1; ///< Port in suspend state - uint32_t port_reset : 1; ///< 1=Port is in Reset. 0=Port is not in Reset - uint32_t nxp_highspeed_status : 1; ///< NXP customized: 0=connected to the port is not in High-speed mode, 1=connected to the port is in High-speed mode - uint32_t line_status : 2; ///< D+/D- state: 00: SE0, 10: J-state, 01: K-state - uint32_t port_power : 1; ///< 0= power off, 1= power on - uint32_t port_owner : 1; ///< not used by NXP - uint32_t port_indicator_control : 2; ///< 00b: off, 01b: Amber, 10b: green, 11b: undefined - uint32_t port_test_control : 4; ///< Port test mode, not used by tinyusb - uint32_t wake_on_connect_enable : 1; ///< Enables device connects as wake-up events - uint32_t wake_on_disconnect_enable : 1; ///< Enables device disconnects as wake-up events - uint32_t wake_on_over_current_enable : 1; ///< Enables over-current conditions as wake-up events - uint32_t nxp_phy_clock_disable : 1; ///< NXP customized: the PHY can be put into Low Power Suspend – Clock Disable when the downstream device has been put into suspend mode or when no downstream device is connected. Low power suspend is completely under the control of software. 0: enable PHY clock, 1: disable PHY clock - uint32_t nxp_port_force_fullspeed : 1; ///< NXP customized: Writing this bit to a 1 will force the port to only connect at Full Speed. It disables the chirp sequence that allowsthe port to identify itself as High Speed. This is useful for testing FS configurations with a HS host, hub or device. - uint32_t : 1; - uint32_t nxp_port_speed : 2; ///< NXP customized: This register field indicates the speed atwhich the port is operating. For HS mode operation in the host controllerand HS/FS operation in the device controller the port routing steers data to the Protocol engine. For FS and LS mode operation in the host controller, the port routing steers data to the Protocol Engine w/ Embedded Transaction Translator. 0x0: Fullspeed, 0x1: Lowspeed, 0x2: Highspeed - uint32_t TU_RESERVED : 4; - }portsc_bm; - }; -}ehci_registers_t; - -//--------------------------------------------------------------------+ -// EHCI Data Organization -//--------------------------------------------------------------------+ -typedef struct -{ - ehci_link_t period_framelist[EHCI_FRAMELIST_SIZE]; - - // for NXP ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist) - // [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms - ehci_qhd_t period_head_arr[4]; - - // Note control qhd of dev0 is used as head of async list - struct { - ehci_qhd_t qhd; - ehci_qtd_t qtd; - }control[CFG_TUSB_HOST_DEVICE_MAX+1]; - - ehci_qhd_t qhd_pool[HCD_MAX_ENDPOINT]; - ehci_qtd_t qtd_pool[HCD_MAX_XFER] TU_ATTR_ALIGNED(32); - - ehci_registers_t* regs; - - volatile uint32_t uframe_number; -}ehci_data_t; - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_EHCI_H_ */ - -/** @} */ -/** @} */ diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c deleted file mode 100644 index 44acebf72..000000000 --- a/src/host/ohci/ohci.c +++ /dev/null @@ -1,686 +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. - * - * This file is part of the TinyUSB stack. - */ - -#include - -#if TUSB_OPT_HOST_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC40XX) -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "osal/osal.h" - -#include "../hcd.h" -#include "../usbh_hcd.h" -#include "ohci.h" - -// TODO remove -#include "chip.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -#define OHCI_REG ((ohci_registers_t *) LPC_USB_BASE) - -enum { - OHCI_CONTROL_FUNCSTATE_RESET = 0, - OHCI_CONTROL_FUNCSTATE_RESUME, - OHCI_CONTROL_FUNCSTATE_OPERATIONAL, - OHCI_CONTROL_FUNCSTATE_SUSPEND -}; - -enum { - OHCI_CONTROL_CONTROL_BULK_RATIO = 3, ///< This specifies the service ratio between Control and Bulk EDs. 0 = 1:1, 3 = 4:1 - OHCI_CONTROL_LIST_PERIODIC_ENABLE_MASK = TU_BIT(2), - OHCI_CONTROL_LIST_ISOCHRONOUS_ENABLE_MASK = TU_BIT(3), - OHCI_CONTROL_LIST_CONTROL_ENABLE_MASK = TU_BIT(4), - OHCI_CONTROL_LIST_BULK_ENABLE_MASK = TU_BIT(5), -}; - -enum { - OHCI_FMINTERVAL_FI = 0x2EDF, // 7.3.1 nominal (reset) value - OHCI_FMINTERVAL_FSMPS = (6*(OHCI_FMINTERVAL_FI-210)) / 7, // 5.4 calculated based on maximum overhead + bit stuffing -}; - -enum { - OHCI_PERIODIC_START = 0x3E67 -}; - -enum { - OHCI_INT_SCHEDULING_OVERUN_MASK = TU_BIT(0), - OHCI_INT_WRITEBACK_DONEHEAD_MASK = TU_BIT(1), - OHCI_INT_SOF_MASK = TU_BIT(2), - OHCI_INT_RESUME_DETECTED_MASK = TU_BIT(3), - OHCI_INT_UNRECOVERABLE_ERROR_MASK = TU_BIT(4), - OHCI_INT_FRAME_OVERFLOW_MASK = TU_BIT(5), - OHCI_INT_RHPORT_STATUS_CHANGE_MASK = TU_BIT(6), - - OHCI_INT_OWNERSHIP_CHANGE_MASK = TU_BIT(30), - OHCI_INT_MASTER_ENABLE_MASK = TU_BIT(31), -}; - -enum { - OHCI_RHPORT_CURRENT_CONNECT_STATUS_MASK = TU_BIT(0), - OHCI_RHPORT_PORT_ENABLE_STATUS_MASK = TU_BIT(1), - OHCI_RHPORT_PORT_SUSPEND_STATUS_MASK = TU_BIT(2), - OHCI_RHPORT_PORT_OVER_CURRENT_INDICATOR_MASK = TU_BIT(3), - OHCI_RHPORT_PORT_RESET_STATUS_MASK = TU_BIT(4), ///< write '1' to reset port - - OHCI_RHPORT_PORT_POWER_STATUS_MASK = TU_BIT(8), - OHCI_RHPORT_LOW_SPEED_DEVICE_ATTACHED_MASK = TU_BIT(9), - - OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK = TU_BIT(16), - OHCI_RHPORT_PORT_ENABLE_CHANGE_MASK = TU_BIT(17), - OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK = TU_BIT(18), - OHCI_RHPORT_OVER_CURRENT_CHANGE_MASK = TU_BIT(19), - OHCI_RHPORT_PORT_RESET_CHANGE_MASK = TU_BIT(20), - - OHCI_RHPORT_ALL_CHANGE_MASK = OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK | OHCI_RHPORT_PORT_ENABLE_CHANGE_MASK | - OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK | OHCI_RHPORT_OVER_CURRENT_CHANGE_MASK | OHCI_RHPORT_PORT_RESET_CHANGE_MASK -}; - -enum { - OHCI_CCODE_NO_ERROR = 0, - OHCI_CCODE_CRC = 1, - OHCI_CCODE_BIT_STUFFING = 2, - OHCI_CCODE_DATA_TOGGLE_MISMATCH = 3, - OHCI_CCODE_STALL = 4, - OHCI_CCODE_DEVICE_NOT_RESPONDING = 5, - OHCI_CCODE_PID_CHECK_FAILURE = 6, - OHCI_CCODE_UNEXPECTED_PID = 7, - OHCI_CCODE_DATA_OVERRUN = 8, - OHCI_CCODE_DATA_UNDERRUN = 9, - OHCI_CCODE_BUFFER_OVERRUN = 12, - OHCI_CCODE_BUFFER_UNDERRUN = 13, - OHCI_CCODE_NOT_ACCESSED = 14, -}; - -enum { - OHCI_INT_ON_COMPLETE_YES = 0, - OHCI_INT_ON_COMPLETE_NO = TU_BIN8(111) -}; -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(256) static ohci_data_t ohci_data; - -static ohci_ed_t * const p_ed_head[] = -{ - [TUSB_XFER_CONTROL] = &ohci_data.control[0].ed, - [TUSB_XFER_BULK ] = &ohci_data.bulk_head_ed, - [TUSB_XFER_INTERRUPT] = &ohci_data.period_head_ed, - [TUSB_XFER_ISOCHRONOUS] = NULL // TODO Isochronous -}; - -static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed); -static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr); - -//--------------------------------------------------------------------+ -// USBH-HCD API -//--------------------------------------------------------------------+ -// Initialization according to 5.1.1.4 -bool hcd_init(uint8_t rhport) -{ - (void) rhport; - - //------------- Data Structure init -------------// - tu_memclr(&ohci_data, sizeof(ohci_data_t)); - for(uint8_t i=0; i<32; i++) - { // assign all interrupt pointes to period head ed - ohci_data.hcca.interrupt_table[i] = (uint32_t) &ohci_data.period_head_ed; - } - - ohci_data.control[0].ed.skip = 1; - ohci_data.bulk_head_ed.skip = 1; - ohci_data.period_head_ed.skip = 1; - - // reset controller - OHCI_REG->command_status_bit.controller_reset = 1; - while( OHCI_REG->command_status_bit.controller_reset ) {} // should not take longer than 10 us - - //------------- init ohci registers -------------// - OHCI_REG->control_head_ed = (uint32_t) &ohci_data.control[0].ed; - OHCI_REG->bulk_head_ed = (uint32_t) &ohci_data.bulk_head_ed; - OHCI_REG->hcca = (uint32_t) &ohci_data.hcca; - - OHCI_REG->interrupt_disable = OHCI_REG->interrupt_enable; // disable all interrupts - OHCI_REG->interrupt_status = OHCI_REG->interrupt_status; // clear current set bits - OHCI_REG->interrupt_enable = OHCI_INT_WRITEBACK_DONEHEAD_MASK | OHCI_INT_RESUME_DETECTED_MASK | - OHCI_INT_UNRECOVERABLE_ERROR_MASK | OHCI_INT_FRAME_OVERFLOW_MASK | OHCI_INT_RHPORT_STATUS_CHANGE_MASK | - OHCI_INT_MASTER_ENABLE_MASK; - - OHCI_REG->control |= OHCI_CONTROL_CONTROL_BULK_RATIO | OHCI_CONTROL_LIST_CONTROL_ENABLE_MASK | - OHCI_CONTROL_LIST_BULK_ENABLE_MASK | OHCI_CONTROL_LIST_PERIODIC_ENABLE_MASK; // TODO Isochronous - - OHCI_REG->frame_interval = (OHCI_FMINTERVAL_FSMPS << 16) | OHCI_FMINTERVAL_FI; - OHCI_REG->periodic_start = (OHCI_FMINTERVAL_FI * 9) / 10; // Periodic start is 90% of frame interval - - OHCI_REG->control_bit.hc_functional_state = OHCI_CONTROL_FUNCSTATE_OPERATIONAL; // make HC's state to operational state TODO use this to suspend (save power) - OHCI_REG->rh_status_bit.local_power_status_change = 1; // set global power for ports - - return true; -} - -uint32_t hcd_uframe_number(uint8_t rhport) -{ - (void) rhport; - return (ohci_data.frame_number_hi << 16 | OHCI_REG->frame_number) << 3; -} - - -//--------------------------------------------------------------------+ -// PORT API -//--------------------------------------------------------------------+ -void hcd_port_reset(uint8_t hostid) -{ - (void) hostid; - OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK; -} - -bool hcd_port_connect_status(uint8_t hostid) -{ - (void) hostid; - return OHCI_REG->rhport_status_bit[0].current_connect_status; -} - -tusb_speed_t hcd_port_speed_get(uint8_t hostid) -{ - (void) hostid; - return OHCI_REG->rhport_status_bit[0].low_speed_device_attached ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; -} - -// endpoints are tied to an address, which only reclaim after a long delay when enumerating -// thus there is no need to make sure ED is not in HC's cahed as it will not for sure -void hcd_device_close(uint8_t rhport, uint8_t dev_addr) -{ - // TODO OHCI - (void) rhport; - - // addr0 serves as static head --> only set skip bit - if ( dev_addr == 0 ) - { - ohci_data.control[0].ed.skip = 1; - }else - { - // remove control - ed_list_remove_by_addr( p_ed_head[TUSB_XFER_CONTROL], dev_addr); - - // remove bulk - ed_list_remove_by_addr(p_ed_head[TUSB_XFER_BULK], dev_addr); - - // remove interrupt - ed_list_remove_by_addr(p_ed_head[TUSB_XFER_INTERRUPT], dev_addr); - - // TODO remove ISO - } -} - -//--------------------------------------------------------------------+ -// Controller API -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// CONTROL PIPE API -//--------------------------------------------------------------------+ -static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_t const * const p_ed) -{ - return (p_ed->ep_number == 0 ) ? TUSB_XFER_CONTROL : - (p_ed->is_iso ) ? TUSB_XFER_ISOCHRONOUS : - (p_ed->is_interrupt_xfer ) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK; -} - -static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type, uint8_t interval) -{ - (void) interval; - - // address 0 is used as async head, which always on the list --> cannot be cleared - if (dev_addr != 0) - { - tu_memclr(p_ed, sizeof(ohci_ed_t)); - } - - p_ed->dev_addr = dev_addr; - p_ed->ep_number = endpoint_addr & 0x0F; - p_ed->pid = (xfer_type == TUSB_XFER_CONTROL) ? OHCI_PID_SETUP : ( (endpoint_addr & TUSB_DIR_IN_MASK) ? OHCI_PID_IN : OHCI_PID_OUT ); - p_ed->speed = _usbh_devices[dev_addr].speed; - p_ed->is_iso = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; - p_ed->max_packet_size = max_packet_size; - - p_ed->used = 1; - p_ed->is_interrupt_xfer = (xfer_type == TUSB_XFER_INTERRUPT ? 1 : 0); -} - -static void gtd_init(ohci_gtd_t* p_td, void* data_ptr, uint16_t total_bytes) -{ - tu_memclr(p_td, sizeof(ohci_gtd_t)); - - p_td->used = 1; - p_td->expected_bytes = total_bytes; - - p_td->buffer_rounding = 1; // less than queued length is not a error - p_td->delay_interrupt = OHCI_INT_ON_COMPLETE_NO; - p_td->condition_code = OHCI_CCODE_NOT_ACCESSED; - - p_td->current_buffer_pointer = data_ptr; - p_td->buffer_end = total_bytes ? (((uint8_t*) data_ptr) + total_bytes-1) : NULL; -} - -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) -{ - (void) rhport; - - ohci_ed_t* p_ed = &ohci_data.control[dev_addr].ed; - ohci_gtd_t *p_setup = &ohci_data.control[dev_addr].gtd; - - gtd_init(p_setup, (void*) setup_packet, 8); - p_setup->index = dev_addr; - p_setup->pid = OHCI_PID_SETUP; - p_setup->data_toggle = TU_BIN8(10); // DATA0 - p_setup->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - - //------------- Attach TDs list to Control Endpoint -------------// - p_ed->td_head.address = (uint32_t) p_setup; - - OHCI_REG->command_status_bit.control_list_filled = 1; - - return true; -} - -// TODO move around -static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr); -static ohci_gtd_t * gtd_find_free(void); -static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd); - -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) -{ - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - // FIXME control only for now - if ( epnum == 0 ) - { - ohci_ed_t* const p_ed = &ohci_data.control[dev_addr].ed; - ohci_gtd_t *p_data = &ohci_data.control[dev_addr].gtd; - - gtd_init(p_data, buffer, buflen); - - p_data->index = dev_addr; - p_data->pid = dir ? OHCI_PID_IN : OHCI_PID_OUT; - p_data->data_toggle = TU_BIN8(11); // DATA1 - p_data->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - - p_ed->td_head.address = (uint32_t) p_data; - - OHCI_REG->command_status_bit.control_list_filled = 1; - }else - { - ohci_ed_t * p_ed = ed_from_addr(dev_addr, ep_addr); - ohci_gtd_t* p_gtd = gtd_find_free(); - - TU_ASSERT(p_gtd); - - gtd_init(p_gtd, buffer, buflen); - p_gtd->index = p_ed-ohci_data.ed_pool; - p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - - td_insert_to_ed(p_ed, p_gtd); - - tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); - if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; - } - - return true; -} - -//--------------------------------------------------------------------+ -// BULK/INT/ISO PIPE API -//--------------------------------------------------------------------+ -static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) -{ - if ( tu_edpt_number(ep_addr) == 0 ) return &ohci_data.control[dev_addr].ed; - - ohci_ed_t* ed_pool = ohci_data.ed_pool; - - for(uint32_t i=0; inext = p_pre->next; - p_pre->next = (uint32_t) p_ed; -} - -static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr) -{ - ohci_ed_t* p_prev = p_head; - - while( p_prev->next ) - { - ohci_ed_t* ed = (ohci_ed_t*) p_prev->next; - - if (ed->dev_addr == dev_addr) - { - // unlink ed - p_prev->next = ed->next; - - // point the removed ED's next pointer to list head to make sure HC can always safely move away from this ED - ed->next = (uint32_t) p_head; - ed->used = 0; - } - - // check next valid since we could remove it - if (p_prev->next) p_prev = (ohci_ed_t*) p_prev->next; - } -} - -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; - - // TODO iso support - TU_ASSERT(ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); - - //------------- Prepare Queue Head -------------// - ohci_ed_t * p_ed; - - if ( ep_desc->bEndpointAddress == 0 ) - { - p_ed = &ohci_data.control[dev_addr].ed; - }else - { - p_ed = ed_find_free(); - } - TU_ASSERT(p_ed); - - ed_init( p_ed, dev_addr, ep_desc->wMaxPacketSize.size, ep_desc->bEndpointAddress, - ep_desc->bmAttributes.xfer, ep_desc->bInterval ); - - // control of dev0 is used as static async head - if ( dev_addr == 0 ) - { - p_ed->skip = 0; // only need to clear skip bit - return true; - } - - ed_list_insert( p_ed_head[ep_desc->bmAttributes.xfer], p_ed ); - - return true; -} - -static ohci_gtd_t * gtd_find_free(void) -{ - for(uint8_t i=0; i < HCD_MAX_XFER; i++) - { - if ( !ohci_data.gtd_pool[i].used ) return &ohci_data.gtd_pool[i]; - } - - return NULL; -} - -static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd) -{ - // tail is always NULL - if ( tu_align16(p_ed->td_head.address) == 0 ) - { // TD queue is empty --> head = TD - p_ed->td_head.address |= (uint32_t) p_gtd; - } - else - { // TODO currently only support queue up to 2 TD each endpoint at a time - ((ohci_gtd_t*) tu_align16(p_ed->td_head.address))->next = (uint32_t) p_gtd; - } -} - -static bool pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) -{ - ohci_ed_t* const p_ed = ed_from_addr(dev_addr, ep_addr); - - // not support ISO yet - TU_VERIFY ( !p_ed->is_iso ); - - ohci_gtd_t * const p_gtd = gtd_find_free(); - TU_ASSERT(p_gtd); // not enough gtd - - gtd_init(p_gtd, buffer, total_bytes); - p_gtd->index = p_ed-ohci_data.ed_pool; - - if ( int_on_complete ) p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - - td_insert_to_ed(p_ed, p_gtd); - - return true; -} - -bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes) -{ - return pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes, false); -} - -bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) -{ - (void) int_on_complete; - TU_ASSERT( pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes, true) ); - - tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); - - if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; - - return true; -} - -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - ohci_ed_t const * const p_ed = ed_from_addr(dev_addr, ep_addr); - return tu_align16(p_ed->td_head.address) != tu_align16(p_ed->td_tail); -} - -bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) -{ - ohci_ed_t const * const p_ed = ed_from_addr(dev_addr, ep_addr); - return p_ed->td_head.halted && p_ed->is_stalled; -} - -bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) -{ - ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr); - - p_ed->is_stalled = 0; - p_ed->td_tail &= 0x0Ful; // set tail pointer back to NULL - - p_ed->td_head.toggle = 0; // reset data toggle - p_ed->td_head.halted = 0; - - if ( TUSB_XFER_BULK == ed_get_xfer_type(p_ed) ) OHCI_REG->command_status_bit.bulk_list_filled = 1; - - return true; -} - - -//--------------------------------------------------------------------+ -// OHCI Interrupt Handler -//--------------------------------------------------------------------+ -static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head) -{ - ohci_td_item_t* td_reverse_head = NULL; - - while(td_head != NULL) - { - uint32_t next = td_head->next; - - // make current's item become reverse's first item - td_head->next = (uint32_t) td_reverse_head; - td_reverse_head = td_head; - - td_head = (ohci_td_item_t*) next; // advance to next item - } - - return td_reverse_head; -} - -static inline bool gtd_is_control(ohci_gtd_t const * const p_qtd) -{ - return ((uint32_t) p_qtd) < ((uint32_t) ohci_data.gtd_pool); // check ohci_data_t for memory layout -} - -static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) -{ - if ( gtd_is_control(p_qtd) ) - { - return &ohci_data.control[p_qtd->index].ed; - }else - { - return &ohci_data.ed_pool[p_qtd->index]; - } -} - -static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) -{ // 5.2.9 OHCI sample code - return (tu_align4k(buffer_end ^ current_buffer) ? 0x1000 : 0) + - tu_offset4k(buffer_end) - tu_offset4k(current_buffer) + 1; -} - -static void done_queue_isr(uint8_t hostid) -{ - (void) hostid; - - // done head is written in reversed order of completion --> need to reverse the done queue first - ohci_td_item_t* td_head = list_reverse ( (ohci_td_item_t*) tu_align16(ohci_data.hcca.done_head) ); - - while( td_head != NULL ) - { - // TODO check if td_head is iso td - //------------- Non ISO transfer -------------// - ohci_gtd_t * const p_qtd = (ohci_gtd_t *) td_head; - xfer_result_t const event = (p_qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS : - (p_qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED; - - p_qtd->used = 0; // free TD - if ( (p_qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) ) - { - ohci_ed_t * const p_ed = gtd_get_ed(p_qtd); - - uint32_t const xferred_bytes = p_qtd->expected_bytes - gtd_xfer_byte_left((uint32_t) p_qtd->buffer_end, (uint32_t) p_qtd->current_buffer_pointer); - - // NOTE Assuming the current list is BULK and there is no other EDs in the list has queued TDs. - // When there is a error resulting this ED is halted, and this EP still has other queued TD - // --> the Bulk list only has this halted EP queueing TDs (remaining) - // --> Bulk list will be considered as not empty by HC !!! while there is no attempt transaction on this list - // --> HC will not process Control list (due to service ratio when Bulk list not empty) - // To walk-around this, the halted ED will have TailP = HeadP (empty list condition), when clearing halt - // the TailP must be set back to NULL for processing remaining TDs - if ((event != XFER_RESULT_SUCCESS)) - { - p_ed->td_tail &= 0x0Ful; - p_ed->td_tail |= tu_align16(p_ed->td_head.address); // mark halted EP as empty queue - if ( event == XFER_RESULT_STALLED ) p_ed->is_stalled = 1; - } - - hcd_event_xfer_complete(p_ed->dev_addr, - tu_edpt_addr(p_ed->ep_number, p_ed->pid == OHCI_PID_IN), - xferred_bytes, event, true); - } - - td_head = (ohci_td_item_t*) td_head->next; - } -} - -void hcd_int_handler(uint8_t hostid) -{ - uint32_t const int_en = OHCI_REG->interrupt_enable; - uint32_t const int_status = OHCI_REG->interrupt_status & int_en; - - if (int_status == 0) return; - - // Frame number overflow - if ( int_status & OHCI_INT_FRAME_OVERFLOW_MASK ) - { - ohci_data.frame_number_hi++; - } - - //------------- RootHub status -------------// - if ( int_status & OHCI_INT_RHPORT_STATUS_CHANGE_MASK ) - { - uint32_t const rhport_status = OHCI_REG->rhport_status[0] & OHCI_RHPORT_ALL_CHANGE_MASK; - - // TODO dual port is not yet supported - if ( rhport_status & OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK ) - { - // TODO check if remote wake-up - if ( OHCI_REG->rhport_status_bit[0].current_connect_status ) - { - // TODO reset port immediately, without this controller will got 2-3 (debouncing connection status change) - OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK; - hcd_event_device_attach(hostid, true); - }else - { - hcd_event_device_remove(hostid, true); - } - } - - if ( rhport_status & OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK) - { - - } - - OHCI_REG->rhport_status[0] = rhport_status; // acknowledge all interrupt - } - - //------------- Transfer Complete -------------// - if ( int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK) - { - done_queue_isr(hostid); - } - - OHCI_REG->interrupt_status = int_status; // Acknowledge handled interrupt -} -//--------------------------------------------------------------------+ -// HELPER -//--------------------------------------------------------------------+ - - -#endif - diff --git a/src/host/ohci/ohci.h b/src/host/ohci/ohci.h deleted file mode 100644 index 2915f8b00..000000000 --- a/src/host/ohci/ohci.h +++ /dev/null @@ -1,293 +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. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup Group_HCD - * @{ - * \defgroup OHCI - * \brief OHCI driver. All documents sources mentioned here (eg section 3.5) is referring to OHCI Specs unless state otherwise - * @{ */ - -#ifndef _TUSB_OHCI_H_ -#define _TUSB_OHCI_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#include "common/tusb_common.h" - -//--------------------------------------------------------------------+ -// OHCI CONFIGURATION & CONSTANTS -//--------------------------------------------------------------------+ -#define HOST_HCD_XFER_INTERRUPT // TODO interrupt is used widely, should always be enalbed -#define OHCI_PERIODIC_LIST (defined HOST_HCD_XFER_INTERRUPT || defined HOST_HCD_XFER_ISOCHRONOUS) - -// TODO merge OHCI with EHCI -enum { - OHCI_MAX_ITD = 4 -}; - -enum { - OHCI_PID_SETUP = 0, - OHCI_PID_OUT, - OHCI_PID_IN, -}; - -//--------------------------------------------------------------------+ -// OHCI Data Structure -//--------------------------------------------------------------------+ -typedef struct { - uint32_t interrupt_table[32]; - volatile uint16_t frame_number; - volatile uint16_t frame_pad; - volatile uint32_t done_head; - uint8_t reserved[116+4]; // TODO try to make use of this area if possible, extra 4 byte to make the whole struct size = 256 -}ohci_hcca_t; // TU_ATTR_ALIGNED(256) - -TU_VERIFY_STATIC( sizeof(ohci_hcca_t) == 256, "size is not correct" ); - -typedef struct { - uint32_t reserved[2]; - volatile uint32_t next; - uint32_t reserved2; -}ohci_td_item_t; - - -typedef struct TU_ATTR_ALIGNED(16) -{ - // Word 0 - uint32_t used : 1; - uint32_t index : 4; // endpoint index the td belongs to, or device address in case of control xfer - uint32_t expected_bytes : 13; // TODO available for hcd - - uint32_t buffer_rounding : 1; - uint32_t pid : 2; - uint32_t delay_interrupt : 3; - volatile uint32_t data_toggle : 2; - volatile uint32_t error_count : 2; - volatile uint32_t condition_code : 4; - - // Word 1 - volatile uint8_t* current_buffer_pointer; - - // Word 2 : next TD - volatile uint32_t next; - - // Word 3 - uint8_t* buffer_end; -} ohci_gtd_t; - -TU_VERIFY_STATIC( sizeof(ohci_gtd_t) == 16, "size is not correct" ); - -typedef struct TU_ATTR_ALIGNED(16) -{ - // Word 0 - uint32_t dev_addr : 7; - uint32_t ep_number : 4; - uint32_t pid : 2; // 00b from TD, 01b Out, 10b In - uint32_t speed : 1; - uint32_t skip : 1; - uint32_t is_iso : 1; - uint32_t max_packet_size : 11; - // HCD: make use of 5 reserved bits - uint32_t used : 1; - uint32_t is_interrupt_xfer : 1; - uint32_t is_stalled : 1; - uint32_t : 2; - - // Word 1 - uint32_t td_tail; - - // Word 2 - volatile union { - uint32_t address; - struct { - uint32_t halted : 1; - uint32_t toggle : 1; - uint32_t : 30; - }; - }td_head; - - // Word 3: next ED - uint32_t next; -} ohci_ed_t; - -TU_VERIFY_STATIC( sizeof(ohci_ed_t) == 16, "size is not correct" ); - -typedef struct TU_ATTR_ALIGNED(32) -{ - /*---------- Word 1 ----------*/ - uint32_t starting_frame : 16; - uint32_t : 5; // can be used - uint32_t delay_interrupt : 3; - uint32_t frame_count : 3; - uint32_t : 1; // can be used - volatile uint32_t condition_code : 4; - - /*---------- Word 2 ----------*/ - uint32_t buffer_page0; // 12 lsb bits can be used - - /*---------- Word 3 ----------*/ - volatile uint32_t next; - - /*---------- Word 4 ----------*/ - uint32_t buffer_end; - - /*---------- Word 5-8 ----------*/ - volatile uint16_t offset_packetstatus[8]; -} ochi_itd_t; - -TU_VERIFY_STATIC( sizeof(ochi_itd_t) == 32, "size is not correct" ); - -// structure with member alignment required from large to small -typedef struct TU_ATTR_ALIGNED(256) -{ - ohci_hcca_t hcca; - - ohci_ed_t bulk_head_ed; // static bulk head (dummy) - ohci_ed_t period_head_ed; // static periodic list head (dummy) - - // control endpoints has reserved resources - struct { - ohci_ed_t ed; - ohci_gtd_t gtd; - }control[CFG_TUSB_HOST_DEVICE_MAX+1]; - - // ochi_itd_t itd[OHCI_MAX_ITD]; // itd requires alignment of 32 - ohci_ed_t ed_pool[HCD_MAX_ENDPOINT]; - ohci_gtd_t gtd_pool[HCD_MAX_XFER]; - - volatile uint16_t frame_number_hi; - -} ohci_data_t; - -//--------------------------------------------------------------------+ -// OHCI Operational Register -//--------------------------------------------------------------------+ - - -//--------------------------------------------------------------------+ -// OHCI Data Organization -//--------------------------------------------------------------------+ -typedef volatile struct -{ - uint32_t revision; - - union { - uint32_t control; - struct { - uint32_t control_bulk_service_ratio : 2; - uint32_t periodic_list_enable : 1; - uint32_t isochronous_enable : 1; - uint32_t control_list_enable : 1; - uint32_t bulk_list_enable : 1; - uint32_t hc_functional_state : 2; - uint32_t interrupt_routing : 1; - uint32_t remote_wakeup_connected : 1; - uint32_t remote_wakeup_enale : 1; - uint32_t TU_RESERVED : 21; - }control_bit; - }; - - union { - uint32_t command_status; - struct { - uint32_t controller_reset : 1; - uint32_t control_list_filled : 1; - uint32_t bulk_list_filled : 1; - uint32_t ownership_change_request : 1; - uint32_t : 12; - uint32_t scheduling_overrun_count : 2; - }command_status_bit; - }; - - uint32_t interrupt_status; - uint32_t interrupt_enable; - uint32_t interrupt_disable; - - uint32_t hcca; - uint32_t period_current_ed; - uint32_t control_head_ed; - uint32_t control_current_ed; - uint32_t bulk_head_ed; - uint32_t bulk_current_ed; - uint32_t done_head; - - uint32_t frame_interval; - uint32_t frame_remaining; - uint32_t frame_number; - uint32_t periodic_start; - uint32_t lowspeed_threshold; - - uint32_t rh_descriptorA; - uint32_t rh_descriptorB; - - union { - uint32_t rh_status; - struct { - uint32_t local_power_status : 1; // read Local Power Status; write: Clear Global Power - uint32_t over_current_indicator : 1; - uint32_t : 13; - uint32_t device_remote_wakeup_enable : 1; - uint32_t local_power_status_change : 1; - uint32_t over_current_indicator_change : 1; - uint32_t : 13; - uint32_t clear_remote_wakeup_enable : 1; - }rh_status_bit; - }; - - union { - uint32_t rhport_status[2]; // TODO NXP OHCI controller only has 2 ports - struct { - uint32_t current_connect_status : 1; - uint32_t port_enable_status : 1; - uint32_t port_suspend_status : 1; - uint32_t port_over_current_indicator : 1; - uint32_t port_reset_status : 1; - uint32_t : 3; - uint32_t port_power_status : 1; - uint32_t low_speed_device_attached : 1; - uint32_t : 6; - uint32_t connect_status_change : 1; - uint32_t port_enable_status_change : 1; - uint32_t port_suspend_status_change : 1; - uint32_t port_over_current_indicator_change : 1; - uint32_t port_reset_status_change : 1; - uint32_t TU_RESERVED : 11; - }rhport_status_bit[2]; - }; -}ohci_registers_t; - -TU_VERIFY_STATIC( sizeof(ohci_registers_t) == 0x5c, "size is not correct"); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_OHCI_H_ */ - -/** @} */ -/** @} */ diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c new file mode 100644 index 000000000..e2327fdc0 --- /dev/null +++ b/src/portable/ehci/ehci.c @@ -0,0 +1,901 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "common/tusb_common.h" + +#if TUSB_OPT_HOST_ENABLED && \ + (CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || \ + CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX ) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "osal/osal.h" + +#include "host/hcd.h" +#include "host/usbh_hcd.h" +#include "ehci.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +// Periodic frame list must be 4K alignment +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data; + +// EHCI portable +uint32_t hcd_ehci_register_addr(uint8_t rhport); +bool hcd_ehci_init (uint8_t rhport); // TODO move later + +//--------------------------------------------------------------------+ +// PROTOTYPE +//--------------------------------------------------------------------+ +static inline ehci_link_t* get_period_head(uint8_t rhport, uint8_t interval_ms) +{ + (void) rhport; + return (ehci_link_t*) &ehci_data.period_head_arr[ tu_log2( tu_min8(EHCI_FRAMELIST_SIZE, interval_ms) ) ]; +} + +static inline ehci_qhd_t* qhd_control(uint8_t dev_addr) +{ + return &ehci_data.control[dev_addr].qhd; +} + +static inline ehci_qhd_t* qhd_async_head(uint8_t rhport) +{ + (void) rhport; + return qhd_control(0); // control qhd of dev0 is used as async head +} + +static inline ehci_qtd_t* qtd_control(uint8_t dev_addr) +{ + return &ehci_data.control[dev_addr].qtd; +} + + +static inline ehci_qhd_t* qhd_next (ehci_qhd_t const * p_qhd); +static inline ehci_qhd_t* qhd_find_free (void); +static inline ehci_qhd_t* qhd_get_from_addr (uint8_t dev_addr, uint8_t ep_addr); + +// determine if a queue head has bus-related error +static inline bool qhd_has_xact_error (ehci_qhd_t * p_qhd) +{ + return (p_qhd->qtd_overlay.buffer_err || p_qhd->qtd_overlay.babble_err || p_qhd->qtd_overlay.xact_err); + //p_qhd->qtd_overlay.non_hs_period_missed_uframe || p_qhd->qtd_overlay.pingstate_err TODO split transaction error +} + +static void qhd_init (ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); + +static inline ehci_qtd_t* qtd_find_free (void); +static inline ehci_qtd_t* qtd_next (ehci_qtd_t const * p_qtd); +static inline void qtd_insert_to_qhd (ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new); +static inline void qtd_remove_1st_from_qhd (ehci_qhd_t *p_qhd); +static void qtd_init (ehci_qtd_t* p_qtd, void* buffer, uint16_t total_bytes); + +static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type); +static inline ehci_link_t* list_next (ehci_link_t *p_link_pointer); + +//--------------------------------------------------------------------+ +// HCD API +//--------------------------------------------------------------------+ + +uint32_t hcd_uframe_number(uint8_t rhport) +{ + (void) rhport; + return ehci_data.uframe_number + ehci_data.regs->frame_index; +} + +void hcd_port_reset(uint8_t rhport) +{ + (void) rhport; + + ehci_registers_t* regs = ehci_data.regs; + +// regs->portsc_bm.port_enabled = 0; // disable port before reset +// regs->portsc_bm.port_reset = 1; + + uint32_t portsc = regs->portsc; + + portsc &= ~(EHCI_PORTSC_MASK_PORT_EANBLED); + portsc |= EHCI_PORTSC_MASK_PORT_RESET; + + regs->portsc = portsc; +} + +#if 0 +void hcd_port_reset_end(uint8_t rhport) +{ + (void) rhport; + + ehci_registers_t* regs = ehci_data.regs; + regs->portsc_bm.port_reset = 0; +} +#endif + +bool hcd_port_connect_status(uint8_t rhport) +{ + (void) rhport; + return ehci_data.regs->portsc_bm.current_connect_status; +} + +tusb_speed_t hcd_port_speed_get(uint8_t rhport) +{ + (void) rhport; + return (tusb_speed_t) ehci_data.regs->portsc_bm.nxp_port_speed; // NXP specific port speed +} + +static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr) +{ + for(ehci_link_t* prev = list_head; + !prev->terminate && (tu_align32(prev->address) != (uint32_t) list_head); + prev = list_next(prev) ) + { + // TODO check type for ISO iTD and siTD + ehci_qhd_t* qhd = (ehci_qhd_t*) list_next(prev); + if ( qhd->dev_addr == dev_addr ) + { + // TODO deactive all TD, wait for QHD to inactive before removal + prev->address = qhd->next.address; + + // EHCI 4.8.2 link the removed qhd to async head (which always reachable by Host Controller) + qhd->next.address = ((uint32_t) list_head) | (EHCI_QTYPE_QHD << 1); + + if ( qhd->int_smask ) + { + // period list queue element is guarantee to be free in the next frame (1 ms) + qhd->used = 0; + }else + { + // async list use async advance handshake + // mark as removing, will completely re-usable when async advance isr occurs + qhd->removing = 1; + } + } + } +} + +// Close all opened endpoint belong to this device +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) +{ + // skip dev0 + if (dev_addr == 0) return; + + // Remove from async list + list_remove_qhd_by_addr( (ehci_link_t*) qhd_async_head(rhport), dev_addr ); + + // Remove from all interval period list + for(uint8_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++) + { + list_remove_qhd_by_addr( (ehci_link_t*) &ehci_data.period_head_arr[i], dev_addr); + } + + // Async doorbell (EHCI 4.8.2 for operational details) + ehci_data.regs->command_bm.async_adv_doorbell = 1; +} + +// EHCI controller init +bool hcd_ehci_init(uint8_t rhport) +{ + tu_memclr(&ehci_data, sizeof(ehci_data_t)); + + ehci_data.regs = (ehci_registers_t* ) hcd_ehci_register_addr(rhport); + + ehci_registers_t* regs = ehci_data.regs; + + //------------- CTRLDSSEGMENT Register (skip) -------------// + //------------- USB INT Register -------------// + regs->inten = 0; // 1. disable all the interrupt + regs->status = EHCI_INT_MASK_ALL; // 2. clear all status + + regs->inten = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE | EHCI_INT_MASK_ASYNC_ADVANCE | + EHCI_INT_MASK_NXP_PERIODIC | EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_FRAMELIST_ROLLOVER; + + //------------- Asynchronous List -------------// + ehci_qhd_t * const async_head = qhd_async_head(rhport); + tu_memclr(async_head, sizeof(ehci_qhd_t)); + + async_head->next.address = (uint32_t) async_head; // circular list, next is itself + async_head->next.type = EHCI_QTYPE_QHD; + async_head->head_list_flag = 1; + async_head->qtd_overlay.halted = 1; // inactive most of time + async_head->qtd_overlay.next.terminate = 1; // TODO removed if verified + + regs->async_list_addr = (uint32_t) async_head; + + //------------- Periodic List -------------// + // Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only + for(uint32_t i=0; i<4; i++) + { + ehci_data.period_head_arr[i].int_smask = 1; // queue head in period list must have smask non-zero + ehci_data.period_head_arr[i].qtd_overlay.halted = 1; // dummy node, always inactive + } + + ehci_link_t * const framelist = ehci_data.period_framelist; + ehci_link_t * const period_1ms = get_period_head(rhport, 1); + // all links --> period_head_arr[0] (1ms) + // 0, 2, 4, 6 etc --> period_head_arr[1] (2ms) + // 1, 5 --> period_head_arr[2] (4ms) + // 3 --> period_head_arr[3] (8ms) + + // TODO EHCI_FRAMELIST_SIZE with other size than 8 + for(uint32_t i=0; iterminate = 1; + + regs->periodic_list_base = (uint32_t) framelist; + + //------------- TT Control (NXP only) -------------// + regs->nxp_tt_control = 0; + + //------------- USB CMD Register -------------// + regs->command |= TU_BIT(EHCI_USBCMD_POS_RUN_STOP) | TU_BIT(EHCI_USBCMD_POS_ASYNC_ENABLE) + | TU_BIT(EHCI_USBCMD_POS_PERIOD_ENABLE) // TODO enable period list only there is int/iso endpoint + | ((EHCI_CFG_FRAMELIST_SIZE_BITS & TU_BIN8(011)) << EHCI_USBCMD_POS_FRAMELIST_SZIE) + | ((EHCI_CFG_FRAMELIST_SIZE_BITS >> 2) << EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB); + + //------------- ConfigFlag Register (skip) -------------// + regs->portsc_bm.port_power = 1; // enable port power + + return true; +} + +#if 0 +static void ehci_stop(uint8_t rhport) +{ + (void) rhport; + + ehci_registers_t* regs = ehci_data.regs; + + regs->command_bm.run_stop = 0; + + // USB Spec: controller has to stop within 16 uframe = 2 frames + while( regs->status_bm.hc_halted == 0 ) {} +} +#endif + +//--------------------------------------------------------------------+ +// CONTROL PIPE API +//--------------------------------------------------------------------+ +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + // FIXME control only for now + if ( epnum == 0 ) + { + ehci_qhd_t* qhd = qhd_control(dev_addr); + ehci_qtd_t* qtd = qtd_control(dev_addr); + + qtd_init(qtd, buffer, buflen); + + // first first data toggle is always 1 (data & setup stage) + qtd->data_toggle = 1; + qtd->pid = dir ? EHCI_PID_IN : EHCI_PID_OUT; + qtd->int_on_complete = 1; + qtd->next.terminate = 1; + + // sw region + qhd->p_qtd_list_head = qtd; + qhd->p_qtd_list_tail = qtd; + + // attach TD + qhd->qtd_overlay.next.address = (uint32_t) qtd; + }else + { + ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); + ehci_qtd_t *p_qtd = qtd_find_free(); + TU_ASSERT(p_qtd); + + qtd_init(p_qtd, buffer, buflen); + p_qtd->pid = p_qhd->pid; + + // Insert TD to QH + qtd_insert_to_qhd(p_qhd, p_qtd); + + p_qhd->p_qtd_list_tail->int_on_complete = 1; + + // attach head QTD to QHD start transferring + p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; + } + + return true; +} + +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) +{ + (void) rhport; + + ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd; + ehci_qtd_t* td = &ehci_data.control[dev_addr].qtd; + + qtd_init(td, (void*) setup_packet, 8); + td->pid = EHCI_PID_SETUP; + td->int_on_complete = 1; + td->next.terminate = 1; + + // sw region + qhd->p_qtd_list_head = td; + qhd->p_qtd_list_tail = td; + + // attach TD + qhd->qtd_overlay.next.address = (uint32_t) td; + + return true; +} + +//--------------------------------------------------------------------+ +// BULK/INT/ISO PIPE API +//--------------------------------------------------------------------+ +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +{ + (void) rhport; + + // TODO not support ISO yet + TU_ASSERT (ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); + + //------------- Prepare Queue Head -------------// + ehci_qhd_t * p_qhd; + + if ( ep_desc->bEndpointAddress == 0 ) + { + p_qhd = qhd_control(dev_addr); + }else + { + p_qhd = qhd_find_free(); + } + TU_ASSERT(p_qhd); + + qhd_init(p_qhd, dev_addr, ep_desc); + + // control of dev0 is always present as async head + if ( dev_addr == 0 ) return true; + + // Insert to list + ehci_link_t * list_head = NULL; + + switch (ep_desc->bmAttributes.xfer) + { + case TUSB_XFER_CONTROL: + case TUSB_XFER_BULK: + list_head = (ehci_link_t*) qhd_async_head(rhport); + break; + + case TUSB_XFER_INTERRUPT: + list_head = get_period_head(rhport, p_qhd->interval_ms); + break; + + case TUSB_XFER_ISOCHRONOUS: + // TODO iso is not supported + break; + + default: break; + } + + TU_ASSERT(list_head); + + // TODO might need to disable async/period list + list_insert(list_head, (ehci_link_t*) p_qhd, EHCI_QTYPE_QHD); + + return true; +} + +bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes) +{ + //------------- set up QTD -------------// + ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); + ehci_qtd_t *p_qtd = qtd_find_free(); + + TU_ASSERT(p_qtd); + + qtd_init(p_qtd, buffer, total_bytes); + p_qtd->pid = p_qhd->pid; + + //------------- insert TD to TD list -------------// + qtd_insert_to_qhd(p_qhd, p_qtd); + + return true; +} + +bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) +{ + TU_ASSERT ( hcd_pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes) ); + + ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); + + if ( int_on_complete ) + { // the just added qtd is pointed by list_tail + p_qhd->p_qtd_list_tail->int_on_complete = 1; + } + p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; // attach head QTD to QHD start transferring + + return true; +} + +bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +{ + ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); + return !p_qhd->qtd_overlay.halted && (p_qhd->p_qtd_list_head != NULL); +} + +bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) +{ + ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); + return p_qhd->qtd_overlay.halted && !qhd_has_xact_error(p_qhd); +} + +bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) +{ + ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); + p_qhd->qtd_overlay.halted = 0; + // TODO reset data toggle ? + return true; +} + +//--------------------------------------------------------------------+ +// EHCI Interrupt Handler +//--------------------------------------------------------------------+ + +// async_advance is handshake between usb stack & ehci controller. +// This isr mean it is safe to modify previously removed queue head from async list. +// In tinyusb, queue head is only removed when device is unplugged. +static void async_advance_isr(uint8_t rhport) +{ + (void) rhport; + + ehci_qhd_t* qhd_pool = ehci_data.qhd_pool; + for(uint32_t i = 0; i < HCD_MAX_ENDPOINT; i++) + { + if ( qhd_pool[i].removing ) + { + qhd_pool[i].removing = 0; + qhd_pool[i].used = 0; + } + } +} + +static void port_connect_status_change_isr(uint8_t hostid) +{ + // NOTE There is an sequence plug->unplug->…..-> plug if device is powering with pre-plugged device + if (ehci_data.regs->portsc_bm.current_connect_status) + { + hcd_port_reset(hostid); + hcd_event_device_attach(hostid, true); + }else // device unplugged + { + hcd_event_device_remove(hostid, true); + } +} + +static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) +{ + // free all TDs from the head td to the first active TD + while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active) + { + // TD need to be freed and removed from qhd, before invoking callback + bool is_ioc = (p_qhd->p_qtd_list_head->int_on_complete != 0); + p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; + + p_qhd->p_qtd_list_head->used = 0; // free QTD + qtd_remove_1st_from_qhd(p_qhd); + + if (is_ioc) + { + // end of request + // call USBH callback + hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), p_qhd->total_xferred_bytes, XFER_RESULT_SUCCESS, true); + p_qhd->total_xferred_bytes = 0; + } + } +} + +static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head) +{ + ehci_qhd_t *p_qhd = async_head; + do + { + if ( !p_qhd->qtd_overlay.halted ) // halted or error is processed in error isr + { + qhd_xfer_complete_isr(p_qhd); + } + p_qhd = qhd_next(p_qhd); + }while(p_qhd != async_head); // async list traversal, stop if loop around +} + +static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms) +{ + uint16_t max_loop = 0; + uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1); + ehci_link_t next_item = * get_period_head(hostid, interval_ms); + + // TODO abstract max loop guard for period + while( !next_item.terminate && + !(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) && + max_loop < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUSB_HOST_DEVICE_MAX) + { + switch ( next_item.type ) + { + case EHCI_QTYPE_QHD: + { + ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) tu_align32(next_item.address); + if ( !p_qhd_int->qtd_overlay.halted ) + { + qhd_xfer_complete_isr(p_qhd_int); + } + } + break; + + case EHCI_QTYPE_ITD: // TODO support hs/fs ISO + case EHCI_QTYPE_SITD: + case EHCI_QTYPE_FSTN: + + default: break; + } + + next_item = *list_next(&next_item); + max_loop++; + } +} + +static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) +{ + if ( (p_qhd->dev_addr != 0 && p_qhd->qtd_overlay.halted) || // addr0 cannot be protocol STALL + qhd_has_xact_error(p_qhd) ) + { + // current qhd has error in transaction + xfer_result_t error_event; + + // no error bits are set, endpoint is halted due to STALL + error_event = qhd_has_xact_error(p_qhd) ? XFER_RESULT_FAILED : XFER_RESULT_STALLED; + + p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; + +// if ( XFER_RESULT_FAILED == error_event ) TU_BREAKPOINT(); // TODO skip unplugged device + + p_qhd->p_qtd_list_head->used = 0; // free QTD + qtd_remove_1st_from_qhd(p_qhd); + + if ( 0 == p_qhd->ep_number ) + { + // control cannot be halted --> clear all qtd list + p_qhd->p_qtd_list_head = NULL; + p_qhd->p_qtd_list_tail = NULL; + + p_qhd->qtd_overlay.next.terminate = 1; + p_qhd->qtd_overlay.alternate.terminate = 1; + p_qhd->qtd_overlay.halted = 0; + + ehci_qtd_t *p_setup = qtd_control(p_qhd->dev_addr); + p_setup->used = 0; + } + + // call USBH callback + hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), p_qhd->total_xferred_bytes, error_event, true); + + p_qhd->total_xferred_bytes = 0; + } +} + +static void xfer_error_isr(uint8_t hostid) +{ + //------------- async list -------------// + ehci_qhd_t * const async_head = qhd_async_head(hostid); + ehci_qhd_t *p_qhd = async_head; + do + { + qhd_xfer_error_isr( p_qhd ); + p_qhd = qhd_next(p_qhd); + }while(p_qhd != async_head); // async list traversal, stop if loop around + + //------------- TODO refractor period list -------------// + uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1); + for (uint8_t interval_ms=1; interval_ms <= EHCI_FRAMELIST_SIZE; interval_ms *= 2) + { + ehci_link_t next_item = * get_period_head(hostid, interval_ms); + + // TODO abstract max loop guard for period + while( !next_item.terminate && + !(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) ) + { + switch ( next_item.type ) + { + case EHCI_QTYPE_QHD: + { + ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) tu_align32(next_item.address); + qhd_xfer_error_isr(p_qhd_int); + } + break; + + // TODO support hs/fs ISO + case EHCI_QTYPE_ITD: + case EHCI_QTYPE_SITD: + case EHCI_QTYPE_FSTN: + default: break; + } + + next_item = *list_next(&next_item); + } + } +} + +//------------- Host Controller Driver's Interrupt Handler -------------// +void hcd_int_handler(uint8_t rhport) +{ + ehci_registers_t* regs = ehci_data.regs; + + uint32_t int_status = regs->status; + int_status &= regs->inten; + + regs->status |= int_status; // Acknowledge handled interrupt + + if (int_status == 0) return; + + if (int_status & EHCI_INT_MASK_FRAMELIST_ROLLOVER) + { + ehci_data.uframe_number += (EHCI_FRAMELIST_SIZE << 3); + } + + if (int_status & EHCI_INT_MASK_PORT_CHANGE) + { + uint32_t port_status = regs->portsc & EHCI_PORTSC_MASK_ALL; + + if (regs->portsc_bm.connect_status_change) + { + port_connect_status_change_isr(rhport); + } + + regs->portsc |= port_status; // Acknowledge change bits in portsc + } + + if (int_status & EHCI_INT_MASK_ERROR) + { + xfer_error_isr(rhport); + } + + //------------- some QTD/SITD/ITD with IOC set is completed -------------// + if (int_status & EHCI_INT_MASK_NXP_ASYNC) + { + async_list_xfer_complete_isr( qhd_async_head(rhport) ); + } + + if (int_status & EHCI_INT_MASK_NXP_PERIODIC) + { + for (uint8_t i=1; i <= EHCI_FRAMELIST_SIZE; i *= 2) + { + period_list_xfer_complete_isr( rhport, i ); + } + } + + //------------- There is some removed async previously -------------// + if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) // need to place after EHCI_INT_MASK_NXP_ASYNC + { + async_advance_isr(rhport); + } +} + +//--------------------------------------------------------------------+ +// HELPER +//--------------------------------------------------------------------+ + + +//------------- queue head helper -------------// +static inline ehci_qhd_t* qhd_find_free (void) +{ + for (uint32_t i=0; inext.address); +} + +static inline ehci_qhd_t* qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) +{ + ehci_qhd_t* qhd_pool = ehci_data.qhd_pool; + + for(uint32_t i=0; inext.address); +} + +static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd) +{ + if (p_qhd->p_qtd_list_head == p_qhd->p_qtd_list_tail) // last TD --> make it NULL + { + p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = NULL; + }else + { + p_qhd->p_qtd_list_head = qtd_next( p_qhd->p_qtd_list_head ); + } +} + +static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new) +{ + if (p_qhd->p_qtd_list_head == NULL) // empty list + { + p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = p_qtd_new; + }else + { + p_qhd->p_qtd_list_tail->next.address = (uint32_t) p_qtd_new; + p_qhd->p_qtd_list_tail = p_qtd_new; + } +} + +static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +{ + // address 0 is used as async head, which always on the list --> cannot be cleared (ehci halted otherwise) + if (dev_addr != 0) + { + tu_memclr(p_qhd, sizeof(ehci_qhd_t)); + } + + uint8_t const xfer_type = ep_desc->bmAttributes.xfer; + uint8_t const interval = ep_desc->bInterval; + + p_qhd->dev_addr = dev_addr; + p_qhd->fl_inactive_next_xact = 0; + p_qhd->ep_number = tu_edpt_number(ep_desc->bEndpointAddress); + p_qhd->ep_speed = _usbh_devices[dev_addr].speed; + p_qhd->data_toggle_control= (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0; + p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static asyn list head + p_qhd->max_packet_size = ep_desc->wMaxPacketSize.size; + p_qhd->fl_ctrl_ep_flag = ((xfer_type == TUSB_XFER_CONTROL) && (p_qhd->ep_speed != TUSB_SPEED_HIGH)) ? 1 : 0; + p_qhd->nak_reload = 0; + + // Bulk/Control -> smask = cmask = 0 + // TODO Isochronous + if (TUSB_XFER_INTERRUPT == xfer_type) + { + if (TUSB_SPEED_HIGH == p_qhd->ep_speed) + { + TU_ASSERT( interval <= 16, ); + if ( interval < 4) // sub milisecond interval + { + p_qhd->interval_ms = 0; + p_qhd->int_smask = (interval == 1) ? TU_BIN8(11111111) : + (interval == 2) ? TU_BIN8(10101010) : TU_BIN8(01000100); + }else + { + p_qhd->interval_ms = (uint8_t) tu_min16( 1 << (interval-4), 255 ); + p_qhd->int_smask = TU_BIT(interval % 8); + } + }else + { + TU_ASSERT( 0 != interval, ); + // Full/Low: 4.12.2.1 (EHCI) case 1 schedule start split at 1 us & complete split at 2,3,4 uframes + p_qhd->int_smask = 0x01; + p_qhd->fl_int_cmask = TU_BIN8(11100); + p_qhd->interval_ms = interval; + } + }else + { + p_qhd->int_smask = p_qhd->fl_int_cmask = 0; + } + + p_qhd->fl_hub_addr = _usbh_devices[dev_addr].hub_addr; + p_qhd->fl_hub_port = _usbh_devices[dev_addr].hub_port; + p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet + + //------------- HCD Management Data -------------// + p_qhd->used = 1; + p_qhd->removing = 0; + p_qhd->p_qtd_list_head = NULL; + p_qhd->p_qtd_list_tail = NULL; + p_qhd->pid = tu_edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint + + //------------- active, but no TD list -------------// + p_qhd->qtd_overlay.halted = 0; + p_qhd->qtd_overlay.next.terminate = 1; + p_qhd->qtd_overlay.alternate.terminate = 1; + if (TUSB_XFER_BULK == xfer_type && p_qhd->ep_speed == TUSB_SPEED_HIGH && p_qhd->pid == EHCI_PID_OUT) + { + p_qhd->qtd_overlay.ping_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11 + } +} + +static void qtd_init(ehci_qtd_t* p_qtd, void* buffer, uint16_t total_bytes) +{ + tu_memclr(p_qtd, sizeof(ehci_qtd_t)); + + p_qtd->used = 1; + + p_qtd->next.terminate = 1; // init to null + p_qtd->alternate.terminate = 1; // not used, always set to terminated + p_qtd->active = 1; + p_qtd->err_count = 3; // TODO 3 consecutive errors tolerance + p_qtd->data_toggle = 0; + p_qtd->total_bytes = total_bytes; + p_qtd->expected_bytes = total_bytes; + + p_qtd->buffer[0] = (uint32_t) buffer; + for(uint8_t i=1; i<5; i++) + { + p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096; + } +} + +//------------- List Managing Helper -------------// +static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type) +{ + new->address = current->address; + current->address = ((uint32_t) new) | (new_type << 1); +} + +static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer) +{ + return (ehci_link_t*) tu_align32(p_link_pointer->address); +} + +#endif diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h new file mode 100644 index 000000000..212f605b1 --- /dev/null +++ b/src/portable/ehci/ehci.h @@ -0,0 +1,460 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup Group_HCD + * @{ + * \defgroup EHCI + * \brief EHCI driver. All documents sources mentioned here (eg section 3.5) is referring to EHCI Specs unless state otherwise + * @{ */ + +#ifndef _TUSB_EHCI_H_ +#define _TUSB_EHCI_H_ + + +/* Abbreviation + * HC: Host Controller + * HCD: Host Controller Driver + * QHD: Queue Head for non-ISO transfer + * QTD: Queue Transfer Descriptor for non-ISO transfer + * ITD: Iso Transfer Descriptor for highspeed + * SITD: Split ISO Transfer Descriptor for full-speed + * SMASK: Start Split mask for Slipt Transaction + * CMASK: Complete Split mask for Slipt Transaction +*/ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// EHCI CONFIGURATION & CONSTANTS +//--------------------------------------------------------------------+ +#define EHCI_CFG_FRAMELIST_SIZE_BITS 7 /// Framelist Size (NXP specific) (0:1024) - (1:512) - (2:256) - (3:128) - (4:64) - (5:32) - (6:16) - (7:8) +#define EHCI_FRAMELIST_SIZE (1024 >> EHCI_CFG_FRAMELIST_SIZE_BITS) + +// TODO merge OHCI with EHCI +enum { + EHCI_MAX_ITD = 4, + EHCI_MAX_SITD = 16 +}; + +//------------- Validation -------------// +TU_VERIFY_STATIC(EHCI_CFG_FRAMELIST_SIZE_BITS <= 7, "incorrect value"); + +//--------------------------------------------------------------------+ +// EHCI Data Structure +//--------------------------------------------------------------------+ +enum +{ + EHCI_QTYPE_ITD = 0 , + EHCI_QTYPE_QHD , + EHCI_QTYPE_SITD , + EHCI_QTYPE_FSTN +}; + +/// EHCI PID +enum +{ + EHCI_PID_OUT = 0 , + EHCI_PID_IN , + EHCI_PID_SETUP +}; + +/// Link pointer +typedef union { + uint32_t address; + struct { + uint32_t terminate : 1; + uint32_t type : 2; + }; +}ehci_link_t; + +/// Queue Element Transfer Descriptor +/// Qtd is used to declare overlay in ehci_qhd_t -> cannot be declared with TU_ATTR_ALIGNED(32) +typedef struct +{ + // Word 0: Next QTD Pointer + ehci_link_t next; + + // Word 1: Alternate Next QTD Pointer (not used) + union{ + ehci_link_t alternate; + struct { + uint32_t : 5; + uint32_t used : 1; + uint32_t : 10; + uint32_t expected_bytes : 16; + }; + }; + + // Word 2: qTQ Token + volatile uint32_t ping_err : 1 ; ///< For Highspeed: 0 Out, 1 Ping. Full/Slow used as error indicator + volatile uint32_t non_hs_split_state : 1 ; ///< Used by HC to track the state of slipt transaction + volatile uint32_t non_hs_missed_uframe : 1 ; ///< HC misses a complete slip transaction + volatile uint32_t xact_err : 1 ; ///< Error (Timeout, CRC, Bad PID ... ) + volatile uint32_t babble_err : 1 ; ///< Babble detected, also set Halted bit to 1 + volatile uint32_t buffer_err : 1 ; ///< Data overrun/underrun error + volatile uint32_t halted : 1 ; ///< Serious error or STALL received + volatile uint32_t active : 1 ; ///< Start transfer, clear by HC when complete + + uint32_t pid : 2 ; ///< 0: OUT, 1: IN, 2 Setup + volatile uint32_t err_count : 2 ; ///< Error Counter of consecutive errors + volatile uint32_t current_page : 3 ; ///< Index into the qTD buffer pointer list + uint32_t int_on_complete : 1 ; ///< Interrupt on complete + volatile uint32_t total_bytes : 15 ; ///< Transfer bytes, decreased during transaction + volatile uint32_t data_toggle : 1 ; ///< Data Toogle bit + + + /// Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page + uint32_t buffer[5]; +} ehci_qtd_t; + +TU_VERIFY_STATIC( sizeof(ehci_qtd_t) == 32, "size is not correct" ); + +/// Queue Head +typedef struct TU_ATTR_ALIGNED(32) +{ + // Word 0: Next QHD + ehci_link_t next; + + // Word 1: Endpoint Characteristics + uint32_t dev_addr : 7 ; ///< device address + uint32_t fl_inactive_next_xact : 1 ; ///< Only valid for Periodic with Full/Slow speed + uint32_t ep_number : 4 ; ///< EP number + uint32_t ep_speed : 2 ; ///< 0: Full, 1: Low, 2: High + uint32_t data_toggle_control : 1 ; ///< 0: use DT in qHD, 1: use DT in qTD + uint32_t head_list_flag : 1 ; ///< Head of the queue + uint32_t max_packet_size : 11 ; ///< Max packet size + uint32_t fl_ctrl_ep_flag : 1 ; ///< 1 if is Full/Low speed control endpoint + uint32_t nak_reload : 4 ; ///< Used by HC + + // Word 2: Endpoint Capabilities + uint32_t int_smask : 8 ; ///< Interrupt Schedule Mask + uint32_t fl_int_cmask : 8 ; ///< Split Completion Mask for Full/Slow speed + uint32_t fl_hub_addr : 7 ; ///< Hub Address for Full/Slow speed + uint32_t fl_hub_port : 7 ; ///< Hub Port for Full/Slow speed + uint32_t mult : 2 ; ///< Transaction per micro frame + + // Word 3: Current qTD Pointer + volatile uint32_t qtd_addr; + + // Word 4-11: Transfer Overlay + volatile ehci_qtd_t qtd_overlay; + + //--------------------------------------------------------------------+ + /// Due to the fact QHD is 32 bytes aligned but occupies only 48 bytes + /// thus there are 16 bytes padding free that we can make use of. + //--------------------------------------------------------------------+ + uint8_t used; + uint8_t removing; // removed from asyn list, waiting for async advance + uint8_t pid; + uint8_t interval_ms; // polling interval in frames (or milisecond) + + uint16_t total_xferred_bytes; // number of bytes xferred until a qtd with ioc bit set + uint8_t reserved2[2]; + + ehci_qtd_t * volatile p_qtd_list_head; // head of the scheduled TD list + ehci_qtd_t * volatile p_qtd_list_tail; // tail of the scheduled TD list +} ehci_qhd_t; + +TU_VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" ); + +/// Highspeed Isochronous Transfer Descriptor (section 3.3) +typedef struct TU_ATTR_ALIGNED(32) { + // Word 0: Next Link Pointer + ehci_link_t next; + + // Word 1-8: iTD Transaction Status and Control List + struct { + // iTD Control + volatile uint32_t offset : 12 ; ///< This field is a value that is an offset, expressed in bytes, from the beginning of a buffer. + volatile uint32_t page_select : 3 ; ///< These bits are set by software to indicate which of the buffer page pointers the offset field in this slot should be concatenated to produce the starting memory address for this transaction. The valid range of values for this field is 0 to 6 + uint32_t int_on_complete : 1 ; ///< If this bit is set to a one, it specifies that when this transaction completes, the Host Controller should issue an interrupt at the next interrupt threshold + volatile uint32_t length : 12 ; ///< For an OUT, this field is the number of data bytes the host controller will send during the transaction. The host controller is not required to update this field to reflect the actual number of bytes transferred during the transfer + ///< For an IN, the initial value of the field is the number of bytes the host expects the endpoint to deliver. During the status update, the host controller writes back the number of bytes successfully received. The value in this register is the actual byte count + // iTD Status + volatile uint32_t error : 1 ; ///< Set to a one by the Host Controller during status update in the case where the host did not receive a valid response from the device (Timeout, CRC, Bad PID, etc.). This bit may only be set for isochronous IN transactions. + volatile uint32_t babble_err : 1 ; ///< Set to a 1 by the Host Controller during status update when a babble is detected during the transaction + volatile uint32_t buffer_err : 1 ; ///< Set to a 1 by the Host Controller during status update to indicate that the Host Controller is unable to keep up with the reception of incoming data (overrun) or is unable to supply data fast enough during transmission (underrun). + volatile uint32_t active : 1 ; ///< Set to 1 by software to enable the execution of an isochronous transaction by the Host Controller + } xact[8]; + + // Word 9-15 Buffer Page Pointer List (Plus) + uint32_t BufferPointer[7]; + +// // FIXME: Store meta data into buffer pointer reserved for saving memory +// /*---------- HCD Area ----------*/ +// uint32_t used; +// uint32_t IhdIdx; +// uint32_t reserved[6]; +} ehci_itd_t; + +TU_VERIFY_STATIC( sizeof(ehci_itd_t) == 64, "size is not correct" ); + +/// Split (Full-Speed) Isochronous Transfer Descriptor +typedef struct TU_ATTR_ALIGNED(32) +{ + // Word 0: Next Link Pointer + ehci_link_t next; + + // Word 1: siTD Endpoint Characteristics + uint32_t dev_addr : 7; ///< This field selects the specific device serving as the data source or sink. + uint32_t : 1; ///< reserved + uint32_t ep_number : 4; ///< This 4-bit field selects the particular endpoint number on the device serving as the data source or sink. + uint32_t : 4; ///< This field is reserved and should be set to zero. + uint32_t hub_addr : 7; ///< This field holds the device address of the transaction translators’ hub. + uint32_t : 1; ///< reserved + uint32_t port_number : 7; ///< This field is the port number of the recipient transaction translator. + uint32_t direction : 1; ///< 0 = OUT; 1 = IN. This field encodes whether the full-speed transaction should be an IN or OUT. + + // Word 2: Micro-frame Schedule Control + uint8_t int_smask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute complete-split transactions + uint8_t fl_int_cmask; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute start-split transactions. + uint16_t reserved ; ///< reserved + + // Word 3: siTD Transfer Status and Control + // Status [7:0] TODO indentical to qTD Token'status --> refractor later + volatile uint32_t : 1 ; // reserved + volatile uint32_t split_state : 1 ; + volatile uint32_t missed_uframe : 1 ; + volatile uint32_t xact_err : 1 ; + volatile uint32_t babble_err : 1 ; + volatile uint32_t buffer_err : 1 ; + volatile uint32_t error : 1 ; + volatile uint32_t active : 1 ; + // Micro-frame Schedule Control + volatile uint32_t cmask_progress : 8 ; ///< This field is used by the host controller to record which split-completes have been executed. See Section 4.12.3.3.2 for behavioral requirements. + volatile uint32_t total_bytes : 10 ; ///< This field is initialized by software to the total number of bytes expected in this transfer. Maximum value is 1023 + volatile uint32_t : 4 ; ///< reserved + volatile uint32_t page_select : 1 ; ///< Used to indicate which data page pointer should be concatenated with the CurrentOffsetfield to construct a data buffer pointer + uint32_t int_on_complete : 1 ; ///< Do not interrupt when transaction is complete. 1 = Do interrupt when transaction is complete + uint32_t : 0 ; // padding to the end of current storage unit + + /// Word 4-5: Buffer Pointer List + uint32_t buffer[2]; // buffer[1] TP: Transaction Position - T-Count: Transaction Count + +// union{ +// uint32_t BufferPointer1; +// struct { +// volatile uint32_t TCount : 3; +// volatile uint32_t TPosition : 2; +// }; +// }; + + /*---------- Word 6 ----------*/ + ehci_link_t back; + + /// SITD is 32-byte aligned but occupies only 28 --> 4 bytes for storing extra data + uint8_t used; + uint8_t ihd_idx; + uint8_t reserved2[2]; +} ehci_sitd_t; + +TU_VERIFY_STATIC( sizeof(ehci_sitd_t) == 32, "size is not correct" ); + +//--------------------------------------------------------------------+ +// EHCI Operational Register +//--------------------------------------------------------------------+ +enum ehci_interrupt_mask_{ + EHCI_INT_MASK_USB = TU_BIT(0), + EHCI_INT_MASK_ERROR = TU_BIT(1), + EHCI_INT_MASK_PORT_CHANGE = TU_BIT(2), + + EHCI_INT_MASK_FRAMELIST_ROLLOVER = TU_BIT(3), + EHCI_INT_MASK_PCI_HOST_SYSTEM_ERROR = TU_BIT(4), + EHCI_INT_MASK_ASYNC_ADVANCE = TU_BIT(5), + EHCI_INT_MASK_NXP_SOF = TU_BIT(7), + + EHCI_INT_MASK_NXP_ASYNC = TU_BIT(18), + EHCI_INT_MASK_NXP_PERIODIC = TU_BIT(19), + + EHCI_INT_MASK_ALL = + EHCI_INT_MASK_USB | EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE | + EHCI_INT_MASK_FRAMELIST_ROLLOVER | EHCI_INT_MASK_PCI_HOST_SYSTEM_ERROR | + EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_NXP_SOF | + EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_NXP_PERIODIC +}; + +enum ehci_usbcmd_pos_ { + EHCI_USBCMD_POS_RUN_STOP = 0, + EHCI_USBCMD_POS_FRAMELIST_SZIE = 2, + EHCI_USBCMD_POS_PERIOD_ENABLE = 4, + EHCI_USBCMD_POS_ASYNC_ENABLE = 5, + EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB = 15, + EHCI_USBCMD_POS_INTERRUPT_THRESHOLD = 16 +}; + +enum ehci_portsc_change_mask_{ + EHCI_PORTSC_MASK_CURRENT_CONNECT_STATUS = TU_BIT(0), + EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE = TU_BIT(1), + EHCI_PORTSC_MASK_PORT_EANBLED = TU_BIT(2), + EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE = TU_BIT(3), + EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE = TU_BIT(5), + + EHCI_PORTSC_MASK_PORT_RESET = TU_BIT(8), + + EHCI_PORTSC_MASK_ALL = + EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE | + EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE | + EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE +}; + +typedef volatile struct +{ + union { + uint32_t command; + + struct { + uint32_t run_stop : 1 ; ///< 1=Run. 0=Stop + uint32_t reset : 1 ; ///< SW write 1 to reset HC, clear by HC when complete + uint32_t framelist_size : 2 ; ///< Frame List size 0: 1024, 1: 512, 2: 256 + uint32_t periodic_enable : 1 ; ///< This bit controls whether the host controller skips processing the Periodic Schedule. Values mean: 0b Do not process the Periodic Schedule 1b Use the PERIODICLISTBASE register to access the Periodic Schedule. + uint32_t async_enable : 1 ; ///< This bit controls whether the host controller skips processing the Asynchronous Schedule. Values mean: 0b Do not process the Asynchronous Schedule 1b Use the ASYNCLISTADDR register to access the Asynchronous Schedule. + uint32_t async_adv_doorbell : 1 ; ///< Tell HC to interrupt next time it advances async list. Clear by HC + uint32_t light_reset : 1 ; ///< Reset HC without affecting ports state + uint32_t async_park_count : 2 ; ///< not used by tinyusb + uint32_t : 1 ; + uint32_t async_park_enable : 1 ; ///< Enable park mode, not used by tinyusb + uint32_t : 3 ; + uint32_t nxp_framelist_size_msb : 1 ; ///< NXP customized : Bit 2 of the Frame List Size bits \n 011b: 128 elements \n 100b: 64 elements \n 101b: 32 elements \n 110b: 16 elements \n 111b: 8 elements + uint32_t int_threshold : 8 ; ///< Default 08h. Interrupt rate in unit of micro frame + }command_bm; + }; + + union { + uint32_t status; + + struct { + uint32_t usb : 1 ; ///< qTD with IOC is retired + uint32_t usb_error : 1 ; ///< qTD retired due to error + uint32_t port_change_detect : 1 ; ///< Set when PortOwner or ForcePortResume change from 0 -> 1 + uint32_t framelist_rollover : 1 ; ///< R/WC The Host Controller sets this bit to a one when the Frame List Index(see Section 2.3.4) rolls over from its maximum value to zero. The exact value at which the rollover occurs depends on the frame list size. For example, if the frame list size (as programmed in the Frame List Sizefield of the USBCMD register) is 1024, the Frame Index Registerrolls over every time FRINDEX[13] toggles. Similarly, if the size is 512, the Host Controller sets this bit to a one every time FRINDEX[12] toggles. + uint32_t pci_host_system_error : 1 ; ///< R/WC (not used by NXP) The Host Controller sets this bit to 1 when a serious error occurs during a host system access involving the Host Controller module. In a PCI system, conditions that set this bit to 1 include PCI Parity error, PCI Master Abort, and PCI Target Abort. When this error occurs, the Host Controller clears the Run/Stop bit in the Command register to prevent further execution of the scheduled TDs. + uint32_t async_adv : 1 ; ///< Async Advance interrupt + uint32_t : 1 ; + uint32_t nxp_int_sof : 1 ; ///< NXP customized: this bit will be set every 125us and can be used by host controller driver as a time base. + uint32_t : 4 ; + uint32_t hc_halted : 1 ; ///< Opposite value to run_stop bit. + uint32_t reclamation : 1 ; ///< Used to detect empty async shecudle + uint32_t periodic_status : 1 ; ///< Periodic schedule status + uint32_t async_status : 1 ; ///< Async schedule status + uint32_t : 2 ; + uint32_t nxp_int_async : 1 ; ///< NXP customized: This bit is set by the Host Controller when the cause of an interrupt is a completion of a USB transaction where the Transfer Descriptor (TD) has an interrupt on complete (IOC) bit set andthe TD was from the asynchronous schedule. This bit is also set by the Host when a short packet is detected andthe packet is on the asynchronous schedule. + uint32_t nxp_int_period : 1 ; ///< NXP customized: This bit is set by the Host Controller when the cause of an interrupt is a completion of a USB transaction where the Transfer Descriptor (TD) has an interrupt on complete (IOC) bit set andthe TD was from the periodic schedule. + uint32_t : 12 ; + }status_bm; + }; + + union{ + uint32_t inten; + + struct { + uint32_t usb : 1 ; + uint32_t usb_error : 1 ; + uint32_t port_change_detect : 1 ; + uint32_t framelist_rollover : 1 ; + uint32_t pci_host_system_error : 1 ; + uint32_t async_adv : 1 ; + uint32_t : 1 ; + uint32_t nxp_int_sof : 1 ; + uint32_t : 10 ; + uint32_t nxp_int_async : 1 ; + uint32_t nxp_int_period : 1 ; + uint32_t : 12 ; + }inten_bm; + }; + + uint32_t frame_index ; ///< Micro frame counter + uint32_t ctrl_ds_seg ; ///< Control Data Structure Segment + uint32_t periodic_list_base ; ///< Beginning address of perodic frame list + uint32_t async_list_addr ; ///< Address of next async QHD to be executed + uint32_t nxp_tt_control ; ///< nxp embedded transaction translator (reserved by EHCI specs) + uint32_t reserved[8] ; + uint32_t config_flag ; ///< not used by NXP + + union { + uint32_t portsc ; ///< port status and control + struct { + uint32_t current_connect_status : 1; ///< 0: No device, 1: Device is present on port + uint32_t connect_status_change : 1; ///< Change in Current Connect Status + uint32_t port_enabled : 1; ///< Ports can only be enabled by HC as a part of the reset and enable. SW can write 0 to disable + uint32_t port_enable_change : 1; ///< Port Enabled has changed + uint32_t over_current_active : 1; ///< Port has an over-current condition + uint32_t over_current_change : 1; ///< Change to Over-current Active + uint32_t force_port_resume : 1; ///< Resume detected/driven on port. This functionality defined for manipulating this bit depends on the value of the Suspend bit. + uint32_t suspend : 1; ///< Port in suspend state + uint32_t port_reset : 1; ///< 1=Port is in Reset. 0=Port is not in Reset + uint32_t nxp_highspeed_status : 1; ///< NXP customized: 0=connected to the port is not in High-speed mode, 1=connected to the port is in High-speed mode + uint32_t line_status : 2; ///< D+/D- state: 00: SE0, 10: J-state, 01: K-state + uint32_t port_power : 1; ///< 0= power off, 1= power on + uint32_t port_owner : 1; ///< not used by NXP + uint32_t port_indicator_control : 2; ///< 00b: off, 01b: Amber, 10b: green, 11b: undefined + uint32_t port_test_control : 4; ///< Port test mode, not used by tinyusb + uint32_t wake_on_connect_enable : 1; ///< Enables device connects as wake-up events + uint32_t wake_on_disconnect_enable : 1; ///< Enables device disconnects as wake-up events + uint32_t wake_on_over_current_enable : 1; ///< Enables over-current conditions as wake-up events + uint32_t nxp_phy_clock_disable : 1; ///< NXP customized: the PHY can be put into Low Power Suspend – Clock Disable when the downstream device has been put into suspend mode or when no downstream device is connected. Low power suspend is completely under the control of software. 0: enable PHY clock, 1: disable PHY clock + uint32_t nxp_port_force_fullspeed : 1; ///< NXP customized: Writing this bit to a 1 will force the port to only connect at Full Speed. It disables the chirp sequence that allowsthe port to identify itself as High Speed. This is useful for testing FS configurations with a HS host, hub or device. + uint32_t : 1; + uint32_t nxp_port_speed : 2; ///< NXP customized: This register field indicates the speed atwhich the port is operating. For HS mode operation in the host controllerand HS/FS operation in the device controller the port routing steers data to the Protocol engine. For FS and LS mode operation in the host controller, the port routing steers data to the Protocol Engine w/ Embedded Transaction Translator. 0x0: Fullspeed, 0x1: Lowspeed, 0x2: Highspeed + uint32_t TU_RESERVED : 4; + }portsc_bm; + }; +}ehci_registers_t; + +//--------------------------------------------------------------------+ +// EHCI Data Organization +//--------------------------------------------------------------------+ +typedef struct +{ + ehci_link_t period_framelist[EHCI_FRAMELIST_SIZE]; + + // for NXP ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist) + // [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms + ehci_qhd_t period_head_arr[4]; + + // Note control qhd of dev0 is used as head of async list + struct { + ehci_qhd_t qhd; + ehci_qtd_t qtd; + }control[CFG_TUSB_HOST_DEVICE_MAX+1]; + + ehci_qhd_t qhd_pool[HCD_MAX_ENDPOINT]; + ehci_qtd_t qtd_pool[HCD_MAX_XFER] TU_ATTR_ALIGNED(32); + + ehci_registers_t* regs; + + volatile uint32_t uframe_number; +}ehci_data_t; + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_EHCI_H_ */ + +/** @} */ +/** @} */ diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c new file mode 100644 index 000000000..ee294856b --- /dev/null +++ b/src/portable/ohci/ohci.c @@ -0,0 +1,688 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include + +#if TUSB_OPT_HOST_ENABLED && \ + (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC40XX) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "osal/osal.h" + +#include "host/hcd.h" +#include "host/usbh_hcd.h" +#include "ohci.h" + +// TODO remove +#include "chip.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +#define OHCI_REG ((ohci_registers_t *) LPC_USB_BASE) + +enum { + OHCI_CONTROL_FUNCSTATE_RESET = 0, + OHCI_CONTROL_FUNCSTATE_RESUME, + OHCI_CONTROL_FUNCSTATE_OPERATIONAL, + OHCI_CONTROL_FUNCSTATE_SUSPEND +}; + +enum { + OHCI_CONTROL_CONTROL_BULK_RATIO = 3, ///< This specifies the service ratio between Control and Bulk EDs. 0 = 1:1, 3 = 4:1 + OHCI_CONTROL_LIST_PERIODIC_ENABLE_MASK = TU_BIT(2), + OHCI_CONTROL_LIST_ISOCHRONOUS_ENABLE_MASK = TU_BIT(3), + OHCI_CONTROL_LIST_CONTROL_ENABLE_MASK = TU_BIT(4), + OHCI_CONTROL_LIST_BULK_ENABLE_MASK = TU_BIT(5), +}; + +enum { + OHCI_FMINTERVAL_FI = 0x2EDF, // 7.3.1 nominal (reset) value + OHCI_FMINTERVAL_FSMPS = (6*(OHCI_FMINTERVAL_FI-210)) / 7, // 5.4 calculated based on maximum overhead + bit stuffing +}; + +enum { + OHCI_PERIODIC_START = 0x3E67 +}; + +enum { + OHCI_INT_SCHEDULING_OVERUN_MASK = TU_BIT(0), + OHCI_INT_WRITEBACK_DONEHEAD_MASK = TU_BIT(1), + OHCI_INT_SOF_MASK = TU_BIT(2), + OHCI_INT_RESUME_DETECTED_MASK = TU_BIT(3), + OHCI_INT_UNRECOVERABLE_ERROR_MASK = TU_BIT(4), + OHCI_INT_FRAME_OVERFLOW_MASK = TU_BIT(5), + OHCI_INT_RHPORT_STATUS_CHANGE_MASK = TU_BIT(6), + + OHCI_INT_OWNERSHIP_CHANGE_MASK = TU_BIT(30), + OHCI_INT_MASTER_ENABLE_MASK = TU_BIT(31), +}; + +enum { + OHCI_RHPORT_CURRENT_CONNECT_STATUS_MASK = TU_BIT(0), + OHCI_RHPORT_PORT_ENABLE_STATUS_MASK = TU_BIT(1), + OHCI_RHPORT_PORT_SUSPEND_STATUS_MASK = TU_BIT(2), + OHCI_RHPORT_PORT_OVER_CURRENT_INDICATOR_MASK = TU_BIT(3), + OHCI_RHPORT_PORT_RESET_STATUS_MASK = TU_BIT(4), ///< write '1' to reset port + + OHCI_RHPORT_PORT_POWER_STATUS_MASK = TU_BIT(8), + OHCI_RHPORT_LOW_SPEED_DEVICE_ATTACHED_MASK = TU_BIT(9), + + OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK = TU_BIT(16), + OHCI_RHPORT_PORT_ENABLE_CHANGE_MASK = TU_BIT(17), + OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK = TU_BIT(18), + OHCI_RHPORT_OVER_CURRENT_CHANGE_MASK = TU_BIT(19), + OHCI_RHPORT_PORT_RESET_CHANGE_MASK = TU_BIT(20), + + OHCI_RHPORT_ALL_CHANGE_MASK = OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK | OHCI_RHPORT_PORT_ENABLE_CHANGE_MASK | + OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK | OHCI_RHPORT_OVER_CURRENT_CHANGE_MASK | OHCI_RHPORT_PORT_RESET_CHANGE_MASK +}; + +enum { + OHCI_CCODE_NO_ERROR = 0, + OHCI_CCODE_CRC = 1, + OHCI_CCODE_BIT_STUFFING = 2, + OHCI_CCODE_DATA_TOGGLE_MISMATCH = 3, + OHCI_CCODE_STALL = 4, + OHCI_CCODE_DEVICE_NOT_RESPONDING = 5, + OHCI_CCODE_PID_CHECK_FAILURE = 6, + OHCI_CCODE_UNEXPECTED_PID = 7, + OHCI_CCODE_DATA_OVERRUN = 8, + OHCI_CCODE_DATA_UNDERRUN = 9, + OHCI_CCODE_BUFFER_OVERRUN = 12, + OHCI_CCODE_BUFFER_UNDERRUN = 13, + OHCI_CCODE_NOT_ACCESSED = 14, +}; + +enum { + OHCI_INT_ON_COMPLETE_YES = 0, + OHCI_INT_ON_COMPLETE_NO = TU_BIN8(111) +}; +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(256) static ohci_data_t ohci_data; + +static ohci_ed_t * const p_ed_head[] = +{ + [TUSB_XFER_CONTROL] = &ohci_data.control[0].ed, + [TUSB_XFER_BULK ] = &ohci_data.bulk_head_ed, + [TUSB_XFER_INTERRUPT] = &ohci_data.period_head_ed, + [TUSB_XFER_ISOCHRONOUS] = NULL // TODO Isochronous +}; + +static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed); +static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr); + +//--------------------------------------------------------------------+ +// USBH-HCD API +//--------------------------------------------------------------------+ +// Initialization according to 5.1.1.4 +bool hcd_init(uint8_t rhport) +{ + (void) rhport; + + //------------- Data Structure init -------------// + tu_memclr(&ohci_data, sizeof(ohci_data_t)); + for(uint8_t i=0; i<32; i++) + { // assign all interrupt pointes to period head ed + ohci_data.hcca.interrupt_table[i] = (uint32_t) &ohci_data.period_head_ed; + } + + ohci_data.control[0].ed.skip = 1; + ohci_data.bulk_head_ed.skip = 1; + ohci_data.period_head_ed.skip = 1; + + // reset controller + OHCI_REG->command_status_bit.controller_reset = 1; + while( OHCI_REG->command_status_bit.controller_reset ) {} // should not take longer than 10 us + + //------------- init ohci registers -------------// + OHCI_REG->control_head_ed = (uint32_t) &ohci_data.control[0].ed; + OHCI_REG->bulk_head_ed = (uint32_t) &ohci_data.bulk_head_ed; + OHCI_REG->hcca = (uint32_t) &ohci_data.hcca; + + OHCI_REG->interrupt_disable = OHCI_REG->interrupt_enable; // disable all interrupts + OHCI_REG->interrupt_status = OHCI_REG->interrupt_status; // clear current set bits + OHCI_REG->interrupt_enable = OHCI_INT_WRITEBACK_DONEHEAD_MASK | OHCI_INT_RESUME_DETECTED_MASK | + OHCI_INT_UNRECOVERABLE_ERROR_MASK | OHCI_INT_FRAME_OVERFLOW_MASK | OHCI_INT_RHPORT_STATUS_CHANGE_MASK | + OHCI_INT_MASTER_ENABLE_MASK; + + OHCI_REG->control |= OHCI_CONTROL_CONTROL_BULK_RATIO | OHCI_CONTROL_LIST_CONTROL_ENABLE_MASK | + OHCI_CONTROL_LIST_BULK_ENABLE_MASK | OHCI_CONTROL_LIST_PERIODIC_ENABLE_MASK; // TODO Isochronous + + OHCI_REG->frame_interval = (OHCI_FMINTERVAL_FSMPS << 16) | OHCI_FMINTERVAL_FI; + OHCI_REG->periodic_start = (OHCI_FMINTERVAL_FI * 9) / 10; // Periodic start is 90% of frame interval + + OHCI_REG->control_bit.hc_functional_state = OHCI_CONTROL_FUNCSTATE_OPERATIONAL; // make HC's state to operational state TODO use this to suspend (save power) + OHCI_REG->rh_status_bit.local_power_status_change = 1; // set global power for ports + + return true; +} + +uint32_t hcd_uframe_number(uint8_t rhport) +{ + (void) rhport; + return (ohci_data.frame_number_hi << 16 | OHCI_REG->frame_number) << 3; +} + + +//--------------------------------------------------------------------+ +// PORT API +//--------------------------------------------------------------------+ +void hcd_port_reset(uint8_t hostid) +{ + (void) hostid; + OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK; +} + +bool hcd_port_connect_status(uint8_t hostid) +{ + (void) hostid; + return OHCI_REG->rhport_status_bit[0].current_connect_status; +} + +tusb_speed_t hcd_port_speed_get(uint8_t hostid) +{ + (void) hostid; + return OHCI_REG->rhport_status_bit[0].low_speed_device_attached ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; +} + +// endpoints are tied to an address, which only reclaim after a long delay when enumerating +// thus there is no need to make sure ED is not in HC's cahed as it will not for sure +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) +{ + // TODO OHCI + (void) rhport; + + // addr0 serves as static head --> only set skip bit + if ( dev_addr == 0 ) + { + ohci_data.control[0].ed.skip = 1; + }else + { + // remove control + ed_list_remove_by_addr( p_ed_head[TUSB_XFER_CONTROL], dev_addr); + + // remove bulk + ed_list_remove_by_addr(p_ed_head[TUSB_XFER_BULK], dev_addr); + + // remove interrupt + ed_list_remove_by_addr(p_ed_head[TUSB_XFER_INTERRUPT], dev_addr); + + // TODO remove ISO + } +} + +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// CONTROL PIPE API +//--------------------------------------------------------------------+ +static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_t const * const p_ed) +{ + return (p_ed->ep_number == 0 ) ? TUSB_XFER_CONTROL : + (p_ed->is_iso ) ? TUSB_XFER_ISOCHRONOUS : + (p_ed->is_interrupt_xfer ) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK; +} + +static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type, uint8_t interval) +{ + (void) interval; + + // address 0 is used as async head, which always on the list --> cannot be cleared + if (dev_addr != 0) + { + tu_memclr(p_ed, sizeof(ohci_ed_t)); + } + + p_ed->dev_addr = dev_addr; + p_ed->ep_number = endpoint_addr & 0x0F; + p_ed->pid = (xfer_type == TUSB_XFER_CONTROL) ? OHCI_PID_SETUP : ( (endpoint_addr & TUSB_DIR_IN_MASK) ? OHCI_PID_IN : OHCI_PID_OUT ); + p_ed->speed = _usbh_devices[dev_addr].speed; + p_ed->is_iso = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; + p_ed->max_packet_size = max_packet_size; + + p_ed->used = 1; + p_ed->is_interrupt_xfer = (xfer_type == TUSB_XFER_INTERRUPT ? 1 : 0); +} + +static void gtd_init(ohci_gtd_t* p_td, void* data_ptr, uint16_t total_bytes) +{ + tu_memclr(p_td, sizeof(ohci_gtd_t)); + + p_td->used = 1; + p_td->expected_bytes = total_bytes; + + p_td->buffer_rounding = 1; // less than queued length is not a error + p_td->delay_interrupt = OHCI_INT_ON_COMPLETE_NO; + p_td->condition_code = OHCI_CCODE_NOT_ACCESSED; + + p_td->current_buffer_pointer = data_ptr; + p_td->buffer_end = total_bytes ? (((uint8_t*) data_ptr) + total_bytes-1) : NULL; +} + +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) +{ + (void) rhport; + + ohci_ed_t* p_ed = &ohci_data.control[dev_addr].ed; + ohci_gtd_t *p_setup = &ohci_data.control[dev_addr].gtd; + + gtd_init(p_setup, (void*) setup_packet, 8); + p_setup->index = dev_addr; + p_setup->pid = OHCI_PID_SETUP; + p_setup->data_toggle = TU_BIN8(10); // DATA0 + p_setup->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + + //------------- Attach TDs list to Control Endpoint -------------// + p_ed->td_head.address = (uint32_t) p_setup; + + OHCI_REG->command_status_bit.control_list_filled = 1; + + return true; +} + +// TODO move around +static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr); +static ohci_gtd_t * gtd_find_free(void); +static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd); + +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + // FIXME control only for now + if ( epnum == 0 ) + { + ohci_ed_t* const p_ed = &ohci_data.control[dev_addr].ed; + ohci_gtd_t *p_data = &ohci_data.control[dev_addr].gtd; + + gtd_init(p_data, buffer, buflen); + + p_data->index = dev_addr; + p_data->pid = dir ? OHCI_PID_IN : OHCI_PID_OUT; + p_data->data_toggle = TU_BIN8(11); // DATA1 + p_data->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + + p_ed->td_head.address = (uint32_t) p_data; + + OHCI_REG->command_status_bit.control_list_filled = 1; + }else + { + ohci_ed_t * p_ed = ed_from_addr(dev_addr, ep_addr); + ohci_gtd_t* p_gtd = gtd_find_free(); + + TU_ASSERT(p_gtd); + + gtd_init(p_gtd, buffer, buflen); + p_gtd->index = p_ed-ohci_data.ed_pool; + p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + + td_insert_to_ed(p_ed, p_gtd); + + tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); + if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; + } + + return true; +} + +//--------------------------------------------------------------------+ +// BULK/INT/ISO PIPE API +//--------------------------------------------------------------------+ +static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) +{ + if ( tu_edpt_number(ep_addr) == 0 ) return &ohci_data.control[dev_addr].ed; + + ohci_ed_t* ed_pool = ohci_data.ed_pool; + + for(uint32_t i=0; inext = p_pre->next; + p_pre->next = (uint32_t) p_ed; +} + +static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr) +{ + ohci_ed_t* p_prev = p_head; + + while( p_prev->next ) + { + ohci_ed_t* ed = (ohci_ed_t*) p_prev->next; + + if (ed->dev_addr == dev_addr) + { + // unlink ed + p_prev->next = ed->next; + + // point the removed ED's next pointer to list head to make sure HC can always safely move away from this ED + ed->next = (uint32_t) p_head; + ed->used = 0; + } + + // check next valid since we could remove it + if (p_prev->next) p_prev = (ohci_ed_t*) p_prev->next; + } +} + +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +{ + (void) rhport; + + // TODO iso support + TU_ASSERT(ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); + + //------------- Prepare Queue Head -------------// + ohci_ed_t * p_ed; + + if ( ep_desc->bEndpointAddress == 0 ) + { + p_ed = &ohci_data.control[dev_addr].ed; + }else + { + p_ed = ed_find_free(); + } + TU_ASSERT(p_ed); + + ed_init( p_ed, dev_addr, ep_desc->wMaxPacketSize.size, ep_desc->bEndpointAddress, + ep_desc->bmAttributes.xfer, ep_desc->bInterval ); + + // control of dev0 is used as static async head + if ( dev_addr == 0 ) + { + p_ed->skip = 0; // only need to clear skip bit + return true; + } + + ed_list_insert( p_ed_head[ep_desc->bmAttributes.xfer], p_ed ); + + return true; +} + +static ohci_gtd_t * gtd_find_free(void) +{ + for(uint8_t i=0; i < HCD_MAX_XFER; i++) + { + if ( !ohci_data.gtd_pool[i].used ) return &ohci_data.gtd_pool[i]; + } + + return NULL; +} + +static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd) +{ + // tail is always NULL + if ( tu_align16(p_ed->td_head.address) == 0 ) + { // TD queue is empty --> head = TD + p_ed->td_head.address |= (uint32_t) p_gtd; + } + else + { // TODO currently only support queue up to 2 TD each endpoint at a time + ((ohci_gtd_t*) tu_align16(p_ed->td_head.address))->next = (uint32_t) p_gtd; + } +} + +static bool pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) +{ + ohci_ed_t* const p_ed = ed_from_addr(dev_addr, ep_addr); + + // not support ISO yet + TU_VERIFY ( !p_ed->is_iso ); + + ohci_gtd_t * const p_gtd = gtd_find_free(); + TU_ASSERT(p_gtd); // not enough gtd + + gtd_init(p_gtd, buffer, total_bytes); + p_gtd->index = p_ed-ohci_data.ed_pool; + + if ( int_on_complete ) p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + + td_insert_to_ed(p_ed, p_gtd); + + return true; +} + +bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes) +{ + return pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes, false); +} + +bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) +{ + (void) int_on_complete; + TU_ASSERT( pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes, true) ); + + tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); + + if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; + + return true; +} + +bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +{ + ohci_ed_t const * const p_ed = ed_from_addr(dev_addr, ep_addr); + return tu_align16(p_ed->td_head.address) != tu_align16(p_ed->td_tail); +} + +bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) +{ + ohci_ed_t const * const p_ed = ed_from_addr(dev_addr, ep_addr); + return p_ed->td_head.halted && p_ed->is_stalled; +} + +bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) +{ + ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr); + + p_ed->is_stalled = 0; + p_ed->td_tail &= 0x0Ful; // set tail pointer back to NULL + + p_ed->td_head.toggle = 0; // reset data toggle + p_ed->td_head.halted = 0; + + if ( TUSB_XFER_BULK == ed_get_xfer_type(p_ed) ) OHCI_REG->command_status_bit.bulk_list_filled = 1; + + return true; +} + + +//--------------------------------------------------------------------+ +// OHCI Interrupt Handler +//--------------------------------------------------------------------+ +static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head) +{ + ohci_td_item_t* td_reverse_head = NULL; + + while(td_head != NULL) + { + uint32_t next = td_head->next; + + // make current's item become reverse's first item + td_head->next = (uint32_t) td_reverse_head; + td_reverse_head = td_head; + + td_head = (ohci_td_item_t*) next; // advance to next item + } + + return td_reverse_head; +} + +static inline bool gtd_is_control(ohci_gtd_t const * const p_qtd) +{ + return ((uint32_t) p_qtd) < ((uint32_t) ohci_data.gtd_pool); // check ohci_data_t for memory layout +} + +static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) +{ + if ( gtd_is_control(p_qtd) ) + { + return &ohci_data.control[p_qtd->index].ed; + }else + { + return &ohci_data.ed_pool[p_qtd->index]; + } +} + +static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) +{ // 5.2.9 OHCI sample code + return (tu_align4k(buffer_end ^ current_buffer) ? 0x1000 : 0) + + tu_offset4k(buffer_end) - tu_offset4k(current_buffer) + 1; +} + +static void done_queue_isr(uint8_t hostid) +{ + (void) hostid; + + // done head is written in reversed order of completion --> need to reverse the done queue first + ohci_td_item_t* td_head = list_reverse ( (ohci_td_item_t*) tu_align16(ohci_data.hcca.done_head) ); + + while( td_head != NULL ) + { + // TODO check if td_head is iso td + //------------- Non ISO transfer -------------// + ohci_gtd_t * const p_qtd = (ohci_gtd_t *) td_head; + xfer_result_t const event = (p_qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS : + (p_qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED; + + p_qtd->used = 0; // free TD + if ( (p_qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) ) + { + ohci_ed_t * const p_ed = gtd_get_ed(p_qtd); + + uint32_t const xferred_bytes = p_qtd->expected_bytes - gtd_xfer_byte_left((uint32_t) p_qtd->buffer_end, (uint32_t) p_qtd->current_buffer_pointer); + + // NOTE Assuming the current list is BULK and there is no other EDs in the list has queued TDs. + // When there is a error resulting this ED is halted, and this EP still has other queued TD + // --> the Bulk list only has this halted EP queueing TDs (remaining) + // --> Bulk list will be considered as not empty by HC !!! while there is no attempt transaction on this list + // --> HC will not process Control list (due to service ratio when Bulk list not empty) + // To walk-around this, the halted ED will have TailP = HeadP (empty list condition), when clearing halt + // the TailP must be set back to NULL for processing remaining TDs + if ((event != XFER_RESULT_SUCCESS)) + { + p_ed->td_tail &= 0x0Ful; + p_ed->td_tail |= tu_align16(p_ed->td_head.address); // mark halted EP as empty queue + if ( event == XFER_RESULT_STALLED ) p_ed->is_stalled = 1; + } + + hcd_event_xfer_complete(p_ed->dev_addr, + tu_edpt_addr(p_ed->ep_number, p_ed->pid == OHCI_PID_IN), + xferred_bytes, event, true); + } + + td_head = (ohci_td_item_t*) td_head->next; + } +} + +void hcd_int_handler(uint8_t hostid) +{ + uint32_t const int_en = OHCI_REG->interrupt_enable; + uint32_t const int_status = OHCI_REG->interrupt_status & int_en; + + if (int_status == 0) return; + + // Frame number overflow + if ( int_status & OHCI_INT_FRAME_OVERFLOW_MASK ) + { + ohci_data.frame_number_hi++; + } + + //------------- RootHub status -------------// + if ( int_status & OHCI_INT_RHPORT_STATUS_CHANGE_MASK ) + { + uint32_t const rhport_status = OHCI_REG->rhport_status[0] & OHCI_RHPORT_ALL_CHANGE_MASK; + + // TODO dual port is not yet supported + if ( rhport_status & OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK ) + { + // TODO check if remote wake-up + if ( OHCI_REG->rhport_status_bit[0].current_connect_status ) + { + // TODO reset port immediately, without this controller will got 2-3 (debouncing connection status change) + OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK; + hcd_event_device_attach(hostid, true); + }else + { + hcd_event_device_remove(hostid, true); + } + } + + if ( rhport_status & OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK) + { + + } + + OHCI_REG->rhport_status[0] = rhport_status; // acknowledge all interrupt + } + + //------------- Transfer Complete -------------// + if ( int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK) + { + done_queue_isr(hostid); + } + + OHCI_REG->interrupt_status = int_status; // Acknowledge handled interrupt +} +//--------------------------------------------------------------------+ +// HELPER +//--------------------------------------------------------------------+ + + +#endif + diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h new file mode 100644 index 000000000..7f9e55b21 --- /dev/null +++ b/src/portable/ohci/ohci.h @@ -0,0 +1,291 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup Group_HCD + * @{ + * \defgroup OHCI + * \brief OHCI driver. All documents sources mentioned here (eg section 3.5) is referring to OHCI Specs unless state otherwise + * @{ */ + +#ifndef _TUSB_OHCI_H_ +#define _TUSB_OHCI_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// OHCI CONFIGURATION & CONSTANTS +//--------------------------------------------------------------------+ +#define HOST_HCD_XFER_INTERRUPT // TODO interrupt is used widely, should always be enalbed +#define OHCI_PERIODIC_LIST (defined HOST_HCD_XFER_INTERRUPT || defined HOST_HCD_XFER_ISOCHRONOUS) + +// TODO merge OHCI with EHCI +enum { + OHCI_MAX_ITD = 4 +}; + +enum { + OHCI_PID_SETUP = 0, + OHCI_PID_OUT, + OHCI_PID_IN, +}; + +//--------------------------------------------------------------------+ +// OHCI Data Structure +//--------------------------------------------------------------------+ +typedef struct { + uint32_t interrupt_table[32]; + volatile uint16_t frame_number; + volatile uint16_t frame_pad; + volatile uint32_t done_head; + uint8_t reserved[116+4]; // TODO try to make use of this area if possible, extra 4 byte to make the whole struct size = 256 +}ohci_hcca_t; // TU_ATTR_ALIGNED(256) + +TU_VERIFY_STATIC( sizeof(ohci_hcca_t) == 256, "size is not correct" ); + +typedef struct { + uint32_t reserved[2]; + volatile uint32_t next; + uint32_t reserved2; +}ohci_td_item_t; + + +typedef struct TU_ATTR_ALIGNED(16) +{ + // Word 0 + uint32_t used : 1; + uint32_t index : 4; // endpoint index the td belongs to, or device address in case of control xfer + uint32_t expected_bytes : 13; // TODO available for hcd + + uint32_t buffer_rounding : 1; + uint32_t pid : 2; + uint32_t delay_interrupt : 3; + volatile uint32_t data_toggle : 2; + volatile uint32_t error_count : 2; + volatile uint32_t condition_code : 4; + + // Word 1 + volatile uint8_t* current_buffer_pointer; + + // Word 2 : next TD + volatile uint32_t next; + + // Word 3 + uint8_t* buffer_end; +} ohci_gtd_t; + +TU_VERIFY_STATIC( sizeof(ohci_gtd_t) == 16, "size is not correct" ); + +typedef struct TU_ATTR_ALIGNED(16) +{ + // Word 0 + uint32_t dev_addr : 7; + uint32_t ep_number : 4; + uint32_t pid : 2; // 00b from TD, 01b Out, 10b In + uint32_t speed : 1; + uint32_t skip : 1; + uint32_t is_iso : 1; + uint32_t max_packet_size : 11; + // HCD: make use of 5 reserved bits + uint32_t used : 1; + uint32_t is_interrupt_xfer : 1; + uint32_t is_stalled : 1; + uint32_t : 2; + + // Word 1 + uint32_t td_tail; + + // Word 2 + volatile union { + uint32_t address; + struct { + uint32_t halted : 1; + uint32_t toggle : 1; + uint32_t : 30; + }; + }td_head; + + // Word 3: next ED + uint32_t next; +} ohci_ed_t; + +TU_VERIFY_STATIC( sizeof(ohci_ed_t) == 16, "size is not correct" ); + +typedef struct TU_ATTR_ALIGNED(32) +{ + /*---------- Word 1 ----------*/ + uint32_t starting_frame : 16; + uint32_t : 5; // can be used + uint32_t delay_interrupt : 3; + uint32_t frame_count : 3; + uint32_t : 1; // can be used + volatile uint32_t condition_code : 4; + + /*---------- Word 2 ----------*/ + uint32_t buffer_page0; // 12 lsb bits can be used + + /*---------- Word 3 ----------*/ + volatile uint32_t next; + + /*---------- Word 4 ----------*/ + uint32_t buffer_end; + + /*---------- Word 5-8 ----------*/ + volatile uint16_t offset_packetstatus[8]; +} ochi_itd_t; + +TU_VERIFY_STATIC( sizeof(ochi_itd_t) == 32, "size is not correct" ); + +// structure with member alignment required from large to small +typedef struct TU_ATTR_ALIGNED(256) +{ + ohci_hcca_t hcca; + + ohci_ed_t bulk_head_ed; // static bulk head (dummy) + ohci_ed_t period_head_ed; // static periodic list head (dummy) + + // control endpoints has reserved resources + struct { + ohci_ed_t ed; + ohci_gtd_t gtd; + }control[CFG_TUSB_HOST_DEVICE_MAX+1]; + + // ochi_itd_t itd[OHCI_MAX_ITD]; // itd requires alignment of 32 + ohci_ed_t ed_pool[HCD_MAX_ENDPOINT]; + ohci_gtd_t gtd_pool[HCD_MAX_XFER]; + + volatile uint16_t frame_number_hi; + +} ohci_data_t; + +//--------------------------------------------------------------------+ +// OHCI Operational Register +//--------------------------------------------------------------------+ + + +//--------------------------------------------------------------------+ +// OHCI Data Organization +//--------------------------------------------------------------------+ +typedef volatile struct +{ + uint32_t revision; + + union { + uint32_t control; + struct { + uint32_t control_bulk_service_ratio : 2; + uint32_t periodic_list_enable : 1; + uint32_t isochronous_enable : 1; + uint32_t control_list_enable : 1; + uint32_t bulk_list_enable : 1; + uint32_t hc_functional_state : 2; + uint32_t interrupt_routing : 1; + uint32_t remote_wakeup_connected : 1; + uint32_t remote_wakeup_enale : 1; + uint32_t TU_RESERVED : 21; + }control_bit; + }; + + union { + uint32_t command_status; + struct { + uint32_t controller_reset : 1; + uint32_t control_list_filled : 1; + uint32_t bulk_list_filled : 1; + uint32_t ownership_change_request : 1; + uint32_t : 12; + uint32_t scheduling_overrun_count : 2; + }command_status_bit; + }; + + uint32_t interrupt_status; + uint32_t interrupt_enable; + uint32_t interrupt_disable; + + uint32_t hcca; + uint32_t period_current_ed; + uint32_t control_head_ed; + uint32_t control_current_ed; + uint32_t bulk_head_ed; + uint32_t bulk_current_ed; + uint32_t done_head; + + uint32_t frame_interval; + uint32_t frame_remaining; + uint32_t frame_number; + uint32_t periodic_start; + uint32_t lowspeed_threshold; + + uint32_t rh_descriptorA; + uint32_t rh_descriptorB; + + union { + uint32_t rh_status; + struct { + uint32_t local_power_status : 1; // read Local Power Status; write: Clear Global Power + uint32_t over_current_indicator : 1; + uint32_t : 13; + uint32_t device_remote_wakeup_enable : 1; + uint32_t local_power_status_change : 1; + uint32_t over_current_indicator_change : 1; + uint32_t : 13; + uint32_t clear_remote_wakeup_enable : 1; + }rh_status_bit; + }; + + union { + uint32_t rhport_status[2]; // TODO NXP OHCI controller only has 2 ports + struct { + uint32_t current_connect_status : 1; + uint32_t port_enable_status : 1; + uint32_t port_suspend_status : 1; + uint32_t port_over_current_indicator : 1; + uint32_t port_reset_status : 1; + uint32_t : 3; + uint32_t port_power_status : 1; + uint32_t low_speed_device_attached : 1; + uint32_t : 6; + uint32_t connect_status_change : 1; + uint32_t port_enable_status_change : 1; + uint32_t port_suspend_status_change : 1; + uint32_t port_over_current_indicator_change : 1; + uint32_t port_reset_status_change : 1; + uint32_t TU_RESERVED : 11; + }rhport_status_bit[2]; + }; +}ohci_registers_t; + +TU_VERIFY_STATIC( sizeof(ohci_registers_t) == 0x5c, "size is not correct"); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_OHCI_H_ */ + +/** @} */ +/** @} */ -- cgit v1.3.1 From c5422a5c48984f4ea2a5fb6b22f6778183002f68 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Tue, 23 Feb 2021 12:06:41 -0600 Subject: rp2040: use TU endpoint conventions and remove redundant variables --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 31 ++++++++++++++-------------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 12 +++++------ src/portable/raspberrypi/rp2040/rp2040_usb.h | 4 ---- 3 files changed, 21 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 95b0963a3..1e67726ac 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -48,20 +48,21 @@ // Init these in dcd_init static uint8_t *next_buffer_ptr; -// Endpoints 0-15, direction 0 for out and 1 for in. +// Endpoints 0-15, direction TUSB_DIR_OUT for out and TUSB_DIR_IN for in. static struct hw_endpoint hw_endpoints[16][2] = {0}; -static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, uint8_t in) +static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, tusb_dir_t dir) { - return &hw_endpoints[num][in]; + return &hw_endpoints[num][dir]; } static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr) { uint8_t num = tu_edpt_number(ep_addr); - uint8_t in = (ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0; - return hw_endpoint_get_by_num(num, in); + tusb_dir_t dir = tu_edpt_dir(ep_addr); + return hw_endpoint_get_by_num(num, dir); } + static void _hw_endpoint_alloc(struct hw_endpoint *ep) { uint size = TU_MIN(64, ep->wMaxPacketSize); @@ -102,12 +103,10 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep) static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint wMaxPacketSize, uint8_t transfer_type) { uint8_t num = tu_edpt_number(ep_addr); - bool in = ep_addr & TUSB_DIR_IN_MASK; + tusb_dir_t dir = tu_edpt_dir(ep_addr); ep->ep_addr = ep_addr; - ep->in = in; // For device, IN is a tx transfer and OUT is an rx transfer - ep->rx = in == false; - ep->num = num; + ep->rx = (dir == TUSB_DIR_OUT); // Response to a setup packet on EP0 starts with pid of 1 ep->next_pid = num == 0 ? 1u : 0u; @@ -131,7 +130,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint wMax ep->transfer_type = transfer_type; // Every endpoint has a buffer control register in dpram - if (ep->in) + if (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) { ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in; } @@ -143,7 +142,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint wMax // Clear existing buffer control state *ep->buffer_control = 0; - if (ep->num == 0) + if (tu_edpt_number(ep->ep_addr) == 0) { // EP0 has no endpoint control register because // the buffer offsets are fixed @@ -155,7 +154,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint wMax else { // Set the endpoint control register (starts at EP1, hence num-1) - if (in) + if (dir == TUSB_DIR_IN) { ep->endpoint_control = &usb_dpram->ep_ctrl[num-1].in; } @@ -259,10 +258,10 @@ static void ep0_0len_status(void) static void _hw_endpoint_stall(struct hw_endpoint *ep) { assert(!ep->stalled); - if (ep->num == 0) + if (tu_edpt_number(ep->ep_addr) == 0) { // A stall on EP0 has to be armed so it can be cleared on the next setup packet - usb_hw_set->ep_stall_arm = ep->in ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; + usb_hw_set->ep_stall_arm = (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; } _hw_endpoint_buffer_control_set_mask32(ep, USB_BUF_CTRL_STALL); ep->stalled = true; @@ -276,10 +275,10 @@ static void hw_endpoint_stall(uint8_t ep_addr) static void _hw_endpoint_clear_stall(struct hw_endpoint *ep) { - if (ep->num == 0) + if (tu_edpt_number(ep->ep_addr) == 0) { // Probably already been cleared but no harm - usb_hw_clear->ep_stall_arm = ep->in ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; + usb_hw_clear->ep_stall_arm = (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; } _hw_endpoint_buffer_control_clear_mask32(ep, USB_BUF_CTRL_STALL); ep->stalled = false; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 339297ad6..6c6911f2f 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -84,7 +84,7 @@ void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_m value |= or_mask; if (or_mask & USB_BUF_CTRL_AVAIL) { if (*ep->buffer_control & USB_BUF_CTRL_AVAIL) { - panic("ep %d %s was already available", ep->num, ep_dir_string[ep->in]); + panic("ep %d %s was already available", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); } *ep->buffer_control = value & ~USB_BUF_CTRL_AVAIL; // 12 cycle delay.. (should be good for 48*12Mhz = 576Mhz) @@ -141,11 +141,11 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len) { _hw_endpoint_lock_update(ep, 1); - pico_trace("Start transfer of total len %d on ep %d %s\n", total_len, ep->num, ep_dir_string[ep->in]); + pico_trace("Start transfer of total len %d on ep %d %s\n", total_len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); if (ep->active) { // TODO: Is this acceptable for interrupt packets? - pico_warn("WARN: starting new transfer on already active ep %d %s\n", ep->num, ep_dir_string[ep->in]); + pico_warn("WARN: starting new transfer on already active ep %d %s\n", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); hw_endpoint_reset_transfer(ep); } @@ -223,7 +223,7 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) // Part way through a transfer if (!ep->active) { - panic("Can't continue xfer on inactive ep %d %s", ep->num, ep_dir_string); + panic("Can't continue xfer on inactive ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string); } // Update EP struct from hardware state @@ -244,7 +244,7 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) if (ep->len == ep->total_len) { pico_trace("Completed transfer of %d bytes on ep %d %s\n", - ep->len, ep->num, ep_dir_string[ep->in]); + ep->len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); // Notify caller we are done so it can notify the tinyusb // stack _hw_endpoint_lock_update(ep, -1); @@ -263,7 +263,7 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) void _hw_endpoint_xfer(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len, bool start) { // Trace - pico_trace("hw_endpoint_xfer ep %d %s", ep->num, ep_dir_string[ep->in]); + pico_trace("hw_endpoint_xfer ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); pico_trace(" total_len %d, start=%d\n", total_len, start); assert(ep->configured); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 7c3234e8d..40b845a88 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -42,10 +42,6 @@ struct hw_endpoint { // Is this a valid struct bool configured; - // EP direction - bool in; - // EP num (not including direction) - uint8_t num; // Transfer direction (i.e. IN is rx for host but tx for device) // allows us to common up transfer functions -- cgit v1.3.1 From 313dd1439db037e676429d11646008f143e6bdb9 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 23 Feb 2021 19:41:21 +0100 Subject: Implement dcd_edpt_iso_xfer() for dcd_da146xx.c BUT WITHOUT DMA SUPPORT --- src/class/audio/audio_device.c | 1 - src/portable/dialog/da146xx/dcd_da146xx.c | 102 +++++++++++++++++++++++++++--- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 3 files changed, 94 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index c71ad6b8e..ef533e540 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -135,7 +135,6 @@ typedef struct CFG_TUSB_MCU == OPT_MCU_RP2040 || /* Don't want to change driver */ \ CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI || /* Intermediate software buffer required */ \ CFG_TUSB_MCU == OPT_MCU_CXD56 || /* No clue how driver works */ \ - CFG_TUSB_MCU == OPT_MCU_DA1469X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ CFG_TUSB_MCU == OPT_MCU_NRF5X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ CFG_TUSB_MCU == OPT_MCU_LPC11UXX || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 59f728d08..8e1a5ddfd 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -25,6 +25,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_DA1469X @@ -196,6 +197,7 @@ typedef struct typedef struct { EPx_REGS * regs; uint8_t * buffer; + tu_fifo_t * ff; // Total length of current transfer uint16_t total_len; // Bytes transferred so far @@ -292,7 +294,6 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) EPx_REGS *regs = xfer->regs; uint8_t const epnum = tu_edpt_number(xfer->ep_addr); - src = &xfer->buffer[xfer->transferred]; left_to_send = xfer->total_len - xfer->transferred; if (left_to_send > xfer->max_packet_size - xfer->last_packet_size) { @@ -301,12 +302,51 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) // Loop checks TCOUNT all the time since this value is saturated to 31 // and can't be read just once before. - while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && left_to_send > 0) + + if (xfer->ff) { - regs->txd = *src++; - xfer->last_packet_size++; - left_to_send--; + // Since TCOUNT is to be considered, we handle the FIFO reading manually here + // As we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies + // Check for first linear part + uint8_t * src; + uint16_t len = tu_fifo_get_linear_read_info(xfer->ff, 0, &src, left_to_send); // We want to read from the FIFO + uint16_t len1 = len; + while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && len1 > 0) + { + regs->txd = *src++; + xfer->last_packet_size++; + len1--; + } + + tu_fifo_advance_read_pointer(ff, len-len1); + left_to_send -= (len-len1); + + // Check for wrapped part + if ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) && left_to_send > 0) + { + len = tu_fifo_get_linear_read_info(xfer->ff, 0, &src, left_to_send); // We want to read from the FIFO + len1 = len; + while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && len1 > 0) + { + regs->txd = *src++; + xfer->last_packet_size++; + len1--; + } + tu_fifo_advance_read_pointer(ff, len-len1); + left_to_send -= (len-len1); + } } + else + { + src = &xfer->buffer[xfer->transferred]; + while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && left_to_send > 0) + { + regs->txd = *src++; + xfer->last_packet_size++; + left_to_send--; + } + } + if (epnum != 0) { if (left_to_send > 0) @@ -363,13 +403,14 @@ static void start_rx_packet(xfer_ctl_t *xfer) xfer->last_packet_size = 0; if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE) { - if (try_allocate_dma(epnum, TUSB_DIR_OUT)) + if (try_allocate_dma(epnum, TUSB_DIR_OUT) && !xfer->ff) { start_rx_dma(&xfer->regs->rxd, xfer->buffer + xfer->transferred, size); } else { // Other endpoint is using DMA in that direction, fall back to interrupts. + // Or if an ISO EP transfer was scheduled, currently not handled by DMA! // For endpoint size greater then FIFO size enable FIFO level warning interrupt // when FIFO has less then 17 bytes free. xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RFWL_Msk; @@ -409,7 +450,7 @@ static void start_tx_packet(xfer_ctl_t *xfer) regs->txc = USB_USB_TXC1_REG_USB_IGN_ISOMSK_Msk; if (xfer->data1) xfer->regs->txc |= USB_USB_TXC1_REG_USB_TOGGLE_TX_Msk; - if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE && try_allocate_dma(epnum, TUSB_DIR_IN)) + if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE && try_allocate_dma(epnum, TUSB_DIR_IN) && !xfer->ff) { // Whole packet will be put in FIFO by DMA. Set LAST bit before start. start_tx_dma(xfer->buffer + xfer->transferred, ®s->txd, size); @@ -430,9 +471,16 @@ static void read_rx_fifo(xfer_ctl_t *xfer, uint16_t bytes_in_fifo) if (remaining < bytes_in_fifo) receive_this_time = remaining; - uint8_t *buf = xfer->buffer + xfer->transferred + xfer->last_packet_size; + if (xfer->ff) + { + tu_fifo_write_n(xfer->ff, (const void *) ®s->rxd, receive_this_time); + } + else + { + uint8_t *buf = xfer->buffer + xfer->transferred + xfer->last_packet_size; - for (int i = 0; i < receive_this_time; ++i) buf[i] = regs->rxd; + for (int i = 0; i < receive_this_time; ++i) buf[i] = regs->rxd; + } xfer->last_packet_size += receive_this_time; } @@ -918,6 +966,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t (void)rhport; xfer->buffer = buffer; + xfer->ff = NULL; xfer->total_len = total_bytes; xfer->last_packet_size = 0; xfer->transferred = 0; @@ -934,6 +983,41 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t return true; } +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + + (void)rhport; + + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; + xfer->last_packet_size = 0; + xfer->transferred = 0; + + if (dir == TUSB_DIR_IN) + { + tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_CST); + } + else + { + tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); + } + + if (dir == TUSB_DIR_OUT) + { + start_rx_packet(xfer); + } + else // IN + { + start_tx_packet(xfer); + } + + return true; +} + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 5f8c44638..1d0bb5107 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -684,7 +684,7 @@ bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ uint8_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = NULL; // Indicates a FIFO shall be used + xfer->buffer = NULL; xfer->ff = ff; xfer->total_len = total_bytes; -- cgit v1.3.1 From c76e04f83584c55719a178b8308b3b2d0141b064 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 23 Feb 2021 19:50:54 +0100 Subject: Add dcd_edpt_iso_xfer() to dcd_template.c --- src/portable/template/dcd_template.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src') diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 618812416..7a9a0ae22 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -25,6 +25,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if CFG_TUSB_MCU == OPT_MCU_NONE @@ -104,6 +105,16 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return false; } +// Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + (void) ep_addr; + (void) ff; + (void) total_bytes; + return false; +} + // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { -- cgit v1.3.1 From 387bf1478efb89b5df12801dd904f93c374649b1 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 23 Feb 2021 19:52:31 +0100 Subject: Fix missing , in tusb_fifo.h --- src/common/tusb_fifo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 8e1c015ec..8cc448db0 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -98,7 +98,7 @@ typedef struct .item_size = sizeof(_type), \ .overwritable = _overwritable, \ .max_pointer_idx = 2*(_depth)-1, \ - .non_used_index_space = UINT16_MAX - (2*(_depth)-1) \ + .non_used_index_space = UINT16_MAX - (2*(_depth)-1), \ .wr_mode = TU_FIFO_COPY_INC, \ .rd_mode = TU_FIFO_COPY_INC, \ } -- cgit v1.3.1 From 00248de15a7f95f563503595099d68cd0c08cff5 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 23 Feb 2021 20:23:26 +0100 Subject: Fix shadowing declartion in dcd_da146xx.c --- src/portable/dialog/da146xx/dcd_da146xx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 8e1a5ddfd..dff2d00fb 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -290,7 +290,6 @@ void tusb_vbus_changed(bool present) static void fill_tx_fifo(xfer_ctl_t * xfer) { int left_to_send; - uint8_t const *src; EPx_REGS *regs = xfer->regs; uint8_t const epnum = tu_edpt_number(xfer->ep_addr); @@ -338,7 +337,7 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) } else { - src = &xfer->buffer[xfer->transferred]; + uint8_t const *src = &xfer->buffer[xfer->transferred]; while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && left_to_send > 0) { regs->txd = *src++; -- cgit v1.3.1 From e00178a1afefc9b0b2d4fc440a6db536a4bb7afe Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Tue, 23 Feb 2021 14:04:56 -0600 Subject: rp2040: don't compile in host code when in device mode --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 10 ++++++++++ src/portable/raspberrypi/rp2040/rp2040_usb.h | 4 ++++ 2 files changed, 14 insertions(+) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 339297ad6..80d4c2990 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -44,10 +44,12 @@ static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) { // sense to have worker and IRQ on same core, however I think using critsec is about equivalent. } +#ifdef RP2040_USB_HOST_MODE static inline void _hw_endpoint_update_last_buf(struct hw_endpoint *ep) { ep->last_buf = ep->len + ep->transfer_size == ep->total_len; } +#endif void rp2040_usb_init(void) { @@ -68,7 +70,9 @@ void hw_endpoint_reset_transfer(struct hw_endpoint *ep) { ep->stalled = false; ep->active = false; +#ifdef RP2040_USB_HOST_MODE ep->sent_setup = false; +#endif ep->total_len = 0; ep->len = 0; ep->transfer_size = 0; @@ -122,6 +126,7 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; ep->next_pid ^= 1u; +#ifdef RP2040_USB_HOST_MODE // Is this the last buffer? Only really matters for host mode. Will trigger // the trans complete irq but also stop it polling. We only really care about // trans complete for setup packets being sent @@ -130,6 +135,7 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) pico_trace("Last buf (%d bytes left)\n", ep->transfer_size); val |= USB_BUF_CTRL_LAST; } +#endif // Finally, write to buffer_control which will trigger the transfer // the next time the controller polls this dpram address @@ -156,9 +162,11 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t ep->transfer_size = tu_min32(total_len, ep->wMaxPacketSize); ep->active = true; ep->user_buf = buffer; +#ifdef RP2040_USB_HOST_MODE // Recalculate if this is the last buffer _hw_endpoint_update_last_buf(ep); ep->buf_sel = 0; +#endif _hw_endpoint_start_next_buffer(ep); _hw_endpoint_lock_update(ep, -1); @@ -232,7 +240,9 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) // Now we have synced our state with the hardware. Is there more data to transfer? uint remaining_bytes = ep->total_len - ep->len; ep->transfer_size = tu_min32(remaining_bytes, ep->wMaxPacketSize); +#ifdef RP2040_USB_HOST_MODE _hw_endpoint_update_last_buf(ep); +#endif // Can happen because of programmer error so check for it if (ep->len > ep->total_len) diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 7c3234e8d..db9845491 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -71,11 +71,13 @@ struct hw_endpoint uint len; // Amount of data with the hardware uint transfer_size; +#ifdef RP2040_USB_HOST_MODE // Only needed for host mode bool last_buf; // HOST BUG. Host will incorrect write status to top half of buffer // control register when doing transfers > 1 packet uint8_t buf_sel; +#endif // User buffer in main memory uint8_t *user_buf; @@ -84,11 +86,13 @@ struct hw_endpoint // Interrupt, bulk, etc uint8_t transfer_type; +#ifdef RP2040_USB_HOST_MODE // Only needed for host uint8_t dev_addr; bool sent_setup; // If interrupt endpoint uint8_t interrupt_num; +#endif }; void rp2040_usb_init(void); -- cgit v1.3.1 From cb33840a9bd2013b3acc1b0fa1088d18e9cc035a Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 23 Feb 2021 21:15:27 +0100 Subject: Fix pointer type --- src/portable/dialog/da146xx/dcd_da146xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index dff2d00fb..53c12787c 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -308,7 +308,7 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) // As we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part uint8_t * src; - uint16_t len = tu_fifo_get_linear_read_info(xfer->ff, 0, &src, left_to_send); // We want to read from the FIFO + uint16_t len = tu_fifo_get_linear_read_info(xfer->ff, 0, &((void *) src), left_to_send); // We want to read from the FIFO uint16_t len1 = len; while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && len1 > 0) { @@ -323,7 +323,7 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) // Check for wrapped part if ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) && left_to_send > 0) { - len = tu_fifo_get_linear_read_info(xfer->ff, 0, &src, left_to_send); // We want to read from the FIFO + len = tu_fifo_get_linear_read_info(xfer->ff, 0, &((void *) src), left_to_send); // We want to read from the FIFO len1 = len; while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && len1 > 0) { -- cgit v1.3.1 From 697c9476b75afa22a139325e9ae53d21fa5ed992 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 23 Feb 2021 21:42:38 +0100 Subject: Fix pointer type --- src/portable/dialog/da146xx/dcd_da146xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 53c12787c..1fa722d63 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -308,7 +308,7 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) // As we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part uint8_t * src; - uint16_t len = tu_fifo_get_linear_read_info(xfer->ff, 0, &((void *) src), left_to_send); // We want to read from the FIFO + uint16_t len = tu_fifo_get_linear_read_info(xfer->ff, 0, (void **) &src, left_to_send); // We want to read from the FIFO uint16_t len1 = len; while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && len1 > 0) { @@ -323,7 +323,7 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) // Check for wrapped part if ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) && left_to_send > 0) { - len = tu_fifo_get_linear_read_info(xfer->ff, 0, &((void *) src), left_to_send); // We want to read from the FIFO + len = tu_fifo_get_linear_read_info(xfer->ff, 0, (void **) &src, left_to_send); // We want to read from the FIFO len1 = len; while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && len1 > 0) { -- cgit v1.3.1 From a7f07a1a63a07000a35357194dff7d61890c60c6 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 23 Feb 2021 21:53:17 +0100 Subject: Fix pointer type --- src/portable/dialog/da146xx/dcd_da146xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 1fa722d63..69ea5d87f 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -317,7 +317,7 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) len1--; } - tu_fifo_advance_read_pointer(ff, len-len1); + tu_fifo_advance_read_pointer(xfer->ff, len-len1); left_to_send -= (len-len1); // Check for wrapped part @@ -331,7 +331,7 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) xfer->last_packet_size++; len1--; } - tu_fifo_advance_read_pointer(ff, len-len1); + tu_fifo_advance_read_pointer(xfer->ff, len-len1); left_to_send -= (len-len1); } } -- cgit v1.3.1 From a07062672933a5e2ba21db806217ce69243ceabe Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Feb 2021 14:27:20 +0700 Subject: add itf argument to hid API to support multiple instances following API signature is changed: - tud_hid_descriptor_report_cb() - tud_hid_get_report_cb() - tud_hid_set_report_cb() - tud_hid_boot_mode_cb() - tud_hid_set_idle_cb() --- examples/device/hid_composite/src/main.c | 6 ++-- .../device/hid_composite/src/usb_descriptors.c | 3 +- examples/device/hid_composite_freertos/src/main.c | 6 ++-- .../hid_composite_freertos/src/usb_descriptors.c | 2 +- examples/device/hid_generic_inout/src/main.c | 6 ++-- .../device/hid_generic_inout/src/usb_descriptors.c | 3 +- src/class/hid/hid_device.c | 41 ++++------------------ src/class/hid/hid_device.h | 14 -------- 8 files changed, 23 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 9fb2de88d..512f6f9d9 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -239,9 +239,10 @@ void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len) // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) +uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { // TODO not Implemented + (void) itf; (void) report_id; (void) report_type; (void) buffer; @@ -252,9 +253,10 @@ uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) +void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { // TODO set LED based on CAPLOCK, NUMLOCK etc... + (void) itf; (void) report_id; (void) report_type; (void) buffer; diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index ec4976188..ccc1306bd 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -82,8 +82,9 @@ uint8_t const desc_hid_report[] = // 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) +uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) { + (void) itf; return desc_hid_report; } diff --git a/examples/device/hid_composite_freertos/src/main.c b/examples/device/hid_composite_freertos/src/main.c index aa006fbea..79dc2ec69 100644 --- a/examples/device/hid_composite_freertos/src/main.c +++ b/examples/device/hid_composite_freertos/src/main.c @@ -299,9 +299,10 @@ void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len) // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) +uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { // TODO not Implemented + (void) itf; (void) report_id; (void) report_type; (void) buffer; @@ -312,9 +313,10 @@ uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) +void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { // TODO set LED based on CAPLOCK, NUMLOCK etc... + (void) itf; (void) report_id; (void) report_type; (void) buffer; diff --git a/examples/device/hid_composite_freertos/src/usb_descriptors.c b/examples/device/hid_composite_freertos/src/usb_descriptors.c index ec4976188..da91b71ec 100644 --- a/examples/device/hid_composite_freertos/src/usb_descriptors.c +++ b/examples/device/hid_composite_freertos/src/usb_descriptors.c @@ -82,7 +82,7 @@ uint8_t const desc_hid_report[] = // 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) +uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) { return desc_hid_report; } diff --git a/examples/device/hid_generic_inout/src/main.c b/examples/device/hid_generic_inout/src/main.c index 4573bd7e0..65874f483 100644 --- a/examples/device/hid_generic_inout/src/main.c +++ b/examples/device/hid_generic_inout/src/main.c @@ -121,9 +121,10 @@ void tud_resume_cb(void) // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) +uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { // TODO not Implemented + (void) itf; (void) report_id; (void) report_type; (void) buffer; @@ -134,9 +135,10 @@ uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) +void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { // This example doesn't use multiple report and report ID + (void) itf; (void) report_id; (void) report_type; diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index ef7450e8f..db4ddd76e 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -78,8 +78,9 @@ uint8_t const desc_hid_report[] = // 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) +uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) { + (void) itf; return desc_hid_report; } diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 4cdcecc9e..18d35bc20 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -251,11 +251,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t } else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { - uint8_t const * desc_report = tud_hid_descriptor_report_cb( - #if CFG_TUD_HID > 1 - hid_itf // TODO for backward compatible callback, remove later when appropriate - #endif - ); + uint8_t const * desc_report = tud_hid_descriptor_report_cb(hid_itf); tud_control_xfer(rhport, request, (void*) desc_report, p_hid->report_desc_len); } else @@ -275,12 +271,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); - uint16_t xferlen = tud_hid_get_report_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength - ); + uint16_t xferlen = tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); TU_ASSERT( xferlen > 0 ); tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); @@ -298,12 +289,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); - tud_hid_set_report_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength - ); + tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength); } break; @@ -314,12 +300,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t if ( tud_hid_set_idle_cb ) { // stall request if callback return false - TU_VERIFY( tud_hid_set_idle_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - p_hid->idle_rate) - ); + TU_VERIFY( tud_hid_set_idle_cb( hid_itf, p_hid->idle_rate) ); } tud_control_status(rhport, request); @@ -354,12 +335,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t { if (tud_hid_boot_mode_cb) { - tud_hid_boot_mode_cb( - #if CFG_TUD_HID > 1 - hid_itf, // TODO for backward compatible callback, remove later when appropriate - #endif - p_hid->boot_mode - ); + tud_hid_boot_mode_cb(hid_itf, p_hid->boot_mode); } } break; @@ -400,12 +376,7 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Received report else if (ep_addr == p_hid->ep_out) { - tud_hid_set_report_cb( - #if CFG_TUD_HID > 1 - itf, // TODO for backward compatible callback, remove later when appropriate - #endif - 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes - ); + tud_hid_set_report_cb(itf, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index d5de53221..0c59d5d20 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -88,8 +88,6 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 // Callbacks (Weak is optional) //--------------------------------------------------------------------+ -#if CFG_TUD_HID > 1 - // Invoked when received GET HID REPORT DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf); @@ -111,18 +109,6 @@ TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t itf, uint8_t boot_mode); // - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t itf, uint8_t idle_rate); -#else - -// TODO for backward compatible callback, remove later when appropriate -uint8_t const * tud_hid_descriptor_report_cb(void); -uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); -void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); - -TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t boot_mode); -TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); - -#endif - // Invoked when sent REPORT successfully to host // Application can use this to send the next report // Note: For composite reports, report[0] is report ID -- cgit v1.3.1 From 448dcdc4cf6ff20a96840fc23944167fc4e88501 Mon Sep 17 00:00:00 2001 From: Kamil Tomaszewski Date: Wed, 24 Feb 2021 17:39:16 +0100 Subject: spresense: fix setup processed flag --- src/portable/sony/cxd56/dcd_cxd56.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 904176ba1..54958182b 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -329,6 +329,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to { if (total_bytes == 0) { + usbdcd_driver.setup_processed = true; dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, false); } else if (ep_addr == 0x00 && total_bytes == usbdcd_driver.outlen) @@ -350,12 +351,15 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to } } - usbdcd_driver.setup_processed = true; struct usb_ctrlreq_s ctrl; - if (osal_queue_receive(usbdcd_driver.setup_queue, &ctrl)) + if (usbdcd_driver.setup_processed) { - dcd_event_setup_received(0, (uint8_t *)&ctrl, false); + if (osal_queue_receive(usbdcd_driver.setup_queue, &ctrl)) + { + usbdcd_driver.setup_processed = false; + dcd_event_setup_received(0, (uint8_t *)&ctrl, false); + } } } else -- cgit v1.3.1 From cc948288bd0a56457ffdc521e34bbc71ecbec40a Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 25 Feb 2021 11:18:37 +0100 Subject: Revert tusb_fifo.h include form to original. --- src/common/tusb_fifo.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 8cc448db0..2cab2abf8 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -53,7 +53,6 @@ extern "C" { #endif #if CFG_FIFO_MUTEX -#include "osal/osal.h" #define tu_fifo_mutex_t osal_mutex_t #endif -- cgit v1.3.1 From 762f262be76480717227a6f32bd4a190a9d263ea Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Thu, 25 Feb 2021 07:58:54 -0600 Subject: rp2040: requested change from TU_MIN to tu_min16 --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 9c43b6fdb..9d36734b6 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -64,7 +64,7 @@ static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr) } static void _hw_endpoint_alloc(struct hw_endpoint *ep) { - uint16_t size = TU_MIN(64, ep->wMaxPacketSize); + uint16_t size = tu_min16(64, ep->wMaxPacketSize); // Assumes single buffered for now ep->hw_data_buf = next_buffer_ptr; -- cgit v1.3.1 From 999ef227d0151bae5db09da7a9b3ed3be20ef891 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Thu, 25 Feb 2021 08:45:47 -0600 Subject: rp2040: requested code mode in rp2040_usb.h --- src/portable/raspberrypi/rp2040/rp2040_usb.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index db9845491..3448d2539 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -71,13 +71,6 @@ struct hw_endpoint uint len; // Amount of data with the hardware uint transfer_size; -#ifdef RP2040_USB_HOST_MODE - // Only needed for host mode - bool last_buf; - // HOST BUG. Host will incorrect write status to top half of buffer - // control register when doing transfers > 1 packet - uint8_t buf_sel; -#endif // User buffer in main memory uint8_t *user_buf; @@ -87,6 +80,11 @@ struct hw_endpoint uint8_t transfer_type; #ifdef RP2040_USB_HOST_MODE + // Only needed for host mode + bool last_buf; + // HOST BUG. Host will incorrect write status to top half of buffer + // control register when doing transfers > 1 packet + uint8_t buf_sel; // Only needed for host uint8_t dev_addr; bool sent_setup; -- cgit v1.3.1 From e6e7c73f6e5ff53e3b4869fdc9abfd809d1e50a8 Mon Sep 17 00:00:00 2001 From: Liam Fraser Date: Thu, 25 Feb 2021 15:48:19 +0000 Subject: Update RP2040 hcd_init to have rhport argument. --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index efb2bd430..0f2779453 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -363,9 +363,10 @@ static void hw_endpoint_init(uint8_t dev_addr, const tusb_desc_endpoint_t *ep_de //--------------------------------------------------------------------+ // HCD API //--------------------------------------------------------------------+ -bool hcd_init(void) +bool hcd_init(uint8_t rhport) { - pico_trace("hcd_init\n"); + pico_trace("hcd_init %d\n", rhport); + assert(rhport == 0); // Reset any previous state rp2040_usb_init(); -- cgit v1.3.1 From 07a04255da4442fb0790130ac65c648d0884255a Mon Sep 17 00:00:00 2001 From: amit verma Date: Thu, 25 Feb 2021 23:13:21 +0530 Subject: initial break request handling --- src/class/cdc/cdc_device.c | 11 +++++++++++ src/class/cdc/cdc_device.h | 3 +++ 2 files changed, 14 insertions(+) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 58f485a5d..5a74b4876 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -396,6 +396,17 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); } break; + case CDC_REQUEST_SEND_BREAK: + if (stage == CONTROL_STAGE_SETUP) + { + tud_control_status(rhport, request); + } + else if (stage == CONTROL_STAGE_ACK) + { + TU_LOG2(" Send Break\r\n"); + if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); + } + break; default: return false; // stall unsupported request } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 62dcd3c0a..d10fe68db 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -133,6 +133,9 @@ static inline bool tud_cdc_write_clear (void); // Invoked when received new data TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); +// Invoked when received send break +TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t wait_ms); + // Invoked when received `wanted_char` TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); -- cgit v1.3.1 From 55a46a5c3b7ad3afb70a995954baa6148381b3a5 Mon Sep 17 00:00:00 2001 From: boggyb Date: Fri, 26 Feb 2021 11:00:34 +0530 Subject: Update cdc_device.h Minor api callback change as requested --- src/class/cdc/cdc_device.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index d10fe68db..0885922c6 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -133,9 +133,6 @@ static inline bool tud_cdc_write_clear (void); // Invoked when received new data TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); -// Invoked when received send break -TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t wait_ms); - // Invoked when received `wanted_char` TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); @@ -148,6 +145,9 @@ TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); // Invoked when line coding is change via SET_LINE_CODING TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding); +// Invoked when received send break +TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); + //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ -- cgit v1.3.1 From f6b48c07fca039ea49be49062298e1dc8cc78471 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 26 Feb 2021 14:05:08 +0700 Subject: add rp2040 to host example build --- examples/host/cdc_msc_hid/.only.MCU_RP2040 | 0 examples/host/cdc_msc_hid/CMakeLists.txt | 46 ++++++++++++++++++++++++++++ hw/bsp/rp2040/family.cmake | 9 +++++- src/host/usbh.c | 2 ++ src/osal/osal.h | 1 - src/osal/osal_none.h | 9 +----- src/osal/osal_pico.h | 4 +-- src/portable/raspberrypi/rp2040/rp2040_usb.c | 14 ++++----- src/portable/raspberrypi/rp2040/rp2040_usb.h | 2 +- 9 files changed, 66 insertions(+), 21 deletions(-) create mode 100644 examples/host/cdc_msc_hid/.only.MCU_RP2040 create mode 100644 examples/host/cdc_msc_hid/CMakeLists.txt (limited to 'src') diff --git a/examples/host/cdc_msc_hid/.only.MCU_RP2040 b/examples/host/cdc_msc_hid/.only.MCU_RP2040 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/cdc_msc_hid/CMakeLists.txt b/examples/host/cdc_msc_hid/CMakeLists.txt new file mode 100644 index 000000000..dc2effde9 --- /dev/null +++ b/examples/host/cdc_msc_hid/CMakeLists.txt @@ -0,0 +1,46 @@ +# use directory name for project id +get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME) +set(PROJECT ${BOARD}-${PROJECT}) + +# TOP is absolute path to root directory of TinyUSB git repo +set(TOP "../../..") +get_filename_component(TOP "${TOP}" REALPATH) + +# Check for -DFAMILY= +if(FAMILY STREQUAL "esp32s2") + cmake_minimum_required(VERSION 3.5) + include(${TOP}/hw/bsp/${FAMILY}/family.cmake) + project(${PROJECT}) + +elseif(FAMILY STREQUAL "rp2040") + cmake_minimum_required(VERSION 3.12) + set(PICO_SDK_PATH ${TOP}/hw/mcu/raspberrypi/pico-sdk) + include(${PICO_SDK_PATH}/pico_sdk_init.cmake) + project(${PROJECT}) + pico_sdk_init() + add_executable(${PROJECT}) + + include(${TOP}/hw/bsp/${FAMILY}/family.cmake) + + # Example source + target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c + ) + + # Example include + target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + + # Example defines + target_compile_definitions(${PROJECT} PUBLIC + CFG_TUSB_OS=OPT_OS_PICO + ) + + target_link_libraries(${PROJECT} pico_stdlib pico_fix_rp2040_usb_device_enumeration) + pico_add_extra_outputs(${PROJECT}) + +else() + message(FATAL_ERROR "Invalid FAMILY specified") +endif() diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake index e4f5f47b4..d2e164be5 100644 --- a/hw/bsp/rp2040/family.cmake +++ b/hw/bsp/rp2040/family.cmake @@ -13,8 +13,15 @@ set(SRC_TINYUSB ${TOP}/src/class/net/net_device.c ${TOP}/src/class/usbtmc/usbtmc_device.c ${TOP}/src/class/vendor/vendor_device.c - ${TOP}/src/portable/raspberrypi/${FAMILY}/dcd_rp2040.c + ${TOP}/src/host/hub.c + ${TOP}/src/host/usbh.c + ${TOP}/src/host/usbh_control.c + ${TOP}/src/class/cdc/cdc_host.c + ${TOP}/src/class/hid/hid_host.c + ${TOP}/src/class/msc/msc_host.c ${TOP}/src/portable/raspberrypi/${FAMILY}/rp2040_usb.c + ${TOP}/src/portable/raspberrypi/${FAMILY}/dcd_rp2040.c + ${TOP}/src/portable/raspberrypi/${FAMILY}/hcd_rp2040.c ) target_sources(${PROJECT} PUBLIC diff --git a/src/host/usbh.c b/src/host/usbh.c index 0bc6378b2..a4ee4cb5c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -157,6 +157,7 @@ tusb_speed_t tuh_device_get_speed (uint8_t const dev_addr) return (tusb_speed_t) _usbh_devices[dev_addr].speed; } +#if CFG_TUSB_OS == OPT_OS_NONE void osal_task_delay(uint32_t msec) { (void) msec; @@ -164,6 +165,7 @@ void osal_task_delay(uint32_t msec) const uint32_t start = hcd_frame_number(TUH_OPT_RHPORT); while ( ( hcd_frame_number(TUH_OPT_RHPORT) - start ) < msec ) {} } +#endif //--------------------------------------------------------------------+ // CLASS-USBD API (don't require to verify parameters) diff --git a/src/osal/osal.h b/src/osal/osal.h index 02e3e0a06..28bdf479c 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -66,7 +66,6 @@ typedef void (*osal_task_func_t)( void * ); //--------------------------------------------------------------------+ // OSAL Porting API //--------------------------------------------------------------------+ -//static inline void osal_task_delay(uint32_t msec); //------------- Semaphore -------------// static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef); diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index ea6818621..a1f997cf2 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -34,14 +34,7 @@ //--------------------------------------------------------------------+ // TASK API //--------------------------------------------------------------------+ -//static inline void osal_task_delay(uint32_t msec) -//{ -// (void) msec; -// // TODO only used by Host stack, will implement using SOF -// -//// uint32_t start = tusb_hal_millis(); -//// while ( ( tusb_hal_millis() - start ) < msec ) {} -//} + //--------------------------------------------------------------------+ // Binary Semaphore API diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index de964a7a0..c277af271 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -39,12 +39,10 @@ //--------------------------------------------------------------------+ // TASK API //--------------------------------------------------------------------+ -#ifndef RP2040_USB_HOST_MODE static inline void osal_task_delay(uint32_t msec) { - sleep_ms(msec); + sleep_ms(msec); } -#endif //--------------------------------------------------------------------+ // Binary Semaphore API diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 4e0850af8..4866f0fea 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -43,7 +43,7 @@ static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) { // sense to have worker and IRQ on same core, however I think using critsec is about equivalent. } -#ifdef RP2040_USB_HOST_MODE +#if TUSB_OPT_HOST_ENABLED static inline void _hw_endpoint_update_last_buf(struct hw_endpoint *ep) { ep->last_buf = ep->len + ep->transfer_size == ep->total_len; @@ -69,7 +69,7 @@ void hw_endpoint_reset_transfer(struct hw_endpoint *ep) { ep->stalled = false; ep->active = false; -#ifdef RP2040_USB_HOST_MODE +#if TUSB_OPT_HOST_ENABLED ep->sent_setup = false; #endif ep->total_len = 0; @@ -92,7 +92,7 @@ void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_m *ep->buffer_control = value & ~USB_BUF_CTRL_AVAIL; // 12 cycle delay.. (should be good for 48*12Mhz = 576Mhz) // Don't need delay in host mode as host is in charge -#ifndef RP2040_USB_HOST_MODE +#if !TUSB_OPT_HOST_ENABLED __asm volatile ( "b 1f\n" "1: b 1f\n" @@ -125,7 +125,7 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; ep->next_pid ^= 1u; -#ifdef RP2040_USB_HOST_MODE +#if TUSB_OPT_HOST_ENABLED // Is this the last buffer? Only really matters for host mode. Will trigger // the trans complete irq but also stop it polling. We only really care about // trans complete for setup packets being sent @@ -161,7 +161,7 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t ep->transfer_size = tu_min16(total_len, ep->wMaxPacketSize); ep->active = true; ep->user_buf = buffer; -#ifdef RP2040_USB_HOST_MODE +#if TUSB_OPT_HOST_ENABLED // Recalculate if this is the last buffer _hw_endpoint_update_last_buf(ep); ep->buf_sel = 0; @@ -181,7 +181,7 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); uint16_t transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; -#ifdef RP2040_USB_HOST_MODE +#if TUSB_OPT_HOST_ENABLED // tag::host_buf_sel_fix[] if (ep->buf_sel == 1) { @@ -239,7 +239,7 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) // Now we have synced our state with the hardware. Is there more data to transfer? uint16_t remaining_bytes = ep->total_len - ep->len; ep->transfer_size = tu_min16(remaining_bytes, ep->wMaxPacketSize); -#ifdef RP2040_USB_HOST_MODE +#if TUSB_OPT_HOST_ENABLED _hw_endpoint_update_last_buf(ep); #endif diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index e92b70416..986bd2f07 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -79,7 +79,7 @@ struct hw_endpoint // Interrupt, bulk, etc uint8_t transfer_type; -#ifdef RP2040_USB_HOST_MODE +#if TUSB_OPT_HOST_ENABLED // Only needed for host mode bool last_buf; // HOST BUG. Host will incorrect write status to top half of buffer -- cgit v1.3.1 From eb44b6f7db33e89c0d1dc369d914f18388deff53 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Fri, 26 Feb 2021 11:07:34 -0600 Subject: rp2040: improve _hw_endpoint_init() --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 787add15d..d32870439 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -102,8 +102,8 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep) static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { - uint8_t num = tu_edpt_number(ep_addr); - tusb_dir_t dir = tu_edpt_dir(ep_addr); + const uint8_t num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); ep->ep_addr = ep_addr; // For device, IN is a tx transfer and OUT is an rx transfer ep->rx = (dir == TUSB_DIR_OUT); @@ -130,7 +130,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t ep->transfer_type = transfer_type; // Every endpoint has a buffer control register in dpram - if (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) + if (dir == TUSB_DIR_IN) { ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in; } @@ -142,7 +142,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t // Clear existing buffer control state *ep->buffer_control = 0; - if (tu_edpt_number(ep->ep_addr) == 0) + if (num == 0) { // EP0 has no endpoint control register because // the buffer offsets are fixed -- cgit v1.3.1 From 72c1066ed152916cb99dee5e5749b78916d4ba76 Mon Sep 17 00:00:00 2001 From: Duddie Date: Sun, 28 Feb 2021 22:18:35 +0800 Subject: Fix Endpoint descriptor for MIDI Device Endpoint descriptor should be 9 bytes in length (not 7) and have two extra bytes at the end: bRefresh and bSynchAddress According to MIDI USB specification 1.0 (6.2.1 Standard MS Bulk Data Endpoint Descriptor) --- src/device/usbd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index b5f7dceba..8aeb6aff8 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -289,10 +289,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* MS Out Jack (External), connected to In Jack Embedded */\ 9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0 -#define TUD_MIDI_DESC_EP_LEN(_numcables) (7 + 4 + (_numcables)) +#define TUD_MIDI_DESC_EP_LEN(_numcables) (9 + 4 + (_numcables)) #define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ /* Endpoint */\ - 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + 9, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0, 0, 0, \ /* MS Endpoint (connected to embedded jack) */\ (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables -- cgit v1.3.1 From 8ec99694d228d31ee0b4033346498238c6605967 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 1 Mar 2021 09:09:15 +0100 Subject: audio_decive clean up and bootstrapping of linear (formerly evade) buff. --- src/class/audio/audio_device.c | 300 +++++++++++++++++++++++------------------ src/class/audio/audio_device.h | 42 +++--- 2 files changed, 188 insertions(+), 154 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index ef533e540..a29abc496 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -30,6 +30,22 @@ * * In case you need more alternate interfaces, you need to define additional defines for this specific alternate interface. Just define them and set them in the set_interface function. * + * There are three data flow structures currently implemented, where at least one SW-FIFO is used to decouple the asynchronous processes MCU vs. host + * + * 1. Input data -> SW-FIFO -> MCU USB + * + * The most easiest version, available in case the target MCU can handle the software FIFO (SW-FIFO) and if it is implemented in the device driver (if yes then dcd_edpt_iso_xfer() is available) + * + * 2. Input data -> SW-FIFO -> Linear buffer -> MCU USB + * + * In case the target MCU can not handle a SW-FIFO, a linear buffer is used. This uses the default function dcd_edpt_xfer(). In this case more memory is required. + * + * 3. (Input data 1 | Input data 2 | ... | Input data N) -> (SW-FIFO 1 | SW-FIFO 2 | ... | SW-FIFO N) -> Linear buffer -> MCU USB + * + * This case is used if you have more channels which need to be combined into one stream. Every channel has its own SW-FIFO. All data is encoded into an Linear buffer. + * + * The same holds in the RX case. + * * */ #include "tusb_option.h" @@ -47,17 +63,45 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ + // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically +#if ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || /* Intermediate software buffer required */ \ + CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ + CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ + CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_RP2040 || /* Don't want to change driver */ \ + CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI || /* Intermediate software buffer required */ \ + CFG_TUSB_MCU == OPT_MCU_CXD56 || /* No clue how driver works */ \ + CFG_TUSB_MCU == OPT_MCU_NRF5X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ + CFG_TUSB_MCU == OPT_MCU_LPC11UXX || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ + CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC15XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC51UXX || \ + CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ + CFG_TUSB_MCU == OPT_MCU_LPC55XX || \ + CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ + CFG_TUSB_MCU == OPT_MCU_LPC40XX || \ + CFG_TUSB_MCU == OPT_MCU_SAMD11 || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ + CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ + CFG_TUSB_MCU == OPT_MCU_SAMD51 || \ + CFG_TUSB_MCU == OPT_MCU_SAME5X ) + +#define USE_LINEAR_BUFFER 1 + +#else +#define USE_LINEAR_BUFFER 0 +#endif + typedef struct { uint8_t rhport; uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EPSIZE_IN uint8_t ep_in; // TX audio data EP. uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EPSIZE_OUT uint8_t ep_out; // Incoming (into uC) audio data EP. uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) @@ -82,6 +126,8 @@ typedef struct // EP Transfer buffers and FIFOs #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE + +#if !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE CFG_TUSB_MEM_ALIGN uint8_t ep_out_buf[CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE]; tu_fifo_t ep_out_ff; @@ -89,13 +135,15 @@ typedef struct osal_mutex_def_t ep_out_ff_mutex; #endif +#endif + #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). #endif #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE CFG_TUSB_MEM_ALIGN uint8_t ep_in_buf[CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE]; tu_fifo_t ep_in_ff; @@ -112,60 +160,41 @@ typedef struct // Support FIFOs #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - tu_fifo_t tx_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; - CFG_TUSB_MEM_ALIGN uint8_t tx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE]; + tu_fifo_t tx_supp_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; + CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; + osal_mutex_def_t tx_supp_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; #endif #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - tu_fifo_t rx_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; - CFG_TUSB_MEM_ALIGN uint8_t rx_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE]; + tu_fifo_t rx_supp_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; + CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; + osal_mutex_def_t rx_supp_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; #endif #endif - // Evasion buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically -#if ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || /* Intermediate software buffer required */ \ - CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ - CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ - CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_RP2040 || /* Don't want to change driver */ \ - CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI || /* Intermediate software buffer required */ \ - CFG_TUSB_MCU == OPT_MCU_CXD56 || /* No clue how driver works */ \ - CFG_TUSB_MCU == OPT_MCU_NRF5X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ - CFG_TUSB_MCU == OPT_MCU_LPC11UXX || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ - CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC15XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC51UXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC55XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ - CFG_TUSB_MCU == OPT_MCU_LPC40XX || \ - CFG_TUSB_MCU == OPT_MCU_SAMD11 || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ - CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ - CFG_TUSB_MCU == OPT_MCU_SAMD51 || \ - CFG_TUSB_MCU == OPT_MCU_SAME5X ) - -#define USE_EVADE_BUFFER 1 - -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE - CFG_TUSB_MEM_ALIGN uint8_t evasion_buf_out[CFG_TUD_AUDIO_EPSIZE_OUT]; + // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used +#if CFG_TUD_AUDIO_EPSIZE_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE) + CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out[CFG_TUD_AUDIO_EPSIZE_OUT]; +#define USE_LINEAR_BUFFER_RX 1 #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE - CFG_TUSB_MEM_ALIGN uint8_t evasion_buf_in[CFG_TUD_AUDIO_EPSIZE_IN]; +#if CFG_TUD_AUDIO_EPSIZE_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE) + CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in[CFG_TUD_AUDIO_EPSIZE_IN]; +#define USE_LINEAR_BUFFER_TX 1 #endif -#endif +} audiod_interface_t; -#ifndef USE_EVADE_BUFFER -#define USE_EVADE_BUFFER 0 +#ifndef USE_LINEAR_BUFFER_TX +#define USE_LINEAR_BUFFER_TX 0 #endif -} audiod_interface_t; +#ifndef USE_LINEAR_BUFFER_RX +#define USE_LINEAR_BUFFER_RX 0 +#endif #define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ctrl_buf) @@ -177,19 +206,19 @@ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; extern const uint16_t tud_audio_desc_lengths[]; #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio); +static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); #endif #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio); #endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -static bool audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); #endif static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); @@ -228,7 +257,7 @@ bool tud_audio_n_mounted(uint8_t itf) // READ API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE uint16_t tud_audio_n_available(uint8_t itf) { @@ -248,35 +277,35 @@ bool tud_audio_n_clear_ep_out_ff(uint8_t itf) return tu_fifo_clear(&_audiod_itf[itf].ep_out_ff); } -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#endif + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT // Delete all content in the support RX FIFOs bool tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_clear(&_audiod_itf[itf].rx_ff[channelId]); + return tu_fifo_clear(&_audiod_itf[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_count(&_audiod_itf[itf].rx_ff[channelId]); + return tu_fifo_count(&_audiod_itf[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); - return tu_fifo_read_n(&_audiod_itf[itf].rx_ff[channelId], buffer, bufsize); + return tu_fifo_read_n(&_audiod_itf[itf].rx_supp_ff[channelId], buffer, bufsize); } #endif -#endif - -// This function is called once an audio packet is received by the USB and is responsible for decoding received stream into audio channels. +// This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO (or support FIFOs + decoding of received stream into audio channels). // If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE = 0. #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) +static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) { uint8_t idxDriver, idxItf; uint8_t const *dummy2; @@ -288,13 +317,10 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); } - // Get number of bytes in EP OUT SW FIFO - uint16_t n_bytes_received = tu_fifo_count(&audio->ep_out_ff); - - // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now decoded into support RX software FIFO + // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT switch (CFG_TUD_AUDIO_FORMAT_TYPE_RX) { @@ -309,7 +335,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) { case AUDIO_DATA_FORMAT_TYPE_I_PCM: - TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio)); + TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio, n_bytes_received)); break; default: @@ -327,13 +353,22 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) break; } -#endif - // Prepare for next transmission -#if USE_EVADE_BUFFER - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + +#else + +#if USE_LINEAR_BUFFER_RX + // Data currently is in linear buffer, copy into EP OUT FIFO + TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); + + // Schedule for next receive + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); #else - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE), false); + // Data is already placed in EP FIFO, schedule for next receive + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, CFG_TUD_AUDIO_EPSIZE_OUT), false); +#endif + #endif // Call a weak callback here - a possibility for user to get informed decoding was completed @@ -345,37 +380,33 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio) #endif //CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE // The following functions are used in case CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE != 0 -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) { (void) rhport; // We assume there is always the correct number of samples available for decoding - extra checks make no sense here - uint16_t const n_bytes = tu_fifo_count(&audio->ep_out_ff); - uint16_t cnt = CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; + uint16_t idxSample = 0; - while (cnt <= n_bytes) + while (cnt <= n_bytes_received) { for (uint8_t cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_RX; cntChannel++) { // If 8, 16, or 32 bit values are to be copied #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == CFG_TUD_AUDIO_RX_ITEMSIZE // If this aborts then the target buffer is full - TU_VERIFY(tu_fifo_read_n_into_other_fifo(&audio->ep_out_ff, &audio->rx_ff[cntChannel], 0, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); + TU_VERIFY(tu_fifo_write_n(&audio->rx_supp_ff[cntChannel], &audio->lin_buf_out[idxSample], CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); #else - uint32_t sample = 0; - - // Get sample from buffer - TU_VERIFY(tu_fifo_read_n(&audio->ep_out_ff, &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); - + uint32_t sample = audio->lin_buf_out[idxSample]; #if CFG_TUD_AUDIO_JUSTIFICATION_RX == CFG_TUD_AUDIO_LEFT_JUSTIFIED sample = sample << 8; #endif - TU_VERIFY(tu_fifo_write_n(&audio->rx_ff[cntChannel], &sample, CFG_TUD_AUDIO_RX_ITEMSIZE)); + TU_VERIFY(tu_fifo_write_n(&audio->rx_supp_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); #endif + idxSample += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; } cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; @@ -392,7 +423,7 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) // WRITE API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE /** * \brief Write data to EP in buffer @@ -417,18 +448,20 @@ bool tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete return tu_fifo_clear(&_audiod_itf[itf].ep_in_ff); } -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into EP SW FIFO +#endif + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); audiod_interface_t* audio = &_audiod_itf[itf]; - uint16_t n_bytes_copied = tu_fifo_count(&audio->ep_in_ff); + uint16_t n_bytes_copied = tu_fifo_count(&audio->tx_supp_ff[0]); TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio)); - n_bytes_copied -= tu_fifo_count(&audio->ep_in_ff); - n_bytes_copied = n_bytes_copied*audio->ep_in_ff.item_size; + n_bytes_copied -= tu_fifo_count(&audio->tx_supp_ff[0]); + n_bytes_copied = n_bytes_copied*audio->tx_supp_ff[0].item_size; return n_bytes_copied; } @@ -436,17 +469,16 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force a bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); - return tu_fifo_clear(&_audiod_itf[itf].tx_ff[channelId]); + return tu_fifo_clear(&_audiod_itf[itf].tx_supp_ff[channelId]); } uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); - return tu_fifo_write_n(&_audiod_itf[itf].tx_ff[channelId], data, len); + return tu_fifo_write_n(&_audiod_itf[itf].tx_supp_ff[channelId], data, len); } #endif -#endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -492,7 +524,11 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->altSetting[idxItf])); -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE + // Send everything in ISO EP FIFO + uint16_t n_bytes_tx; + + // If support FIFOs are used, encode and schedule transmit +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) { case AUDIO_FORMAT_TYPE_UNDEFINED: @@ -507,8 +543,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) { case AUDIO_DATA_FORMAT_TYPE_I_PCM: - TU_VERIFY(audiod_encode_type_I_pcm(rhport, audio)); - + n_bytes_tx = audiod_encode_type_I_pcm(rhport, audio); break; default: @@ -525,17 +560,22 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) TU_BREAKPOINT(); break; } -#endif - // Send everything in ISO EP FIFO - uint16_t n_bytes_tx = tu_fifo_count(&audio->ep_in_ff); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); - // Schedule transmit -#if USE_EVADE_BUFFER - tu_fifo_write_n(&audio->ep_in_ff, audio->evasion_buf_in, n_bytes_tx); - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->evasion_buf_in, n_bytes_tx)); #else - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); + // No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule + + n_bytes_tx = tu_fifo_count(&audio->ep_in_ff); + + #if USE_LINEAR_BUFFER_TX + tu_fifo_write_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); + #else + // Send everything in ISO EP FIFO + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); + #endif + #endif // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame @@ -546,21 +586,22 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) #endif //CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN // Take samples from the support buffer and encode them into the IN EP software FIFO -static bool audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) +// Returns number of bytes written into linear buffer +static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { // We encode directly into IN EP's FIFO - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_ff[0]); // We first look for the minimum number of bytes and afterwards convert it to sample size + uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_supp_ff[0]); // We first look for the minimum number of bytes and afterwards convert it to sample size uint8_t cntChannel; for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) { - uint16_t const count = tu_fifo_count(&audio->tx_ff[cntChannel]); + uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cntChannel]); if (count < nSamplesPerChannelToSend) { nSamplesPerChannelToSend = count; @@ -571,13 +612,14 @@ static bool audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) nSamplesPerChannelToSend = nSamplesPerChannelToSend / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; // Check if there is enough - if (nSamplesPerChannelToSend == 0) return true; + if (nSamplesPerChannelToSend == 0) return 0; // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! nSamplesPerChannelToSend = tu_min16(nSamplesPerChannelToSend, nEndpointSampleCapacity); // Encode uint16_t cntSample; + uint16_t idxSample = 0; for (cntSample = 0; cntSample < nSamplesPerChannelToSend; cntSample++) { @@ -585,21 +627,22 @@ static bool audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { // If 8, 16, or 32 bit values are to be copied #if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == CFG_TUD_AUDIO_TX_ITEMSIZE - tu_fifo_read_n_into_other_fifo(&audio->tx_ff[cntChannel], &audio->ep_in_ff, 0, CFG_TUD_AUDIO_TX_ITEMSIZE); + tu_fifo_read_n(&audio->tx_supp_ff[cntChannel], &audio->lin_buf_in[idxSample], CFG_TUD_AUDIO_TX_ITEMSIZE); #else uint32_t sample = 0; // Get sample from buffer - tu_fifo_read_n(&audio->tx_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); + tu_fifo_read_n(&audio->tx_supp_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); #if CFG_TUD_AUDIO_JUSTIFICATION_TX == CFG_TUD_AUDIO_LEFT_JUSTIFIED sample = sample << 8; #endif - tu_fifo_write_n(&audio->ep_in_ff, &sample, CFG_TUD_AUDIO_TX_ITEMSIZE); + audio->lin_buf_in[idxSample] = sample; #endif + idxSample += CFG_TUD_AUDIO_TX_ITEMSIZE; } } - return true; + return nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_TX_ITEMSIZE; } #endif //CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE @@ -624,7 +667,7 @@ void audiod_init(void) audiod_interface_t* audio = &_audiod_itf[i]; // Initialize IN EP FIFO if required -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE tu_fifo_config(&audio->ep_in_ff, &audio->ep_in_buf, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex)); @@ -632,7 +675,7 @@ void audiod_init(void) #endif // Initialize OUT EP FIFO if required -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->ep_out_ff, osal_mutex_create(&audio->ep_out_ff_mutex)); @@ -640,23 +683,23 @@ void audiod_init(void) #endif // Initialize TX support FIFOs if required -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { - tu_fifo_config(&audio->tx_ff[cnt], &audio->tx_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, 1, true); + tu_fifo_config(&audio->tx_supp_ff[cnt], &audio->tx_supp_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->tx_ff[cnt], osal_mutex_create(&audio->tx_ff_mutex[cnt])); + tu_fifo_config_mutex(&audio->tx_supp_ff[cnt], osal_mutex_create(&audio->tx_supp_ff_mutex[cnt])); #endif } #endif // Initialize RX support FIFOs if required -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { - tu_fifo_config(&audio->rx_ff[cnt], &audio->rx_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, 1, true); + tu_fifo_config(&audio->rx_supp_ff[cnt], &audio->rx_supp_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->rx_ff[cnt], osal_mutex_create(&audio->rx_ff_mutex[cnt])); + tu_fifo_config_mutex(&audio->rx_supp_ff[cnt], osal_mutex_create(&audio->rx_supp_ff_mutex[cnt])); #endif } #endif @@ -672,25 +715,25 @@ void audiod_reset(uint8_t rhport) audiod_interface_t* audio = &_audiod_itf[i]; tu_memclr(audio, ITF_MEM_RESET_SIZE); -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE tu_fifo_clear(&audio->ep_in_ff); #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE tu_fifo_clear(&audio->ep_out_ff); #endif #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) { - tu_fifo_clear(&audio->tx_ff[cnt]); + tu_fifo_clear(&audio->tx_supp_ff[cnt]); } #endif #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) { - tu_fifo_clear(&audio->rx_ff[cnt]); + tu_fifo_clear(&audio->rx_supp_ff[cnt]); } #endif } @@ -731,7 +774,6 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin TU_ASSERT( i < CFG_TUD_AUDIO ); // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - // TODO: Find a way to find end of current audio function and avoid necessity of tud_audio_desc_lengths - since now max_length is available we could do this surely somehow uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor return drv_len; @@ -840,7 +882,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * //TODO: We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! usbd_edpt_clear_stall(rhport, ep_addr); -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EPSIZE_IN if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP { // Save address @@ -856,7 +898,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * } #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EPSIZE_OUT if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary { @@ -868,8 +910,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Prepare for incoming data -#if USE_EVADE_BUFFER - TU_VERIFY(usbd_edpt_xfer(rhport, _audiod_itf[idxDriver].ep_out, _audiod_itf[idxDriver].evasion_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); +#if USE_LINEAR_BUFFER_RX + TU_VERIFY(usbd_edpt_xfer(rhport, _audiod_itf[idxDriver].ep_out, _audiod_itf[idxDriver].lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); #else TU_VERIFY(usbd_edpt_iso_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].ep_out_ff, CFG_TUD_AUDIO_EPSIZE_OUT), false); #endif @@ -1161,15 +1203,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // New audio packet received if (_audiod_itf[idxDriver].ep_out == ep_addr) { - // Save into buffer - do whatever has to be done - // TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], _audiod_itf[idxDriver].ep_out_buf, xferred_bytes)); - -#if USE_EVADE_BUFFER - TU_VERIFY(tu_fifo_write_n(&_audiod_itf[idxDriver].ep_out_ff, _audiod_itf[idxDriver].evasion_buf_out, (uint16_t) xferred_bytes)); // Copy data into FIFO -#endif - - TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver])); - + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], (uint16_t) xferred_bytes)); return true; } diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 38495f72d..ca74d68f4 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -235,26 +235,26 @@ extern "C" { //--------------------------------------------------------------------+ bool tud_audio_n_mounted (uint8_t itf); -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE uint16_t tud_audio_n_available (uint8_t itf); uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); bool tud_audio_n_clear_ep_out_ff (uint8_t itf); // Delete all content in the EP OUT FIFO -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#endif + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT bool tud_audio_n_clear_rx_support_ff (uint8_t itf, uint8_t channelId); // Delete all content in the support RX FIFOs uint16_t tud_audio_n_available_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_read_support_ff (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); #endif -#endif - #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); bool tud_audio_n_clear_ep_in_ff (uint8_t itf); // Delete all content in the EP IN FIFO -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN uint16_t tud_audio_n_flush_tx_support_ff (uint8_t itf); // Force all content in the support TX FIFOs to be written into EP SW FIFO bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_write_support_ff (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); @@ -274,35 +274,35 @@ static inline bool tud_audio_mounted (void); // RX API -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE static inline uint16_t tud_audio_available (void); static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#endif + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId); static inline uint16_t tud_audio_available_support_ff (uint8_t channelId); static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize); #endif -#endif - // TX API -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE static inline uint16_t tud_audio_write (const void * data, uint16_t len); static inline bool tud_audio_clear_ep_in_ff (void); -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#endif + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN static inline uint16_t tud_audio_flush_tx_support_ff (void); static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId); static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len); #endif -#endif - // INT CTR API #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -380,7 +380,7 @@ static inline bool tud_audio_mounted(void) // RX API -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE static inline uint16_t tud_audio_available (void) { @@ -397,7 +397,9 @@ static inline bool tud_audio_clear_ep_out_ff (void) return tud_audio_n_clear_ep_out_ff(0); } -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#endif + +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId) { @@ -416,11 +418,9 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, #endif -#endif - // TX API -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE static inline uint16_t tud_audio_write (const void * data, uint16_t len) { @@ -432,7 +432,9 @@ static inline bool tud_audio_clear_ep_in_ff (void) return tud_audio_n_clear_ep_in_ff(0); } -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#endif + +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN static inline uint16_t tud_audio_flush_tx_support_ff (void) { @@ -451,8 +453,6 @@ static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, #endif -#endif - #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len) { -- cgit v1.3.1 From 1676a836d137bc67e24b778abe72addfa835ff20 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 2 Mar 2021 14:54:12 +0700 Subject: fix rp2040 host build --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 0f2779453..224f6ef21 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -291,14 +291,16 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t assert(ep->buffer_control); assert(ep->hw_data_buf); - uint8_t num = tu_edpt_number(ep_addr); + uint8_t const num = tu_edpt_number(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); + bool in = ep_addr & TUSB_DIR_IN_MASK; ep->ep_addr = ep_addr; ep->dev_addr = dev_addr; - ep->in = in; + // For host, IN to host == RX, anything else rx == false - ep->rx = in == true; - ep->num = num; + ep->rx = (dir == TUSB_DIR_IN); + // Response to a setup packet on EP0 starts with pid of 1 ep->next_pid = num == 0 ? 1u : 0u; ep->wMaxPacketSize = wMaxPacketSize; @@ -327,9 +329,9 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t // device address // endpoint number / direction // preamble - uint32_t reg = dev_addr | (ep->num << USB_ADDR_ENDP1_ENDPOINT_LSB); + uint32_t reg = dev_addr | (num << USB_ADDR_ENDP1_ENDPOINT_LSB); // Assert the interrupt endpoint is IN_TO_HOST - assert(ep->in); + assert(dir == TUSB_DIR_IN); if (need_pre(dev_addr)) { @@ -462,7 +464,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * if (ep == &epx) { // That has set up buffer control, endpoint control etc // for host we have to initiate the transfer - usb_hw->dev_addr_ctrl = dev_addr | ep->num << USB_ADDR_ENDP_ENDPOINT_LSB; + usb_hw->dev_addr_ctrl = dev_addr | (tu_edpt_number(ep_addr) << USB_ADDR_ENDP_ENDPOINT_LSB); uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | sie_ctrl_base; flags |= ep->rx ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS; // Set pre if we are a low speed device on full speed hub -- cgit v1.3.1 From 9d5e3691706f3f17edd701310b967c729240a507 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 2 Mar 2021 23:24:36 +0700 Subject: rp2040 add disconnection detection - also use dcd_event_bus_reset() - Add TODO for suspend, resume later on (need to test with/without vbus detection). --- src/device/usbd.c | 21 ++++++++------ src/portable/raspberrypi/rp2040/dcd_rp2040.c | 43 ++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 4fc221888..911977eb0 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -992,11 +992,15 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) switch (event->event_id) { case DCD_EVENT_UNPLUGGED: - _usbd_dev.connected = 0; - _usbd_dev.addressed = 0; - _usbd_dev.cfg_num = 0; - _usbd_dev.suspended = 0; - osal_queue_send(_usbd_q, event, in_isr); + // UNPLUGGED event can be bouncing, only processing if we are currently connected + if ( _usbd_dev.connected ) + { + _usbd_dev.connected = 0; + _usbd_dev.addressed = 0; + _usbd_dev.cfg_num = 0; + _usbd_dev.suspended = 0; + osal_queue_send(_usbd_q, event, in_isr); + } break; case DCD_EVENT_SOF: @@ -1004,9 +1008,10 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) break; case DCD_EVENT_SUSPEND: - // NOTE: When plugging/unplugging device, the D+/D- state are unstable and can accidentally meet the - // SUSPEND condition ( Idle for 3ms ). Some MCUs such as SAMD doesn't distinguish suspend vs disconnect as well. - // We will skip handling SUSPEND/RESUME event if not currently connected + // NOTE: When plugging/unplugging device, the D+/D- state are unstable and + // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ). + // In addition, some MCUs such as SAMD or boards that haven no VBUS detection cannot distinguish + // suspended vs disconnected. We will skip handling SUSPEND/RESUME event if not currently connected if ( _usbd_dev.connected ) { _usbd_dev.suspended = 1; diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index d32870439..84dce0248 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -317,13 +317,45 @@ static void dcd_rp2040_irq(void) pico_trace("BUS RESET (addr %d -> %d)\n", assigned_address, 0); usb_hw->dev_addr_ctrl = 0; handled |= USB_INTS_BUS_RESET_BITS; - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; #if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX rp2040_usb_device_enumeration_fix(); #endif } + if (status & USB_INTS_DEV_CONN_DIS_BITS) + { + handled |= USB_INTS_DEV_CONN_DIS_BITS; + + if ( usb_hw->sie_status & USB_SIE_STATUS_CONNECTED_BITS ) + { + // Connected: nothing to do + }else + { + // Disconnected + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + } + + usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS; + } + +#if 0 // TODO Enable SUSPEND & RESUME interrupt and test later on with/without VBUS detection + if (status & USB_INTS_DEV_SUSPEND_BITS) + { + handled |= USB_INTS_DEV_SUSPEND_BITS; + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + usb_hw_clear->sie_status = USB_SIE_STATUS_SUSPENDED_BITS; + } + + if (status & USB_INTS_DEV_RESUME_FROM_HOST_BITS) + { + handled |= USB_INTS_DEV_RESUME_FROM_HOST_BITS; + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS; + } +#endif + if (status ^ handled) { panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled)); @@ -364,8 +396,10 @@ void dcd_init (uint8_t rhport) // Enable individual controller IRQS here. Processor interrupt enable will be used // for the global interrupt enable... + // TODO Enable SUSPEND & RESUME interrupt usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS; - usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS; + usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS | + USB_INTS_DEV_CONN_DIS_BITS /* | USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS */ ; dcd_connect(rhport); } @@ -393,8 +427,9 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) void dcd_remote_wakeup(uint8_t rhport) { - pico_info("dcd_remote_wakeup %d is not supported yet\n", rhport); + pico_info("dcd_remote_wakeup %d\n", rhport); assert(rhport == 0); + usb_hw_set->sie_ctrl = USB_SIE_CTRL_RESUME_BITS; } // disconnect by disabling internal pull-up resistor on D+/D- @@ -402,6 +437,7 @@ void dcd_disconnect(uint8_t rhport) { pico_info("dcd_disconnect %d\n", rhport); assert(rhport == 0); + //TU_LOG2("dcd_disconnect\n"); usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; } @@ -410,6 +446,7 @@ void dcd_connect(uint8_t rhport) { pico_info("dcd_connect %d\n", rhport); assert(rhport == 0); + //TU_LOG2("dcd_connect\n"); usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; } -- cgit v1.3.1 From fc35b3f72dc2f73ecd9df3e14484ef493803fd7b Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 2 Mar 2021 17:24:58 +0100 Subject: Switch back OPT_MCU_DA1469X to use linear buffers --- src/class/audio/audio_device.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index a29abc496..32745002c 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -65,6 +65,7 @@ // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically #if ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || /* Intermediate software buffer required */ \ + CFG_TUSB_MCU == OPT_MCU_DA1469X || /* Intermediate software buffer required */ \ CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ -- cgit v1.3.1 From a298045f6c57ed3bad23ce44a1944016a882e08c Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 2 Mar 2021 23:30:21 +0700 Subject: clean up --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 84dce0248..ba708081c 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -437,7 +437,6 @@ void dcd_disconnect(uint8_t rhport) { pico_info("dcd_disconnect %d\n", rhport); assert(rhport == 0); - //TU_LOG2("dcd_disconnect\n"); usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; } @@ -446,7 +445,6 @@ void dcd_connect(uint8_t rhport) { pico_info("dcd_connect %d\n", rhport); assert(rhport == 0); - //TU_LOG2("dcd_connect\n"); usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; } -- cgit v1.3.1 From c8b6d9b9906f8185ef6edb84962446328c9f68cb Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 2 Mar 2021 19:28:35 +0100 Subject: Revert implementation of dcd_edpt_iso_xfer() --- src/portable/dialog/da146xx/dcd_da146xx.c | 103 +++--------------------------- 1 file changed, 10 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 69ea5d87f..59f728d08 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -25,7 +25,6 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_DA1469X @@ -197,7 +196,6 @@ typedef struct typedef struct { EPx_REGS * regs; uint8_t * buffer; - tu_fifo_t * ff; // Total length of current transfer uint16_t total_len; // Bytes transferred so far @@ -290,9 +288,11 @@ void tusb_vbus_changed(bool present) static void fill_tx_fifo(xfer_ctl_t * xfer) { int left_to_send; + uint8_t const *src; EPx_REGS *regs = xfer->regs; uint8_t const epnum = tu_edpt_number(xfer->ep_addr); + src = &xfer->buffer[xfer->transferred]; left_to_send = xfer->total_len - xfer->transferred; if (left_to_send > xfer->max_packet_size - xfer->last_packet_size) { @@ -301,51 +301,12 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) // Loop checks TCOUNT all the time since this value is saturated to 31 // and can't be read just once before. - - if (xfer->ff) + while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && left_to_send > 0) { - // Since TCOUNT is to be considered, we handle the FIFO reading manually here - // As we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies - // Check for first linear part - uint8_t * src; - uint16_t len = tu_fifo_get_linear_read_info(xfer->ff, 0, (void **) &src, left_to_send); // We want to read from the FIFO - uint16_t len1 = len; - while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && len1 > 0) - { - regs->txd = *src++; - xfer->last_packet_size++; - len1--; - } - - tu_fifo_advance_read_pointer(xfer->ff, len-len1); - left_to_send -= (len-len1); - - // Check for wrapped part - if ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) && left_to_send > 0) - { - len = tu_fifo_get_linear_read_info(xfer->ff, 0, (void **) &src, left_to_send); // We want to read from the FIFO - len1 = len; - while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && len1 > 0) - { - regs->txd = *src++; - xfer->last_packet_size++; - len1--; - } - tu_fifo_advance_read_pointer(xfer->ff, len-len1); - left_to_send -= (len-len1); - } + regs->txd = *src++; + xfer->last_packet_size++; + left_to_send--; } - else - { - uint8_t const *src = &xfer->buffer[xfer->transferred]; - while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && left_to_send > 0) - { - regs->txd = *src++; - xfer->last_packet_size++; - left_to_send--; - } - } - if (epnum != 0) { if (left_to_send > 0) @@ -402,14 +363,13 @@ static void start_rx_packet(xfer_ctl_t *xfer) xfer->last_packet_size = 0; if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE) { - if (try_allocate_dma(epnum, TUSB_DIR_OUT) && !xfer->ff) + if (try_allocate_dma(epnum, TUSB_DIR_OUT)) { start_rx_dma(&xfer->regs->rxd, xfer->buffer + xfer->transferred, size); } else { // Other endpoint is using DMA in that direction, fall back to interrupts. - // Or if an ISO EP transfer was scheduled, currently not handled by DMA! // For endpoint size greater then FIFO size enable FIFO level warning interrupt // when FIFO has less then 17 bytes free. xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RFWL_Msk; @@ -449,7 +409,7 @@ static void start_tx_packet(xfer_ctl_t *xfer) regs->txc = USB_USB_TXC1_REG_USB_IGN_ISOMSK_Msk; if (xfer->data1) xfer->regs->txc |= USB_USB_TXC1_REG_USB_TOGGLE_TX_Msk; - if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE && try_allocate_dma(epnum, TUSB_DIR_IN) && !xfer->ff) + if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE && try_allocate_dma(epnum, TUSB_DIR_IN)) { // Whole packet will be put in FIFO by DMA. Set LAST bit before start. start_tx_dma(xfer->buffer + xfer->transferred, ®s->txd, size); @@ -470,16 +430,9 @@ static void read_rx_fifo(xfer_ctl_t *xfer, uint16_t bytes_in_fifo) if (remaining < bytes_in_fifo) receive_this_time = remaining; - if (xfer->ff) - { - tu_fifo_write_n(xfer->ff, (const void *) ®s->rxd, receive_this_time); - } - else - { - uint8_t *buf = xfer->buffer + xfer->transferred + xfer->last_packet_size; + uint8_t *buf = xfer->buffer + xfer->transferred + xfer->last_packet_size; - for (int i = 0; i < receive_this_time; ++i) buf[i] = regs->rxd; - } + for (int i = 0; i < receive_this_time; ++i) buf[i] = regs->rxd; xfer->last_packet_size += receive_this_time; } @@ -965,7 +918,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t (void)rhport; xfer->buffer = buffer; - xfer->ff = NULL; xfer->total_len = total_bytes; xfer->last_packet_size = 0; xfer->transferred = 0; @@ -982,41 +934,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - - (void)rhport; - - xfer->buffer = NULL; - xfer->ff = ff; - xfer->total_len = total_bytes; - xfer->last_packet_size = 0; - xfer->transferred = 0; - - if (dir == TUSB_DIR_IN) - { - tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_CST); - } - else - { - tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); - } - - if (dir == TUSB_DIR_OUT) - { - start_rx_packet(xfer); - } - else // IN - { - start_tx_packet(xfer); - } - - return true; -} - void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); -- cgit v1.3.1 From 7b8a08d2e1519afba6045e2a77898afecb1943e1 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 2 Mar 2021 20:00:39 +0100 Subject: Rename dcd_edpt_iso_xfer() to dcd_edpt_xfer_fifo() --- src/class/audio/audio_device.c | 2 +- src/device/dcd.h | 2 +- src/device/usbd.c | 2 +- src/portable/espressif/esp32s2/dcd_esp32s2.c | 2 +- src/portable/microchip/samg/dcd_samg.c | 2 +- src/portable/nuvoton/nuc120/dcd_nuc120.c | 4 ++-- src/portable/nuvoton/nuc121/dcd_nuc121.c | 2 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 4 ++-- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 2 +- src/portable/template/dcd_template.c | 2 +- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 32745002c..37d6a36a7 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -34,7 +34,7 @@ * * 1. Input data -> SW-FIFO -> MCU USB * - * The most easiest version, available in case the target MCU can handle the software FIFO (SW-FIFO) and if it is implemented in the device driver (if yes then dcd_edpt_iso_xfer() is available) + * The most easiest version, available in case the target MCU can handle the software FIFO (SW-FIFO) and if it is implemented in the device driver (if yes then dcd_edpt_xfer_fifo() is available) * * 2. Input data -> SW-FIFO -> Linear buffer -> MCU USB * diff --git a/src/device/dcd.h b/src/device/dcd.h index f0a552434..89f8760d0 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -135,7 +135,7 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit an ISO transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index c087e2b38..1879729e8 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1246,7 +1246,7 @@ bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if (dcd_edpt_iso_xfer(rhport, ep_addr, ff, total_bytes)) + if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) { TU_LOG2("OK\r\n"); return true; diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 25e54418f..ade79f107 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -357,7 +357,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void)rhport; diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 1edbba629..5866e1ce8 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -297,7 +297,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 9ff34e760..0e7157d4c 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -77,7 +77,7 @@ static bool active_ep0_xfer; static struct xfer_ctl_t { uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */ - tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_iso_xfer() */ + tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_xfer_fifo() */ union { uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */ uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */ @@ -297,7 +297,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 8aa97ad10..65a41463c 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -303,7 +303,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 0a690d84d..0d82a28c0 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -95,7 +95,7 @@ static uint32_t bufseg_addr; static struct xfer_ctl_t { uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */ - tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_iso_xfer() */ + tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_xfer_fifo() */ union { uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */ uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */ @@ -412,7 +412,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index e2fd48d74..dbd514f86 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -867,7 +867,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 1d0bb5107..6dad05ba1 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -675,7 +675,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 7a9a0ae22..ba656385b 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -106,7 +106,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } // Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; (void) ep_addr; diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 61cbe1cf7..a8da1ae49 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -347,7 +347,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } -bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; -- cgit v1.3.1 From bd2bab7aff4f0e1dc34cace24c90a7755c00d369 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 2 Mar 2021 21:41:51 +0100 Subject: Remove set_copy_modes(), implement: tu_fifo_read_n_const_addr(), tu_fifo_write_n_const_addr() --- src/common/tusb_fifo.c | 164 +++++++++++++++++++++++++++++++------------------ src/common/tusb_fifo.h | 28 +-------- 2 files changed, 105 insertions(+), 87 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index c785a77a6..94e9d90ec 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -62,6 +62,15 @@ static void tu_fifo_unlock(tu_fifo_t *f) #endif +/** \enum tu_fifo_copy_mode_t + * \brief Write modes intended to allow special read and write functions to be able to copy data to and from USB hardware FIFOs as needed for e.g. STM32s + */ +typedef enum +{ + TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode + TU_FIFO_COPY_CST, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO +} tu_fifo_copy_mode_t; + bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) { if (depth > 0x8000) return false; // Maximum depth is 2^15 items @@ -76,8 +85,6 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si f->max_pointer_idx = 2*depth - 1; // Limit index space to 2*depth - this allows for a fast "modulo" calculation but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable only if overflow happens once (important for unsupervised DMA applications) f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; - f->rd_mode = f->wr_mode = TU_FIFO_COPY_INC; // Default copy mode is incrementing addresses - f->rd_idx = f->wr_idx = 0; tu_fifo_unlock(f); @@ -160,9 +167,9 @@ static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t wRel) memcpy(f->buffer + (wRel * f->item_size), data, f->item_size); } -static inline void _ff_push_copy_fct(tu_fifo_t* f, void * dst, const void * src, uint16_t len) +static inline void _ff_push_copy_fct(tu_fifo_t* f, void * dst, const void * src, uint16_t len, tu_fifo_copy_mode_t copy_mode) { - switch (f->rd_mode) + switch (copy_mode) { case TU_FIFO_COPY_INC: memcpy(dst, src, len); @@ -174,9 +181,9 @@ static inline void _ff_push_copy_fct(tu_fifo_t* f, void * dst, const void * src, } } -static inline void _ff_pull_copy_fct(tu_fifo_t* f, void * dst, const void * src, uint16_t len) +static inline void _ff_pull_copy_fct(tu_fifo_t* f, void * dst, const void * src, uint16_t len, tu_fifo_copy_mode_t copy_mode) { - switch (f->wr_mode) + switch (copy_mode) { case TU_FIFO_COPY_INC: memcpy(dst, src, len); @@ -189,21 +196,21 @@ static inline void _ff_pull_copy_fct(tu_fifo_t* f, void * dst, const void * src, } // send n items to FIFO WITHOUT updating write pointer -static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRel) +static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRel, tu_fifo_copy_mode_t copy_mode) { if(wRel + n <= f->depth) // Linear mode only { - _ff_push_copy_fct(f, f->buffer + (wRel * f->item_size), data, n*f->item_size); + _ff_push_copy_fct(f, f->buffer + (wRel * f->item_size), data, n*f->item_size, copy_mode); } else // Wrap around { uint16_t nLin = f->depth - wRel; // Write data to linear part of buffer - _ff_push_copy_fct(f, f->buffer + (wRel * f->item_size), data, nLin*f->item_size); + _ff_push_copy_fct(f, f->buffer + (wRel * f->item_size), data, nLin*f->item_size, copy_mode); // Write data wrapped around - _ff_push_copy_fct(f, f->buffer, ((uint8_t const*) data) + nLin*f->item_size, (n - nLin) * f->item_size); + _ff_push_copy_fct(f, f->buffer, ((uint8_t const*) data) + nLin*f->item_size, (n - nLin) * f->item_size, copy_mode); } } @@ -214,21 +221,21 @@ static inline void _ff_pull(tu_fifo_t* f, void * p_buffer, uint16_t rRel) } // get n items from FIFO WITHOUT updating read pointer -static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel) +static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel, tu_fifo_copy_mode_t copy_mode) { if(rRel + n <= f->depth) // Linear mode only { - _ff_pull_copy_fct(f, p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); + _ff_pull_copy_fct(f, p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size, copy_mode); } else // Wrap around { uint16_t nLin = f->depth - rRel; // Read data from linear part of buffer - _ff_pull_copy_fct(f, p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size); + _ff_pull_copy_fct(f, p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size, copy_mode); // Read data wrapped part - _ff_pull_copy_fct(f, (uint8_t*)p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size); + _ff_pull_copy_fct(f, (uint8_t*)p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size, copy_mode); } } @@ -337,7 +344,7 @@ static bool _tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer, uin // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs) +static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs, tu_fifo_copy_mode_t copy_mode) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); @@ -359,7 +366,7 @@ static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffe uint16_t rRel = get_relative_pointer(f, rAbs, offset); // Peek data - _ff_pull_n(f, p_buffer, n, rRel); + _ff_pull_n(f, p_buffer, n, rRel, copy_mode); return n; } @@ -370,6 +377,59 @@ static inline uint16_t _tu_fifo_remaining(tu_fifo_t* f, uint16_t wAbs, uint16_t return f->depth - _tu_fifo_count(f, wAbs, rAbs); } +static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu_fifo_copy_mode_t copy_mode) +{ + if ( n == 0 ) return 0; + + tu_fifo_lock(f); + + uint16_t w = f->wr_idx, r = f->rd_idx; + uint8_t const* buf8 = (uint8_t const*) data; + + if (!f->overwritable) + { + // Not overwritable limit up to full + n = tu_min16(n, _tu_fifo_remaining(f, w, r)); + } + else if (n >= f->depth) + { + // Only copy last part + buf8 = buf8 + (n - f->depth) * f->item_size; + n = f->depth; + + // We start writing at the read pointer's position since we fill the complete + // buffer and we do not want to modify the read pointer within a write function! + // This would end up in a race condition with read functions! + w = r; + } + + uint16_t wRel = get_relative_pointer(f, w, 0); + + // Write data + _ff_push_n(f, buf8, n, wRel, copy_mode); + + // Advance pointer + f->wr_idx = advance_pointer(f, w, n); + + tu_fifo_unlock(f); + + return n; +} + +static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) +{ + tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! + + // Peek the data + n = _tu_fifo_peek_at_n(f, 0, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + + // Advance read pointer + f->rd_idx = advance_pointer(f, f->rd_idx, n); + + tu_fifo_unlock(f); + return n; +} + /******************************************************************************/ /*! @brief Get number of items in FIFO. @@ -526,16 +586,12 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) /******************************************************************************/ uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n) { - tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! - - // Peek the data - n = _tu_fifo_peek_at_n(f, 0, buffer, n, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable - - // Advance read pointer - f->rd_idx = advance_pointer(f, f->rd_idx, n); + return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_INC); +} - tu_fifo_unlock(f); - return n; +uint16_t tu_fifo_read_n_const_addr(tu_fifo_t* f, void * buffer, uint16_t n) +{ + return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_CST); } /******************************************************************************/ @@ -615,7 +671,7 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t n) { tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! - bool ret = _tu_fifo_peek_at_n(f, offset, p_buffer, n, f->wr_idx, f->rd_idx); + bool ret = _tu_fifo_peek_at_n(f, offset, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); tu_fifo_unlock(f); return ret; } @@ -693,12 +749,12 @@ uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint // Copy linear size uint16_t sz = f_target->depth - wr_rel_tgt; - _tu_fifo_peek_at_n(f, offset, &f_target->buffer[wr_rel_tgt], sz, f_wr_idx, f_rd_idx); + _tu_fifo_peek_at_n(f, offset, &f_target->buffer[wr_rel_tgt], sz, f_wr_idx, f_rd_idx, TU_FIFO_COPY_INC); if (n > sz) { // Copy remaining, now wrapped part, into target buffer - _tu_fifo_peek_at_n(f, offset + sz, f_target->buffer, n-sz, f_wr_idx, f_rd_idx); + _tu_fifo_peek_at_n(f, offset + sz, f_target->buffer, n-sz, f_wr_idx, f_rd_idx, TU_FIFO_COPY_INC); } tu_fifo_unlock(f_target); @@ -759,41 +815,27 @@ bool tu_fifo_write(tu_fifo_t* f, const void * data) /******************************************************************************/ uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n) { - if ( n == 0 ) return 0; - - tu_fifo_lock(f); - - uint16_t w = f->wr_idx, r = f->rd_idx; - uint8_t const* buf8 = (uint8_t const*) data; - - if (!f->overwritable) - { - // Not overwritable limit up to full - n = tu_min16(n, _tu_fifo_remaining(f, w, r)); - } - else if (n >= f->depth) - { - // Only copy last part - buf8 = buf8 + (n - f->depth) * f->item_size; - n = f->depth; - - // We start writing at the read pointer's position since we fill the complete - // buffer and we do not want to modify the read pointer within a write function! - // This would end up in a race condition with read functions! - w = r; - } - - uint16_t wRel = get_relative_pointer(f, w, 0); - - // Write data - _ff_push_n(f, buf8, n, wRel); - - // Advance pointer - f->wr_idx = advance_pointer(f, w, n); + return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_INC); +} - tu_fifo_unlock(f); +/******************************************************************************/ +/*! + @brief This function will write n elements into the array index specified by + the write pointer and increment the write index. The source address will + not be incremented which is useful for reading from registers. - return n; + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] data + The pointer to data to add to the FIFO + @param[in] count + Number of element + @return Number of written elements + */ +/******************************************************************************/ +uint16_t tu_fifo_write_n_const_addr(tu_fifo_t* f, const void * data, uint16_t n) +{ + return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_CST); } /******************************************************************************/ diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 2cab2abf8..feacc7a12 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -56,15 +56,6 @@ extern "C" { #define tu_fifo_mutex_t osal_mutex_t #endif -/** \enum tu_fifo_copy_mode_t - * \brief Write modes intended to allow special read and write functions to be able to copy data to and from USB hardware FIFOs as needed for e.g. STM32s - */ -typedef enum -{ - TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode - TU_FIFO_COPY_CST, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO -} tu_fifo_copy_mode_t; - /** \struct tu_fifo_t * \brief Simple Circular FIFO */ @@ -81,9 +72,6 @@ typedef struct volatile uint16_t wr_idx ; ///< write pointer volatile uint16_t rd_idx ; ///< read pointer - tu_fifo_copy_mode_t wr_mode ; ///< write mode - default is TU_FIFO_COPY_INC - tu_fifo_copy_mode_t rd_mode ; ///< read mode - default is TU_FIFO_COPY_INC - #if CFG_FIFO_MUTEX tu_fifo_mutex_t mutex; #endif @@ -98,8 +86,6 @@ typedef struct .overwritable = _overwritable, \ .max_pointer_idx = 2*(_depth)-1, \ .non_used_index_space = UINT16_MAX - (2*(_depth)-1), \ - .wr_mode = TU_FIFO_COPY_INC, \ - .rd_mode = TU_FIFO_COPY_INC, \ } #define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ @@ -120,9 +106,11 @@ static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t mutex_hdl) bool tu_fifo_write (tu_fifo_t* f, void const * p_data); uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t n); +uint16_t tu_fifo_write_n_const_addr (tu_fifo_t* f, const void * data, uint16_t n); bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); +uint16_t tu_fifo_read_n_const_addr (tu_fifo_t* f, void * buffer, uint16_t n); uint16_t tu_fifo_read_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n); bool tu_fifo_peek_at (tu_fifo_t* f, uint16_t pos, void * p_buffer); @@ -160,18 +148,6 @@ static inline uint16_t tu_fifo_depth(tu_fifo_t* f) return f->depth; } -// When writing into the FIFO by fifo_write_n(), rd_mode determines how the pointer read from is modified -static inline void tu_fifo_set_copy_mode_read(tu_fifo_t* f, tu_fifo_copy_mode_t rd_mode) -{ - f->rd_mode = rd_mode; -} - -// When reading from the FIFO by fifo_read_n() or fifo_peek_n(), wr_mode determines how the pointer written to is modified -static inline void tu_fifo_set_copy_mode_write(tu_fifo_t* f, tu_fifo_copy_mode_t wr_mode) -{ - f->wr_mode = wr_mode; -} - #ifdef __cplusplus } #endif -- cgit v1.3.1 From 3cdb82c21c7425c8fb6ba88b2a85a6238edb777a Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 2 Mar 2021 21:42:24 +0100 Subject: Change for copy modes in dcd_synopsis.c --- src/portable/st/synopsys/dcd_synopsys.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 6dad05ba1..e2390fe57 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -688,16 +688,6 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 xfer->ff = ff; xfer->total_len = total_bytes; - // Set copy mode to constant address - required since data copied to or from the hardware USB FIFO needs to be written at a constant address - if (dir == TUSB_DIR_IN) - { - tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_CST); - } - else - { - tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); - } - uint16_t num_packets = (total_bytes / xfer->max_size); uint8_t const short_packet_size = total_bytes % xfer->max_size; @@ -912,7 +902,7 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ if (xfer->ff) { // Ring buffer - tu_fifo_write_n(xfer->ff, (const void *) rx_fifo, bcnt); + tu_fifo_write_n_const_addr(xfer->ff, (const void *) rx_fifo, bcnt); } else { @@ -1032,7 +1022,7 @@ static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OT if (xfer->ff) { usb_fifo_t tx_fifo = FIFO_BASE(rhport, n); - tu_fifo_read_n(xfer->ff, (void *) tx_fifo, packet_size); + tu_fifo_read_n_const_addr(xfer->ff, (void *) tx_fifo, packet_size); } else { -- cgit v1.3.1 From a1b07ae14c7133a012c48346923304e5d4062ecd Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 2 Mar 2021 21:52:42 +0100 Subject: Change copy modes for new read/write functions in tusb_fifo.c --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 14 ++------------ src/portable/microchip/samg/dcd_samg.c | 7 ++----- src/portable/nuvoton/nuc120/dcd_nuc120.c | 2 -- src/portable/nuvoton/nuc121/dcd_nuc121.c | 2 -- src/portable/nuvoton/nuc505/dcd_nuc505.c | 6 ++---- src/portable/template/dcd_template.c | 2 +- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 2 -- 7 files changed, 7 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index ade79f107..eb2c05153 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -382,16 +382,6 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 num_packets++; } - // Set copy mode to constant address - required since data copied to or from the hardware USB FIFO needs to be written at a constant address - if (dir == TUSB_DIR_IN) - { - tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_CST); - } - else - { - tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); - } - ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), num_packets, total_bytes); @@ -527,7 +517,7 @@ static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ if (xfer->ff) { // Ring buffer - tu_fifo_write_n(xfer->ff, (const void *) rx_fifo, to_recv_size); + tu_fifo_write_n_const_addr(xfer->ff, (const void *) rx_fifo, to_recv_size); } else { @@ -583,7 +573,7 @@ static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, if (xfer->ff) { - tu_fifo_read_n(xfer->ff, (void *) tx_fifo, to_xfer_size); + tu_fifo_read_n_const_addr(xfer->ff, (void *) tx_fifo, to_xfer_size); } else { diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 5866e1ce8..07ab9e83f 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -312,14 +312,11 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 if (dir == TUSB_DIR_OUT) { - tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); - // Enable interrupt when starting OUT transfer if (epnum != 0) UDP->UDP_IER |= (1 << epnum); } else { - tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_CST); tu_fifo_read_n(ff, (void *) &UDP->UDP_FDR[epnum], xfer_packet_len(xfer)); // TX ready for transfer @@ -440,7 +437,7 @@ void dcd_int_handler(uint8_t rhport) // write to EP fifo if (xfer->ff) { - tu_fifo_read_n(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len); + tu_fifo_read_n_const_addr(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len); } else { @@ -473,7 +470,7 @@ void dcd_int_handler(uint8_t rhport) // Read from EP fifo if (xfer->ff) { - tu_fifo_write_n(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len); + tu_fifo_write_n_const_addr(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len); } else { diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 0e7157d4c..06ffa2965 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -314,12 +314,10 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 if (TUSB_DIR_IN == dir) { - tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_INC); // For the PHY in nuc120 the source and destination pointer have to be incremented! dcd_in_xfer(xfer, ep); } else { - tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_INC); // For the PHY in nuc120 the source and destination pointer have to be incremented! xfer->out_bytes_so_far = 0; ep->MXPLD = xfer->max_packet_size; } diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 65a41463c..6d98ba08a 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -320,12 +320,10 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 if (TUSB_DIR_IN == dir) { - tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_INC); // For the PHY in nuc120 the source and destination pointer have to be incremented! dcd_in_xfer(xfer, ep); } else { - tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_INC); // For the PHY in nuc120 the source and destination pointer have to be incremented! xfer->out_bytes_so_far = 0; ep->MXPLD = xfer->max_packet_size; } diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 0d82a28c0..5d15ca962 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -183,7 +183,7 @@ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) /* provided buffers are thankfully 32-bit aligned, allowing most data to be transfered as 32-bit */ if (xfer->ff) { - tu_fifo_read_n(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now); + tu_fifo_read_n_const_addr(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now); } else { @@ -431,12 +431,10 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 if (TUSB_DIR_IN == dir) { - tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_CST); // For the PHY in nuc505 the source and destination pointer have to be constant! ep->EPINTEN = USBD_EPINTEN_BUFEMPTYIEN_Msk; } else { - tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); // For the PHY in nuc505 the source and destination pointer have to be constant! xfer->out_bytes_so_far = 0; ep->EPINTEN = USBD_EPINTEN_RXPKIEN_Msk; } @@ -659,7 +657,7 @@ void dcd_int_handler(uint8_t rhport) /* copy the data from the PC to the previously provided buffer */ if (xfer->ff) { - tu_fifo_write_n(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far)); + tu_fifo_write_n_const_addr(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far)); } else { diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index ba656385b..d8c8753d3 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -105,7 +105,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return false; } -// Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack +// Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index a8da1ae49..40b12eb04 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -365,12 +365,10 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 if(dir == TUSB_DIR_OUT) { - tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_INC); // For the PHY in msp430 the source and destination pointer have to be incremented! ep_regs[BCTX] &= ~NAK; } else { - tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_INC); // For the PHY in msp430 the source and destination pointer have to be incremented! USBIEPIFG |= (1 << epnum); } -- cgit v1.3.1 From 848e403e3744eda8091330db1e6f23f86871ffaa Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 3 Mar 2021 08:18:57 +0100 Subject: Fix unused parameter in _ff_push_copy_fct() and _ff_pull_copy_fct --- src/common/tusb_fifo.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 94e9d90ec..d4251abea 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -167,7 +167,7 @@ static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t wRel) memcpy(f->buffer + (wRel * f->item_size), data, f->item_size); } -static inline void _ff_push_copy_fct(tu_fifo_t* f, void * dst, const void * src, uint16_t len, tu_fifo_copy_mode_t copy_mode) +static inline void _ff_push_copy_fct(void * dst, const void * src, uint16_t len, tu_fifo_copy_mode_t copy_mode) { switch (copy_mode) { @@ -181,7 +181,7 @@ static inline void _ff_push_copy_fct(tu_fifo_t* f, void * dst, const void * src, } } -static inline void _ff_pull_copy_fct(tu_fifo_t* f, void * dst, const void * src, uint16_t len, tu_fifo_copy_mode_t copy_mode) +static inline void _ff_pull_copy_fct(void * dst, const void * src, uint16_t len, tu_fifo_copy_mode_t copy_mode) { switch (copy_mode) { @@ -200,17 +200,17 @@ static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRe { if(wRel + n <= f->depth) // Linear mode only { - _ff_push_copy_fct(f, f->buffer + (wRel * f->item_size), data, n*f->item_size, copy_mode); + _ff_push_copy_fct(f->buffer + (wRel * f->item_size), data, n*f->item_size, copy_mode); } else // Wrap around { uint16_t nLin = f->depth - wRel; // Write data to linear part of buffer - _ff_push_copy_fct(f, f->buffer + (wRel * f->item_size), data, nLin*f->item_size, copy_mode); + _ff_push_copy_fct(f->buffer + (wRel * f->item_size), data, nLin*f->item_size, copy_mode); // Write data wrapped around - _ff_push_copy_fct(f, f->buffer, ((uint8_t const*) data) + nLin*f->item_size, (n - nLin) * f->item_size, copy_mode); + _ff_push_copy_fct(f->buffer, ((uint8_t const*) data) + nLin*f->item_size, (n - nLin) * f->item_size, copy_mode); } } @@ -225,17 +225,17 @@ static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel, { if(rRel + n <= f->depth) // Linear mode only { - _ff_pull_copy_fct(f, p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size, copy_mode); + _ff_pull_copy_fct(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size, copy_mode); } else // Wrap around { uint16_t nLin = f->depth - rRel; // Read data from linear part of buffer - _ff_pull_copy_fct(f, p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size, copy_mode); + _ff_pull_copy_fct(p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size, copy_mode); // Read data wrapped part - _ff_pull_copy_fct(f, (uint8_t*)p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size, copy_mode); + _ff_pull_copy_fct((uint8_t*)p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size, copy_mode); } } -- cgit v1.3.1 From a655a4169e4a7be4b547f012643a86d198d46b1f Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Mar 2021 01:18:49 +0700 Subject: add note for MIDI (audio v1.0) endpoint decriptor use 9 bytes instead of 7 --- src/device/usbd.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index 8aeb6aff8..56615b081 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -254,6 +254,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval //------------- MIDI -------------// +// MIDI v1.0 is based on Audio v1.0 #define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7) #define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \ @@ -291,7 +292,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_MIDI_DESC_EP_LEN(_numcables) (9 + 4 + (_numcables)) #define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \ - /* Endpoint */\ + /* Endpoint: Note Audio v1.0's endpoint has 9 bytes instead of 7 */\ 9, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0, 0, 0, \ /* MS Endpoint (connected to embedded jack) */\ (uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables -- cgit v1.3.1 From 8cabbb28df17bfcb7c549a98aec4eef4e70bba12 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Mar 2021 18:36:18 +0700 Subject: fix enum walkaround forever check for SE0 when pull up is disabled --- hw/bsp/rp2040/family.c | 4 +-- hw/bsp/rp2040/family.mk | 1 + src/portable/raspberrypi/rp2040/dcd_rp2040.c | 43 +++++++++++++++++++--------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 5 +++- 4 files changed, 37 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c index ec4088ea1..9995c23d7 100644 --- a/hw/bsp/rp2040/family.c +++ b/hw/bsp/rp2040/family.c @@ -80,8 +80,8 @@ bool __no_inline_not_in_flash_func(get_bootsel_button)() { #if defined(LOGGER_RTT) // Logging with RTT -// If RTT Control Block is not found by 'Auto Detection` -// try to use 'Search Range` with '0x20000000 0x10000' +// - If RTT Control Block is not found by 'Auto Detection` try to use 'Search Range` with '0x20000000 0x10000' +// - SWD speed is rather slow around 1000Khz #include "pico/stdio/driver.h" #include "SEGGER_RTT.h" diff --git a/hw/bsp/rp2040/family.mk b/hw/bsp/rp2040/family.mk index 9aacae37d..b0fb58ff7 100644 --- a/hw/bsp/rp2040/family.mk +++ b/hw/bsp/rp2040/family.mk @@ -1,3 +1,4 @@ FAMILY_SUBMODULES = hw/mcu/raspberrypi/pico-sdk JLINK_DEVICE = rp2040_m0_0 +PYOCD_TARGET = rp2040 diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index ba708081c..f844a0c65 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -312,18 +312,7 @@ static void dcd_rp2040_irq(void) hw_handle_buff_status(); } - if (status & USB_INTS_BUS_RESET_BITS) - { - pico_trace("BUS RESET (addr %d -> %d)\n", assigned_address, 0); - usb_hw->dev_addr_ctrl = 0; - handled |= USB_INTS_BUS_RESET_BITS; - dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); - usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; -#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX - rp2040_usb_device_enumeration_fix(); -#endif - } - + // SE0 for 2 us or more, usually together with Bus Reset if (status & USB_INTS_DEV_CONN_DIS_BITS) { handled |= USB_INTS_DEV_CONN_DIS_BITS; @@ -340,7 +329,35 @@ static void dcd_rp2040_irq(void) usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS; } -#if 0 // TODO Enable SUSPEND & RESUME interrupt and test later on with/without VBUS detection + // SE0 for 2.5 us or more + if (status & USB_INTS_BUS_RESET_BITS) + { + pico_trace("BUS RESET\n"); + usb_hw->dev_addr_ctrl = 0; + handled |= USB_INTS_BUS_RESET_BITS; + dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); + usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; + +#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX + // Only run enumeration walk-around if pull up is enabled + if ( usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS ) + { + rp2040_usb_device_enumeration_fix(); + } +#endif + } + +#if 0 + // TODO Enable SUSPEND & RESUME interrupt and test later on with/without VBUS detection + + /* Note from pico datasheet 4.1.2.6.4 (v1.2) + * If you enable the suspend interrupt, it is likely you will see a suspend interrupt when + * the device is first connected but the bus is idle. The bus can be idle for a few ms before + * the host begins sending start of frame packets. You will also see a suspend interrupt + * when the device is disconnected if you do not have a VBUS detect circuit connected. This is + * because without VBUS detection, it is impossible to tell the difference between + * being disconnected and suspended. + */ if (status & USB_INTS_DEV_SUSPEND_BITS) { handled |= USB_INTS_DEV_SUSPEND_BITS; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index c6f6d7231..98ffea9a3 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -60,8 +60,11 @@ void rp2040_usb_init(void) memset(usb_hw, 0, sizeof(*usb_hw)); memset(usb_dpram, 0, sizeof(*usb_dpram)); - // Mux to phy + // Mux the controller to the onboard usb phy usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; + + // Force VBUS detect so the device thinks it is plugged into a host + // TODO support VBUs detect usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; } -- cgit v1.3.1 From 33a29c9e4ca9aebb3469c8f8114365acc3614321 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Mar 2021 19:30:08 +0700 Subject: add midi comment --- src/class/midi/midi_device.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 325fc4669..29019cc1d 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -387,6 +387,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint p_midi->ep_out = ep_addr; } + // Class Specific MIDI Stream endpoint descriptor drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); -- cgit v1.3.1 From 7e56f46957452c21a5f6228d0aff2d5544c04b9f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 4 Mar 2021 13:52:14 +0100 Subject: Extend FIFO mutex to use separate write and read mutexes. Adjust all USB drivers using FIFO and mutexes. --- src/class/audio/audio_device.c | 16 +++---- src/class/cdc/cdc_device.c | 4 +- src/class/midi/midi_device.c | 4 +- src/class/vendor/vendor_device.c | 4 +- src/common/tusb_fifo.c | 97 +++++++++++++++++++++++++--------------- src/common/tusb_fifo.h | 8 ++-- 6 files changed, 80 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 37d6a36a7..c0d3e123c 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -133,7 +133,7 @@ typedef struct tu_fifo_t ep_out_ff; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex; + osal_mutex_def_t ep_out_ff_mutex_rd; // No need for write mutex as only USB driver writes into FIFO #endif #endif @@ -149,7 +149,7 @@ typedef struct tu_fifo_t ep_in_ff; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex; + osal_mutex_def_t ep_in_ff_mutex_wr; // No need for read mutex as only USB driver reads from FIFO #endif #endif @@ -164,7 +164,7 @@ typedef struct tu_fifo_t tx_supp_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_TX]; + osal_mutex_def_t tx_supp_ff_mutex_wr[CFG_TUD_AUDIO_N_CHANNELS_TX]; // No need for read mutex as only USB driver reads from FIFO #endif #endif @@ -172,7 +172,7 @@ typedef struct tu_fifo_t rx_supp_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex[CFG_TUD_AUDIO_N_CHANNELS_RX]; + osal_mutex_def_t rx_supp_ff_mutex_rd[CFG_TUD_AUDIO_N_CHANNELS_RX]; // No need for write mutex as only USB driver writes into FIFO #endif #endif @@ -671,7 +671,7 @@ void audiod_init(void) #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE tu_fifo_config(&audio->ep_in_ff, &audio->ep_in_buf, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex)); + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex_wr), NULL); #endif #endif @@ -679,7 +679,7 @@ void audiod_init(void) #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, osal_mutex_create(&audio->ep_out_ff_mutex)); + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&audio->ep_out_ff_mutex_rd)); #endif #endif @@ -689,7 +689,7 @@ void audiod_init(void) { tu_fifo_config(&audio->tx_supp_ff[cnt], &audio->tx_supp_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->tx_supp_ff[cnt], osal_mutex_create(&audio->tx_supp_ff_mutex[cnt])); + tu_fifo_config_mutex(&audio->tx_supp_ff[cnt], osal_mutex_create(&audio->tx_supp_ff_mutex_wr[cnt]), NULL); #endif } #endif @@ -700,7 +700,7 @@ void audiod_init(void) { tu_fifo_config(&audio->rx_supp_ff[cnt], &audio->rx_supp_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->rx_supp_ff[cnt], osal_mutex_create(&audio->rx_supp_ff_mutex[cnt])); + tu_fifo_config_mutex(&audio->rx_supp_ff[cnt], NULL, osal_mutex_create(&audio->rx_supp_ff_mutex_rd[cnt])); #endif } #endif diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 58f485a5d..c679dc71e 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -243,8 +243,8 @@ void cdcd_init(void) tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&p_cdc->rx_ff, osal_mutex_create(&p_cdc->rx_ff_mutex)); - tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex)); + tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, osal_mutex_create(&p_cdc->rx_ff_mutex)); + tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex), NULL); #endif } } diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 325fc4669..c61bad17c 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -310,8 +310,8 @@ void midid_init(void) tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); // OBVS. #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&midi->rx_ff, osal_mutex_create(&midi->rx_ff_mutex)); - tu_fifo_config_mutex(&midi->tx_ff, osal_mutex_create(&midi->tx_ff_mutex)); + tu_fifo_config_mutex(&midi->rx_ff, NULL, osal_mutex_create(&midi->rx_ff_mutex)); + tu_fifo_config_mutex(&midi->tx_ff, osal_mutex_create(&midi->tx_ff_mutex), NULL); #endif } } diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 3fcea89c4..9b0a3c25f 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -146,8 +146,8 @@ void vendord_init(void) tu_fifo_config(&p_itf->tx_ff, p_itf->tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, 1, false); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&p_itf->rx_ff, osal_mutex_create(&p_itf->rx_ff_mutex)); - tu_fifo_config_mutex(&p_itf->tx_ff, osal_mutex_create(&p_itf->tx_ff_mutex)); + tu_fifo_config_mutex(&p_itf->rx_ff, NULL, osal_mutex_create(&p_itf->rx_ff_mutex)); + tu_fifo_config_mutex(&p_itf->tx_ff, osal_mutex_create(&p_itf->tx_ff_mutex), NULL); #endif } } diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index d4251abea..44b4a11c0 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -39,31 +39,49 @@ // implement mutex lock and unlock #if CFG_FIFO_MUTEX -static void tu_fifo_lock(tu_fifo_t *f) +static void tu_fifo_lock_wr(tu_fifo_t *f) { - if (f->mutex) + if (f->mutex_wr) { - osal_mutex_lock(f->mutex, OSAL_TIMEOUT_WAIT_FOREVER); + osal_mutex_lock(f->mutex_wr, OSAL_TIMEOUT_WAIT_FOREVER); } } -static void tu_fifo_unlock(tu_fifo_t *f) +static void tu_fifo_unlock_wr(tu_fifo_t *f) { - if (f->mutex) + if (f->mutex_wr) { - osal_mutex_unlock(f->mutex); + osal_mutex_unlock(f->mutex_wr); + } +} + +static void tu_fifo_lock_rd(tu_fifo_t *f) +{ + if (f->mutex_rd) + { + osal_mutex_lock(f->mutex_rd, OSAL_TIMEOUT_WAIT_FOREVER); + } +} + +static void tu_fifo_unlock_rd(tu_fifo_t *f) +{ + if (f->mutex_rd) + { + osal_mutex_unlock(f->mutex_rd); } } #else -#define tu_fifo_lock(_ff) -#define tu_fifo_unlock(_ff) +#define tu_fifo_lock_wr(_ff) +#define tu_fifo_unlock_wr(_ff) +#define tu_fifo_lock_rd(_ff) +#define tu_fifo_unlock_rd(_ff) #endif /** \enum tu_fifo_copy_mode_t - * \brief Write modes intended to allow special read and write functions to be able to copy data to and from USB hardware FIFOs as needed for e.g. STM32s + * \brief Write modes intended to allow special read and write functions to be able to copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others */ typedef enum { @@ -75,7 +93,8 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si { if (depth > 0x8000) return false; // Maximum depth is 2^15 items - tu_fifo_lock(f); + tu_fifo_lock_wr(f); + tu_fifo_lock_rd(f); f->buffer = (uint8_t*) buffer; f->depth = depth; @@ -87,7 +106,8 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si f->rd_idx = f->wr_idx = 0; - tu_fifo_unlock(f); + tu_fifo_unlock_wr(f); + tu_fifo_lock_rd(f); return true; } @@ -381,7 +401,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu { if ( n == 0 ) return 0; - tu_fifo_lock(f); + tu_fifo_lock_wr(f); uint16_t w = f->wr_idx, r = f->rd_idx; uint8_t const* buf8 = (uint8_t const*) data; @@ -411,14 +431,14 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu // Advance pointer f->wr_idx = advance_pointer(f, w, n); - tu_fifo_unlock(f); + tu_fifo_unlock_wr(f); return n; } static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) { - tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! + tu_fifo_lock_rd(f); // TODO: Here we may distinguish for read and write pointer mutexes! // Peek the data n = _tu_fifo_peek_at_n(f, 0, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable @@ -426,7 +446,7 @@ static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo // Advance read pointer f->rd_idx = advance_pointer(f, f->rd_idx, n); - tu_fifo_unlock(f); + tu_fifo_unlock_rd(f); return n; } @@ -533,9 +553,9 @@ bool tu_fifo_overflowed(tu_fifo_t* f) // Only use in case tu_fifo_overflow() returned true! void tu_fifo_correct_read_pointer(tu_fifo_t* f) { - tu_fifo_lock(f); + tu_fifo_lock_rd(f); _tu_fifo_correct_read_pointer(f, f->wr_idx); - tu_fifo_unlock(f); + tu_fifo_unlock_rd(f); } /******************************************************************************/ @@ -556,7 +576,7 @@ void tu_fifo_correct_read_pointer(tu_fifo_t* f) /******************************************************************************/ bool tu_fifo_read(tu_fifo_t* f, void * buffer) { - tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! + tu_fifo_lock_rd(f); // TODO: Here we may distinguish for read and write pointer mutexes! // Peek the data bool ret = _tu_fifo_peek_at(f, 0, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable @@ -564,7 +584,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) // Advance pointer f->rd_idx = advance_pointer(f, f->rd_idx, ret); - tu_fifo_unlock(f); + tu_fifo_unlock_rd(f); return ret; } @@ -615,7 +635,8 @@ uint16_t tu_fifo_read_n_const_addr(tu_fifo_t* f, void * buffer, uint16_t n) /******************************************************************************/ uint16_t tu_fifo_read_n_into_other_fifo(tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n) { - tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! + tu_fifo_lock_rd(f); + tu_fifo_lock_wr(f_target); // Conduct copy n = tu_fifo_peek_n_into_other_fifo(f, f_target, offset, n); @@ -623,7 +644,8 @@ uint16_t tu_fifo_read_n_into_other_fifo(tu_fifo_t* f, tu_fifo_t* f_target, uint1 // Advance read pointer f->rd_idx = advance_pointer(f, f->rd_idx, n); - tu_fifo_unlock(f); + tu_fifo_unlock_rd(f); + tu_fifo_unlock_wr(f_target); return n; } @@ -645,9 +667,9 @@ uint16_t tu_fifo_read_n_into_other_fifo(tu_fifo_t* f, tu_fifo_t* f_target, uint1 /******************************************************************************/ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) { - tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! + tu_fifo_lock_rd(f); bool ret = _tu_fifo_peek_at(f, offset, p_buffer, f->wr_idx, f->rd_idx); - tu_fifo_unlock(f); + tu_fifo_unlock_rd(f); return ret; } @@ -670,9 +692,9 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) /******************************************************************************/ uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t n) { - tu_fifo_lock(f); // TODO: Here we may distinguish for read and write pointer mutexes! + tu_fifo_lock_rd(f); bool ret = _tu_fifo_peek_at_n(f, offset, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); - tu_fifo_unlock(f); + tu_fifo_unlock_rd(f); return ret; } @@ -719,7 +741,7 @@ uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint cnt -= offset; if (cnt < n) n = cnt; - tu_fifo_lock(f_target); // Lock both read and write pointers - in case of an overwritable FIFO both may be modified + tu_fifo_lock_wr(f_target); // Lock both read and write pointers - in case of an overwritable FIFO both may be modified uint16_t wr_rel_tgt = get_relative_pointer(f_target, f_target->wr_idx, 0); @@ -757,7 +779,7 @@ uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint _tu_fifo_peek_at_n(f, offset + sz, f_target->buffer, n-sz, f_wr_idx, f_rd_idx, TU_FIFO_COPY_INC); } - tu_fifo_unlock(f_target); + tu_fifo_unlock_wr(f_target); return n; } @@ -780,7 +802,7 @@ uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint /******************************************************************************/ bool tu_fifo_write(tu_fifo_t* f, const void * data) { - tu_fifo_lock(f); + tu_fifo_lock_wr(f); uint16_t w = f->wr_idx; @@ -794,7 +816,7 @@ bool tu_fifo_write(tu_fifo_t* f, const void * data) // Advance pointer f->wr_idx = advance_pointer(f, w, 1); - tu_fifo_unlock(f); + tu_fifo_unlock_wr(f); return true; } @@ -848,12 +870,13 @@ uint16_t tu_fifo_write_n_const_addr(tu_fifo_t* f, const void * data, uint16_t n) /******************************************************************************/ bool tu_fifo_clear(tu_fifo_t *f) { - tu_fifo_lock(f); + tu_fifo_lock_wr(f); + tu_fifo_lock_rd(f); f->rd_idx = f->wr_idx = 0; f->max_pointer_idx = 2*f->depth-1; f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; - tu_fifo_unlock(f); - + tu_fifo_unlock_wr(f); + tu_fifo_unlock_rd(f); return true; } @@ -869,11 +892,13 @@ bool tu_fifo_clear(tu_fifo_t *f) /******************************************************************************/ bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { - tu_fifo_lock(f); + tu_fifo_lock_wr(f); + tu_fifo_lock_rd(f); f->overwritable = overwritable; - tu_fifo_unlock(f); + tu_fifo_unlock_wr(f); + tu_fifo_unlock_rd(f); return true; } @@ -996,9 +1021,9 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, // Check overflow and correct if required if (cnt > f->depth) { - tu_fifo_lock(f); + tu_fifo_lock_rd(f); _tu_fifo_correct_read_pointer(f, w); - tu_fifo_unlock(f); + tu_fifo_unlock_rd(f); r = f->rd_idx; cnt = f->depth; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index feacc7a12..6e0ecdc82 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -73,7 +73,8 @@ typedef struct volatile uint16_t rd_idx ; ///< read pointer #if CFG_FIFO_MUTEX - tu_fifo_mutex_t mutex; + tu_fifo_mutex_t mutex_wr; + tu_fifo_mutex_t mutex_rd; #endif } tu_fifo_t; @@ -98,9 +99,10 @@ bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); #if CFG_FIFO_MUTEX -static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t mutex_hdl) +static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mutex_hdl, tu_fifo_mutex_t read_mutex_hdl) { - f->mutex = mutex_hdl; + f->mutex_wr = write_mutex_hdl; + f->mutex_rd = read_mutex_hdl; } #endif -- cgit v1.3.1 From 2e28861cf83dd735485b1f27552716da5d4043e8 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 4 Mar 2021 18:20:22 +0100 Subject: Remove TODOs done. --- src/common/tusb_fifo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 44b4a11c0..1b1e9ca3b 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -438,7 +438,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) { - tu_fifo_lock_rd(f); // TODO: Here we may distinguish for read and write pointer mutexes! + tu_fifo_lock_rd(f); // Peek the data n = _tu_fifo_peek_at_n(f, 0, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable @@ -576,7 +576,7 @@ void tu_fifo_correct_read_pointer(tu_fifo_t* f) /******************************************************************************/ bool tu_fifo_read(tu_fifo_t* f, void * buffer) { - tu_fifo_lock_rd(f); // TODO: Here we may distinguish for read and write pointer mutexes! + tu_fifo_lock_rd(f); // Peek the data bool ret = _tu_fifo_peek_at(f, 0, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable -- cgit v1.3.1 From de1f36f2b02b00d8012748be304186e1eb78c728 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 4 Mar 2021 19:52:48 +0100 Subject: Adapt mutexes in fifo.c --- src/common/tusb_fifo.c | 102 ++++++++++++++++++++----------------------------- 1 file changed, 42 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 1b1e9ca3b..6a31b6373 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -39,44 +39,26 @@ // implement mutex lock and unlock #if CFG_FIFO_MUTEX -static void tu_fifo_lock_wr(tu_fifo_t *f) +static void tu_fifo_lock(tu_fifo_mutex_t mutex) { - if (f->mutex_wr) + if (mutex) { - osal_mutex_lock(f->mutex_wr, OSAL_TIMEOUT_WAIT_FOREVER); + osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); } } -static void tu_fifo_unlock_wr(tu_fifo_t *f) +static void tu_fifo_unlock(tu_fifo_mutex_t mutex) { - if (f->mutex_wr) + if (mutex) { - osal_mutex_unlock(f->mutex_wr); - } -} - -static void tu_fifo_lock_rd(tu_fifo_t *f) -{ - if (f->mutex_rd) - { - osal_mutex_lock(f->mutex_rd, OSAL_TIMEOUT_WAIT_FOREVER); - } -} - -static void tu_fifo_unlock_rd(tu_fifo_t *f) -{ - if (f->mutex_rd) - { - osal_mutex_unlock(f->mutex_rd); + osal_mutex_unlock(mutex); } } #else -#define tu_fifo_lock_wr(_ff) -#define tu_fifo_unlock_wr(_ff) -#define tu_fifo_lock_rd(_ff) -#define tu_fifo_unlock_rd(_ff) +#define tu_fifo_lock(_mutex) +#define tu_fifo_unlock(_mutex) #endif @@ -93,8 +75,8 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si { if (depth > 0x8000) return false; // Maximum depth is 2^15 items - tu_fifo_lock_wr(f); - tu_fifo_lock_rd(f); + tu_fifo_lock(f->mutex_wr); + tu_fifo_lock(f->mutex_rd); f->buffer = (uint8_t*) buffer; f->depth = depth; @@ -106,8 +88,8 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si f->rd_idx = f->wr_idx = 0; - tu_fifo_unlock_wr(f); - tu_fifo_lock_rd(f); + tu_fifo_unlock(f->mutex_wr); + tu_fifo_lock(f->mutex_rd); return true; } @@ -401,7 +383,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu { if ( n == 0 ) return 0; - tu_fifo_lock_wr(f); + tu_fifo_lock(f->mutex_wr); uint16_t w = f->wr_idx, r = f->rd_idx; uint8_t const* buf8 = (uint8_t const*) data; @@ -431,14 +413,14 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu // Advance pointer f->wr_idx = advance_pointer(f, w, n); - tu_fifo_unlock_wr(f); + tu_fifo_unlock(f->mutex_wr); return n; } static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) { - tu_fifo_lock_rd(f); + tu_fifo_lock(f->mutex_rd); // Peek the data n = _tu_fifo_peek_at_n(f, 0, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable @@ -446,7 +428,7 @@ static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo // Advance read pointer f->rd_idx = advance_pointer(f, f->rd_idx, n); - tu_fifo_unlock_rd(f); + tu_fifo_unlock(f->mutex_rd); return n; } @@ -553,9 +535,9 @@ bool tu_fifo_overflowed(tu_fifo_t* f) // Only use in case tu_fifo_overflow() returned true! void tu_fifo_correct_read_pointer(tu_fifo_t* f) { - tu_fifo_lock_rd(f); + tu_fifo_lock(f->mutex_rd); _tu_fifo_correct_read_pointer(f, f->wr_idx); - tu_fifo_unlock_rd(f); + tu_fifo_unlock(f->mutex_rd); } /******************************************************************************/ @@ -576,7 +558,7 @@ void tu_fifo_correct_read_pointer(tu_fifo_t* f) /******************************************************************************/ bool tu_fifo_read(tu_fifo_t* f, void * buffer) { - tu_fifo_lock_rd(f); + tu_fifo_lock(f->mutex_rd); // Peek the data bool ret = _tu_fifo_peek_at(f, 0, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable @@ -584,7 +566,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) // Advance pointer f->rd_idx = advance_pointer(f, f->rd_idx, ret); - tu_fifo_unlock_rd(f); + tu_fifo_unlock(f->mutex_rd); return ret; } @@ -635,8 +617,8 @@ uint16_t tu_fifo_read_n_const_addr(tu_fifo_t* f, void * buffer, uint16_t n) /******************************************************************************/ uint16_t tu_fifo_read_n_into_other_fifo(tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n) { - tu_fifo_lock_rd(f); - tu_fifo_lock_wr(f_target); + tu_fifo_lock(f->mutex_rd); + tu_fifo_lock(f_target->mutex_wr); // Conduct copy n = tu_fifo_peek_n_into_other_fifo(f, f_target, offset, n); @@ -644,8 +626,8 @@ uint16_t tu_fifo_read_n_into_other_fifo(tu_fifo_t* f, tu_fifo_t* f_target, uint1 // Advance read pointer f->rd_idx = advance_pointer(f, f->rd_idx, n); - tu_fifo_unlock_rd(f); - tu_fifo_unlock_wr(f_target); + tu_fifo_unlock(f->mutex_rd); + tu_fifo_unlock(f_target->mutex_wr); return n; } @@ -667,9 +649,9 @@ uint16_t tu_fifo_read_n_into_other_fifo(tu_fifo_t* f, tu_fifo_t* f_target, uint1 /******************************************************************************/ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) { - tu_fifo_lock_rd(f); + tu_fifo_lock(f->mutex_rd); bool ret = _tu_fifo_peek_at(f, offset, p_buffer, f->wr_idx, f->rd_idx); - tu_fifo_unlock_rd(f); + tu_fifo_unlock(f->mutex_rd); return ret; } @@ -692,9 +674,9 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) /******************************************************************************/ uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t n) { - tu_fifo_lock_rd(f); + tu_fifo_lock(f->mutex_rd); bool ret = _tu_fifo_peek_at_n(f, offset, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); - tu_fifo_unlock_rd(f); + tu_fifo_unlock(f->mutex_rd); return ret; } @@ -741,7 +723,7 @@ uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint cnt -= offset; if (cnt < n) n = cnt; - tu_fifo_lock_wr(f_target); // Lock both read and write pointers - in case of an overwritable FIFO both may be modified + tu_fifo_lock(f_target->mutex_wr); // Lock both read and write pointers - in case of an overwritable FIFO both may be modified uint16_t wr_rel_tgt = get_relative_pointer(f_target, f_target->wr_idx, 0); @@ -779,7 +761,7 @@ uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint _tu_fifo_peek_at_n(f, offset + sz, f_target->buffer, n-sz, f_wr_idx, f_rd_idx, TU_FIFO_COPY_INC); } - tu_fifo_unlock_wr(f_target); + tu_fifo_unlock(f_target->mutex_wr); return n; } @@ -802,7 +784,7 @@ uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint /******************************************************************************/ bool tu_fifo_write(tu_fifo_t* f, const void * data) { - tu_fifo_lock_wr(f); + tu_fifo_lock(f->mutex_wr); uint16_t w = f->wr_idx; @@ -816,7 +798,7 @@ bool tu_fifo_write(tu_fifo_t* f, const void * data) // Advance pointer f->wr_idx = advance_pointer(f, w, 1); - tu_fifo_unlock_wr(f); + tu_fifo_unlock(f->mutex_wr); return true; } @@ -870,13 +852,13 @@ uint16_t tu_fifo_write_n_const_addr(tu_fifo_t* f, const void * data, uint16_t n) /******************************************************************************/ bool tu_fifo_clear(tu_fifo_t *f) { - tu_fifo_lock_wr(f); - tu_fifo_lock_rd(f); + tu_fifo_lock(f->mutex_wr); + tu_fifo_lock(f->mutex_rd); f->rd_idx = f->wr_idx = 0; f->max_pointer_idx = 2*f->depth-1; f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; - tu_fifo_unlock_wr(f); - tu_fifo_unlock_rd(f); + tu_fifo_unlock(f->mutex_wr); + tu_fifo_unlock(f->mutex_rd); return true; } @@ -892,13 +874,13 @@ bool tu_fifo_clear(tu_fifo_t *f) /******************************************************************************/ bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { - tu_fifo_lock_wr(f); - tu_fifo_lock_rd(f); + tu_fifo_lock(f->mutex_wr); + tu_fifo_lock(f->mutex_rd); f->overwritable = overwritable; - tu_fifo_unlock_wr(f); - tu_fifo_unlock_rd(f); + tu_fifo_unlock(f->mutex_wr); + tu_fifo_unlock(f->mutex_rd); return true; } @@ -1021,9 +1003,9 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, // Check overflow and correct if required if (cnt > f->depth) { - tu_fifo_lock_rd(f); + tu_fifo_lock(f->mutex_rd); _tu_fifo_correct_read_pointer(f, w); - tu_fifo_unlock_rd(f); + tu_fifo_unlock(f->mutex_rd); r = f->rd_idx; cnt = f->depth; } -- cgit v1.3.1 From eeea19c0ab1c6e66c56eabac49e2c0f190e9a080 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 10 Mar 2021 11:33:03 +0700 Subject: usbd ack SET_INTERFACE if it is not implemented by class driver. --- src/device/usbd.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 911977eb0..ca5a482fc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -699,13 +699,21 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE if ( !invoke_class_control(rhport, driver, p_request) ) { - // 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); + // For GET_INTERFACE and SET_INTERFACE, it is mandatory to respond even if the class + // driver doesn't use alternate settings or implement this + TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type); - uint8_t alternate = 0; - tud_control_xfer(rhport, p_request, &alternate, 1); + if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) + { + uint8_t alternate = 0; + tud_control_xfer(rhport, p_request, &alternate, 1); + }else if (TUSB_REQ_SET_INTERFACE == p_request->bRequest) + { + tud_control_status(rhport, p_request); + } else + { + return false; + } } } break; -- cgit v1.3.1 From 7fc99a9e1104703566945ace1b2e1ed59819ba48 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 10 Mar 2021 10:19:45 +0100 Subject: Call One time tu_fifo_write_n on cdcd_xfer_cb Signed-off-by: HiFiPhile --- src/class/cdc/cdc_device.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 5a74b4876..64cb4ab2c 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -432,25 +432,25 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Received new data if ( ep_addr == p_cdc->ep_out ) { + tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); + // TODO search for wanted char first for better performance - for(uint32_t i=0; irx_ff, &p_cdc->epout_buf[i]); - + if (tud_cdc_rx_wanted_cb && ( ((signed char) p_cdc->wanted_char) != -1)) { // Check for wanted char and invoke callback if needed - if ( tud_cdc_rx_wanted_cb && ( ((signed char) p_cdc->wanted_char) != -1 ) && ( p_cdc->wanted_char == p_cdc->epout_buf[i] ) ) - { - tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); + for (uint32_t i=0; iwanted_char == p_cdc->epout_buf[i] ) { + tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); + } } } - + // invoke receive callback (if there is still data) if (tud_cdc_rx_cb && tu_fifo_count(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); - + // prepare for OUT transaction _prep_out_transaction(p_cdc); } - + // Data sent to host, we continue to fetch from tx fifo to send. // Note: This will cause incorrect baudrate set in line coding. // Though maybe the baudrate is not really important !!! -- cgit v1.3.1 From e864bda6272485a33398ebf0f139607bf244f237 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 10 Mar 2021 17:21:59 +0700 Subject: fix build with freertos --- src/common/tusb_fifo.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 6e0ecdc82..0276c8044 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -53,6 +53,7 @@ extern "C" { #endif #if CFG_FIFO_MUTEX +#include "osal/osal.h" #define tu_fifo_mutex_t osal_mutex_t #endif -- cgit v1.3.1 From a397353916db36d925f5aec654fc66d5ca09f427 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 10 Mar 2021 17:58:39 +0700 Subject: fix ci build with rp2040 --- src/common/tusb_fifo.h | 2 +- src/device/dcd.h | 5 +++-- src/osal/osal_pico.h | 4 ++-- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 0276c8044..62ee942d2 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -109,7 +109,7 @@ static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mute bool tu_fifo_write (tu_fifo_t* f, void const * p_data); uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t n); -uint16_t tu_fifo_write_n_const_addr (tu_fifo_t* f, const void * data, uint16_t n); +uint16_t tu_fifo_write_n_const_addr (tu_fifo_t* f, const void * data, uint16_t n); bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); diff --git a/src/device/dcd.h b/src/device/dcd.h index 89f8760d0..1e5b3ff1e 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -134,8 +134,9 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); -// Submit an ISO transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); +// Submit an transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack +// This API is optional, may be useful for register-based for transferring data. +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index c277af271..bae1217eb 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -143,7 +143,7 @@ static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) // TODO: revisit... docs say that mutexes are never used from IRQ context, // however osal_queue_recieve may be. therefore my assumption is that // the fifo mutex is not populated for queues used from an IRQ context - assert(!qhdl->ff.mutex); + //assert(!qhdl->ff.mutex); _osal_q_lock(qhdl); bool success = tu_fifo_read(&qhdl->ff, data); @@ -157,7 +157,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in // TODO: revisit... docs say that mutexes are never used from IRQ context, // however osal_queue_recieve may be. therefore my assumption is that // the fifo mutex is not populated for queues used from an IRQ context - assert(!qhdl->ff.mutex); + //assert(!qhdl->ff.mutex); _osal_q_lock(qhdl); bool success = tu_fifo_write(&qhdl->ff, data); diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index f844a0c65..7731078b5 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -35,7 +35,8 @@ #include "pico/fix/rp2040_usb_device_enumeration.h" #endif - +#include "osal/osal.h" +#include "common/tusb_fifo.h" #include "device/dcd.h" /*------------------------------------------------------------------*/ -- cgit v1.3.1 From d5a5a1cab63e8e43b22f13db95df35afdfa6befb Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 10 Mar 2021 19:32:13 +0100 Subject: Implement audio PCM type I enc./decoding acc. to 2.3.1.5 Audio Streams Extending capabilities of support FIFOs Removing copy from to FIFO Adjusting audio examples Remove peek/read into other FIFO --- examples/device/audio_test/src/main.c | 6 +- examples/device/audio_test/src/tusb_config.h | 9 +- examples/device/uac2_headset/src/tusb_config.h | 1 - src/class/audio/audio_device.c | 187 ++++++++++++++++--------- src/class/audio/audio_device.h | 70 ++++----- src/common/tusb_fifo.c | 155 ++------------------ src/common/tusb_fifo.h | 2 - 7 files changed, 168 insertions(+), 262 deletions(-) (limited to 'src') diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index c63e64934..c2406bd23 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -73,12 +73,12 @@ int main(void) tusb_init(); // Init values - sampFreq = 48000; + sampFreq = AUDIO_SAMPLE_RATE; clkValid = 1; sampleFreqRng.wNumSubRanges = 1; - sampleFreqRng.subrange[0].bMin = 48000; - sampleFreqRng.subrange[0].bMax = 48000; + sampleFreqRng.subrange[0].bMin = AUDIO_SAMPLE_RATE; + sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE; sampleFreqRng.subrange[0].bRes = 0; while (1) diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index c6d786398..6ee5d937c 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -91,9 +91,12 @@ extern "C" { // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- +#ifndef AUDIO_SAMPLE_RATE +#define AUDIO_SAMPLE_RATE 48000 +#endif + // Audio format type #define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_I -#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED // Audio format type I specifications #define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM @@ -101,8 +104,8 @@ extern "C" { #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 2 // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_EPSIZE_IN 48*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX*CFG_TUD_AUDIO_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x 1 Channels -#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN + 1 // Just for safety one sample more space +#define CFG_TUD_AUDIO_EPSIZE_IN 48 * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX // ceil(f_s/1000) * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX +#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN + CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX // Just for safety one sample more space // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) #define CFG_TUD_AUDIO_N_AS_INT 1 diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 2ad76b7dc..45acf0093 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -110,7 +110,6 @@ extern "C" { #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 2 #define CFG_TUD_AUDIO_N_CHANNELS_RX 2 #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 2 -#define CFG_TUD_AUDIO_RX_ITEMSIZE 2 #define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index c0d3e123c..00d95ede5 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -161,18 +161,18 @@ typedef struct // Support FIFOs #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - tu_fifo_t tx_supp_ff[CFG_TUD_AUDIO_N_CHANNELS_TX]; - CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_TX][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE]; + tu_fifo_t tx_supp_ff[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO]; + CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr[CFG_TUD_AUDIO_N_CHANNELS_TX]; // No need for read mutex as only USB driver reads from FIFO + osal_mutex_def_t tx_supp_ff_mutex_wr[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO #endif #endif #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - tu_fifo_t rx_supp_ff[CFG_TUD_AUDIO_N_CHANNELS_RX]; - CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf[CFG_TUD_AUDIO_N_CHANNELS_RX][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE]; + tu_fifo_t rx_supp_ff[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO]; + CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd[CFG_TUD_AUDIO_N_CHANNELS_RX]; // No need for write mutex as only USB driver writes into FIFO + osal_mutex_def_t rx_supp_ff_mutex_rd[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO #endif #endif @@ -284,19 +284,19 @@ bool tud_audio_n_clear_ep_out_ff(uint8_t itf) // Delete all content in the support RX FIFOs bool tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); return tu_fifo_clear(&_audiod_itf[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); return tu_fifo_count(&_audiod_itf[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_RX); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); return tu_fifo_read_n(&_audiod_itf[itf].rx_supp_ff[channelId], buffer, bufsize); } #endif @@ -382,35 +382,55 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ // The following functions are used in case CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE != 0 #if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT + +// Decoding according to 2.3.1.5 Audio Streams static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) { (void) rhport; - // We assume there is always the correct number of samples available for decoding - extra checks make no sense here + // Determine amount of samples + uint16_t const nChannelsPerFF = CFG_TUD_AUDIO_N_CHANNELS_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; + uint16_t const nBytesToCopy = nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; + uint16_t const nSamplesPerFFToRead = n_bytes_received / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; + uint8_t cnt_ff; + + // Decode + void * dst; + uint8_t * src; + uint8_t * dst_end; + uint16_t len; + + for (cnt_ff = 0; cnt_ff < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt_ff++) + { + src = &audio->lin_buf_out[cnt_ff*nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX]; - uint16_t cnt = CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; - uint16_t idxSample = 0; + len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nSamplesPerFFToRead); + tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); - while (cnt <= n_bytes_received) - { - for (uint8_t cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_RX; cntChannel++) - { - // If 8, 16, or 32 bit values are to be copied -#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == CFG_TUD_AUDIO_RX_ITEMSIZE - // If this aborts then the target buffer is full - TU_VERIFY(tu_fifo_write_n(&audio->rx_supp_ff[cntChannel], &audio->lin_buf_out[idxSample], CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); -#else - uint32_t sample = audio->lin_buf_out[idxSample]; -#if CFG_TUD_AUDIO_JUSTIFICATION_RX == CFG_TUD_AUDIO_LEFT_JUSTIFIED - sample = sample << 8; -#endif + dst_end = dst + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; - TU_VERIFY(tu_fifo_write_n(&audio->rx_supp_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX)); -#endif - idxSample += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; + while((uint8_t *)dst < dst_end) + { + memcpy(dst, src, nBytesToCopy); + dst = (uint8_t *)dst + nBytesToCopy; + src += nBytesToCopy * CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; } - cnt += CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX; + // Handle wrapped part of FIFO + if (len < nSamplesPerFFToRead) + { + len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nSamplesPerFFToRead - len); + tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); + + dst_end = dst + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; + + while((uint8_t *)dst < dst_end) + { + memcpy(dst, src, nBytesToCopy); + dst = (uint8_t *)dst + nBytesToCopy; + src += nBytesToCopy * CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; + } + } } // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it @@ -469,13 +489,13 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force a bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO); return tu_fifo_clear(&_audiod_itf[itf].tx_supp_ff[channelId]); } uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_CHANNELS_TX); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO); return tu_fifo_write_n(&_audiod_itf[itf].tx_supp_ff[channelId], data, len); } #endif @@ -590,60 +610,91 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) #if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN // Take samples from the support buffer and encode them into the IN EP software FIFO // Returns number of bytes written into linear buffer + +/* 2.3.1.7.1 PCM Format +The PCM (Pulse Coded Modulation) format is the most commonly used audio format to represent audio +data streams. The audio data is not compressed and uses a signed two’s-complement fixed point format. It +is left-justified (the sign bit is the Msb) and data is padded with trailing zeros to fill the remaining unused +bits of the subslot. The binary point is located to the right of the sign bit so that all values lie within the +range [-1, +1) +*/ + +/* + * This function encodes channels saved within the support FIFOs into one stream by interleaving the PCM samples + * in the support FIFOs according to 2.3.1.5 Audio Streams. It does not control justification (left or right) and + * does not change the number of bytes per sample. + * */ + static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { - // We encode directly into IN EP's FIFO - abort if previous transfer not complete + // We encode directly into IN EP's linear buffer - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples - uint16_t const nEndpointSampleCapacity = CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE / CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - uint16_t nSamplesPerChannelToSend = tu_fifo_count(&audio->tx_supp_ff[0]); // We first look for the minimum number of bytes and afterwards convert it to sample size - uint8_t cntChannel; + uint16_t const nChannelsPerFF = CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; + uint16_t const nBytesToCopy = nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + uint16_t const capSamplesPerFF = CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; + uint16_t nSamplesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); + uint8_t cnt_ff; - for (cntChannel = 1; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + for (cnt_ff = 1; cnt_ff < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt_ff++) { - uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cntChannel]); - if (count < nSamplesPerChannelToSend) + uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cnt_ff]); + if (count < nSamplesPerFFToSend) { - nSamplesPerChannelToSend = count; + nSamplesPerFFToSend = count; } } - // Convert to sample size - nSamplesPerChannelToSend = nSamplesPerChannelToSend / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - // Check if there is enough - if (nSamplesPerChannelToSend == 0) return 0; + if (nSamplesPerFFToSend == 0) return 0; // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - nSamplesPerChannelToSend = tu_min16(nSamplesPerChannelToSend, nEndpointSampleCapacity); + nSamplesPerFFToSend = tu_min16(nSamplesPerFFToSend, capSamplesPerFF); + + // Round to full number of samples (flooring) + nSamplesPerFFToSend = (nSamplesPerFFToSend / nChannelsPerFF) * nChannelsPerFF; // Encode - uint16_t cntSample; - uint16_t idxSample = 0; + void * src; + uint8_t * dst; + uint8_t * src_end; + uint16_t len; - for (cntSample = 0; cntSample < nSamplesPerChannelToSend; cntSample++) + for (cnt_ff = 0; cnt_ff < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt_ff++) { - for (cntChannel = 0; cntChannel < CFG_TUD_AUDIO_N_CHANNELS_TX; cntChannel++) + dst = &audio->lin_buf_in[cnt_ff*nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX]; + + len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nSamplesPerFFToSend); + tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); + + src_end = src + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + + while((uint8_t *)src < src_end) { - // If 8, 16, or 32 bit values are to be copied -#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == CFG_TUD_AUDIO_TX_ITEMSIZE - tu_fifo_read_n(&audio->tx_supp_ff[cntChannel], &audio->lin_buf_in[idxSample], CFG_TUD_AUDIO_TX_ITEMSIZE); -#else - uint32_t sample = 0; + memcpy(dst, src, nBytesToCopy); + src = (uint8_t *)src + nBytesToCopy; + dst += nBytesToCopy * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; + } - // Get sample from buffer - tu_fifo_read_n(&audio->tx_supp_ff[cntChannel], &sample, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX); + // Handle wrapped part of FIFO + if (len < nSamplesPerFFToSend) + { + len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nSamplesPerFFToSend - len); + tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); -#if CFG_TUD_AUDIO_JUSTIFICATION_TX == CFG_TUD_AUDIO_LEFT_JUSTIFIED - sample = sample << 8; -#endif - audio->lin_buf_in[idxSample] = sample; -#endif - idxSample += CFG_TUD_AUDIO_TX_ITEMSIZE; + src_end = src + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + + while((uint8_t *)src < src_end) + { + memcpy(dst, src, nBytesToCopy); + src = (uint8_t *)src + nBytesToCopy; + dst += nBytesToCopy * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; + } } } - return nSamplesPerChannelToSend * CFG_TUD_AUDIO_N_CHANNELS_TX * CFG_TUD_AUDIO_TX_ITEMSIZE; + + return nSamplesPerFFToSend * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; } #endif //CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE @@ -685,9 +736,9 @@ void audiod_init(void) // Initialize TX support FIFOs if required #if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt++) { - tu_fifo_config(&audio->tx_supp_ff[cnt], &audio->tx_supp_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, 1, true); + tu_fifo_config(&audio->tx_supp_ff[cnt], &audio->tx_supp_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->tx_supp_ff[cnt], osal_mutex_create(&audio->tx_supp_ff_mutex_wr[cnt]), NULL); #endif @@ -696,9 +747,9 @@ void audiod_init(void) // Initialize RX support FIFOs if required #if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt++) { - tu_fifo_config(&audio->rx_supp_ff[cnt], &audio->rx_supp_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, 1, true); + tu_fifo_config(&audio->rx_supp_ff[cnt], &audio->rx_supp_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX, true); #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&audio->rx_supp_ff[cnt], NULL, osal_mutex_create(&audio->rx_supp_ff_mutex_rd[cnt])); #endif @@ -725,14 +776,14 @@ void audiod_reset(uint8_t rhport) #endif #if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_TX; cnt++) + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt++) { tu_fifo_clear(&audio->tx_supp_ff[cnt]); } #endif #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_CHANNELS_RX; cnt++) + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt++) { tu_fifo_clear(&audio->rx_supp_ff[cnt]); } diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index ca74d68f4..730d42c38 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -50,7 +50,7 @@ #error You must define an audio class control request buffer size! #endif -// End point sizes - Limits: Full Speed <= 1023, High Speed <= 1024 +// End point sizes IN BYTES - Limits: Full Speed <= 1023, High Speed <= 1024 #ifndef CFG_TUD_AUDIO_EPSIZE_IN #define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX #endif @@ -76,13 +76,13 @@ #define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE 0 #endif -// General information of number of TX and/or RX channels - is used in case support FIFOs (see below) are used and can be used for descriptor definitions +// General information of number of TX and/or RX channels - is used in combination with support FIFOs (see below) and can be used for descriptor definitions #ifndef CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_N_CHANNELS_TX 0 +#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 #endif #ifndef CFG_TUD_AUDIO_N_CHANNELS_RX -#define CFG_TUD_AUDIO_N_CHANNELS_RX 0 +#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 #endif // Use of TX/RX support FIFOs @@ -104,7 +104,7 @@ // The encoding/decoding starts when the private callback functions // - audio_tx_done_cb() // - audio_rx_done_cb() -// are invoked. If support FIFOs are used the corresponding encoding/decoding functions are called from there. +// are invoked. If support FIFOs are used, the corresponding encoding/decoding functions are called from there. // Once encoding/decoding is done the result is put directly into the EP_X_SW_BUFFER_FIFOs. You can use the public callback functions // - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() // - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() @@ -120,13 +120,31 @@ // - audio_rx_done_cb() // functions. -// Size of support FIFOs - if size > 0 there are as many FIFOs set up as TX/RX channels defined +// The number of support FIFOs and number of channels is decoupled. The PCM encoding/decoding works depending on the ratio CFG_TUD_AUDIO_N_CHANNELS_XX / CFG_TUD_AUDIO_N_XX_SUPPORT_SW_FIFO, where currently 1:1 and 2:1 is implemented. The version 2:1 is useful in case of I2S for which usually 2 are channels already interleaved available. + +// Size of support FIFOs IN SAMPLES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO and CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO #ifndef CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE 0 // Buffer size per channel - minimum size: ceil(f_s/1000)*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX +#define CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE 0 // FIFO size - minimum size: // ceil(f_s/1000) * CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO #endif #ifndef CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE 0 // Buffer size per channel - minimum size: ceil(f_s/1000)*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX +#define CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE 0 // FIFO size - minimum size: ceil(f_s/1000) * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO +#endif + +#ifndef CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO +#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#define CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO CFG_TUD_AUDIO_N_CHANNELS_TX // default size is equal to number of channels +#else +#define CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO 0 +#endif +#endif + +#ifndef CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO +#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#define CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO CFG_TUD_AUDIO_N_CHANNELS_RX // default size is equal to number of channels +#else +#define CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO 0 +#endif #endif // Enable/disable feedback EP (required for asynchronous RX applications) @@ -167,20 +185,6 @@ #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 #endif -#ifndef CFG_TUD_AUDIO_TX_ITEMSIZE -#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 1 -#define CFG_TUD_AUDIO_TX_ITEMSIZE 1 -#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX == 2 -#define CFG_TUD_AUDIO_TX_ITEMSIZE 2 -#else -#define CFG_TUD_AUDIO_TX_ITEMSIZE 4 -#endif -#endif - -#if CFG_TUD_AUDIO_TX_ITEMSIZE < CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX -#error FIFO element size (ITEMSIZE) must not be smaller then sample size -#endif - #endif #if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I @@ -193,26 +197,6 @@ #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 #endif -#if CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 1 -#define CFG_TUD_AUDIO_RX_ITEMSIZE 1 -#elif CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX == 2 -#define CFG_TUD_AUDIO_RX_ITEMSIZE 2 -#else -#define CFG_TUD_AUDIO_RX_ITEMSIZE 4 -#endif - -#endif - -// In case PCM encoding/decoding of 24 into 32 bits, the adjustment needs to be defined -#define CFG_TUD_AUDIO_LEFT_JUSTIFIED -#define CFG_TUD_AUDIO_RIGHT_JUSTIFIED - -#ifndef CFG_TUD_AUDIO_JUSTIFICATION_RX -#define CFG_TUD_AUDIO_JUSTIFICATION_RX CFG_TUD_AUDIO_LEFT_JUSTIFIED -#endif - -#ifndef CFG_TUD_AUDIO_JUSTIFICATION_TX -#define CFG_TUD_AUDIO_JUSTIFICATION_TX CFG_TUD_AUDIO_LEFT_JUSTIFIED #endif //static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); @@ -256,7 +240,7 @@ bool tud_audio_n_clear_ep_in_ff (uint8_t itf); #if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN uint16_t tud_audio_n_flush_tx_support_ff (uint8_t itf); // Force all content in the support TX FIFOs to be written into EP SW FIFO -bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); +bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_write_support_ff (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); #endif diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 6a31b6373..4936d5e7d 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -596,42 +596,6 @@ uint16_t tu_fifo_read_n_const_addr(tu_fifo_t* f, void * buffer, uint16_t n) return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_CST); } -/******************************************************************************/ -/*! - @brief This function will read n elements from the array index specified by - the read pointer and increment the read index. It copies the elements - into another FIFO and as such takes care of wraps etc. - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] f_target - Pointer to target FIFO i.e. to copy into - @param[in] offset - Position to read from in the FIFO buffer with respect to read pointer - @param[in] n - Number of items to peek - - @returns number of items read from the FIFO - */ -/******************************************************************************/ -uint16_t tu_fifo_read_n_into_other_fifo(tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n) -{ - tu_fifo_lock(f->mutex_rd); - tu_fifo_lock(f_target->mutex_wr); - - // Conduct copy - n = tu_fifo_peek_n_into_other_fifo(f, f_target, offset, n); - - // Advance read pointer - f->rd_idx = advance_pointer(f, f->rd_idx, n); - - tu_fifo_unlock(f->mutex_rd); - tu_fifo_unlock(f_target->mutex_wr); - - return n; -} - /******************************************************************************/ /*! @brief Read one item without removing it from the FIFO. @@ -680,92 +644,6 @@ uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint1 return ret; } -/******************************************************************************/ -/*! - @brief Read n items without removing it from the FIFO and copy them into another FIFO. - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] f_target - Pointer to target FIFO i.e. to copy into - @param[in] offset - Position to read from in the FIFO buffer with respect to read pointer - @param[in] n - Number of items to peek - - @returns Number of bytes written to p_buffer - */ -/******************************************************************************/ -uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n) -{ - // Copy is only possible if both FIFOs have common element size - TU_VERIFY(f->item_size == f_target->item_size); - - // Work on local copies on case any pointer changes in between (only necessary if something is written into FIFO f in the meantime) - uint16_t f_wr_idx = f->wr_idx; - uint16_t f_rd_idx = f->rd_idx; - - uint16_t cnt = _tu_fifo_count(f, f_wr_idx, f_rd_idx); - - // Check overflow and correct if required - if (cnt > f->depth) - { - _tu_fifo_correct_read_pointer(f, f->wr_idx); - f_rd_idx = f->rd_idx; - cnt = f->depth; - } - - // Skip beginning of buffer - if (cnt == 0 || offset >= cnt) return 0; - - // Check if we can read something at and after offset - if too less is available we read what remains - cnt -= offset; - if (cnt < n) n = cnt; - - tu_fifo_lock(f_target->mutex_wr); // Lock both read and write pointers - in case of an overwritable FIFO both may be modified - - uint16_t wr_rel_tgt = get_relative_pointer(f_target, f_target->wr_idx, 0); - - if (!f_target->overwritable) - { - // Not overwritable limit up to full - n = tu_min16(n, tu_fifo_remaining(f_target)); - } - - // Advance write pointer - not required for later - f_target->wr_idx = advance_pointer(f_target, f_target->wr_idx, n); - - if (n >= f_target->depth) - { - offset += n - f_target->depth; - - // We start writing at the read pointer's position since we fill the complete - // buffer and we do not want to modify the read pointer within a write function! - // This would end up in a race condition with read functions! - wr_rel_tgt = get_relative_pointer(f_target, f_target->rd_idx, 0); - - n = f_target->depth; - - // Update write pointer - f_target->wr_idx = advance_pointer(f_target, f_target->rd_idx, n); - } - - // Copy linear size - uint16_t sz = f_target->depth - wr_rel_tgt; - _tu_fifo_peek_at_n(f, offset, &f_target->buffer[wr_rel_tgt], sz, f_wr_idx, f_rd_idx, TU_FIFO_COPY_INC); - - if (n > sz) - { - // Copy remaining, now wrapped part, into target buffer - _tu_fifo_peek_at_n(f, offset + sz, f_target->buffer, n-sz, f_wr_idx, f_rd_idx, TU_FIFO_COPY_INC); - } - - tu_fifo_unlock(f_target->mutex_wr); - - return n; -} - /******************************************************************************/ /*! @brief Write one element into the buffer. @@ -976,7 +854,7 @@ void tu_fifo_backward_read_pointer(tu_fifo_t *f, uint16_t n) Returns the length and pointer from which bytes can be read in a linear manner. This is of major interest for DMA transmissions. If returned length is zero the corresponding pointer is invalid. The returned length is limited to the number - of BYTES n which the user wants to write into the buffer. + of ITEMS n which the user wants to write into the buffer. The write pointer does NOT get advanced, use tu_fifo_advance_read_pointer() to do so! If the length returned is less than n i.e. lendepth; } - // Convert to bytes - cnt = cnt * f->item_size; - // Skip beginning of buffer if (cnt == 0 || offset >= cnt) return 0; @@ -1027,16 +902,14 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, // Check if there is a wrap around necessary uint16_t len; - if (w >= r) { + if (w > r) { len = w - r; } else { - len = f->depth - r; + len = f->depth - r; // Also the case if FIFO was full } - len = len * f->item_size; - // Limit to required length len = tu_min16(n, len); @@ -1060,31 +933,31 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, @param[in] f Pointer to FIFO @param[in] offset - Number of bytes to ignore before start writing + Number of ITEMS to ignore before start writing @param[out] **ptr Pointer to start writing to @param[in] n - Number of BYTES to write into buffer + Number of ITEMS to write into buffer @return len - Length of linear part IN BYTES, if zero corresponding pointer ptr is invalid + Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n) { uint16_t w = f->wr_idx, r = f->rd_idx; - uint16_t free = _tu_fifo_remaining(f, w, r) * f->item_size; + uint16_t free = _tu_fifo_remaining(f, w, r); if (!f->overwritable) { // Not overwritable limit up to full n = tu_min16(n, free); } - else if (n >= f->depth * f->item_size) + else if (n >= f->depth) { // If overwrite is allowed it must be less than or equal to 2 x buffer length, otherwise the overflow can not be resolved by the read functions - TU_VERIFY(n <= 2*f->depth * f->item_size); + TU_VERIFY(n <= 2*f->depth); - n = f->depth * f->item_size; + n = f->depth; // We start writing at the read pointer's position since we fill the complete // buffer and we do not want to modify the read pointer within a write function! // This would end up in a race condition with read functions! @@ -1108,8 +981,6 @@ uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, void **ptr len = f->depth - w; } - len = len * f->item_size; - // Limit to required length len = tu_min16(n, len); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 6e0ecdc82..d31e52f1c 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -113,11 +113,9 @@ uint16_t tu_fifo_write_n_const_addr (tu_fifo_t* f, const void * dat bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); uint16_t tu_fifo_read_n_const_addr (tu_fifo_t* f, void * buffer, uint16_t n); -uint16_t tu_fifo_read_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n); bool tu_fifo_peek_at (tu_fifo_t* f, uint16_t pos, void * p_buffer); uint16_t tu_fifo_peek_at_n (tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n); -uint16_t tu_fifo_peek_n_into_other_fifo (tu_fifo_t* f, tu_fifo_t* f_target, uint16_t offset, uint16_t n); uint16_t tu_fifo_count (tu_fifo_t* f); bool tu_fifo_empty (tu_fifo_t* f); -- cgit v1.3.1 From 5caad485f199ab6acfa237d84bf3d84cf41dcfdd Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 11 Mar 2021 20:36:46 +0100 Subject: Add fifo empty check. Signed-off-by: HiFiPhile --- src/class/cdc/cdc_device.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 64cb4ab2c..d9b098bb2 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -434,11 +434,10 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ { tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); - // TODO search for wanted char first for better performance + // Check for wanted char and invoke callback if needed if (tud_cdc_rx_wanted_cb && ( ((signed char) p_cdc->wanted_char) != -1)) { - // Check for wanted char and invoke callback if needed for (uint32_t i=0; iwanted_char == p_cdc->epout_buf[i] ) { + if ( p_cdc->wanted_char == p_cdc->epout_buf[i] && tu_fifo_count(&p_cdc->rx_ff) ) { tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); } } -- cgit v1.3.1 From 31373fd55cefced35cfaaa61fb8f9aa3e5ec0bc6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 12 Mar 2021 12:55:18 +0700 Subject: use !tu_fifo_empty() instead of tu_fifo_count() --- src/class/cdc/cdc_device.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index d9b098bb2..c24edb757 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -95,7 +95,8 @@ static void _prep_out_transaction (cdcd_interface_t* p_cdc) // fifo can be changed before endpoint is claimed available = tu_fifo_remaining(&p_cdc->rx_ff); - if ( available >= sizeof(p_cdc->epout_buf) ) { + if ( available >= sizeof(p_cdc->epout_buf) ) + { usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); }else { @@ -435,16 +436,19 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); // Check for wanted char and invoke callback if needed - if (tud_cdc_rx_wanted_cb && ( ((signed char) p_cdc->wanted_char) != -1)) { - for (uint32_t i=0; iwanted_char == p_cdc->epout_buf[i] && tu_fifo_count(&p_cdc->rx_ff) ) { + if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) ) + { + for ( uint32_t i = 0; i < xferred_bytes; i++ ) + { + if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) ) + { tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); } } } // invoke receive callback (if there is still data) - if (tud_cdc_rx_cb && tu_fifo_count(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); + if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); // prepare for OUT transaction _prep_out_transaction(p_cdc); -- cgit v1.3.1 From 3a27a9405f3354468c9ff8ae2ddd5d350e1ce19a Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Fri, 12 Mar 2021 15:10:47 +0700 Subject: Release 0.9.0 (#716) * update change log for release * move changelog into docs/ * more changelog * increase macro version --- changelog.md | 297 ----------------------------------------- docs/changelog.md | 392 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/tusb_option.h | 2 +- 3 files changed, 393 insertions(+), 298 deletions(-) delete mode 100644 changelog.md create mode 100644 docs/changelog.md (limited to 'src') diff --git a/changelog.md b/changelog.md deleted file mode 100644 index d645b4fbf..000000000 --- a/changelog.md +++ /dev/null @@ -1,297 +0,0 @@ -# TinyUSB Changelog - -## WIP - -- Fix dropping MIDI sysex message when fifo is full -- Add DPad/Hat support for HID Gamepad -- Add tud_hid_report_complete_cb() API - -## 0.8.0 - 2021.02.05 - -### Device Controller Driver - -- Added new device support for Raspberry Pi RP2040 -- Added new device support for NXP Kinetis KL25ZXX -- Use dcd_event_bus_reset() with link speed to replace bus_signal -- ESP32-S2: - - Add bus suspend and wakeup support -- SAMD21: - - Fix (walkaround) samd21 setup_packet overflow by USB DMA -- STM32 Synopsys: - - Rework USB FIFO allocation scheme and allow RX FIFO size reduction -- Sony CXD56 - - Update Update Spresense SDK to 2.0.2 - - Fix dcd issues with setup packets - - Correct EP number for cdc_msc example - -### USB Device - -**UBSD** - -- Rework usbd control transfer to have additional stage parameter for setup, data, status -- Fix tusb_init() return true instead of TUSB_ERROR_NONE -- Added new API tud_connected() that return true after device got out of bus reset and received the very first setup packet - -**Class Driver** - -- CDC - - Allow to transmit data, even if the host does not support control line states i.e set DTR -- HID - - change default CFG_TUD_HID_EP_BUFSIZE from 16 to 64 -- MIDI - - Fix midi sysex sending bug -- MSC - - Invoke only scsi complete callback after status transaction is complete. - - Fix scsi_mode_sense6_t padding, which cause IAR compiler internal error. -- USBTMC - - Change interrupt endpoint example size to 8 instead of 2 for better compatibility with mcu - -**Example** - -- Support make from windows cmd.exe -- Add HID Consumer Control (media keys) to hid_composite & hid_composite_freertos examples - -### USB Host - -No noticeable changes to host stack - -### New Boards - -- NXP/Freescale Freedom FRDM-KL25Z -- Feather Double M33 express -- Raspberry Pi Pico -- Adafruit Feather RP2040 -- Adafruit Itsy Bitsy RP2040 -- Adafruit QT RP2040 -- Adfruit Feather ESP32-S2 -- Adafruit Magtag 29" Eink -- Adafruit Metro ESP32-S2 -- Adafruit PyBadge -- Adafruit PyPortal -- Great Scott Gadgets' LUNA D11 & D21 - -## 0.7.0 - 2020.11.08 - -### Device Controller Driver - -- Added new support for Espressif ESP32-S2 -- Added new support for Dialog DA1469x -- Enhance STM32 Synopsys - - Support bus events disconnection/suspend/resume/wakeup - - Improve transfer performance with optimizing xfer and fifo size - - Support Highspeed port (OTG_HS) with both internal and external PHY - - Support multiple usb ports with rhport=1 is highspeed on selected MCUs e.g H743, F23. It is possible to have OTG_HS to run on Fullspeed PHY (e.g lacking external PHY) - - Add ISO transfer, fix odd/even frame - - Fix FIFO flush during stall - - Implement dcd_edpt_close() API - - Support F105, F107 -- Enhance STM32 fsdev - - Improve dcd fifo allocation - - Fix ISTR race condition - - Support remap USB IRQ on supported MCUs - - Implement dcd_edpt_close() API -- Enhance NUC 505: enhance set configure behavior -- Enhance SAMD - - Fix race condition with setup packet - - Add SAMD11 option `OPT_MCU_SAMD11` - - Add SAME5x option `OPT_MCU_SAME5X` -- Fix SAMG control data toggle and stall race condition -- Enhance nRF - - Fix hanged when tud_task() is called within critical section (disabled interrupt) - - Fix disconnect bus event not submitted - - Implement ISO transfer and dcd_edpt_close() - -### USB Device - -**USBD** - -- Add new class driver for **Bluetooth HCI** class driver with example can be found in [mynewt-tinyusb-example](https://github.com/hathach/mynewt-tinyusb-example) since it needs mynewt OS to run with. -- Fix USBD endpoint usage racing condition with `usbd_edpt_claim()/usbd_edpt_release()` -- Added `tud_task_event_ready()` and `osal_queue_empty()`. This API is needed to check before enter low power mode with WFI/WFE -- Rename USB IRQ Handler to `dcd_int_handler()`. Application must define IRQ handler in which it calls this API. -- Add `dcd_connect()` and `dcd_disconnect()` to enable/disable internal pullup on D+/D- on supported MCUs. -- Add `usbd_edpt_open()` -- Remove `dcd_set_config()` -- Add *OPT_OS_CUMSTOM* as hook for application to overwrite and/or add their own OS implementation -- Support SET_INTERFACE, GET_INTERFACE request -- Add Logging for debug with optional uart/rtt/swo printf retarget or `CFG_TUSB_DEBUG_PRINTF` hook -- Add IAR compiler support -- Support multiple configuration descriptors. `TUD_CONFIG_DESCRIPTOR()` template has extra config_num as 1st argument -- Improve USB Highspeed support with actual link speed detection with `dcd_event_bus_reset()` -- Enhance class driver management - - `usbd_driver_open()` add max length argument, and return length of interface (0 for not supported). Return value is used for finding appropriate driver - - Add application implemented class driver via `usbd_app_driver_get_cb()` - - IAD is handled to assign driver id -- Added `tud_descriptor_device_qualifier_cb()` callback -- Optimize `tu_fifo` bulk write/read transfer -- Forward non-std control request to class driver -- Let application handle Microsoft OS 1.0 Descriptors (the 0xEE index string) -- Fix OSAL FreeRTOS yield from ISR - -**Class Drivers** - -- USBNET: remove ACM-EEM due to lack of support from host -- USBTMC: fix descriptors when INT EP is disabled -- CDC: - - Send zero length packet for end of data when needed - - Add `tud_cdc_tx_complete_cb()` callback - - Change tud_cdc_n_write_flush() return number of bytes forced to transfer, and flush when writing enough data to fifo -- MIDI: - - Add packet interface - - Add multiple jack descriptors - - Fix MIDI driver for sysex -- DFU Runtime: fix response to SET_INTERFACE and DFU_GETSTATUS request -- Rename some configure macro to make it clear that those are used directly for endpoint transfer - - CFG_TUD_HID_BUFSIZE to `CFG_TUD_HID_EP_BUFSIZE - - CFG_TUD_CDC_EPSIZE to CFG_TUD_CDC_EP_BUFSIZE - - CFG_TUD_MSC_BUFSIZE to CFG_TUD_MSC_EP_BUFSIZE - - CFG_TUD_MIDI_EPSIZE to CFG_TUD_MIDI_EP_BUFSIZE -- HID: - - Fix gamepad template descriptor - - Add multiple HID interface API - - Add extra comma to HID_REPORT_ID - -### USB Host - -- Rework USB host stack (still work in progress) - - Fix compile error with pipehandle - - Rework usbh control and enumeration as non-blocking -- Improve Hub, MSC, HID host driver - -### Examples - -- Add new hid_composite_freertos -- Add new dynamic_configuration to demonstrate how to switch configuration descriptors -- Add new hid_multiple_interface -- Enhance `net_lwip_webserver` example - - Add multiple configuration: RNDIS for Windows, CDC-ECM for macOS (Linux will work with both) - - Update lwip to STABLE-2_1_2_RELEASE for net_lwip_webserver -- Added new Audio example: audio_test uac2_headsest - -### New Boards - -- Espressif ESP32-S2: saola_1, kaluga_1 -- STM32: F746 Nucleo, H743 Eval, H743 Nucleo, F723 discovery, stlink v3 mini, STM32L4r5 Nucleo -- Dialog DA1469x dk pro and dk usb -- Microchip: Great Scoot Gadgets' LUNA, samd11_xplained, D5035-01, atsamd21 xplained pro -- nRF: ItsyBitsy nRF52840 - -## 0.6.0 - 2020.03.30 - -Added **CONTRIBUTORS.md** to give proper credit for contributors to the stack. Special thanks to [Nathan Conrad](https://github.com/pigrew), [Peter Lawrence](https://github.com/majbthrd) and [William D. Jones](https://github.com/cr1901) and others for spending their precious time to add lots of features and ports for this release. - -### Added - -**MCUs** - -- Added support for Microchip SAMG55 -- Added support for Nordic nRF52833 -- Added support for Nuvoton: NUC120, NUC121/NUC125, NUC126, NUC505 -- Added support for NXP LPC: 51Uxx, 54xxx, 55xx -- Added support for NXP iMXRT: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064 -- Added support for Sony CXD56 (Spresense) -- Added support for STM32: L0, F0, F1, F2, F3, F4, F7, H7 -- Added support for TI MSP430 -- Added support for ValentyUSB's eptri - -**Class Driver** - -- Added DFU Runtime class driver -- Added Network class driver with RNDIS, CDC-ECM, CDC-EEM (work in progress) -- Added USBTMC class driver -- Added WebUSB class driver using vendor-specific class -- Added multiple instances support for CDC and MIDI -- Added a handful of unit test with Ceedling. -- Added LOG support for debugging with CFG_TUSB_DEBUG -- Added `tud_descriptor_bos_cb()` for BOS descriptor (required for USB 2.1) -- Added `dcd_edpt0_status_complete()` as optional API for DCD - -**Examples** - -Following examples are added: - -- board_test -- cdc_dual_ports -- dfu_rt -- hid_composite -- net_lwip_webserver -- usbtmc -- webusb_serial - -**Boards** - -Following boards are added: - -- adafruit_clue -- arduino_nano33_ble -- circuitplayground_bluefruit -- circuitplayground_express -- feather_m0_express -- feather_nrf52840_sense -- feather_stm32f405 -- fomu -- itsybitsy_m0 -- itsybitsy_m4 -- lpcxpresso11u37 -- lpcxpresso1549 -- lpcxpresso51u68 -- lpcxpresso54114 -- lpcxpresso55s69 -- mbed1768 -- mimxrt1010_evk -- mimxrt1015_evk -- mimxrt1020_evk -- mimxrt1050_evkb -- mimxrt1060_evk -- mimxrt1064_evk -- msp_exp430f5529lp -- ngx4330 -- nrf52840_mdk_dongle -- nutiny_nuc121s -- nutiny_nuc125s -- nutiny_nuc126v -- nutiny_sdk_nuc120 -- nutiny_sdk_nuc505 -- pca10059 -- pca10100 -- pyboardv11 -- raytac_mdbt50q_rx -- samg55xplained -- seeeduino_xiao -- spresense -- stm32f070rbnucleo -- stm32f072disco -- stm32f103bluepill -- stm32f207nucleo -- stm32f401blackpill -- stm32f411blackpill -- stm32f411disco -- stm32f412disco -- stm32f767nucleo -- stm32h743nucleo -- stm32l0538disco -- stm32l476disco -- teensy_40 - -### Changed - -- Changed `tud_descriptor_string_cb()` to have additional Language ID argument -- Merged hal_nrf5x.c into dcd_nrf5x.c -- Merged dcd_samd21.c and dcd_samd51.c into dcd_samd.c -- Generalized dcd_stm32f4.c to dcd_synopsys.c -- Changed cdc_msc_hid to cdc_msc (drop hid) due to limited endpoints number of some MCUs -- Improved DCD SAMD stability, fix missing setup packet occasionally -- Improved usbd/usbd_control with proper hanlding of zero-length packet (ZLP) -- Improved STM32 DCD FSDev -- Improved STM32 DCD Synopsys -- Migrated CI from Travis to Github Action -- Updated nrfx submodule to 2.1.0 -- Fixed mynewt osal queue definition -- Fixed cdc_msc_freertos example build for all MCUs - -## 0.5.0 (Initial Release) - 2019.07.10 - -First release, device stack works great, host stack works but still need improvement. -- Special thanks to @adafruit team, especially @tannewt to help out immensely to rework device stack: simplify osal & control transfer, adding SAMD21/SAMD51 ports, writing porting docs, adding MIDI class support etc... -- Thanks to @cr1901 for adding STM32F4 port. -- Thanks to @PTS93 and @todbot for HID raw API diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 000000000..0e5f12e83 --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1,392 @@ +# TinyUSB Changelog + +## 0.9.0 - 2021.03.12 + +### Device Stack + +#### Device Controller Driver (DCD) + +RP2040 + +- Fix endpoint buffer reallocation overrun problem +- Fix osal_pico queue overflow in initialization +- Fix Isochronous endpoint buffer size in transfer +- Optimize hardware endpoint struct to reduce RAM usage +- Fix enum walkaround forever check for SE0 when pull up is disabled + +Sony CXD56 + +- Pass the correct speed on Spresense +- Fix setup processed flag + +NXP Transdimention + +- Update dcd_init() to reset controller to device mode + +#### USB Device Driver (USBD) + +- Fix issue with status zlp (tud_control_status) is returned by class driver with SET/CLEAR_FEATURE for endpoint. +- Correct endpoint size check for fullspeed bulk, can be 8, 16, 32, 64 +- Ack SET_INTERFACE even if it is not implemented by class driver. + +#### Device Class Driver + +DFU Runtime + +- rename dfu_rt to dfu_runtime for easy reading + +CDC + +- Add tud_cdc_send_break_cb() to support break request +- Improve CDC receive, minor behavior changes: when tud_cdc_rx_wanted_cb() is invoked wanted_char may not be the last byte in the fifo + +HID + +- [Breaking] Add itf argument to hid API to support multiple instances, follow API has signature changes + - tud_hid_descriptor_report_cb() + - tud_hid_get_report_cb() + - tud_hid_set_report_cb() + - tud_hid_boot_mode_cb() + - tud_hid_set_idle_cb() +- Add report complete callback tud_hid_report_complete_cb() API +- Add DPad/Hat support for HID Gamepad + - TUD_HID_REPORT_DESC_GAMEPAD() now support 16 buttons, 2 joysticks, 1 hat/dpad + - Add hid_gamepad_report_t along with GAMEPAD_BUTTON_ and GAMEPAD_HAT_ enum + - Add Gamepad to hid_composite / hid_composite_freertos example + +MIDI + +- Fix dropping MIDI sysex message when fifo is full +- Fix typo in tud_midi_write24(), make example less ambigous for cable and channel +- Fix incorrect endpoint descriptor length, MIDI v1 use Audio v1 which has 9-byte endpoint descriptor (instead of 7) + +### Host Stack + +#### Host Controller Driver (HCD) + +- Add rhport to hcd_init() +- Improve EHCI/OHCI driver abstraction + - Move echi/ohci files to portable/ + - Rename hcd_lpc18_43 to hcd_transdimension + - Sub hcd API with hcd_ehci_init(), hcd_ehci_register_addr() +- Update NXP transdimention hcd_init() to reset controller to host mode + - Ported hcd to rt10xx + +#### USB Host Driver (USBH) + +- No noticeable changes to usbh + +#### Host Class Driver + +MSC + +- Rename tuh_msc_scsi_inquiry() to tuh_msc_inquiry() +- Rename tuh_msc_mounted_cb/tuh_msc_unmounted_cb to tuh_msc_mount_cb/tuh_msc_unmount_cb to match device stack naming +- Change tuh_msc_is_busy() to tuh_msc_ready() +- Add read10 and write10 function: tuh_msc_read10(), tuh_msc_write10() +- Read_Capacity is invoked as part of enumeration process +- Add tuh_msc_get_block_count(), tuh_msc_get_block_size() +- Add CFG_TUH_MSC_MAXLUN (default to 4) to hold lun capacities + +### Others + +- Add basic support for rt-thread OS +- Change zero bitfield length to more explicit padding +- Build example now fetch required submodules on the fly while running `make` without prio submodule init for mcu drivers +- Update pico-sdk to v1.1.0 + +**New Boards** + +- Microchip SAM E54 Xplained Pro +- LPCXpresso 55s28 +- LPCXpresso 18s37 + +## 0.8.0 - 2021.02.05 + +### Device Controller Driver + +- Added new device support for Raspberry Pi RP2040 +- Added new device support for NXP Kinetis KL25ZXX +- Use dcd_event_bus_reset() with link speed to replace bus_signal +- ESP32-S2: + - Add bus suspend and wakeup support +- SAMD21: + - Fix (walkaround) samd21 setup_packet overflow by USB DMA +- STM32 Synopsys: + - Rework USB FIFO allocation scheme and allow RX FIFO size reduction +- Sony CXD56 + - Update Update Spresense SDK to 2.0.2 + - Fix dcd issues with setup packets + - Correct EP number for cdc_msc example + +### USB Device + +**USBD** + +- Rework usbd control transfer to have additional stage parameter for setup, data, status +- Fix tusb_init() return true instead of TUSB_ERROR_NONE +- Added new API tud_connected() that return true after device got out of bus reset and received the very first setup packet + +**Class Driver** + +- CDC + - Allow to transmit data, even if the host does not support control line states i.e set DTR +- HID + - change default CFG_TUD_HID_EP_BUFSIZE from 16 to 64 +- MIDI + - Fix midi sysex sending bug +- MSC + - Invoke only scsi complete callback after status transaction is complete. + - Fix scsi_mode_sense6_t padding, which cause IAR compiler internal error. +- USBTMC + - Change interrupt endpoint example size to 8 instead of 2 for better compatibility with mcu + +**Example** + +- Support make from windows cmd.exe +- Add HID Consumer Control (media keys) to hid_composite & hid_composite_freertos examples + +### USB Host + +No noticeable changes to host stack + +### New Boards + +- NXP/Freescale Freedom FRDM-KL25Z +- Feather Double M33 express +- Raspberry Pi Pico +- Adafruit Feather RP2040 +- Adafruit Itsy Bitsy RP2040 +- Adafruit QT RP2040 +- Adfruit Feather ESP32-S2 +- Adafruit Magtag 29" Eink +- Adafruit Metro ESP32-S2 +- Adafruit PyBadge +- Adafruit PyPortal +- Great Scott Gadgets' LUNA D11 & D21 + +## 0.7.0 - 2020.11.08 + +### Device Controller Driver + +- Added new support for Espressif ESP32-S2 +- Added new support for Dialog DA1469x +- Enhance STM32 Synopsys + - Support bus events disconnection/suspend/resume/wakeup + - Improve transfer performance with optimizing xfer and fifo size + - Support Highspeed port (OTG_HS) with both internal and external PHY + - Support multiple usb ports with rhport=1 is highspeed on selected MCUs e.g H743, F23. It is possible to have OTG_HS to run on Fullspeed PHY (e.g lacking external PHY) + - Add ISO transfer, fix odd/even frame + - Fix FIFO flush during stall + - Implement dcd_edpt_close() API + - Support F105, F107 +- Enhance STM32 fsdev + - Improve dcd fifo allocation + - Fix ISTR race condition + - Support remap USB IRQ on supported MCUs + - Implement dcd_edpt_close() API +- Enhance NUC 505: enhance set configure behavior +- Enhance SAMD + - Fix race condition with setup packet + - Add SAMD11 option `OPT_MCU_SAMD11` + - Add SAME5x option `OPT_MCU_SAME5X` +- Fix SAMG control data toggle and stall race condition +- Enhance nRF + - Fix hanged when tud_task() is called within critical section (disabled interrupt) + - Fix disconnect bus event not submitted + - Implement ISO transfer and dcd_edpt_close() + +### USB Device + +**USBD** + +- Add new class driver for **Bluetooth HCI** class driver with example can be found in [mynewt-tinyusb-example](https://github.com/hathach/mynewt-tinyusb-example) since it needs mynewt OS to run with. +- Fix USBD endpoint usage racing condition with `usbd_edpt_claim()/usbd_edpt_release()` +- Added `tud_task_event_ready()` and `osal_queue_empty()`. This API is needed to check before enter low power mode with WFI/WFE +- Rename USB IRQ Handler to `dcd_int_handler()`. Application must define IRQ handler in which it calls this API. +- Add `dcd_connect()` and `dcd_disconnect()` to enable/disable internal pullup on D+/D- on supported MCUs. +- Add `usbd_edpt_open()` +- Remove `dcd_set_config()` +- Add *OPT_OS_CUMSTOM* as hook for application to overwrite and/or add their own OS implementation +- Support SET_INTERFACE, GET_INTERFACE request +- Add Logging for debug with optional uart/rtt/swo printf retarget or `CFG_TUSB_DEBUG_PRINTF` hook +- Add IAR compiler support +- Support multiple configuration descriptors. `TUD_CONFIG_DESCRIPTOR()` template has extra config_num as 1st argument +- Improve USB Highspeed support with actual link speed detection with `dcd_event_bus_reset()` +- Enhance class driver management + - `usbd_driver_open()` add max length argument, and return length of interface (0 for not supported). Return value is used for finding appropriate driver + - Add application implemented class driver via `usbd_app_driver_get_cb()` + - IAD is handled to assign driver id +- Added `tud_descriptor_device_qualifier_cb()` callback +- Optimize `tu_fifo` bulk write/read transfer +- Forward non-std control request to class driver +- Let application handle Microsoft OS 1.0 Descriptors (the 0xEE index string) +- Fix OSAL FreeRTOS yield from ISR + +**Class Drivers** + +- USBNET: remove ACM-EEM due to lack of support from host +- USBTMC: fix descriptors when INT EP is disabled +- CDC: + - Send zero length packet for end of data when needed + - Add `tud_cdc_tx_complete_cb()` callback + - Change tud_cdc_n_write_flush() return number of bytes forced to transfer, and flush when writing enough data to fifo +- MIDI: + - Add packet interface + - Add multiple jack descriptors + - Fix MIDI driver for sysex +- DFU Runtime: fix response to SET_INTERFACE and DFU_GETSTATUS request +- Rename some configure macro to make it clear that those are used directly for endpoint transfer + - CFG_TUD_HID_BUFSIZE to `CFG_TUD_HID_EP_BUFSIZE + - CFG_TUD_CDC_EPSIZE to CFG_TUD_CDC_EP_BUFSIZE + - CFG_TUD_MSC_BUFSIZE to CFG_TUD_MSC_EP_BUFSIZE + - CFG_TUD_MIDI_EPSIZE to CFG_TUD_MIDI_EP_BUFSIZE +- HID: + - Fix gamepad template descriptor + - Add multiple HID interface API + - Add extra comma to HID_REPORT_ID + +### USB Host + +- Rework USB host stack (still work in progress) + - Fix compile error with pipehandle + - Rework usbh control and enumeration as non-blocking +- Improve Hub, MSC, HID host driver + +### Examples + +- Add new hid_composite_freertos +- Add new dynamic_configuration to demonstrate how to switch configuration descriptors +- Add new hid_multiple_interface +- Enhance `net_lwip_webserver` example + - Add multiple configuration: RNDIS for Windows, CDC-ECM for macOS (Linux will work with both) + - Update lwip to STABLE-2_1_2_RELEASE for net_lwip_webserver +- Added new Audio example: audio_test uac2_headsest + +### New Boards + +- Espressif ESP32-S2: saola_1, kaluga_1 +- STM32: F746 Nucleo, H743 Eval, H743 Nucleo, F723 discovery, stlink v3 mini, STM32L4r5 Nucleo +- Dialog DA1469x dk pro and dk usb +- Microchip: Great Scoot Gadgets' LUNA, samd11_xplained, D5035-01, atsamd21 xplained pro +- nRF: ItsyBitsy nRF52840 + +## 0.6.0 - 2020.03.30 + +Added **CONTRIBUTORS.md** to give proper credit for contributors to the stack. Special thanks to [Nathan Conrad](https://github.com/pigrew), [Peter Lawrence](https://github.com/majbthrd) and [William D. Jones](https://github.com/cr1901) and others for spending their precious time to add lots of features and ports for this release. + +### Added + +**MCUs** + +- Added support for Microchip SAMG55 +- Added support for Nordic nRF52833 +- Added support for Nuvoton: NUC120, NUC121/NUC125, NUC126, NUC505 +- Added support for NXP LPC: 51Uxx, 54xxx, 55xx +- Added support for NXP iMXRT: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064 +- Added support for Sony CXD56 (Spresense) +- Added support for STM32: L0, F0, F1, F2, F3, F4, F7, H7 +- Added support for TI MSP430 +- Added support for ValentyUSB's eptri + +**Class Driver** + +- Added DFU Runtime class driver +- Added Network class driver with RNDIS, CDC-ECM, CDC-EEM (work in progress) +- Added USBTMC class driver +- Added WebUSB class driver using vendor-specific class +- Added multiple instances support for CDC and MIDI +- Added a handful of unit test with Ceedling. +- Added LOG support for debugging with CFG_TUSB_DEBUG +- Added `tud_descriptor_bos_cb()` for BOS descriptor (required for USB 2.1) +- Added `dcd_edpt0_status_complete()` as optional API for DCD + +**Examples** + +Following examples are added: + +- board_test +- cdc_dual_ports +- dfu_rt +- hid_composite +- net_lwip_webserver +- usbtmc +- webusb_serial + +**Boards** + +Following boards are added: + +- adafruit_clue +- arduino_nano33_ble +- circuitplayground_bluefruit +- circuitplayground_express +- feather_m0_express +- feather_nrf52840_sense +- feather_stm32f405 +- fomu +- itsybitsy_m0 +- itsybitsy_m4 +- lpcxpresso11u37 +- lpcxpresso1549 +- lpcxpresso51u68 +- lpcxpresso54114 +- lpcxpresso55s69 +- mbed1768 +- mimxrt1010_evk +- mimxrt1015_evk +- mimxrt1020_evk +- mimxrt1050_evkb +- mimxrt1060_evk +- mimxrt1064_evk +- msp_exp430f5529lp +- ngx4330 +- nrf52840_mdk_dongle +- nutiny_nuc121s +- nutiny_nuc125s +- nutiny_nuc126v +- nutiny_sdk_nuc120 +- nutiny_sdk_nuc505 +- pca10059 +- pca10100 +- pyboardv11 +- raytac_mdbt50q_rx +- samg55xplained +- seeeduino_xiao +- spresense +- stm32f070rbnucleo +- stm32f072disco +- stm32f103bluepill +- stm32f207nucleo +- stm32f401blackpill +- stm32f411blackpill +- stm32f411disco +- stm32f412disco +- stm32f767nucleo +- stm32h743nucleo +- stm32l0538disco +- stm32l476disco +- teensy_40 + +### Changed + +- Changed `tud_descriptor_string_cb()` to have additional Language ID argument +- Merged hal_nrf5x.c into dcd_nrf5x.c +- Merged dcd_samd21.c and dcd_samd51.c into dcd_samd.c +- Generalized dcd_stm32f4.c to dcd_synopsys.c +- Changed cdc_msc_hid to cdc_msc (drop hid) due to limited endpoints number of some MCUs +- Improved DCD SAMD stability, fix missing setup packet occasionally +- Improved usbd/usbd_control with proper hanlding of zero-length packet (ZLP) +- Improved STM32 DCD FSDev +- Improved STM32 DCD Synopsys +- Migrated CI from Travis to Github Action +- Updated nrfx submodule to 2.1.0 +- Fixed mynewt osal queue definition +- Fixed cdc_msc_freertos example build for all MCUs + +## 0.5.0 (Initial Release) - 2019.07.10 + +First release, device stack works great, host stack works but still need improvement. +- Special thanks to @adafruit team, especially @tannewt to help out immensely to rework device stack: simplify osal & control transfer, adding SAMD21/SAMD51 ports, writing porting docs, adding MIDI class support etc... +- Thanks to @cr1901 for adding STM32F4 port. +- Thanks to @PTS93 and @todbot for HID raw API diff --git a/src/tusb_option.h b/src/tusb_option.h index 6cbdefbf1..cafe9e522 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -28,7 +28,7 @@ #define _TUSB_OPTION_H_ #define TUSB_VERSION_MAJOR 0 -#define TUSB_VERSION_MINOR 8 +#define TUSB_VERSION_MINOR 9 #define TUSB_VERSION_REVISION 0 #define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION) -- cgit v1.3.1 From 4ee1216aaf8c0ea6cefb6f690e4a391fe06f1356 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 13 Mar 2021 00:22:04 +0700 Subject: fix fifo unlock typo, also clean up a bit --- src/common/tusb_fifo.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 4936d5e7d..dc74489f5 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -89,7 +89,7 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si f->rd_idx = f->wr_idx = 0; tu_fifo_unlock(f->mutex_wr); - tu_fifo_lock(f->mutex_rd); + tu_fifo_unlock(f->mutex_rd); return true; } @@ -104,9 +104,10 @@ static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) // Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address // Code adapted from dcd_synopsis.c -static void _tu_fifo_read_from_const_src_ptr(void * __restrict dst, const void * __restrict src, uint16_t len) +// TODO generalize with configurable 1 byte or 4 byte each read +static void _tu_fifo_read_from_const_src_ptr(void * dst, const void * src, uint16_t len) { - uint8_t CFG_TUSB_MEM_ALIGN * dst_u8 = (uint8_t *)dst; + uint8_t * dst_u8 = (uint8_t *)dst; volatile uint32_t * rx_fifo = (volatile uint32_t *) src; // Reading full available 32 bit words from FIFO @@ -136,15 +137,18 @@ static void _tu_fifo_read_from_const_src_ptr(void * __restrict dst, const void * // Intended to be used to write to hardware USB FIFO in e.g. STM32 where all data is written to a constant address // Code adapted from dcd_synopsis.c -static void _tu_fifo_write_to_const_dst_ptr(void * __restrict dst, const void * __restrict src, uint16_t len) +// TODO generalize with configurable 1 byte or 4 byte each write +static void _tu_fifo_write_to_const_dst_ptr(void * dst, const void * src, uint16_t len) { volatile uint32_t * tx_fifo = (volatile uint32_t *) dst; - uint8_t CFG_TUSB_MEM_ALIGN * src_u8 = (uint8_t *)src; + uint8_t * src_u8 = (uint8_t *)src; // Pushing full available 32 bit words to FIFO - uint16_t full_words = len >> 2; + uint16_t const full_words = len >> 2; for(uint16_t i = 0; i < full_words; i++){ - *tx_fifo = ((uint32_t)(src_u8[3]) << 24) | ((uint32_t)(src_u8[2]) << 16) | ((uint32_t)(src_u8[1]) << 8) | (uint32_t)src_u8[0]; + uint32_t temp32; + memcpy(&temp32, src_u8, 4); + *tx_fifo = temp32; src_u8 += 4; } @@ -200,12 +204,14 @@ static inline void _ff_pull_copy_fct(void * dst, const void * src, uint16_t len, // send n items to FIFO WITHOUT updating write pointer static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRel, tu_fifo_copy_mode_t copy_mode) { - if(wRel + n <= f->depth) // Linear mode only + if(wRel + n <= f->depth) { + // Linear mode only _ff_push_copy_fct(f->buffer + (wRel * f->item_size), data, n*f->item_size, copy_mode); } - else // Wrap around + else { + // Wrap around uint16_t nLin = f->depth - wRel; // Write data to linear part of buffer @@ -225,12 +231,14 @@ static inline void _ff_pull(tu_fifo_t* f, void * p_buffer, uint16_t rRel) // get n items from FIFO WITHOUT updating read pointer static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel, tu_fifo_copy_mode_t copy_mode) { - if(rRel + n <= f->depth) // Linear mode only + if(rRel + n <= f->depth) { + // Linear mode only _ff_pull_copy_fct(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size, copy_mode); } - else // Wrap around + else { + // Wrap around uint16_t nLin = f->depth - rRel; // Read data from linear part of buffer -- cgit v1.3.1 From cd491e296e0c8bce113d5474955d08f4c99b3099 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Mar 2021 18:55:16 +0100 Subject: Intermediate commit --- src/class/audio/audio_device.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 00d95ede5..73f265a8f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -206,6 +206,15 @@ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; extern const uint16_t tud_audio_desc_lengths[]; +// bSubslotSize for PCM encoding/decoding using support FIFOs +#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +extern const tud_audio_n_bytes_per_sample_tx[CFG_TUD_AUDIO][CFG_TUD_AUDIO_N_AS_INT]; +#endif + +#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +extern const tud_audio_n_bytes_per_sample_rx[CFG_TUD_AUDIO][CFG_TUD_AUDIO_N_AS_INT]; +#endif + #if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); #endif -- cgit v1.3.1 From 82e24306e2b0588e944476d71815f83ca392d1b9 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 16 Mar 2021 15:49:09 +0700 Subject: fix build with OPT_MCU_LPC177X_8X --- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 3 ++- src/portable/nxp/lpc17_40/dcd_lpc17_40.h | 6 +++--- src/portable/nxp/lpc17_40/hcd_lpc17_40.c | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 7d867aaba..519d09151 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -26,7 +26,8 @@ #include "tusb_option.h" -#if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC40XX) +#if TUSB_OPT_DEVICE_ENABLED && \ + (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX) #include "device/dcd.h" #include "dcd_lpc17_40.h" diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.h b/src/portable/nxp/lpc17_40/dcd_lpc17_40.h index 1e7c0fbc0..07daa32e4 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.h +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DCD_LPC175X_6X_H_ -#define _TUSB_DCD_LPC175X_6X_H_ +#ifndef _TUSB_DCD_LPC17_40_H_ +#define _TUSB_DCD_LPC17_40_H_ #include "common/tusb_common.h" @@ -149,4 +149,4 @@ enum { } #endif -#endif /* _TUSB_DCD_LPC175X_6X_H_ */ +#endif diff --git a/src/portable/nxp/lpc17_40/hcd_lpc17_40.c b/src/portable/nxp/lpc17_40/hcd_lpc17_40.c index 537b3daba..1c1faed94 100644 --- a/src/portable/nxp/lpc17_40/hcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/hcd_lpc17_40.c @@ -26,7 +26,8 @@ #include "tusb_option.h" -#if (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC40XX) +#if TUSB_OPT_HOST_ENABLED && \ + (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX) #include "chip.h" -- cgit v1.3.1 From 62d4652f86516e1fdd7fa79a29535cf39b2ab2f1 Mon Sep 17 00:00:00 2001 From: Michael Bruno Date: Tue, 16 Mar 2021 10:48:42 -0400 Subject: Update usbtmc_device.c Fix buffer alignment in TMC device class --- src/class/usbtmc/usbtmc_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 88776d169..6c9b42449 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -131,9 +131,9 @@ typedef struct uint8_t ep_int_in; // IN buffer is only used for first packet, not the remainder // in order to deal with prepending header - uint8_t ep_bulk_in_buf[USBTMCD_MAX_PACKET_SIZE]; + CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_in_buf[USBTMCD_MAX_PACKET_SIZE]; // OUT buffer receives one packet at a time - uint8_t ep_bulk_out_buf[USBTMCD_MAX_PACKET_SIZE]; + CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_out_buf[USBTMCD_MAX_PACKET_SIZE]; uint32_t transfer_size_remaining; // also used for requested length for bulk IN. uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes) -- cgit v1.3.1 From ec08dcf61a86686da101f480565c6fae2acc3359 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Wed, 17 Mar 2021 09:25:01 -0400 Subject: Implement requested changes for PR724 --- src/class/usbtmc/usbtmc_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 6c9b42449..d5f8fe41d 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -145,7 +145,7 @@ typedef struct usbtmc_capabilities_specific_t const * capabilities; } usbtmc_interface_state_t; -static usbtmc_interface_state_t usbtmc_state = +CFG_TUSB_MEM_SECTION static usbtmc_interface_state_t usbtmc_state = { .itf_id = 0xFF, }; -- cgit v1.3.1 From 64f41dea62ee48452c4b353cb34ddbd57a8fffad Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 18 Mar 2021 15:07:07 +0700 Subject: fix race condition that could cause drop packet of Bulk OUT transfer NRF_USBD->SIZE.EPOUT[epnum] only need to write once to enable Bulk/Interrupt transfer. We only need to do it in dcd_edpt_open() and dcd_edpt_clear_stall() --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 131 +++++++++++++++++----------------- 1 file changed, 66 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index d9fe2b6ae..6b8095a00 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -53,13 +53,11 @@ enum enum { - // Endpoint number is fixed (8) for ISOOUT and ISOIN. - EP_ISO_NUM = 8, - // CBI endpoints count - EP_COUNT = 8 + EP_ISO_NUM = 8, // Endpoint number is fixed (8) for ISOOUT and ISOIN + EP_CBI_COUNT = 8 // Control Bulk Interrupt endpoints count }; -// Transfer descriptor +// Transfer Descriptor typedef struct { uint8_t* buffer; @@ -67,9 +65,10 @@ typedef struct volatile uint16_t actual_len; uint16_t mps; // max packet size - // nrf52840 will auto ACK OUT packet after DMA is done + // nRF will auto accept OUT packet after DMA is done // indicate packet is already ACK volatile bool data_received; + // Set to true when data was transferred from RAM to ISO IN output buffer. // New data can be put in ISO IN output buffer after SOF. bool iso_in_transfer_ready; @@ -81,7 +80,7 @@ static struct { // All 8 endpoints including control IN & OUT (offset 1) // +1 for ISO endpoints - xfer_td_t xfer[EP_COUNT + 1][2]; + xfer_td_t xfer[EP_CBI_COUNT + 1][2]; // Number of pending DMA that is started but not handled yet by dcd_int_handler(). // Since nRF can only carry one DMA can run at a time, this value is normally be either 0 or 1. @@ -133,7 +132,7 @@ static void edpt_dma_start(volatile uint32_t* reg_startep) { ended = NRF_USBD->EVENTS_ENDISOIN + NRF_USBD->EVENTS_ENDISOOUT; - for (uint8_t i=0; iEVENTS_ENDEPIN[i] + NRF_USBD->EVENTS_ENDEPOUT[i]; } @@ -166,27 +165,6 @@ static inline xfer_td_t* get_td(uint8_t epnum, uint8_t dir) return &_dcd.xfer[epnum][dir]; } -/*------------- CBI OUT Transfer -------------*/ - -// Prepare for a CBI transaction OUT, call at the start -// Allow ACK incoming data -static void xact_out_prepare(uint8_t epnum) -{ - if ( epnum == 0 ) - { - NRF_USBD->TASKS_EP0RCVOUT = 1; - } - else - { - // Write zero value to SIZE register will allow hw to ACK (accept data) - // If it is not already done by DMA - // SIZE.ISOOUT can also be accessed this way - NRF_USBD->SIZE.EPOUT[epnum] = 0; - } - - __ISB(); __DSB(); -} - // Start DMA to move data from Endpoint -> RAM static void xact_out_dma(uint8_t epnum) { @@ -217,15 +195,14 @@ static void xact_out_dma(uint8_t epnum) edpt_dma_start(&NRF_USBD->TASKS_STARTEPOUT[epnum]); } + xfer->buffer += xact_len; xfer->actual_len += xact_len; } -/*------------- CBI IN Transfer -------------*/ - // Prepare for a CBI transaction IN, call at the start // it start DMA to transfer data from RAM -> Endpoint -static void xact_in_prepare(uint8_t epnum) +static void xact_in_dma(uint8_t epnum) { xfer_td_t* xfer = get_td(epnum, TUSB_DIR_IN); @@ -327,6 +304,9 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { NRF_USBD->INTENSET = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + epnum); NRF_USBD->EPOUTEN |= TU_BIT(epnum); + + // Write any value to SIZE register will allow nRF to ACK/accept data + NRF_USBD->SIZE.EPOUT[epnum] = 0; }else { NRF_USBD->INTENSET = TU_BIT(USBD_INTEN_ENDEPIN0_Pos + epnum); @@ -438,20 +418,31 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } else if ( dir == TUSB_DIR_OUT ) { - if ( xfer->data_received ) + if ( epnum == 0 ) { - // nrf52840 auto ACK OUT packet after DMA is done - // Data already received previously --> trigger DMA to copy to SRAM - xact_out_dma(epnum); - } - else + // Accept next Control Out packet + NRF_USBD->TASKS_EP0RCVOUT = 1; + }else { - xact_out_prepare(epnum); + if ( xfer->data_received ) + { + // Data may already be received previously + xfer->data_received = false; + + // start DMA to copy to SRAM + xact_out_dma(epnum); + } + else + { + // nRF auto accept next Bulk/Interrupt OUT packet + // nothing to do + } } } else { - xact_in_prepare(epnum); + // Start DMA to copy data from RAM -> Endpoint + xact_in_dma(epnum); } return true; @@ -477,6 +468,7 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); if ( epnum != 0 && epnum != EP_ISO_NUM ) { @@ -486,6 +478,10 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) // reset data toggle to DATA0 NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | ep_addr; + // Write any value to SIZE register will allow nRF to ACK/accept data + // Drop any pending data + if (dir == TUSB_DIR_OUT) NRF_USBD->SIZE.EPOUT[epnum] = 0; + __ISB(); __DSB(); } } @@ -594,17 +590,18 @@ void dcd_int_handler(uint8_t rhport) // Setup tokens are specific to the Control endpoint. if ( int_status & USBD_INTEN_EP0SETUP_Msk ) { - uint8_t const setup[8] = { - NRF_USBD->BMREQUESTTYPE , NRF_USBD->BREQUEST, NRF_USBD->WVALUEL , NRF_USBD->WVALUEH, - NRF_USBD->WINDEXL , NRF_USBD->WINDEXH , NRF_USBD->WLENGTHL, NRF_USBD->WLENGTHH + uint8_t const setup[8] = + { + NRF_USBD->BMREQUESTTYPE , NRF_USBD->BREQUEST, NRF_USBD->WVALUEL , NRF_USBD->WVALUEH, + NRF_USBD->WINDEXL , NRF_USBD->WINDEXH , NRF_USBD->WLENGTHL, NRF_USBD->WLENGTHH }; // nrf5x hw auto handle set address, there is no need to inform usb stack tusb_control_request_t const * request = (tusb_control_request_t const *) setup; - if ( !(TUSB_REQ_RCPT_DEVICE == request->bmRequestType_bit.recipient && + if ( !(TUSB_REQ_RCPT_DEVICE == request->bmRequestType_bit.recipient && TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_SET_ADDRESS == request->bRequest) ) + TUSB_REQ_SET_ADDRESS == request->bRequest) ) { dcd_event_setup_received(0, setup, true); } @@ -620,15 +617,15 @@ void dcd_int_handler(uint8_t rhport) * For CBI OUT: * - Host -> Endpoint * EPDATA (or EP0DATADONE) interrupted, check EPDATASTATUS.EPOUT[i] - * to start DMA. This step can occur automatically (without sw), - * which means data may or may not ready (data_received flag). + * to start DMA. For Bulk/Interrupt, this step can occur automatically (without sw), + * which means data may or may not be ready (data_received flag). * - Endpoint -> RAM * ENDEPOUT[i] interrupted, transaction complete, sw prepare next transaction * * For CBI IN: * - RAM -> Endpoint * ENDEPIN[i] interrupted indicate DMA is complete. HW will start - * to move daat to host + * to move data to host * - Endpoint -> Host * EPDATA (or EP0DATADONE) interrupted, check EPDATASTATUS.EPIN[i]. * Transaction is complete, sw prepare next transaction @@ -640,27 +637,31 @@ void dcd_int_handler(uint8_t rhport) /* CBI OUT: Endpoint -> SRAM (aka transaction complete) * Note: Since nRF controller auto ACK next packet without SW awareness - * We must handle this stage before Host -> Endpoint just in case - * 2 event happens at once - * ISO OUT: Transaction must fit in single packed, it can be shorter then total + * We must handle this stage before Host -> Endpoint just in case 2 event happens at once + * + * ISO OUT: Transaction must fit in single packet, it can be shorter then total * len if Host decides to sent fewer bytes, it this case transaction is also * complete and next transfer is not initiated here like for CBI. */ - for(uint8_t epnum=0; epnumEPOUT[epnum].AMOUNT; - // Data in endpoint has been consumed - xfer->data_received = false; - // Transfer complete if transaction len < Max Packet Size or total len is transferred if ( (epnum != EP_ISO_NUM) && (xact_len == xfer->mps) && (xfer->actual_len < xfer->total_len) ) { - // Prepare for next transaction - xact_out_prepare(epnum); + if ( epnum == 0 ) + { + // Accept next Control Out packet + NRF_USBD->TASKS_EP0RCVOUT = 1; + }else + { + // nRF auto accept next Bulk/Interrupt OUT packet + // nothing to do + } }else { xfer->total_len = xfer->actual_len; @@ -673,7 +674,7 @@ void dcd_int_handler(uint8_t rhport) // Ended event for CBI IN : nothing to do } - // Endpoint <-> Host + // Endpoint <-> Host ( In & OUT ) if ( int_status & (USBD_INTEN_EPDATA_Msk | USBD_INTEN_EP0DATADONE_Msk) ) { uint32_t data_status = NRF_USBD->EPDATASTATUS; @@ -687,9 +688,9 @@ void dcd_int_handler(uint8_t rhport) bool const is_control_out = (int_status & USBD_INTEN_EP0DATADONE_Msk) && !(NRF_USBD->BMREQUESTTYPE & TUSB_DIR_IN_MASK); // CBI In: Endpoint -> Host (transaction complete) - for(uint8_t epnum=0; epnum<8; epnum++) + for(uint8_t epnum=0; epnumactual_len < xfer->total_len ) { - // prepare next transaction - xact_in_prepare(epnum); + // Start DMA to copy next data packet + xact_in_dma(epnum); } else { // CBI IN complete @@ -708,9 +709,9 @@ void dcd_int_handler(uint8_t rhport) } // CBI OUT: Host -> Endpoint - for(uint8_t epnum=0; epnum<8; epnum++) + for(uint8_t epnum=0; epnumdata_received = true; } -- cgit v1.3.1 From a60bd0c8ac374e9d96fd7248503cf822306547d8 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 23 Mar 2021 19:33:04 +0100 Subject: Fix bug in writing to constant src/dst address. Copying has to be conduct in full words (at least for STM32). Renamed copy function to tu_fifo_write_n_const_addr_full_words() --- src/common/tusb_fifo.c | 201 ++++++++++++++++++--------- src/common/tusb_fifo.h | 4 +- src/portable/espressif/esp32s2/dcd_esp32s2.c | 4 +- src/portable/microchip/samg/dcd_samg.c | 4 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 4 +- src/portable/st/synopsys/dcd_synopsys.c | 6 +- 6 files changed, 149 insertions(+), 74 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index dc74489f5..7d5453850 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -68,7 +68,7 @@ static void tu_fifo_unlock(tu_fifo_mutex_t mutex) typedef enum { TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode - TU_FIFO_COPY_CST, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO + TU_FIFO_COPY_CST_FULL_WORDS, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO } tu_fifo_copy_mode_t; bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) @@ -105,7 +105,7 @@ static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) // Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address // Code adapted from dcd_synopsis.c // TODO generalize with configurable 1 byte or 4 byte each read -static void _tu_fifo_read_from_const_src_ptr(void * dst, const void * src, uint16_t len) +static void _tu_fifo_read_from_const_src_ptr_in_full_words(void * dst, const void * src, uint16_t len) { uint8_t * dst_u8 = (uint8_t *)dst; volatile uint32_t * rx_fifo = (volatile uint32_t *) src; @@ -138,7 +138,7 @@ static void _tu_fifo_read_from_const_src_ptr(void * dst, const void * src, uint1 // Intended to be used to write to hardware USB FIFO in e.g. STM32 where all data is written to a constant address // Code adapted from dcd_synopsis.c // TODO generalize with configurable 1 byte or 4 byte each write -static void _tu_fifo_write_to_const_dst_ptr(void * dst, const void * src, uint16_t len) +static void _tu_fifo_write_to_const_dst_ptr_in_full_words(void * dst, const void * src, uint16_t len) { volatile uint32_t * tx_fifo = (volatile uint32_t *) dst; uint8_t * src_u8 = (uint8_t *)src; @@ -173,55 +173,80 @@ static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t wRel) memcpy(f->buffer + (wRel * f->item_size), data, f->item_size); } -static inline void _ff_push_copy_fct(void * dst, const void * src, uint16_t len, tu_fifo_copy_mode_t copy_mode) -{ - switch (copy_mode) - { - case TU_FIFO_COPY_INC: - memcpy(dst, src, len); - break; - - case TU_FIFO_COPY_CST: - _tu_fifo_read_from_const_src_ptr(dst, src, len); - break; - } -} - -static inline void _ff_pull_copy_fct(void * dst, const void * src, uint16_t len, tu_fifo_copy_mode_t copy_mode) +// send n items to FIFO WITHOUT updating write pointer +static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRel, tu_fifo_copy_mode_t copy_mode) { switch (copy_mode) { case TU_FIFO_COPY_INC: - memcpy(dst, src, len); + if(n <= f->depth-wRel) + { + // Linear mode only + memcpy(f->buffer + (wRel * f->item_size), data, n*f->item_size); + } + else + { + // Wrap around + uint16_t nLin = f->depth - wRel; + + // Write data to linear part of buffer + memcpy(f->buffer + (wRel * f->item_size), data, nLin*f->item_size); + + // Write data wrapped around + memcpy(f->buffer, ((uint8_t const*) data) + nLin*f->item_size, (n - nLin) * f->item_size); + } break; - case TU_FIFO_COPY_CST: - _tu_fifo_write_to_const_dst_ptr(dst, src, len); + case TU_FIFO_COPY_CST_FULL_WORDS: // Intended for hardware buffers from which it can be read word by word only + if(n <= f->depth-wRel) + { + // Linear mode only + _tu_fifo_read_from_const_src_ptr_in_full_words(f->buffer + (wRel * f->item_size), data, n*f->item_size); + } + else + { + // Wrap around case + uint16_t nLin = (f->depth - wRel) * f->item_size; + uint16_t nWrap = (n - nLin) * f->item_size; + + uint8_t * dst_u8 = (uint8_t *)(f->buffer + (wRel * f->item_size)); + volatile uint32_t * rx_fifo = (volatile uint32_t *) data; + CFG_TUSB_MEM_ALIGN uint32_t tmp; + + // Write full words of linear part to buffer + uint16_t full_words = nLin >> 2; + for(uint16_t i = 0; i < full_words; i++) { + tmp = *rx_fifo; + memcpy(dst_u8, &tmp, 4); + // dst_u8[0] = tmp & 0x000000FF; + // dst_u8[1] = (tmp & 0x0000FF00) >> 8; + // dst_u8[2] = (tmp & 0x00FF0000) >> 16; + // dst_u8[3] = (tmp & 0xFF000000) >> 24; + dst_u8 += 4; + } + + // Handle wrap around + uint8_t rem = nLin - (full_words << 2); + uint8_t remrem = 0; + if (rem > 0) + { + tmp = *rx_fifo; + memcpy(dst_u8, &tmp, rem); + remrem = tu_min16(nWrap, 4-rem); + memcpy(f->buffer, ((uint8_t *) &tmp) + rem, remrem); + nWrap -= remrem; + } + + // Final part + if (nWrap > 0) + { + _tu_fifo_read_from_const_src_ptr_in_full_words(f->buffer + remrem, data, nWrap); + } + } break; } } -// send n items to FIFO WITHOUT updating write pointer -static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRel, tu_fifo_copy_mode_t copy_mode) -{ - if(wRel + n <= f->depth) - { - // Linear mode only - _ff_push_copy_fct(f->buffer + (wRel * f->item_size), data, n*f->item_size, copy_mode); - } - else - { - // Wrap around - uint16_t nLin = f->depth - wRel; - - // Write data to linear part of buffer - _ff_push_copy_fct(f->buffer + (wRel * f->item_size), data, nLin*f->item_size, copy_mode); - - // Write data wrapped around - _ff_push_copy_fct(f->buffer, ((uint8_t const*) data) + nLin*f->item_size, (n - nLin) * f->item_size, copy_mode); - } -} - // get one item from FIFO WITHOUT updating read pointer static inline void _ff_pull(tu_fifo_t* f, void * p_buffer, uint16_t rRel) { @@ -231,24 +256,74 @@ static inline void _ff_pull(tu_fifo_t* f, void * p_buffer, uint16_t rRel) // get n items from FIFO WITHOUT updating read pointer static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel, tu_fifo_copy_mode_t copy_mode) { - if(rRel + n <= f->depth) - { - // Linear mode only - _ff_pull_copy_fct(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size, copy_mode); - } - else + switch (copy_mode) { - // Wrap around - uint16_t nLin = f->depth - rRel; - - // Read data from linear part of buffer - _ff_pull_copy_fct(p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size, copy_mode); + case TU_FIFO_COPY_INC: + if(n <= f->depth-rRel) + { + // Linear mode only + memcpy(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); + } + else + { + // Wrap around + uint16_t nLin = f->depth - rRel; + + // Read data from linear part of buffer + memcpy(p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size); + + // Read data wrapped part + memcpy((uint8_t*)p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size); + } + break; - // Read data wrapped part - _ff_pull_copy_fct((uint8_t*)p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size, copy_mode); + case TU_FIFO_COPY_CST_FULL_WORDS: + + if(n <= f->depth-rRel) + { + // Linear mode only + _tu_fifo_write_to_const_dst_ptr_in_full_words(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); + } + else + { + // Wrap around case + uint16_t nLin = (f->depth - rRel) * f->item_size; + uint16_t nWrap = (n - nLin) * f->item_size; + + volatile uint32_t * tx_fifo = (volatile uint32_t *) p_buffer; + uint8_t * src_u8 = f->buffer + (rRel * f->item_size); + CFG_TUSB_MEM_ALIGN uint32_t tmp; + + // Pushing full available 32 bit words to FIFO + uint16_t const full_words = nLin >> 2; + for(uint16_t i = 0; i < full_words; i++){ + memcpy(&tmp, src_u8, 4); + *tx_fifo = tmp; + src_u8 += 4; + } + + // Handle wrap around + uint8_t rem = nLin - (full_words << 2); + uint8_t remrem = 0; + if (rem > 0) + { + tmp = 0; + memcpy(&tmp, src_u8, rem); + remrem = tu_min16(nWrap, 4-rem); + memcpy(((uint8_t *) &tmp) + rem, f->buffer, remrem); + nWrap -= remrem; + *tx_fifo = tmp; + } + + // Final part + if (nWrap > 0) + { + _tu_fifo_write_to_const_dst_ptr_in_full_words(p_buffer, f->buffer + remrem, nWrap); + } + } + break; } } - // Advance an absolute pointer static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) { @@ -599,9 +674,9 @@ uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n) return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_INC); } -uint16_t tu_fifo_read_n_const_addr(tu_fifo_t* f, void * buffer, uint16_t n) +uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint16_t n) { - return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_CST); + return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_CST_FULL_WORDS); } /******************************************************************************/ @@ -723,9 +798,9 @@ uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n) @return Number of written elements */ /******************************************************************************/ -uint16_t tu_fifo_write_n_const_addr(tu_fifo_t* f, const void * data, uint16_t n) +uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t* f, const void * data, uint16_t n) { - return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_CST); + return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_CST_FULL_WORDS); } /******************************************************************************/ @@ -756,7 +831,7 @@ bool tu_fifo_clear(tu_fifo_t *f) Pointer to the FIFO buffer to manipulate @param[in] overwritable Overwritable mode the fifo is set to -*/ + */ /******************************************************************************/ bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { @@ -877,7 +952,7 @@ void tu_fifo_backward_read_pointer(tu_fifo_t *f, uint16_t n) Number of ITEMS to read from buffer @return len Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid -*/ + */ /******************************************************************************/ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n) { @@ -948,7 +1023,7 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, Number of ITEMS to write into buffer @return len Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid -*/ + */ /******************************************************************************/ uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n) { diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 4b4fe92ba..93ed6095d 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -109,11 +109,11 @@ static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mute bool tu_fifo_write (tu_fifo_t* f, void const * p_data); uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t n); -uint16_t tu_fifo_write_n_const_addr (tu_fifo_t* f, const void * data, uint16_t n); +uint16_t tu_fifo_write_n_const_addr_full_words (tu_fifo_t* f, const void * data, uint16_t n); bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); -uint16_t tu_fifo_read_n_const_addr (tu_fifo_t* f, void * buffer, uint16_t n); +uint16_t tu_fifo_read_n_const_addr_full_words (tu_fifo_t* f, void * buffer, uint16_t n); bool tu_fifo_peek_at (tu_fifo_t* f, uint16_t pos, void * p_buffer); uint16_t tu_fifo_peek_at_n (tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n); diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index eb2c05153..28a3bcd07 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -517,7 +517,7 @@ static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ if (xfer->ff) { // Ring buffer - tu_fifo_write_n_const_addr(xfer->ff, (const void *) rx_fifo, to_recv_size); + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, to_recv_size); } else { @@ -573,7 +573,7 @@ static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, if (xfer->ff) { - tu_fifo_read_n_const_addr(xfer->ff, (void *) tx_fifo, to_xfer_size); + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, to_xfer_size); } else { diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 07ab9e83f..8b5bebf85 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -437,7 +437,7 @@ void dcd_int_handler(uint8_t rhport) // write to EP fifo if (xfer->ff) { - tu_fifo_read_n_const_addr(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len); + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len); } else { @@ -470,7 +470,7 @@ void dcd_int_handler(uint8_t rhport) // Read from EP fifo if (xfer->ff) { - tu_fifo_write_n_const_addr(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len); + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len); } else { diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 5d15ca962..67693e335 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -183,7 +183,7 @@ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) /* provided buffers are thankfully 32-bit aligned, allowing most data to be transfered as 32-bit */ if (xfer->ff) { - tu_fifo_read_n_const_addr(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now); + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now); } else { @@ -657,7 +657,7 @@ void dcd_int_handler(uint8_t rhport) /* copy the data from the PC to the previously provided buffer */ if (xfer->ff) { - tu_fifo_write_n_const_addr(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far)); + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far)); } else { diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index e2390fe57..aa927d5a4 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -902,7 +902,7 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ if (xfer->ff) { // Ring buffer - tu_fifo_write_n_const_addr(xfer->ff, (const void *) rx_fifo, bcnt); + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, bcnt); } else { @@ -1008,7 +1008,7 @@ static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OT // Process every single packet (only whole packets can be written to fifo) for(uint16_t i = 0; i < remaining_packets; i++){ - uint16_t remaining_bytes = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos; + volatile uint16_t remaining_bytes = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos; // Packet can not be larger than ep max size uint16_t packet_size = tu_min16(remaining_bytes, xfer->max_size); @@ -1022,7 +1022,7 @@ static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OT if (xfer->ff) { usb_fifo_t tx_fifo = FIFO_BASE(rhport, n); - tu_fifo_read_n_const_addr(xfer->ff, (void *) tx_fifo, packet_size); + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, packet_size); } else { -- cgit v1.3.1 From 143582870c8a4175706109e238f4cfa814ae90bc Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Thu, 4 Mar 2021 23:00:48 +0000 Subject: add efm32gg12 family Signed-off-by: Rafael Silva --- hw/bsp/board_mcu.h | 3 +++ src/tusb_option.h | 5 +++++ 2 files changed, 8 insertions(+) (limited to 'src') diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index a175197e5..3c18f6d3d 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -119,6 +119,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_RP2040 #include "pico.h" + +#elif CFG_TUSB_MCU == OPT_MCU_EFM32GG || CFG_TUSB_MCU == OPT_MCU_EFM32GG11 || CFG_TUSB_MCU == OPT_MCU_EFM32GG12 + #include "em_device.h" #else #error "Missing MCU header" diff --git a/src/tusb_option.h b/src/tusb_option.h index cafe9e522..d0ed78acd 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -103,6 +103,11 @@ // NXP Kinetis #define OPT_MCU_MKL25ZXX 1200 ///< NXP MKL25Zxx +// Silabs +#define OPT_MCU_EFM32GG 1300 ///< Silabs EFM32GG +#define OPT_MCU_EFM32GG11 1301 ///< Silabs EFM32GG11 +#define OPT_MCU_EFM32GG12 1302 ///< Silabs EFM32GG12 + /** @} */ /** \defgroup group_supported_os Supported RTOS -- cgit v1.3.1 From 2807644e7e72150b96be0f40a263f689a6de994a Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Thu, 4 Mar 2021 23:02:42 +0000 Subject: add efm32 driver Signed-off-by: Rafael Silva --- src/portable/silabs/efm32/dcd_efm32.c | 931 ++++++++++++++++++++++++++++++++++ 1 file changed, 931 insertions(+) create mode 100644 src/portable/silabs/efm32/dcd_efm32.c (limited to 'src') diff --git a/src/portable/silabs/efm32/dcd_efm32.c b/src/portable/silabs/efm32/dcd_efm32.c new file mode 100644 index 000000000..bd1f32e6b --- /dev/null +++ b/src/portable/silabs/efm32/dcd_efm32.c @@ -0,0 +1,931 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Rafael Silva (@perigoso) + * Copyright (c) 2021 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && ( \ + (CFG_TUSB_MCU == OPT_MCU_EFM32GG) || \ + (CFG_TUSB_MCU == OPT_MCU_EFM32GG11) || \ + (CFG_TUSB_MCU == OPT_MCU_EFM32GG12) ) + +/* Silabs */ +#include "em_device.h" + +#include "device/dcd.h" + +/* + * Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) + * We disable SOF for now until needed later on + */ +#define USE_SOF 0 + +/* + * Number of endpoints + * 12 software-configurable endpoints (6 IN, 6 OUT) in addition to endpoint 0 + */ +#define EP_COUNT 7 + +/* FIFO size in bytes */ +#define EP_FIFO_SIZE 2048 + +/* Max number of IN EP FIFOs */ +#define EP_FIFO_NUM 7 + +/* */ +typedef struct { + uint8_t *buffer; + uint16_t total_len; + uint16_t queued_len; + uint16_t max_size; + bool short_packet; +} xfer_ctl_t; + +static uint32_t _setup_packet[2]; + +#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] +static xfer_ctl_t xfer_status[EP_COUNT][2]; + +/* Keep count of how many FIFOs are in use */ +static uint8_t _allocated_fifos = 1; /* FIFO0 is always in use */ + +static volatile uint32_t* tx_fifo[EP_FIFO_NUM] = { + USB->FIFO0D, + USB->FIFO1D, + USB->FIFO2D, + USB->FIFO3D, + USB->FIFO4D, + USB->FIFO5D, + USB->FIFO6D, +}; + +/* Register Helpers */ +#define DCTL_WO_BITMASK (USB_DCTL_CGOUTNAK | USB_DCTL_SGOUTNAK | USB_DCTL_CGNPINNAK | USB_DCTL_SGNPINNAK) +#define GUSBCFG_WO_BITMASK (USB_GUSBCFG_CORRUPTTXPKT) +#define DEPCTL_WO_BITMASK (USB_DIEP_CTL_CNAK | USB_DIEP_CTL_SNAK | USB_DIEP_CTL_SETD0PIDEF | USB_DIEP_CTL_SETD1PIDOF) + +/* Will either return an unused FIFO number, or 0 if all are used. */ +static uint8_t get_free_fifo(void) +{ + if(_allocated_fifos < EP_FIFO_NUM) return _allocated_fifos++; + return 0; +} + +/* +static void flush_rx_fifo(void) +{ + USB->GRSTCTL = USB_GRSTCTL_RXFFLSH; + while(USB->GRSTCTL & USB_GRSTCTL_RXFFLSH); +} +*/ + +static void flush_tx_fifo(uint8_t fifo_num) +{ + USB->GRSTCTL = USB_GRSTCTL_TXFFLSH | (fifo_num << _USB_GRSTCTL_TXFNUM_SHIFT); + while(USB->GRSTCTL & USB_GRSTCTL_TXFFLSH); +} + +/* Setup the control endpoint 0. */ +static void bus_reset(void) +{ + USB->DOEP0CTL |= USB_DIEP_CTL_SNAK; + for(uint8_t i = 0; i < EP_COUNT - 1; i++) + { + USB->DOEP[i].CTL |= USB_DIEP_CTL_SNAK; + } + + /* reset address */ + USB->DCFG &= ~_USB_DCFG_DEVADDR_MASK; + + USB->DAINTMSK |= USB_DAINTMSK_OUTEPMSK0 | USB_DAINTMSK_INEPMSK0; + USB->DOEPMSK |= USB_DOEPMSK_SETUPMSK | USB_DOEPMSK_XFERCOMPLMSK; + USB->DIEPMSK |= USB_DIEPMSK_TIMEOUTMSK | USB_DIEPMSK_XFERCOMPLMSK; + + /* + * - All EP OUT shared a unique OUT FIFO which uses + * * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets). + * * 2 locations for OUT endpoint control words. + * * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) + * * 1 location for global NAK (not required/used here). + * * It is recommended to allocate 2 times the largest packet size, therefore + * Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 + */ + flush_tx_fifo(_USB_GRSTCTL_TXFNUM_FALL); // Flush All + USB->GRXFSIZ = 52; + + /* Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) */ + USB->GNPTXFSIZ = (16 << _USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_SHIFT) | (USB->GRXFSIZ & _USB_GNPTXFSIZ_NPTXFSTADDR_MASK); + + /* Ready to receive SETUP packet */ + USB->DOEP0TSIZ |= (1 << _USB_DOEP0TSIZ_SUPCNT_SHIFT); + + USB->GINTMSK |= USB_GINTMSK_IEPINTMSK | USB_GINTMSK_OEPINTMSK; +} + +static void enum_done_processing(void) +{ + /* Maximum packet size for EP 0 is set for both directions by writing DIEPCTL */ + if((USB->DSTS & _USB_DSTS_ENUMSPD_MASK) == USB_DSTS_ENUMSPD_FS) + { + /* Full Speed (PHY on 48 MHz) */ + USB->DOEP0CTL = (USB->DOEP0CTL & ~_USB_DOEP0CTL_MPS_MASK) | _USB_DOEP0CTL_MPS_64B; /* Maximum Packet Size 64 bytes */ + USB->DOEP0CTL &= ~_USB_DOEP0CTL_STALL_MASK; /* clear Stall */ + xfer_status[0][TUSB_DIR_OUT].max_size = 64; + xfer_status[0][TUSB_DIR_IN].max_size = 64; + } + else + { + /* Low Speed (PHY on 6 MHz) */ + USB->DOEP0CTL = (USB->DOEP0CTL & ~_USB_DOEP0CTL_MPS_MASK) | _USB_DOEP0CTL_MPS_8B; /* Maximum Packet Size 64 bytes */ + USB->DOEP0CTL &= ~_USB_DOEP0CTL_STALL_MASK; /* clear Stall */ + xfer_status[0][TUSB_DIR_OUT].max_size = 8; + xfer_status[0][TUSB_DIR_IN].max_size = 8; + } +} + + +/*------------------------------------------------------------------*/ +/* Controller API */ +/*------------------------------------------------------------------*/ +void dcd_init(uint8_t rhport) +{ + (void) rhport; + + /* Reset Core */ + USB->PCGCCTL &= ~USB_PCGCCTL_STOPPCLK; + USB->PCGCCTL &= ~(USB_PCGCCTL_PWRCLMP | USB_PCGCCTL_RSTPDWNMODULE); + + /* Core Soft Reset */ + USB->GRSTCTL |= USB_GRSTCTL_CSFTRST; + while(USB->GRSTCTL & USB_GRSTCTL_CSFTRST); + + while(!(USB->GRSTCTL & USB_GRSTCTL_AHBIDLE)); + + /* Enable PHY pins */ + USB->ROUTE = USB_ROUTE_PHYPEN; + + dcd_disconnect(rhport); + + /* + * Set device speed (Full speed PHY) + * Stall on non-zero len status OUT packets (ctrl transfers) + * periodic frame interval to 80% + */ + USB->DCFG = (USB->DCFG & ~(_USB_DCFG_DEVSPD_MASK | _USB_DCFG_PERFRINT_MASK)) | USB_DCFG_DEVSPD_FS | USB_DCFG_NZSTSOUTHSHK; + + /* Enable Global Interrupts */ + USB->GAHBCFG = (USB->GAHBCFG & ~_USB_GAHBCFG_HBSTLEN_MASK) | USB_GAHBCFG_GLBLINTRMSK; + + /* Force Device Mode */ + USB->GUSBCFG = (USB->GUSBCFG & ~(GUSBCFG_WO_BITMASK | USB_GUSBCFG_FORCEHSTMODE)) | USB_GUSBCFG_FORCEDEVMODE; + + /* No Overrides */ + USB->GOTGCTL &= ~(USB_GOTGCTL_BVALIDOVVAL | USB_GOTGCTL_BVALIDOVEN | USB_GOTGCTL_VBVALIDOVVAL); + + /* Ignore frame numbers on ISO transfers. */ + USB->DCTL = (USB->DCTL & ~DCTL_WO_BITMASK) | USB_DCTL_IGNRFRMNUM; + + /* Setting SNAKs */ + USB->DOEP0CTL |= USB_DIEP_CTL_SNAK; + for(uint8_t i = 0; i < EP_COUNT - 1; i++) + { + USB->DOEP[i].CTL |= USB_DIEP_CTL_SNAK; + } + + /* D. Interruption masking */ + /* Disable all device interrupts */ + USB->DIEPMSK = 0; + USB->DOEPMSK = 0; + USB->DAINTMSK = 0; + USB->DIEPEMPMSK = 0; + USB->GINTMSK = 0; + USB->GOTGINT = ~0U; /* clear OTG ints */ + USB->GINTSTS = ~0U; /* clear pending ints */ + USB->GINTMSK = USB_GINTMSK_MODEMISMSK | + #if USE_SOF + USB_GINTMSK_SOFMSK | + #endif + USB_GINTMSK_ERLYSUSPMSK | + USB_GINTMSK_USBSUSPMSK | + USB_GINTMSK_USBRSTMSK | + USB_GINTMSK_ENUMDONEMSK | + USB_GINTMSK_RESETDETMSK | + USB_GINTMSK_DISCONNINTMSK; + + NVIC_ClearPendingIRQ(USB_IRQn); + + dcd_connect(rhport); +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void) rhport; + + USB->DCFG = (USB->DCFG & ~_USB_DCFG_DEVADDR_MASK) | (dev_addr << _USB_DCFG_DEVADDR_SHIFT); + + /* Response with status after changing device address */ + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; +} + +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + + /* connect by enabling internal pull-up resistor on D+/D- */ + USB->DCTL &= ~(DCTL_WO_BITMASK | USB_DCTL_SFTDISCON); +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + + /* disconnect by disabling internal pull-up resistor on D+/D- */ + USB->DCTL = (USB->DCTL & ~(DCTL_WO_BITMASK)) | USB_DCTL_SFTDISCON; +} + +/*------------------------------------------------------------------*/ +/* DCD Endpoint Port */ +/*------------------------------------------------------------------*/ +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if(dir == TUSB_DIR_IN) + { + if(epnum == 0) + { + USB->DIEP0CTL = (USB->DIEP0CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP0CTL_SNAK | USB_DIEP0CTL_STALL; + + flush_tx_fifo(_USB_GRSTCTL_TXFNUM_F0); + } + else + { + /* Only disable currently enabled non-control endpoint */ + if(USB->DIEP[epnum - 1].CTL & USB_DIEP_CTL_EPENA) + { + USB->DIEP[epnum - 1].CTL = (USB->DIEP[epnum - 1].CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP_CTL_EPDIS | USB_DIEP_CTL_SNAK | USB_DIEP_CTL_STALL; + while(!(USB->DIEP[epnum - 1].INT & USB_DIEP_INT_EPDISBLD)); + USB->DIEP[epnum - 1].INT |= USB_DIEP_INT_EPDISBLD; + } + else + { + USB->DIEP[epnum - 1].CTL = (USB->DIEP[epnum - 1].CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP_CTL_SNAK | USB_DIEP_CTL_STALL; + } + + /* Flush the FIFO */ + uint8_t const fifo_num = ((USB->DIEP[epnum - 1].CTL & _USB_DIEP_CTL_TXFNUM_MASK) >> _USB_DIEP_CTL_TXFNUM_SHIFT); + flush_tx_fifo(fifo_num); + } + } + else + { + if(epnum == 0) + { + USB->DOEP0CTL = (USB->DOEP0CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP0CTL_STALL; + } + else + { + /* Only disable currently enabled non-control endpoint */ + if(USB->DOEP[epnum - 1].CTL & USB_DIEP_CTL_EPENA) + { + /* Asserting GONAK is required to STALL an OUT endpoint. */ + USB->DCTL |= USB_DCTL_SGOUTNAK; + while(!(USB->GINTSTS & USB_GINTSTS_GOUTNAKEFF)); + + /* Disable the endpoint. Note that only STALL and not SNAK is set here. */ + USB->DOEP[epnum - 1].CTL = (USB->DOEP[epnum - 1].CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP_CTL_EPDIS | USB_DIEP_CTL_STALL; + while(USB->DOEP[epnum - 1].INT & USB_DIEP_INT_EPDISBLD); + USB->DOEP[epnum - 1].INT |= USB_DIEP_INT_EPDISBLD; + + /* Allow other OUT endpoints to keep receiving. */ + USB->DCTL |= USB_DCTL_CGOUTNAK; + } + else + { + USB->DIEP[epnum - 1].CTL = (USB->DIEP[epnum - 1].CTL & ~DEPCTL_WO_BITMASK) | USB_DIEP_CTL_STALL; + } + } + } +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if(dir == TUSB_DIR_IN) + { + if(epnum == 0) + { + USB->DIEP0CTL &= ~(DEPCTL_WO_BITMASK | USB_DIEP0CTL_STALL); + } + else + { + USB->DIEP[epnum - 1].CTL &= ~(DEPCTL_WO_BITMASK | USB_DIEP_CTL_STALL); + + /* Required by USB spec to reset DATA toggle bit to DATA0 on interrupt and bulk endpoints. */ + uint8_t eptype = (USB->DIEP[epnum - 1].CTL & _USB_DIEP_CTL_EPTYPE_MASK) >> _USB_DIEP_CTL_EPTYPE_SHIFT; + + if((eptype == _USB_DIEP_CTL_EPTYPE_BULK) || (eptype == _USB_DIEP_CTL_EPTYPE_INT)) + { + USB->DIEP[epnum - 1].CTL |= USB_DIEP_CTL_SETD0PIDEF; + } + } + } + else + { + if(epnum == 0) + { + USB->DOEP0CTL &= ~(DEPCTL_WO_BITMASK | USB_DOEP0CTL_STALL); + } + else + { + USB->DOEP[epnum - 1].CTL &= ~(DEPCTL_WO_BITMASK | USB_DOEP_CTL_STALL); + + /* Required by USB spec to reset DATA toggle bit to DATA0 on interrupt and bulk endpoints. */ + uint8_t eptype = (USB->DOEP[epnum - 1].CTL & _USB_DOEP_CTL_EPTYPE_MASK) >> _USB_DOEP_CTL_EPTYPE_SHIFT; + + if((eptype == _USB_DOEP_CTL_EPTYPE_BULK) || (eptype == _USB_DOEP_CTL_EPTYPE_INT)) + { + USB->DOEP[epnum - 1].CTL |= USB_DOEP_CTL_SETD0PIDEF; + } + } + } +} + +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) +{ + (void)rhport; + + uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); + + TU_ASSERT(p_endpoint_desc->wMaxPacketSize.size <= 64); + TU_ASSERT(epnum < EP_COUNT); + TU_ASSERT(epnum != 0); + + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + xfer->max_size = p_endpoint_desc->wMaxPacketSize.size; + + if(dir == TUSB_DIR_OUT) + { + USB->DOEP[epnum - 1].CTL |= USB_DOEP_CTL_USBACTEP | + (p_endpoint_desc->bmAttributes.xfer << _USB_DOEP_CTL_EPTYPE_SHIFT) | + (p_endpoint_desc->wMaxPacketSize.size << _USB_DOEP_CTL_MPS_SHIFT); + USB->DAINTMSK |= (1 << (_USB_DAINTMSK_OUTEPMSK0_SHIFT + epnum)); + } + else + { + uint8_t fifo_num = get_free_fifo(); + TU_ASSERT(fifo_num != 0); + + USB->DIEP[epnum - 1].CTL &= ~(_USB_DIEP_CTL_TXFNUM_MASK | _USB_DIEP_CTL_EPTYPE_MASK | USB_DIEP_CTL_SETD0PIDEF | _USB_DIEP_CTL_MPS_MASK); + USB->DIEP[epnum - 1].CTL |= USB_DIEP_CTL_USBACTEP | + (fifo_num << _USB_DIEP_CTL_TXFNUM_SHIFT) | + (p_endpoint_desc->bmAttributes.xfer << _USB_DIEP_CTL_EPTYPE_SHIFT) | + ((p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS) ? USB_DIEP_CTL_SETD0PIDEF : 0) | + (p_endpoint_desc->wMaxPacketSize.size << 0); + + USB->DAINTMSK |= (1 << epnum); + + /* Both TXFD and TXSA are in unit of 32-bit words. */ + /* IN FIFO 0 was configured during enumeration, hence the "+ 16". */ + uint16_t const allocated_size = (USB->GRXFSIZ & _USB_GRXFSIZ_RXFDEP_MASK) + 16; + uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_FIFO_NUM-1); + uint32_t const fifo_offset = allocated_size + fifo_size*(fifo_num-1); + + /* DIEPTXF starts at FIFO #1. */ + volatile uint32_t* usb_dieptxf = &USB->DIEPTXF1; + usb_dieptxf[epnum - 1] = (fifo_size << _USB_DIEPTXF1_INEPNTXFDEP_SHIFT) | fifo_offset; + } + return true; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +{ + (void)rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->short_packet = false; + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint8_t short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if(short_packet_size > 0 || (total_bytes == 0)) + { + num_packets++; + } + + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them + // here. + if(dir == TUSB_DIR_IN) + { + if(epnum == 0) + { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + USB->DIEP0TSIZ = (num_packets << _USB_DIEP0TSIZ_PKTCNT_SHIFT) | total_bytes; + USB->DIEP0CTL |= USB_DIEP0CTL_EPENA | USB_DIEP0CTL_CNAK; // Enable | CNAK + } + else + { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + USB->DIEP[epnum - 1].TSIZ = (num_packets << _USB_DIEP_TSIZ_PKTCNT_SHIFT) | total_bytes; + USB->DIEP[epnum - 1].CTL |= USB_DIEP_CTL_EPENA | USB_DIEP_CTL_CNAK; // Enable | CNAK + } + + // Enable fifo empty interrupt only if there are something to put in the fifo. + if(total_bytes != 0) + { + USB->DIEPEMPMSK |= (1 << epnum); + } + } + else + { + if(epnum == 0) + { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + USB->DOEP0TSIZ |= (1 << _USB_DOEP0TSIZ_PKTCNT_SHIFT) | ((xfer->max_size & _USB_DOEP0TSIZ_XFERSIZE_MASK) << _USB_DOEP0TSIZ_XFERSIZE_SHIFT); + USB->DOEP0CTL |= USB_DOEP0CTL_EPENA | USB_DOEP0CTL_CNAK; + } + else + { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + USB->DOEP[epnum - 1].TSIZ |= (1 << _USB_DOEP_TSIZ_PKTCNT_SHIFT) | ((xfer->max_size & _USB_DOEP_TSIZ_XFERSIZE_MASK) << _USB_DOEP_TSIZ_XFERSIZE_SHIFT); + USB->DOEP[epnum - 1].CTL |= USB_DOEP_CTL_EPENA | USB_DOEP_CTL_CNAK; + } + } + return true; +} + +/*------------------------------------------------------------------*/ +/* IRQ */ +/*------------------------------------------------------------------*/ +void dcd_int_enable(uint8_t rhport) +{ + (void) rhport; + + NVIC_EnableIRQ(USB_IRQn); +} + +void dcd_int_disable(uint8_t rhport) +{ + (void) rhport; + + NVIC_DisableIRQ(USB_IRQn); +} + +static void receive_packet(xfer_ctl_t *xfer, uint16_t xfer_size) +{ + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint16_t to_recv_size; + + if(remaining <= xfer->max_size) + { + /* Avoid buffer overflow. */ + to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; + } + else + { + /* Room for full packet, choose recv_size based on what the microcontroller claims. */ + to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; + } + + uint8_t to_recv_rem = to_recv_size % 4; + uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; + + /* Do not assume xfer buffer is aligned. */ + uint8_t *base = (xfer->buffer + xfer->queued_len); + + /* This for loop always runs at least once- skip if less than 4 bytes to collect. */ + if(to_recv_size >= 4) + { + for(uint16_t i = 0; i < to_recv_size_aligned; i += 4) + { + uint32_t tmp = (*USB->FIFO0D); + base[i] = tmp & 0x000000FF; + base[i + 1] = (tmp & 0x0000FF00) >> 8; + base[i + 2] = (tmp & 0x00FF0000) >> 16; + base[i + 3] = (tmp & 0xFF000000) >> 24; + } + } + + /* Do not read invalid bytes from RX FIFO. */ + if(to_recv_rem != 0) + { + uint32_t tmp = (*USB->FIFO0D); + uint8_t *last_32b_bound = base + to_recv_size_aligned; + + last_32b_bound[0] = tmp & 0x000000FF; + if(to_recv_rem > 1) + { + last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; + } + if(to_recv_rem > 2) + { + last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; + } + } + + xfer->queued_len += xfer_size; + + /* Per USB spec, a short OUT packet (including length 0) is always */ + /* indicative of the end of a transfer (at least for ctl, bulk, int). */ + xfer->short_packet = (xfer_size < xfer->max_size); +} + +static void transmit_packet(xfer_ctl_t *xfer, uint8_t fifo_num) +{ + uint16_t remaining; + if(fifo_num == 0) + { + remaining = (USB->DIEP0TSIZ & 0x7FFFFU) >> _USB_DIEP0TSIZ_XFERSIZE_SHIFT; + } + else + { + remaining = (USB->DIEP[fifo_num - 1].TSIZ & 0x7FFFFU) >> _USB_DIEP_TSIZ_XFERSIZE_SHIFT; + } + xfer->queued_len = xfer->total_len - remaining; + + uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; + uint8_t to_xfer_rem = to_xfer_size % 4; + uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; + + /* Buffer might not be aligned to 32b, so we need to force alignment by copying to a temp var. */ + uint8_t *base = (xfer->buffer + xfer->queued_len); + + /* This for loop always runs at least once- skip if less than 4 bytes to send off. */ + if(to_xfer_size >= 4) + { + for(uint16_t i = 0; i < to_xfer_size_aligned; i += 4) + { + uint32_t tmp = base[i] | (base[i + 1] << 8) | (base[i + 2] << 16) | (base[i + 3] << 24); + *tx_fifo[fifo_num] = tmp; + } + } + + /* Do not read beyond end of buffer if not divisible by 4. */ + if(to_xfer_rem != 0) + { + uint32_t tmp = 0; + uint8_t *last_32b_bound = base + to_xfer_size_aligned; + + tmp |= last_32b_bound[0]; + if(to_xfer_rem > 1) + { + tmp |= (last_32b_bound[1] << 8); + } + if(to_xfer_rem > 2) + { + tmp |= (last_32b_bound[2] << 16); + } + + *tx_fifo[fifo_num] = tmp; + } +} + +static void read_rx_fifo(void) +{ + /* + * Pop control word off FIFO (completed xfers will have 2 control words, + * we only pop one ctl word each interrupt). + */ + uint32_t const ctl_word = USB->GRXSTSP; + uint8_t const pktsts = (ctl_word & _USB_GRXSTSP_PKTSTS_MASK) >> _USB_GRXSTSP_PKTSTS_SHIFT; + uint8_t const epnum = (ctl_word & _USB_GRXSTSP_CHNUM_MASK ) >> _USB_GRXSTSP_CHNUM_SHIFT; + uint16_t const bcnt = (ctl_word & _USB_GRXSTSP_BCNT_MASK ) >> _USB_GRXSTSP_BCNT_SHIFT; + + switch(pktsts) + { + case 0x01: /* Global OUT NAK (Interrupt) */ + break; + + case 0x02: + { + /* Out packet recvd */ + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + receive_packet(xfer, bcnt); + } + break; + + case 0x03: + /* Out packet done (Interrupt) */ + break; + + case 0x04: + /* Step 2: Setup transaction completed (Interrupt) */ + /* After this event, OEPINT interrupt will occur with SETUP bit set */ + if(epnum == 0) + { + USB->DOEP0TSIZ |= (1 << _USB_DOEP0TSIZ_SUPCNT_SHIFT); + } + + break; + + case 0x06: + { + /* Step1: Setup data packet received */ + + /* + * We can receive up to three setup packets in succession, but + * only the last one is valid. Therefore we just overwrite it + */ + _setup_packet[0] = (*USB->FIFO0D); + _setup_packet[1] = (*USB->FIFO0D); + } + break; + + default: + /* Invalid, breakpoint. */ + TU_BREAKPOINT(); + break; + } +} + +static void handle_epout_ints(void) +{ + // GINTSTS will be cleared with DAINT == 0 + // DAINT for a given EP clears when DOEPINTx is cleared. + // DOEPINT will be cleared when DAINT's out bits are cleared. + + for(uint8_t n = 0; n < EP_COUNT; n++) + { + xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); + + if(n == 0) + { + if(USB->DAINT & (1 << (_USB_DAINT_OUTEPINT0_SHIFT + n))) + { + // SETUP packet Setup Phase done. + if((USB->DOEP0INT & USB_DOEP0INT_SETUP)) + { + USB->DOEP0INT = USB_DOEP0INT_STUPPKTRCVD | USB_DOEP0INT_SETUP; // clear + dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); + } + + // OUT XFER complete (single packet).q + if(USB->DOEP0INT & USB_DOEP0INT_XFERCOMPL) + { + USB->DOEP0INT = USB_DOEP0INT_XFERCOMPL; + + // Transfer complete if short packet or total len is transferred + if(xfer->short_packet || (xfer->queued_len == xfer->total_len)) + { + xfer->short_packet = false; + dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); + } + else + { + // Schedule another packet to be received. + USB->DOEP0TSIZ |= (1 << _USB_DOEP0TSIZ_PKTCNT_SHIFT) | ((xfer->max_size & _USB_DOEP0TSIZ_XFERSIZE_MASK) << _USB_DOEP0TSIZ_XFERSIZE_SHIFT); + USB->DOEP0CTL |= USB_DOEP0CTL_EPENA | USB_DOEP0CTL_CNAK; + } + } + } + } + else + { + if(USB->DAINT & (1 << (_USB_DAINT_OUTEPINT0_SHIFT + n))) + { + // SETUP packet Setup Phase done. + if((USB->DOEP[n - 1].INT & USB_DOEP_INT_SETUP)) + { + USB->DOEP[n - 1].INT = USB_DOEP_INT_STUPPKTRCVD | USB_DOEP_INT_SETUP; // clear + dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); + } + + // OUT XFER complete (single packet).q + if(USB->DOEP[n - 1].INT & USB_DOEP_INT_XFERCOMPL) + { + USB->DOEP[n - 1].INT = USB_DOEP_INT_XFERCOMPL; + + // Transfer complete if short packet or total len is transferred + if(xfer->short_packet || (xfer->queued_len == xfer->total_len)) + { + xfer->short_packet = false; + dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); + } + else + { + // Schedule another packet to be received. + USB->DOEP[n - 1].TSIZ |= (1 << _USB_DOEP_TSIZ_PKTCNT_SHIFT) | ((xfer->max_size & _USB_DOEP_TSIZ_XFERSIZE_MASK) << _USB_DOEP_TSIZ_XFERSIZE_SHIFT); + USB->DOEP[n - 1].CTL |= USB_DOEP_CTL_EPENA | USB_DOEP_CTL_CNAK; + } + } + } + } + } +} + +static void handle_epin_ints(void) +{ + + for(uint32_t n = 0; n < EP_COUNT; n++) + { + xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN]; + + if(n == 0) + { + if(USB->DAINT & (1 << n)) + { + /* IN XFER complete (entire xfer). */ + if(USB->DIEP0INT & USB_DIEP0INT_XFERCOMPL) + { + USB->DIEP0INT = USB_DIEP0INT_XFERCOMPL; + dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + } + + /* XFER FIFO empty */ + if(USB->DIEP0INT & USB_DIEP0INT_TXFEMP) + { + USB->DIEP0INT = USB_DIEP0INT_TXFEMP; + transmit_packet(xfer, n); + + /* Turn off TXFE if all bytes are written. */ + if(xfer->queued_len == xfer->total_len) + { + USB->DIEPEMPMSK &= ~(1 << n); + } + } + + /* XFER Timeout */ + if(USB->DIEP0INT & USB_DIEP0INT_TIMEOUT) + { + /* Clear interrupt or enpoint will hang. */ + USB->DIEP0INT = USB_DIEP0INT_TIMEOUT; + } + } + } + else + { + if(USB->DAINT & (1 << n)) + { + /* IN XFER complete (entire xfer). */ + if(USB->DIEP[n - 1].INT & USB_DIEP_INT_XFERCOMPL) + { + USB->DIEP[n - 1].INT = USB_DIEP_INT_XFERCOMPL; + dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + } + + /* XFER FIFO empty */ + if(USB->DIEP[n - 1].INT & USB_DIEP_INT_TXFEMP) + { + USB->DIEP[n - 1].INT = USB_DIEP_INT_TXFEMP; + transmit_packet(xfer, n); + + /* Turn off TXFE if all bytes are written. */ + if(xfer->queued_len == xfer->total_len) + { + USB->DIEPEMPMSK &= ~(1 << n); + } + } + + /* XFER Timeout */ + if(USB->DIEP[n - 1].INT & USB_DIEP_INT_TIMEOUT) + { + /* Clear interrupt or enpoint will hang. */ + USB->DIEP[n - 1].INT = USB_DIEP_INT_TIMEOUT; + } + } + } + } +} + +void dcd_int_handler(uint8_t rhport) +{ + (void) rhport; + + const uint32_t int_status = USB->GINTSTS; + + /* USB Reset */ + if(int_status & USB_GINTSTS_USBRST) + { + /* start of reset */ + USB->GINTSTS = USB_GINTSTS_USBRST; + /* FIFOs will be reassigned when the endpoints are reopen */ + _allocated_fifos = 1; + bus_reset(); + } + + /* Reset detected Interrupt */ + if(int_status & USB_GINTSTS_RESETDET) + { + USB->GINTSTS = USB_GINTSTS_RESETDET; + bus_reset(); + } + + /* Enumeration Done */ + if(int_status & USB_GINTSTS_ENUMDONE) + { + /* This interrupt is considered the end of reset. */ + USB->GINTSTS = USB_GINTSTS_ENUMDONE; + enum_done_processing(); + dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + } + + /* OTG Interrupt */ + if(int_status & USB_GINTSTS_OTGINT) + { + /* OTG INT bit is read-only */ + + uint32_t const otg_int = USB->GOTGINT; + + if(otg_int & USB_GOTGINT_SESENDDET) + { + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + } + + USB->GOTGINT = otg_int; + } + + #if USE_SOF + if(int_status & USB_GINTSTS_SOF) + { + USB->GINTSTS = USB_GINTSTS_SOF; + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); + } + #endif + + /* RxFIFO Non-Empty */ + if(int_status & USB_GINTSTS_RXFLVL) + { + /* RXFLVL bit is read-only */ + + /* Mask out RXFLVL while reading data from FIFO */ + USB->GINTMSK &= ~USB_GINTMSK_RXFLVLMSK; + read_rx_fifo(); + USB->GINTMSK |= USB_GINTMSK_RXFLVLMSK; + } + + /* OUT Endpoints Interrupt */ + if(int_status & USB_GINTMSK_OEPINTMSK) + { + /* OEPINT is read-only */ + handle_epout_ints(); + } + + /* IN Endpoints Interrupt */ + if(int_status & USB_GINTMSK_IEPINTMSK) + { + /* IEPINT bit read-only */ + handle_epin_ints(); + } + + /* unhandled */ + USB->GINTSTS |= USB_GINTSTS_CURMOD | + USB_GINTSTS_MODEMIS | + USB_GINTSTS_OTGINT | + USB_GINTSTS_NPTXFEMP | + USB_GINTSTS_GINNAKEFF | + USB_GINTSTS_GOUTNAKEFF | + USB_GINTSTS_ERLYSUSP | + USB_GINTSTS_USBSUSP | + USB_GINTSTS_ISOOUTDROP | + USB_GINTSTS_EOPF | + USB_GINTSTS_EPMIS | + USB_GINTSTS_INCOMPISOIN | + USB_GINTSTS_INCOMPLP | + USB_GINTSTS_FETSUSP | + USB_GINTSTS_PTXFEMP; +} + +#endif -- cgit v1.3.1 From 1e4e87de51e67bc6439b463bf30c1f1b7302d510 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 25 Mar 2021 13:53:26 +0100 Subject: Rework to copy wrapped word bytes by byte in copy_to_cont_dst etc. --- src/common/tusb_fifo.c | 65 +++++++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 7d5453850..e3613e45f 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -215,7 +215,9 @@ static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRe // Write full words of linear part to buffer uint16_t full_words = nLin >> 2; - for(uint16_t i = 0; i < full_words; i++) { + uint8_t rem = nLin - (full_words << 2); + while(full_words--) + { tmp = *rx_fifo; memcpy(dst_u8, &tmp, 4); // dst_u8[0] = tmp & 0x000000FF; @@ -226,22 +228,29 @@ static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRe } // Handle wrap around - uint8_t rem = nLin - (full_words << 2); - uint8_t remrem = 0; if (rem > 0) { - tmp = *rx_fifo; - memcpy(dst_u8, &tmp, rem); - remrem = tu_min16(nWrap, 4-rem); - memcpy(f->buffer, ((uint8_t *) &tmp) + rem, remrem); + uint8_t remrem = tu_min16(nWrap, 4-rem); nWrap -= remrem; + tmp = *rx_fifo; + uint8_t * src_u8 = ((uint8_t *) &tmp); + while(rem--) + { + *dst_u8++ = *src_u8++; + } + dst_u8 = f->buffer; + while(remrem--) + { + *dst_u8++ = *src_u8++; + } } - - // Final part - if (nWrap > 0) + else { - _tu_fifo_read_from_const_src_ptr_in_full_words(f->buffer + remrem, data, nWrap); + dst_u8 = f->buffer; } + + // Final part + if (nWrap > 0) _tu_fifo_read_from_const_src_ptr_in_full_words(dst_u8, data, nWrap); } break; } @@ -295,31 +304,39 @@ static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel, CFG_TUSB_MEM_ALIGN uint32_t tmp; // Pushing full available 32 bit words to FIFO - uint16_t const full_words = nLin >> 2; - for(uint16_t i = 0; i < full_words; i++){ + uint16_t full_words = nLin >> 2; + uint8_t rem = nLin - (full_words << 2); + while(full_words--) + { memcpy(&tmp, src_u8, 4); *tx_fifo = tmp; src_u8 += 4; } - // Handle wrap around - uint8_t rem = nLin - (full_words << 2); - uint8_t remrem = 0; + // Handle wrap around - do it manually as these are only 4 bytes and its faster without memcpy if (rem > 0) { - tmp = 0; - memcpy(&tmp, src_u8, rem); - remrem = tu_min16(nWrap, 4-rem); - memcpy(((uint8_t *) &tmp) + rem, f->buffer, remrem); + uint8_t remrem = tu_min16(nWrap, 4-rem); nWrap -= remrem; + uint8_t * dst_u8 = (uint8_t *)&tmp; + while(rem--) + { + *dst_u8++ = *src_u8++; + } + src_u8 = f->buffer; + while(remrem--) + { + *dst_u8++ = *src_u8++; + } *tx_fifo = tmp; } - - // Final part - if (nWrap > 0) + else { - _tu_fifo_write_to_const_dst_ptr_in_full_words(p_buffer, f->buffer + remrem, nWrap); + src_u8 = f->buffer; } + + // Final linear part + if (nWrap > 0) _tu_fifo_write_to_const_dst_ptr_in_full_words(p_buffer, src_u8, nWrap); } break; } -- cgit v1.3.1 From bfddfbadc72eb389f88e045f68a4219149397a46 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 25 Mar 2021 14:28:59 +0100 Subject: Implement unaligned word copy. --- src/common/tusb_fifo.c | 108 ++++++++++++++++++++++++++++--------------------- 1 file changed, 62 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index e3613e45f..c131a1910 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -107,30 +107,33 @@ static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) // TODO generalize with configurable 1 byte or 4 byte each read static void _tu_fifo_read_from_const_src_ptr_in_full_words(void * dst, const void * src, uint16_t len) { - uint8_t * dst_u8 = (uint8_t *)dst; volatile uint32_t * rx_fifo = (volatile uint32_t *) src; + // Optimize for fast word copies + typedef struct{ + uint32_t val; + } __attribute((__packed__)) unaligned_uint32_t; + + unaligned_uint32_t* dst_una = (unaligned_uint32_t*)dst; + // Reading full available 32 bit words from FIFO uint16_t full_words = len >> 2; - for(uint16_t i = 0; i < full_words; i++) { - uint32_t tmp = *rx_fifo; - dst_u8[0] = tmp & 0x000000FF; - dst_u8[1] = (tmp & 0x0000FF00) >> 8; - dst_u8[2] = (tmp & 0x00FF0000) >> 16; - dst_u8[3] = (tmp & 0xFF000000) >> 24; - dst_u8 += 4; + while(full_words--) + { + dst_una->val = *rx_fifo; + dst_una++; } // Read the remaining 1-3 bytes from FIFO uint8_t bytes_rem = len & 0x03; if(bytes_rem != 0) { + uint8_t * dst_u8 = (uint8_t *)dst_una; uint32_t tmp = *rx_fifo; - dst_u8[0] = tmp & 0x000000FF; - if(bytes_rem > 1) { - dst_u8[1] = (tmp & 0x0000FF00) >> 8; - } - if(bytes_rem > 2) { - dst_u8[2] = (tmp & 0x00FF0000) >> 16; + uint8_t * src = (uint8_t *) &tmp; + + while(bytes_rem--) + { + *dst_u8++ = *src++; } } } @@ -141,29 +144,34 @@ static void _tu_fifo_read_from_const_src_ptr_in_full_words(void * dst, const voi static void _tu_fifo_write_to_const_dst_ptr_in_full_words(void * dst, const void * src, uint16_t len) { volatile uint32_t * tx_fifo = (volatile uint32_t *) dst; - uint8_t * src_u8 = (uint8_t *)src; + + // Optimize for fast word copies + typedef struct{ + uint32_t val; + } __attribute((__packed__)) unaligned_uint32_t; + + unaligned_uint32_t* src_una = (unaligned_uint32_t *) src; // Pushing full available 32 bit words to FIFO - uint16_t const full_words = len >> 2; - for(uint16_t i = 0; i < full_words; i++){ - uint32_t temp32; - memcpy(&temp32, src_u8, 4); - *tx_fifo = temp32; - src_u8 += 4; + uint16_t full_words = len >> 2; + while(full_words--) + { + *tx_fifo = src_una->val; + src_una++; } // Write the remaining 1-3 bytes into FIFO uint8_t bytes_rem = len & 0x03; if(bytes_rem){ - uint32_t tmp_word = 0; - tmp_word |= src_u8[0]; - if(bytes_rem > 1){ - tmp_word |= (uint32_t)(src_u8[1]) << 8; - } - if(bytes_rem > 2){ - tmp_word |= (uint32_t)(src_u8[2]) << 16; + uint8_t * src_u8 = (uint8_t *) src_una; + uint32_t tmp = 0; + uint8_t * dst_u8 = (uint8_t *)&tmp; + + while(bytes_rem--) + { + *dst_u8++ = *src_u8++; } - *tx_fifo = tmp_word; + *tx_fifo = tmp; } } @@ -209,30 +217,31 @@ static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRe uint16_t nLin = (f->depth - wRel) * f->item_size; uint16_t nWrap = (n - nLin) * f->item_size; - uint8_t * dst_u8 = (uint8_t *)(f->buffer + (wRel * f->item_size)); + // Optimize for fast word copies + typedef struct{ + uint32_t val; + } __attribute((__packed__)) unaligned_uint32_t; + + unaligned_uint32_t* dst = (unaligned_uint32_t*)(f->buffer + (wRel * f->item_size)); volatile uint32_t * rx_fifo = (volatile uint32_t *) data; - CFG_TUSB_MEM_ALIGN uint32_t tmp; // Write full words of linear part to buffer uint16_t full_words = nLin >> 2; - uint8_t rem = nLin - (full_words << 2); while(full_words--) { - tmp = *rx_fifo; - memcpy(dst_u8, &tmp, 4); - // dst_u8[0] = tmp & 0x000000FF; - // dst_u8[1] = (tmp & 0x0000FF00) >> 8; - // dst_u8[2] = (tmp & 0x00FF0000) >> 16; - // dst_u8[3] = (tmp & 0xFF000000) >> 24; - dst_u8 += 4; + dst->val = *rx_fifo; + dst++; } + uint8_t * dst_u8; + uint8_t rem = nLin & 0x03; // Handle wrap around if (rem > 0) { + dst_u8 = (uint8_t *)dst; uint8_t remrem = tu_min16(nWrap, 4-rem); nWrap -= remrem; - tmp = *rx_fifo; + uint32_t tmp = *rx_fifo; uint8_t * src_u8 = ((uint8_t *) &tmp); while(rem--) { @@ -299,25 +308,32 @@ static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel, uint16_t nLin = (f->depth - rRel) * f->item_size; uint16_t nWrap = (n - nLin) * f->item_size; + // Optimize for fast word copies + typedef struct{ + uint32_t val; + } __attribute((__packed__)) unaligned_uint32_t; + + unaligned_uint32_t* src = (unaligned_uint32_t*)(f->buffer + (rRel * f->item_size)); + volatile uint32_t * tx_fifo = (volatile uint32_t *) p_buffer; - uint8_t * src_u8 = f->buffer + (rRel * f->item_size); - CFG_TUSB_MEM_ALIGN uint32_t tmp; // Pushing full available 32 bit words to FIFO uint16_t full_words = nLin >> 2; - uint8_t rem = nLin - (full_words << 2); while(full_words--) { - memcpy(&tmp, src_u8, 4); - *tx_fifo = tmp; - src_u8 += 4; + *tx_fifo = src->val; + src++; } + uint8_t * src_u8; + uint8_t rem = nLin & 0x03; // Handle wrap around - do it manually as these are only 4 bytes and its faster without memcpy if (rem > 0) { + src_u8 = (uint8_t *) src; uint8_t remrem = tu_min16(nWrap, 4-rem); nWrap -= remrem; + uint32_t tmp; uint8_t * dst_u8 = (uint8_t *)&tmp; while(rem--) { -- cgit v1.3.1 From 994dddc231c3b7d52e16e5b42d8c42a84e664622 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 25 Mar 2021 14:38:55 +0100 Subject: Fix shadowing parameter in fifo.c --- src/common/tusb_fifo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index c131a1910..d05549e3e 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -129,11 +129,11 @@ static void _tu_fifo_read_from_const_src_ptr_in_full_words(void * dst, const voi if(bytes_rem != 0) { uint8_t * dst_u8 = (uint8_t *)dst_una; uint32_t tmp = *rx_fifo; - uint8_t * src = (uint8_t *) &tmp; + uint8_t * src_u8 = (uint8_t *) &tmp; while(bytes_rem--) { - *dst_u8++ = *src++; + *dst_u8++ = *src_u8++; } } } -- cgit v1.3.1 From 13735eb21de8d21a88871e69859f69db02af93c6 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Sun, 7 Mar 2021 14:53:21 +0900 Subject: added dcd for Renesas USBa --- src/portable/renesas/usba/dcd_usba.c | 755 +++++++++++++++++++++++++++++++++++ 1 file changed, 755 insertions(+) create mode 100644 src/portable/renesas/usba/dcd_usba.c (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c new file mode 100644 index 000000000..b0fa1749d --- /dev/null +++ b/src/portable/renesas/usba/dcd_usba.c @@ -0,0 +1,755 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Koji Kitayama + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_RX63X ) + +#include "device/dcd.h" +#include "iodefine.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ +#define SYSTEM_PRCR_PRC1 (1<<1) +#define SYSTEM_PRCR_PRKEY (0xA5u<<8) + +#define USB_FIFOSEL_TX ((uint16_t)(1u<<5)) +#define USB_FIFOSEL_MBW_8 ((uint16_t)(0u<<10)) +#define USB_FIFOSEL_MBW_16 ((uint16_t)(1u<<10)) +#define USB_IS0_CTSQ ((uint16_t)(7u)) +#define USB_IS0_DVSQ ((uint16_t)(7u<<4)) +#define USB_IS0_VALID ((uint16_t)(1u<<3)) +#define USB_IS0_BRDY ((uint16_t)(1u<<8)) +#define USB_IS0_NRDY ((uint16_t)(1u<<9)) +#define USB_IS0_BEMP ((uint16_t)(1u<<10)) +#define USB_IS0_CTRT ((uint16_t)(1u<<11)) +#define USB_IS0_DVST ((uint16_t)(1u<<12)) +#define USB_IS0_SOFR ((uint16_t)(1u<<13)) +#define USB_IS0_RESM ((uint16_t)(1u<<14)) +#define USB_IS0_VBINT ((uint16_t)(1u<<15)) +#define USB_IS1_SACK ((uint16_t)(1u<<4)) +#define USB_IS1_SIGN ((uint16_t)(1u<<5)) +#define USB_IS1_EOFERR ((uint16_t)(1u<<6)) +#define USB_IS1_ATTCH ((uint16_t)(1u<<11)) +#define USB_IS1_DTCH ((uint16_t)(1u<<12)) +#define USB_IS1_BCHG ((uint16_t)(1u<<14)) +#define USB_IS1_OVRCR ((uint16_t)(1u<<15)) + +#define USB_IS0_CTSQ_MSK (7u) +#define USB_IS0_CTSQ_SETUP (1u) +#define USB_IS0_DVSQ_DEF (1u<<4) +#define USB_IS0_DVSQ_ADDR (2u<<4) +#define USB_IS0_DVSQ_SUSP (4u<<4) + +#define USB_PIPECTR_PID_NAK (0u) +#define USB_PIPECTR_PID_BUF (1u) +#define USB_PIPECTR_PID_STALL (2u) +#define USB_PIPECTR_CCPL (1u<<2) +#define USB_PIPECTR_SQMON (1u<<6) +#define USB_PIPECTR_SQCLR (1u<<8) +#define USB_PIPECTR_ACLRM (1u<<9) +#define USB_PIPECTR_BSTS (1u<<15) + +#define USB_FIFOCTR_DTLN (0x1FF) +#define USB_FIFOCTR_FRDY (1u<<13) +#define USB_FIFOCTR_BCLR (1u<<14) +#define USB_FIFOCTR_BVAL (1u<<15) + +#define USB_PIPECFG_SHTNAK (1u<<7) +#define USB_PIPECFG_DBLB (1u<<9) +#define USB_PIPECFG_BULK (1u<<14) +#define USB_PIPECFG_ISO (3u<<14) +#define USB_PIPECFG_INT (2u<<14) + +#define FIFO_REQ_CLR (1u) +#define FIFO_COMPLETE (1u<<1) + +typedef struct { + union { + struct { + uint16_t : 8; + uint16_t TRCLR: 1; + uint16_t TRENB: 1; + uint16_t : 0; + }; + uint16_t TRE; + }; + uint16_t TRN; +} reg_pipetre_t; + +typedef union { + struct { + volatile uint16_t u8: 8; + volatile uint16_t : 0; + }; + volatile uint16_t u16; +} hw_fifo_t; + +typedef struct TU_ATTR_PACKED +{ + uintptr_t addr; + uint16_t length; + uint16_t remaining; + struct { + uint32_t ep : 8; + uint32_t data: 1; + uint32_t : 0; + }; +} pipe_state_t; + +typedef struct +{ + pipe_state_t pipe[9]; + uint8_t ep[2][16]; /* index for pipe number */ +} dcd_data_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_MEM_SECTION static dcd_data_t _dcd; + +static uint32_t disable_interrupt(void) +{ + uint32_t pswi; + pswi = __builtin_rx_mvfc(0) & 0x010000; + __builtin_rx_clrpsw('I'); + return pswi; +} + +static void enable_interrupt(uint32_t pswi) +{ + __builtin_rx_mvtc(0, __builtin_rx_mvfc(0) | pswi); +} + +static unsigned find_pipe(unsigned xfer) +{ + switch (xfer) { + case TUSB_XFER_ISOCHRONOUS: + for (int i = 1; i <= 2; ++i) { + if (0 == _dcd.pipe[i].ep) return i; + } + break; + case TUSB_XFER_BULK: + for (int i = 3; i <= 5; ++i) { + if (0 == _dcd.pipe[i].ep) return i; + } + for (int i = 1; i <= 1; ++i) { + if (0 == _dcd.pipe[i].ep) return i; + } + break; + case TUSB_XFER_INTERRUPT: + for (int i = 6; i <= 9; ++i) { + if (0 == _dcd.pipe[i].ep) return i; + } + break; + default: + /* No support for control transfer */ + break; + } + return 0; +} + +static volatile uint16_t* get_pipectr(unsigned num) +{ + volatile uint16_t *ctr = NULL; + if (num) { + ctr = (volatile uint16_t*)&USB0.PIPE1CTR.WORD; + ctr += num - 1; + } else { + ctr = (volatile uint16_t*)&USB0.DCPCTR.WORD; + } + return ctr; +} + +static volatile reg_pipetre_t* get_pipetre(unsigned num) +{ + volatile reg_pipetre_t* tre = NULL; + if ((1 <= num) && (num <= 5)) { + tre = (volatile reg_pipetre_t*)&USB0.PIPE1TRE.WORD; + tre += num - 1; + } + return tre; +} + +static volatile uint16_t* ep_addr_to_pipectr(uint8_t rhport, unsigned ep_addr) +{ + (void)rhport; + volatile uint16_t *ctr = NULL; + const unsigned epn = ep_addr & 0xFu; + if (epn) { + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned num = _dcd.ep[dir][epn]; + if (num) { + ctr = (volatile uint16_t*)&USB0.PIPE1CTR.WORD; + ctr += num - 1; + } + } else { + ctr = (volatile uint16_t*)&USB0.DCPCTR.WORD; + } + return ctr; +} + + +/* 1 less than 64 bytes were written + * 2 no bytes were written + * 0 64 bytes were written */ +static int write_fifo(volatile void *fifo, pipe_state_t* pipe, unsigned mps) +{ + unsigned rem = pipe->remaining; + if (!rem) return 2; + unsigned len = (rem < mps) ? rem: mps; + + hw_fifo_t *reg = (hw_fifo_t*)fifo; + uintptr_t addr = pipe->addr + pipe->length - rem; + if (addr & 1u) { + /* addr is not 2-byte aligned */ + reg->u8 = *(const uint8_t *)addr; + ++addr; + --len; + } + while (len >= 2) { + reg->u16 = *(const uint16_t *)addr; + addr += 2; + len -= 2; + } + if (len) { + reg->u8 = *(const uint8_t *)addr; + ++addr; + } + if (rem < mps) return 1; + return 0; +} + +/* 1 if the number of bytes read is less than 64 bytes + * 0 otherwise */ +static int read_fifo(volatile void *fifo, pipe_state_t* pipe, unsigned mps, size_t len) +{ + unsigned rem = pipe->remaining; + if (!rem) return 2; + if (rem < len) len = rem; + pipe->remaining = rem - len; + + hw_fifo_t *reg = (hw_fifo_t*)fifo; + uintptr_t addr = pipe->addr; + while (len--) { + *(uint8_t *)addr = reg->u8; + ++addr; + } + pipe->addr = addr; + if (rem < mps) return 1; + return 0; +} + +static void process_setup_packet(uint8_t rhport) +{ + uint16_t setup_packet[4]; + if (0 == (USB0.INTSTS0.WORD & USB_IS0_VALID)) return; + USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; + setup_packet[0] = USB0.USBREQ.WORD; + setup_packet[1] = USB0.USBVAL; + setup_packet[2] = USB0.USBINDX; + setup_packet[3] = USB0.USBLENG; + USB0.INTSTS0.WORD = ~USB_IS0_VALID; + dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet[0], true); + // TU_LOG1("S\r\n"); +} + +static void process_status_completion(uint8_t rhport) +{ + uint8_t ep_addr; + /* Check the data stage direction */ + if (USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX) { + /* IN transfer. */ + ep_addr = tu_edpt_addr(0, TUSB_DIR_IN); + } else { + /* OUT transfer. */ + ep_addr = tu_edpt_addr(0, TUSB_DIR_OUT); + } + dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, true); + // TU_LOG1("C\r\n"); +} + +static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +{ + (void)rhport; + + pipe_state_t *pipe = &_dcd.pipe[0]; + /* set fifo direction */ + if (ep_addr) { /* IN */ + USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16; + while (!(USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX)) ; + } else { /* OUT */ + USB0.CFIFOSEL.WORD = USB_FIFOSEL_MBW_8; + while (USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX) ; + } + if (total_bytes) { + pipe->addr = (uintptr_t)buffer; + pipe->length = total_bytes; + pipe->remaining = total_bytes; + pipe->data = USB0.DCPCTR.BIT.SQMON; + if (ep_addr) { /* IN */ + TU_ASSERT(USB0.DCPCTR.BIT.BSTS && (USB0.USBREQ.WORD & 0x80)); + if (write_fifo(&USB0.CFIFO.WORD, pipe, 64)) { + USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; + } + } + USB0.DCPCTR.WORD = USB_PIPECTR_PID_BUF; + // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); + } else { + /* ZLP */ + pipe->addr = 0; + pipe->length = 0; + pipe->remaining = 0; + pipe->data = USB0.DCPCTR.BIT.SQMON; + USB0.DCPCTR.WORD = USB_PIPECTR_CCPL | USB_PIPECTR_PID_BUF; + // TU_LOG1("Z %x\r\n", USB0.DCPCTR.WORD); + } + return true; +} + +static void process_edpt0_bemp(uint8_t rhport) +{ + pipe_state_t *pipe = &_dcd.pipe[0]; + unsigned data = pipe->data; + if (USB0.DCPCTR.BIT.SQMON == data) { + TU_LOG1("W %x\r\n", USB0.DCPCTR.WORD); + /* retry transfer */ + int r = write_fifo(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); + if (r) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; + return; + } + const unsigned rem = pipe->remaining; + if (rem > 64) { + pipe->remaining = rem - 64; + pipe->data = data ^ 1; + TU_LOG1("Y %d %x\r\n", rem - 64, USB0.DCPCTR.WORD); + int r = write_fifo(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); + if (r) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; + return; + } + pipe->addr = 0; + pipe->remaining = 0; + dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN), + pipe->length, XFER_RESULT_SUCCESS, true); + // TU_LOG1("c\r\n"); +} + +static void process_edpt0_brdy(uint8_t rhport) +{ + size_t len = USB0.CFIFOCTR.BIT.DTLN; + int cplt = read_fifo(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, len); + if (cplt || (len < 64)) { + if (2 != cplt) { + USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; + } + dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), + _dcd.pipe[0].length - _dcd.pipe[0].remaining, + XFER_RESULT_SUCCESS, true); + // TU_LOG1("c\r\n"); + } +} + +static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +{ + (void)rhport; + + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned num = _dcd.ep[dir][epn]; + + TU_ASSERT(num); + + pipe_state_t *pipe = &_dcd.pipe[num]; + pipe->addr = (uintptr_t)buffer; + pipe->length = total_bytes; + pipe->remaining = total_bytes; + + USB0.PIPESEL.WORD = num; + const unsigned mps = USB0.PIPEMAXP.WORD; + if (dir) { /* IN */ + USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16; + while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; + if (write_fifo(&USB0.D0FIFO.WORD, pipe, mps)) { + USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; + } + USB0.D0FIFOSEL.WORD = 0; + } else { + volatile reg_pipetre_t *pt = get_pipetre(num); + if (pt) { + volatile uint16_t *ctr = get_pipectr(num); + if (*ctr & 0x3) *ctr = USB_PIPECTR_PID_NAK; + pt->TRE = 1u << 8; + pt->TRN = (total_bytes + mps - 1) / mps; + pt->TRENB = 1; + *ctr = USB_PIPECTR_PID_BUF; + } + } + TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); + return true; +} + +static void process_pipe_bemp(uint8_t rhport, unsigned num) +{ + pipe_state_t *pipe = &_dcd.pipe[num]; + const unsigned rem = pipe->remaining; + if (rem > 64) { + pipe->remaining = rem - 64; + TU_LOG1("Y %d\r\n", rem - 64); + USB0.PIPESEL.WORD = num; + const unsigned mps = USB0.PIPEMAXP.WORD; + USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16; + while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; + int r = write_fifo(&USB0.D0FIFO.WORD, pipe, mps); + if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; + USB0.D0FIFOSEL.WORD = 0; + return; + } + pipe->addr = 0; + pipe->remaining = 0; + dcd_event_xfer_complete(rhport, pipe->ep, pipe->length, + XFER_RESULT_SUCCESS, true); + // TU_LOG1("cE\r\n"); +} + +static void process_pipe_brdy(uint8_t rhport, unsigned num) +{ + pipe_state_t *pipe = &_dcd.pipe[num]; + USB0.PIPESEL.WORD = num; + const unsigned mps = USB0.PIPEMAXP.WORD; + USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_8; + while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; + unsigned ctr; + do { + ctr = USB0.D0FIFOCTR.WORD; + } while (!(ctr & USB_FIFOCTR_FRDY)); + const unsigned len = ctr & USB_FIFOCTR_DTLN; + TU_LOG1(">> %d %x %x\r\n", num, USB0.D0FIFOSEL.WORD, ctr); + int cplt = read_fifo(&USB0.D0FIFO.WORD, pipe, mps, len); + if (cplt || (len < mps)) { + if (2 != cplt) { + USB0.D0FIFO.WORD = USB_FIFOCTR_BCLR; + } + USB0.D0FIFOSEL.WORD = 0; + dcd_event_xfer_complete(rhport, pipe->ep, + pipe->length - pipe->remaining, + XFER_RESULT_SUCCESS, true); + TU_LOG1("c\r\n"); + } else { + USB0.D0FIFOSEL.WORD = 0; + } +} + +static void process_bus_reset(uint8_t rhport) +{ + USB0.BEMPENB.WORD = 1; + USB0.BRDYENB.WORD = 1; + USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; + USB0.D0FIFOSEL.WORD = 0; + USB0.D1FIFOSEL.WORD = 0; + volatile uint16_t *ctr = (volatile uint16_t*)((uintptr_t)(&USB0.PIPE1CTR.WORD)); + volatile uint16_t *tre = (volatile uint16_t*)((uintptr_t)(&USB0.PIPE1TRE.WORD)); + for (int i = 1; i <= 5; ++i) { + USB0.PIPESEL.WORD = i; + USB0.PIPECFG.WORD = 0; + *ctr = USB_PIPECTR_ACLRM; + *ctr = 0; + ++ctr; + *tre = (1u<<8); + tre += 2; + } + for (int i = 6; i <= 9; ++i) { + USB0.PIPESEL.WORD = i; + USB0.PIPECFG.WORD = 0; + *ctr = USB_PIPECTR_ACLRM; + *ctr = 0; + ++ctr; + } + tu_varclr(&_dcd); + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); + TU_LOG1("R\r\n"); +} + +static void process_set_address(uint8_t rhport) +{ + const uint32_t addr = USB0.USBADDR.BIT.USBADDR; + if (!addr) return; + const tusb_control_request_t setup_packet = { + .bmRequestType = 0, + .bRequest = 5, + .wValue = addr, + .wIndex = 0, + .wLength = 0, + }; + dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet, true); +} + +/*------------------------------------------------------------------*/ +/* Device API + *------------------------------------------------------------------*/ +void dcd_init(uint8_t rhport) +{ + (void)rhport; + /* Enable USB0 */ + uint32_t pswi = disable_interrupt(); + SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY | SYSTEM_PRCR_PRC1; + MSTP(USB0) = 0; + SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY; + enable_interrupt(pswi); + USB0.SYSCFG.BIT.SCKE = 1; + while (!USB0.SYSCFG.BIT.SCKE) ; + USB0.SYSCFG.BIT.DRPD = 0; + USB0.SYSCFG.BIT.DCFM = 0; + USB0.SYSCFG.BIT.USBE = 1; + + IR(USB0, USBI0) = 0; + + /* Setup default control pipe */ + USB0.DCPMAXP.BIT.MXPS = 64; + USB0.INTENB0.WORD = USB_IS0_VBINT | USB_IS0_BRDY | USB_IS0_BEMP | USB_IS0_DVST | USB_IS0_CTRT; + USB0.BEMPENB.WORD = 1; + USB0.BRDYENB.WORD = 1; + + TU_LOG1("INIT\r\n"); + if (USB0.INTSTS0.BIT.VBSTS) { + dcd_connect(rhport); + } +} + +void dcd_int_enable(uint8_t rhport) +{ + (void)rhport; + IEN(USB0, USBI0) = 1; +} + +void dcd_int_disable(uint8_t rhport) +{ + (void)rhport; + IEN(USB0, USBI0) = 0; +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void)rhport; + (void)dev_addr; +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void)rhport; + /* TODO */ +} + +void dcd_connect(uint8_t rhport) +{ + (void)rhport; + USB0.SYSCFG.BIT.DPRPU = 1; +} + +void dcd_disconnect(uint8_t rhport) +{ + (void)rhport; + USB0.SYSCFG.BIT.DPRPU = 0; +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) +{ + (void)rhport; + + const unsigned ep_addr = ep_desc->bEndpointAddress; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned xfer = ep_desc->bmAttributes.xfer; + + const unsigned mps = ep_desc->wMaxPacketSize.size; + if (xfer == TUSB_XFER_ISOCHRONOUS && mps > 256) { + /* USBB support up to 256 bytes */ + return false; + } + + const unsigned num = find_pipe(xfer); + if (!num) return false; + _dcd.pipe[num].ep = ep_addr; + _dcd.ep[dir][epn] = num; + + /* setup pipe */ + USB0.PIPESEL.WORD = num; + USB0.PIPEMAXP.WORD = mps; + volatile uint16_t *ctr = get_pipectr(num); + *ctr = USB_PIPECTR_ACLRM; + *ctr = 0; + unsigned cfg = (dir << 4) | epn; + if (xfer == TUSB_XFER_BULK) { + cfg |= USB_PIPECFG_BULK | USB_PIPECFG_SHTNAK | USB_PIPECFG_DBLB; + } else if (xfer == TUSB_XFER_INTERRUPT) { + cfg |= USB_PIPECFG_INT; + } else { + cfg |= USB_PIPECFG_ISO | USB_PIPECFG_DBLB; + } + USB0.PIPECFG.WORD = cfg; + if (dir) { + USB0.BEMPENB.WORD |= 1u << num; + *ctr = USB_PIPECTR_PID_BUF; + } else { + USB0.BRDYENB.WORD |= 1u << num; + if (xfer != TUSB_XFER_BULK) { + *ctr = USB_PIPECTR_PID_BUF; + } + } + TU_LOG1("O %d %x %x\r\n", USB0.PIPESEL.WORD, USB0.PIPECFG.WORD, USB0.PIPEMAXP.WORD); + + return true; +} + +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned num = _dcd.ep[dir][epn]; + + USB0.BEMPENB.WORD &= ~(1u << num); + USB0.BRDYENB.WORD &= ~(1u << num); + volatile uint16_t *ctr = get_pipectr(num); + *ctr = 0; + USB0.PIPESEL.WORD = num; + USB0.PIPECFG.WORD = 0; + _dcd.pipe[num].ep = 0; + _dcd.ep[dir][epn] = 0; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +{ + bool r; + const unsigned epn = ep_addr & 0xFu; + dcd_int_disable(rhport); + if (0 == epn) { + r = process_edpt0_xfer(rhport, ep_addr, buffer, total_bytes); + } else { + r = process_pipe_xfer(rhport, ep_addr, buffer, total_bytes); + } + dcd_int_enable(rhport); + return r; +} + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + volatile uint16_t *ctr = ep_addr_to_pipectr(rhport, ep_addr); + if (!ctr) return; + dcd_int_disable(rhport); + const uint32_t pid = *ctr & 0x3; + *ctr = pid | USB_PIPECTR_PID_STALL; + *ctr = USB_PIPECTR_PID_STALL; + dcd_int_enable(rhport); +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + volatile uint16_t *ctr = ep_addr_to_pipectr(rhport, ep_addr); + if (!ctr) return; + dcd_int_disable(rhport); + *ctr = USB_PIPECTR_SQCLR; + + if (ep_addr & TUSB_DIR_IN_MASK) { + *ctr = USB_PIPECTR_PID_BUF; + } else { + /* TODO */ + } + dcd_int_enable(rhport); +} + +//--------------------------------------------------------------------+ +// ISR +//--------------------------------------------------------------------+ +void dcd_int_handler(uint8_t rhport) +{ + (void)rhport; + + unsigned is0 = USB0.INTSTS0.WORD; + /* clear bits except VALID */ + USB0.INTSTS0.WORD = USB_IS0_VALID; + if (is0 & USB_IS0_VBINT) { + if (USB0.INTSTS0.BIT.VBSTS) { + dcd_connect(rhport); + } else { + dcd_disconnect(rhport); + } + } + if (is0 & USB_IS0_DVST) { + switch (is0 & USB_IS0_DVSQ) { + case USB_IS0_DVSQ_DEF: + process_bus_reset(rhport); + break; + case USB_IS0_DVSQ_ADDR: + process_set_address(rhport); + break; + default: + break; + } + } + if (is0 & USB_IS0_CTRT) { + if (is0 & USB_IS0_CTSQ_SETUP) { + /* A setup packet has been received. */ + process_setup_packet(rhport); + } else if (0 == (is0 & USB_IS0_CTSQ_MSK)) { + /* A ZLP has been sent/received. */ + process_status_completion(rhport); + } + } + if (is0 & USB_IS0_BEMP) { + const unsigned m = USB0.BEMPENB.WORD; + unsigned s = USB0.BEMPSTS.WORD & m; + USB0.BEMPSTS.WORD = 0; + if (s & 1) { + process_edpt0_bemp(rhport); + s &= ~1; + } + while (s) { + const unsigned num = __builtin_ctz(s); + process_pipe_bemp(rhport, num); + s &= ~(1< Date: Wed, 24 Mar 2021 00:53:55 +0900 Subject: update for gr_citurs --- hw/bsp/gr_citrus/board.mk | 5 +- hw/bsp/gr_citrus/gr_citrus.c | 8 +- src/portable/renesas/usba/dcd_usba.c | 155 ++++++++++++++++++++++++++++------- src/tusb_option.h | 3 + 4 files changed, 134 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/hw/bsp/gr_citrus/board.mk b/hw/bsp/gr_citrus/board.mk index 8675d8530..53f85aa74 100644 --- a/hw/bsp/gr_citrus/board.mk +++ b/hw/bsp/gr_citrus/board.mk @@ -28,6 +28,7 @@ MCU_DIR = hw/mcu/renesas/rx63n LD_FILE = hw/bsp/$(BOARD)/r5f5631fd.ld SRC_C += \ + src/portable/renesas/usba/dcd_usba.c \ $(MCU_DIR)/vects.c INC += \ @@ -36,10 +37,6 @@ INC += \ SRC_S += $(MCU_DIR)/start.S -# For TinyUSB port source -VENDOR = renesas -CHIP_FAMILY = usba - # For freeRTOS port source FREERTOS_PORT = RX600 diff --git a/hw/bsp/gr_citrus/gr_citrus.c b/hw/bsp/gr_citrus/gr_citrus.c index 3fa568cc0..f8cf8b18d 100644 --- a/hw/bsp/gr_citrus/gr_citrus.c +++ b/hw/bsp/gr_citrus/gr_citrus.c @@ -29,7 +29,7 @@ #include "interrupt_handlers.h" #define IRQ_PRIORITY_CMT0 5 -#define IRQ_PRIORITY_USBI0 5 +#define IRQ_PRIORITY_USBI0 6 #define IRQ_PRIORITY_SCI0 5 #define SYSTEM_PRCR_PRC1 (1<<1) @@ -146,13 +146,17 @@ void board_init(void) MPC.P20PFS.BYTE = 0b01010; PORT2.PMR.BIT.B1 = 1U; MPC.P21PFS.BYTE = 0b01010; - /* USB VBUS -> P16, RXD0 => P21, TXD0 => P20 */ + /* USB VBUS -> P16 DPUPE -> P14 */ + PORT1.PMR.BIT.B4 = 1U; PORT1.PMR.BIT.B6 = 1U; + MPC.P14PFS.BYTE = 0b10001; MPC.P16PFS.BYTE = MPC_PFS_ISEL | 0b10001; + MPC.PFUSB0.BIT.PUPHZS = 1; /* Lock MPC registers */ MPC.PWPR.BIT.PFSWE = 0; MPC.PWPR.BIT.B0WI = 1; + IR(USB0, USBI0) = 0; IPR(USB0, USBI0) = IRQ_PRIORITY_USBI0; /* Enable SCI0 */ diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index b0fa1749d..cc25a3a84 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -72,6 +72,7 @@ #define USB_PIPECTR_SQMON (1u<<6) #define USB_PIPECTR_SQCLR (1u<<8) #define USB_PIPECTR_ACLRM (1u<<9) +#define USB_PIPECTR_INBUFM (1u<<14) #define USB_PIPECTR_BSTS (1u<<15) #define USB_FIFOCTR_DTLN (0x1FF) @@ -213,15 +214,59 @@ static volatile uint16_t* ep_addr_to_pipectr(uint8_t rhport, unsigned ep_addr) return ctr; } +static unsigned wait_for_pipe_ready(void) +{ + unsigned ctr; + do { + ctr = USB0.D0FIFOCTR.WORD; + } while (!(ctr & USB_FIFOCTR_FRDY)); + return ctr; +} + +static unsigned select_pipe(unsigned num, unsigned attr) +{ + USB0.PIPESEL.WORD = num; + USB0.D0FIFOSEL.WORD = num | attr; + while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; + return wait_for_pipe_ready(); +} /* 1 less than 64 bytes were written * 2 no bytes were written - * 0 64 bytes were written */ -static int write_fifo(volatile void *fifo, pipe_state_t* pipe, unsigned mps) + * 0 mps bytes were written */ +static int write_fifo(volatile void *fifo, pipe_state_t* pipe, unsigned mps, unsigned ofs) +{ + unsigned rem = pipe->remaining - ofs; + if (!rem) return 2; + unsigned len = (rem < mps) ? rem: mps; + + hw_fifo_t *reg = (hw_fifo_t*)fifo; + uintptr_t addr = pipe->addr + pipe->length - rem; + if (addr & 1u) { + /* addr is not 2-byte aligned */ + reg->u8 = *(const uint8_t *)addr; + ++addr; + --len; + } + while (len >= 2) { + reg->u16 = *(const uint16_t *)addr; + addr += 2; + len -= 2; + } + if (len) { + reg->u8 = *(const uint8_t *)addr; + ++addr; + } + if (rem < mps) return 1; + return 0; +} +#if 1 +static int write_fifo2(volatile void *fifo, pipe_state_t* pipe, unsigned mps) { unsigned rem = pipe->remaining; if (!rem) return 2; unsigned len = (rem < mps) ? rem: mps; + pipe->remaining = rem - len; hw_fifo_t *reg = (hw_fifo_t*)fifo; uintptr_t addr = pipe->addr + pipe->length - rem; @@ -243,6 +288,7 @@ static int write_fifo(volatile void *fifo, pipe_state_t* pipe, unsigned mps) if (rem < mps) return 1; return 0; } +#endif /* 1 if the number of bytes read is less than 64 bytes * 0 otherwise */ @@ -313,7 +359,7 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, pipe->data = USB0.DCPCTR.BIT.SQMON; if (ep_addr) { /* IN */ TU_ASSERT(USB0.DCPCTR.BIT.BSTS && (USB0.USBREQ.WORD & 0x80)); - if (write_fifo(&USB0.CFIFO.WORD, pipe, 64)) { + if (write_fifo(&USB0.CFIFO.WORD, pipe, 64, 0)) { USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; } } @@ -321,11 +367,11 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); } else { /* ZLP */ - pipe->addr = 0; - pipe->length = 0; - pipe->remaining = 0; - pipe->data = USB0.DCPCTR.BIT.SQMON; - USB0.DCPCTR.WORD = USB_PIPECTR_CCPL | USB_PIPECTR_PID_BUF; + pipe->addr = 0; + pipe->length = 0; + pipe->remaining = 0; + pipe->data = USB0.DCPCTR.BIT.SQMON; + USB0.DCPCTR.WORD = USB_PIPECTR_CCPL | USB_PIPECTR_PID_BUF; // TU_LOG1("Z %x\r\n", USB0.DCPCTR.WORD); } return true; @@ -338,7 +384,7 @@ static void process_edpt0_bemp(uint8_t rhport) if (USB0.DCPCTR.BIT.SQMON == data) { TU_LOG1("W %x\r\n", USB0.DCPCTR.WORD); /* retry transfer */ - int r = write_fifo(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); + int r = write_fifo(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, 0); if (r) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; return; } @@ -347,7 +393,7 @@ static void process_edpt0_bemp(uint8_t rhport) pipe->remaining = rem - 64; pipe->data = data ^ 1; TU_LOG1("Y %d %x\r\n", rem - 64, USB0.DCPCTR.WORD); - int r = write_fifo(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); + int r = write_fifo(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, 0); if (r) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; return; } @@ -393,9 +439,23 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, if (dir) { /* IN */ USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16; while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; - if (write_fifo(&USB0.D0FIFO.WORD, pipe, mps)) { +#if 0 + unsigned ofs = 0; + if (USB0.PIPECFG.BIT.DBLB && (total_bytes > mps)) { + write_fifo(&USB0.D0FIFO.WORD, pipe, mps, 0); + } + if (write_fifo(&USB0.D0FIFO.WORD, pipe, mps, ofs)) { + USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; + } +#else + if (USB0.PIPECFG.BIT.DBLB && (total_bytes > mps)) { + write_fifo2(&USB0.D0FIFO.WORD, pipe, mps); + wait_for_pipe_ready(); + } + if (write_fifo2(&USB0.D0FIFO.WORD, pipe, mps)) { USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; } +#endif USB0.D0FIFOSEL.WORD = 0; } else { volatile reg_pipetre_t *pt = get_pipetre(num); @@ -411,43 +471,76 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); return true; } +#if 0 +static void process_pipe_bemp(uint8_t rhport, unsigned num) +{ + pipe_state_t *pipe = &_dcd.pipe[num]; + unsigned rem = pipe->remaining; + USB0.PIPESEL.WORD = num; + const unsigned mps = USB0.PIPEMAXP.WORD; + if (rem > mps) { + rem -= mps; + pipe->remaining = rem; + if (USB0.PIPECFG.BIT.DBLB) { + if (rem > mps) { + unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_16); + int r = write_fifo(&USB0.D0FIFO.WORD, pipe, mps, mps); + if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; + USB0.D0FIFOSEL.WORD = 0; + TU_LOG1("< %d %x %x %d\r\n", rem, ctr, *get_pipectr(num), r); + } + } else { + unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_16); + int r = write_fifo(&USB0.D0FIFO.WORD, pipe, mps, 0); + if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; + USB0.D0FIFOSEL.WORD = 0; + TU_LOG1("< %d %x %x %d\r\n", rem, ctr, *get_pipectr(num), r); + } + return; + } + pipe->addr = 0; + pipe->remaining = 0; + USB0.D0FIFOSEL.WORD = 0; + dcd_event_xfer_complete(rhport, pipe->ep, pipe->length, + XFER_RESULT_SUCCESS, true); + TU_LOG1("cE\r\n"); +} +#else static void process_pipe_bemp(uint8_t rhport, unsigned num) { pipe_state_t *pipe = &_dcd.pipe[num]; const unsigned rem = pipe->remaining; - if (rem > 64) { - pipe->remaining = rem - 64; - TU_LOG1("Y %d\r\n", rem - 64); + if (rem) { USB0.PIPESEL.WORD = num; const unsigned mps = USB0.PIPEMAXP.WORD; - USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16; - while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; - int r = write_fifo(&USB0.D0FIFO.WORD, pipe, mps); + unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_16); + int r = write_fifo2(&USB0.D0FIFO.WORD, pipe, mps); if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; USB0.D0FIFOSEL.WORD = 0; + TU_LOG1("< %d %x %x %d\r\n", rem, ctr, *get_pipectr(num), r); + return; + } + if (*get_pipectr(num) & USB_PIPECTR_INBUFM) { + TU_LOG1("< SKIP\r\n"); return; } pipe->addr = 0; pipe->remaining = 0; + USB0.D0FIFOSEL.WORD = 0; dcd_event_xfer_complete(rhport, pipe->ep, pipe->length, XFER_RESULT_SUCCESS, true); - // TU_LOG1("cE\r\n"); + TU_LOG1("cE\r\n"); } +#endif static void process_pipe_brdy(uint8_t rhport, unsigned num) { - pipe_state_t *pipe = &_dcd.pipe[num]; - USB0.PIPESEL.WORD = num; - const unsigned mps = USB0.PIPEMAXP.WORD; - USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_8; - while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; - unsigned ctr; - do { - ctr = USB0.D0FIFOCTR.WORD; - } while (!(ctr & USB_FIFOCTR_FRDY)); - const unsigned len = ctr & USB_FIFOCTR_DTLN; - TU_LOG1(">> %d %x %x\r\n", num, USB0.D0FIFOSEL.WORD, ctr); + const unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_8); + const unsigned len = ctr & USB_FIFOCTR_DTLN; + const unsigned mps = USB0.PIPEMAXP.WORD; + pipe_state_t *pipe = &_dcd.pipe[num]; + // TU_LOG1("> %d %x %x\r\n", num, USB0.D0FIFOSEL.WORD, ctr); int cplt = read_fifo(&USB0.D0FIFO.WORD, pipe, mps, len); if (cplt || (len < mps)) { if (2 != cplt) { @@ -457,7 +550,7 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) dcd_event_xfer_complete(rhport, pipe->ep, pipe->length - pipe->remaining, XFER_RESULT_SUCCESS, true); - TU_LOG1("c\r\n"); + // TU_LOG1("c\r\n"); } else { USB0.D0FIFOSEL.WORD = 0; } @@ -589,7 +682,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) const unsigned mps = ep_desc->wMaxPacketSize.size; if (xfer == TUSB_XFER_ISOCHRONOUS && mps > 256) { - /* USBB support up to 256 bytes */ + /* USBa supports up to 256 bytes */ return false; } diff --git a/src/tusb_option.h b/src/tusb_option.h index d0ed78acd..644208ab4 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -108,6 +108,9 @@ #define OPT_MCU_EFM32GG11 1301 ///< Silabs EFM32GG11 #define OPT_MCU_EFM32GG12 1302 ///< Silabs EFM32GG12 +// Renesas RX +#define OPT_MCU_RX63X 1400 ///< Renesas RX63N/631 + /** @} */ /** \defgroup group_supported_os Supported RTOS -- cgit v1.3.1 From 1138f8cc704e09af3335e253e5f244fde90d982f Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Fri, 26 Mar 2021 15:30:43 -0400 Subject: Add DFU Class per Version 1.1 Spec --- src/class/dfu/dfu.h | 107 +++++++ src/class/dfu/dfu_rt_device.c | 667 ++++++++++++++++++++++++++++++++++++++++-- src/class/dfu/dfu_rt_device.h | 111 +++++-- src/common/tusb_types.h | 19 ++ src/device/usbd.c | 8 +- src/device/usbd.h | 15 +- src/device/usbd_control.c | 2 +- src/tusb_option.h | 4 + 8 files changed, 875 insertions(+), 58 deletions(-) create mode 100644 src/class/dfu/dfu.h (limited to 'src') diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h new file mode 100644 index 000000000..39ce567da --- /dev/null +++ b/src/class/dfu/dfu.h @@ -0,0 +1,107 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_DFU_H_ +#define _TUSB_DFU_H_ + +#include "common/tusb_common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Common Definitions +//--------------------------------------------------------------------+ +// DFU Protocol +typedef enum +{ + DFU_PROTOCOL_RT = 0x01, + DFU_PROTOCOL_DFU = 0x02, +} dfu_protocol_type_t; + +// DFU Descriptor Type +typedef enum +{ + DFU_DESC_FUNCTIONAL = 0x21, +} dfu_descriptor_type_t; + +// DFU Requests +typedef enum { + DFU_REQUEST_DETACH = 0, + DFU_REQUEST_DNLOAD = 1, + DFU_REQUEST_UPLOAD = 2, + DFU_REQUEST_GETSTATUS = 3, + DFU_REQUEST_CLRSTATUS = 4, + DFU_REQUEST_GETSTATE = 5, + DFU_REQUEST_ABORT = 6, +} dfu_requests_t; + +// DFU States +typedef enum { + APP_IDLE = 0, + APP_DETACH = 1, + DFU_IDLE = 2, + DFU_DNLOAD_SYNC = 3, + DFU_DNBUSY = 4, + DFU_DNLOAD_IDLE = 5, + DFU_MANIFEST_SYNC = 6, + DFU_MANIFEST = 7, + DFU_MANIFEST_WAIT_RESET = 8, + DFU_UPLOAD_IDLE = 9, + DFU_ERROR = 10, +} dfu_mode_state_t; + +// DFU Status +typedef enum { + DFU_STATUS_OK = 0x00, + DFU_STATUS_ERRTARGET = 0x01, + DFU_STATUS_ERRFILE = 0x02, + DFU_STATUS_ERRWRITE = 0x03, + DFU_STATUS_ERRERASE = 0x04, + DFU_STATUS_ERRCHECK_ERASED = 0x05, + DFU_STATUS_ERRPROG = 0x06, + DFU_STATUS_ERRVERIFY = 0x07, + DFU_STATUS_ERRADDRESS = 0x08, + DFU_STATUS_ERRNOTDONE = 0x09, + DFU_STATUS_ERRFIRMWARE = 0x0A, + DFU_STATUS_ERRVENDOR = 0x0B, + DFU_STATUS_ERRUSBR = 0x0C, + DFU_STATUS_ERRPOR = 0x0D, + DFU_STATUS_ERRUNKNOWN = 0x0E, + DFU_STATUS_ERRSTALLEDPKT = 0x0F, +} dfu_mode_device_status_t; + +#define DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK (1 << 0) +#define DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK (1 << 1) +#define DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK (1 << 2) +#define DFU_FUNC_ATTR_WILL_DETACH_BITMASK (1 << 3) + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DFU_H_ */ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 5700615be..965d1661e 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -34,34 +34,176 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -typedef enum { - DFU_REQUEST_DETACH = 0, - DFU_REQUEST_DNLOAD = 1, - DFU_REQUEST_UPLOAD = 2, - DFU_REQUEST_GETSTATUS = 3, - DFU_REQUEST_CLRSTATUS = 4, - DFU_REQUEST_GETSTATE = 5, - DFU_REQUEST_ABORT = 6, -} dfu_requests_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +typedef struct TU_ATTR_PACKED +{ + dfu_mode_device_status_t status; + dfu_mode_state_t state; + uint8_t attrs; + bool blk_transfer_in_proc; + + uint8_t itf_num; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; +} dfu_state_ctx_t; typedef struct TU_ATTR_PACKED { - uint8_t status; - uint8_t poll_timeout[3]; - uint8_t state; - uint8_t istring; -} dfu_status_t; + uint8_t bStatus; + uint8_t bwPollTimeout[3]; + uint8_t bState; + uint8_t iString; +} dfu_status_req_payload_t; + +TU_VERIFY_STATIC( sizeof(dfu_status_req_payload_t) == 6, "size is not correct"); + +// Only a single dfu state is allowed +CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx; + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); +static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); + +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + +static tu_lookup_entry_t const _dfu_request_lookup[] = +{ + { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, + { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, + { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, + { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, + { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, + { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, + { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, +}; + +static tu_lookup_table_t const _dfu_request_table = +{ + .count = TU_ARRAY_SIZE(_dfu_request_lookup), + .items = _dfu_request_lookup +}; + +static tu_lookup_entry_t const _dfu_mode_state_lookup[] = +{ + { .key = APP_IDLE , .data = "APP_IDLE" }, + { .key = APP_DETACH , .data = "APP_DETACH" }, + { .key = DFU_IDLE , .data = "DFU_IDLE" }, + { .key = DFU_DNLOAD_SYNC , .data = "DFU_DNLOAD_SYNC" }, + { .key = DFU_DNBUSY , .data = "DFU_DNBUSY" }, + { .key = DFU_DNLOAD_IDLE , .data = "DFU_DNLOAD_IDLE" }, + { .key = DFU_MANIFEST_SYNC , .data = "DFU_MANIFEST_SYNC" }, + { .key = DFU_MANIFEST , .data = "DFU_MANIFEST" }, + { .key = DFU_MANIFEST_WAIT_RESET , .data = "DFU_MANIFEST_WAIT_RESET" }, + { .key = DFU_UPLOAD_IDLE , .data = "DFU_UPLOAD_IDLE" }, + { .key = DFU_ERROR , .data = "DFU_ERROR" }, +}; + +static tu_lookup_table_t const _dfu_mode_state_table = +{ + .count = TU_ARRAY_SIZE(_dfu_mode_state_lookup), + .items = _dfu_mode_state_lookup +}; + +static tu_lookup_entry_t const _dfu_mode_status_lookup[] = +{ + { .key = DFU_STATUS_OK , .data = "OK" }, + { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, + { .key = DFU_STATUS_ERRFILE , .data = "errFILE" }, + { .key = DFU_STATUS_ERRWRITE , .data = "errWRITE" }, + { .key = DFU_STATUS_ERRERASE , .data = "errERASE" }, + { .key = DFU_STATUS_ERRCHECK_ERASED , .data = "errCHECK_ERASED" }, + { .key = DFU_STATUS_ERRPROG , .data = "errPROG" }, + { .key = DFU_STATUS_ERRVERIFY , .data = "errVERIFY" }, + { .key = DFU_STATUS_ERRADDRESS , .data = "errADDRESS" }, + { .key = DFU_STATUS_ERRNOTDONE , .data = "errNOTDONE" }, + { .key = DFU_STATUS_ERRFIRMWARE , .data = "errFIRMWARE" }, + { .key = DFU_STATUS_ERRVENDOR , .data = "errVENDOR" }, + { .key = DFU_STATUS_ERRUSBR , .data = "errUSBR" }, + { .key = DFU_STATUS_ERRPOR , .data = "errPOR" }, + { .key = DFU_STATUS_ERRUNKNOWN , .data = "errUNKNOWN" }, + { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, +}; + +static tu_lookup_table_t const _dfu_mode_status_table = +{ + .count = TU_ARRAY_SIZE(_dfu_mode_status_lookup), + .items = _dfu_mode_status_lookup +}; + +#endif + +#define dfu_rtd_debug_print_context() \ +{ \ + TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ + tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), \ + tu_lookup_find(&_dfu_mode_status_table, _dfu_state_ctx.status) ); \ +} //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ void dfu_rtd_init(void) { + if ( tud_dfu_runtime_init_cb ) { + _dfu_state_ctx.state = (tud_dfu_runtime_init_cb() == DFU_PROTOCOL_DFU) ? APP_DETACH : APP_IDLE; + } else { + _dfu_state_ctx.state = APP_IDLE; + } + + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); + _dfu_state_ctx.blk_transfer_in_proc = false; + + dfu_rtd_debug_print_context(); } void dfu_rtd_reset(uint8_t rhport) { - (void) rhport; + if ( tud_dfu_runtime_usb_reset_cb ) + { + tud_dfu_runtime_usb_reset_cb(rhport, _dfu_state_ctx.state); + } + + switch (_dfu_state_ctx.state) + { + case APP_DETACH: + { + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + case DFU_IDLE: + case DFU_DNLOAD_SYNC: + case DFU_DNBUSY: + case DFU_DNLOAD_IDLE: + case DFU_MANIFEST_SYNC: + case DFU_MANIFEST: + case DFU_MANIFEST_WAIT_RESET: + case DFU_UPLOAD_IDLE: + { + _dfu_state_ctx.state = (tud_dfu_runtime_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; + } + break; + + case DFU_ERROR: + default: + { + _dfu_state_ctx.state = APP_IDLE; + } + break; + } + + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); + _dfu_state_ctx.blk_transfer_in_proc = false; + dfu_rtd_debug_print_context(); } uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) @@ -69,9 +211,10 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui (void) rhport; (void) max_len; - // Ensure this is DFU Runtime + // Ensure this is DFU Runtime or Mode TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && - itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT, 0); + ( (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT) + | (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) ), 0); uint8_t const * p_desc = tu_desc_next( itf_desc ); uint16_t drv_len = sizeof(tusb_desc_interface_t); @@ -90,9 +233,16 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui // return false to stall control endpoint (e.g unsupported request) bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - // nothing to do with DATA and ACK stage + if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) + { + dfu_mode_req_dnload_reply(rhport, request); + return true; + } + + // nothing to do with any other DATA or ACK stage if ( stage != CONTROL_STAGE_SETUP ) return true; + TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request @@ -106,34 +256,487 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request // Handle class request only from here TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - switch ( request->bRequest ) + switch (request->bRequest) { case DFU_REQUEST_DETACH: - tud_control_status(rhport, request); - tud_dfu_runtime_reboot_to_dfu_cb(); - break; - + case DFU_REQUEST_DNLOAD: + case DFU_REQUEST_UPLOAD: case DFU_REQUEST_GETSTATUS: + case DFU_REQUEST_CLRSTATUS: + case DFU_REQUEST_GETSTATE: + case DFU_REQUEST_ABORT: { - // status = OK, poll timeout = 0, state = app idle, istring = 0 - uint8_t status_response[6] = { 0, 0, 0, 0, 0, 0 }; - tud_control_xfer(rhport, request, status_response, sizeof(status_response)); + return dfu_state_machine(rhport, request); } break; - default: return false; // stall unsupported request + default: + { + TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); + return ( tud_dfu_runtime_req_nonstandard_cb ) ? tud_dfu_runtime_req_nonstandard_cb(rhport, stage, request) : false; + } + break; } return true; } +void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) +{ + _dfu_state_ctx.status = status; +} -bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) { - (void) rhport; - (void) ep_addr; - (void) result; - (void) xferred_bytes; + TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + uint16_t retval = tud_dfu_runtime_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.epin_buf, wLength); + tud_control_xfer(rhport, request, &_dfu_state_ctx.epin_buf, retval); + return retval; +} + +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + dfu_status_req_payload_t resp; + + resp.bStatus = _dfu_state_ctx.status; + if ( tud_dfu_runtime_get_poll_timeout_cb ) + { + tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); + } else { + memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); + } + resp.bState = _dfu_state_ctx.state; + resp.iString = ( tud_dfu_runtime_get_status_desc_table_index_cb ) ? tud_dfu_runtime_get_status_desc_table_index_cb() : 0; + + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); +} + +static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); +} + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) +{ + // TODO: add "zero" copy mode so the buffer we read into can be provided by the user + // if they wish, there still will be the internal control buffer copy to this buffer + // but this mode would provide zero copy from the class driver to the application + + // setup for data phase + tud_control_xfer(rhport, request, &_dfu_state_ctx.epout_buf, request->wLength); +} + +static void dfu_runtime_start_status_poll_timeout() +{ + uint8_t bwPollTimeout[3] = {0,0,0}; + + if ( tud_dfu_runtime_get_poll_timeout_cb ) + { + tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); + } + + tud_dfu_runtime_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); +} + +void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + dfu_runtime_start_status_poll_timeout(); + tud_dfu_runtime_req_dnload_data_cb(request->wValue, (uint8_t *)&_dfu_state_ctx.epout_buf, request->wLength); + _dfu_state_ctx.blk_transfer_in_proc = false; +} + +void tud_dfu_runtime_poll_timeout_done() +{ + if (_dfu_state_ctx.state == DFU_DNBUSY) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + } else if (_dfu_state_ctx.state == DFU_MANIFEST) + { + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; + } +} + +static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) +{ + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state)); + + switch (_dfu_state_ctx.state) + { + case APP_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DETACH: + { + _dfu_state_ctx.state = APP_DETACH; + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 1) + { + tud_dfu_runtime_reboot_to_dfu_cb(); + } else { + tud_dfu_runtime_detach_start_timer_cb(request->wValue); + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case APP_DETACH: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = APP_IDLE; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + dfu_req_dnload_setup(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_UPLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + { + _dfu_state_ctx.state = DFU_UPLOAD_IDLE; + dfu_req_upload(rhport, request, request->wValue, request->wLength); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + ; // do nothing, but don't stall so continue on + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ( _dfu_state_ctx.blk_transfer_in_proc ) + { + _dfu_state_ctx.state = DFU_DNBUSY; + dfu_req_getstatus_reply(rhport, request); + } else { + _dfu_state_ctx.state = DFU_DNLOAD_IDLE; + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNBUSY: + { + switch (request->bRequest) + { + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + + dfu_req_dnload_setup(rhport, request); + } else { + if ( tud_dfu_runtime_device_data_done_check_cb() ) + { + _dfu_state_ctx.state = DFU_MANIFEST_SYNC; + tud_control_status(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall + } + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if ( tud_dfu_runtime_abort_cb ) + { + tud_dfu_runtime_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + { + _dfu_state_ctx.state = DFU_MANIFEST; + dfu_req_getstatus_reply(rhport, request); + } else { + if ( tud_dfu_runtime_firmware_valid_check_cb() ) + { + _dfu_state_ctx.state = DFU_IDLE; + } + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST: + { + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_WAIT_RESET: + { + // technically we should never even get here, but we will handle it just in case + TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_UPLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_UPLOAD: + { + if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) + { + _dfu_state_ctx.state = DFU_IDLE; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if (tud_dfu_runtime_abort_cb) + { + tud_dfu_runtime_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_ERROR: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_CLRSTATUS: + { + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + default: + _dfu_state_ctx.state = DFU_ERROR; + TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); + return false; // Unexpected state, stall and change to error + } + return true; } + #endif diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index cff43d035..0d8f67a9b 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -29,36 +29,106 @@ #include "common/tusb_common.h" #include "device/usbd.h" +#include "dfu.h" #ifdef __cplusplus extern "C" { #endif - //--------------------------------------------------------------------+ -// Common Definitions +// Application Callback API (weak is optional) //--------------------------------------------------------------------+ +// Allow the application to update the status as required. +// Is set to DFU_STATUS_OK during internal initialization and USB reset +// Value is not checked to allow for custom statuses to be used +void tud_dfu_runtime_set_status(dfu_mode_device_status_t status); -// DFU Protocol -typedef enum -{ - DFU_PROTOCOL_RT = 1, - DFU_PROTOCOL_DFU = 2, -} dfu_protocol_type_t; +// Invoked when a DFU_DETACH request is received and bitWillDetatch is set +void tud_dfu_runtime_reboot_to_dfu_cb(); -// DFU Descriptor Type -typedef enum -{ - DFU_DESC_FUNCTIONAL = 0x21, -} dfu_descriptor_type_t; +// Invoked when a DFU_DETACH request is received and bitWillDetatch is not set +// This should start a timer for wTimeout ms +// The application should then look for a USB reset signal to occur before +// the timeout has elapsed. The reset signal will invoke tud_dfu_runtime_usb_reset_cb. +// If this reset signal is received before the timeout, then the application must +// switch to DFU mode. +// If the timer expires, the app does not need to do anything. +// NOTE: This callback should return immediately, and not implement the delay +// internally, as this can will hold up the USB stack +TU_ATTR_WEAK void tud_dfu_runtime_detach_start_timer_cb(uint16_t wTimeout); +// Invoked when a nonstandard request is received +// Use may be vendor specific. +// Return false to stall +TU_ATTR_WEAK bool tud_dfu_runtime_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ +// Invoked when a reset is received to check if firmware is valid +bool tud_dfu_runtime_firmware_valid_check_cb(); + +// Invoked during initialization of the dfu driver to set attributes +// Return byte set with bitmasks: +// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK +// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK +// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK +// DFU_FUNC_ATTR_WILL_DETACH_BITMASK +// Note: This should match the USB descriptor +uint8_t tud_dfu_runtime_init_attrs_cb(); + +// Invoked during initialization of the dfu driver to start as RT or DFU +// This will determine if the internal state machine will begin in +// APP_IDLE or DFU_IDLE +TU_ATTR_WEAK dfu_protocol_type_t tud_dfu_runtime_init_cb(); + +// Invoked during a DFU_GETSTATUS request to get for the string index +// to the status description string table. +TU_ATTR_WEAK uint8_t tud_dfu_runtime_get_status_desc_table_index_cb(); -// Invoked when received new data -TU_ATTR_WEAK void tud_dfu_runtime_reboot_to_dfu_cb(void); +// Invoked during a USB reset +// Lets the app know that a USB reset has occurred so it can act accordingly, +// See tud_dfu_runtime_detach_start_timer_cb for how to handle the APP_DETACH state +// Other states will be application specific +TU_ATTR_WEAK void tud_dfu_runtime_usb_reset_cb(uint8_t rhport, dfu_mode_state_t state); + +// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use +// before the subsequent DFU_GETSTATUS requests. +// The purpose of this value is to allow the device to tell the host +// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks +// to allow the device to have time to erase, write memory, etc. +// ms_timeout is a pointer to array of length 3. +// Refer to the USB DFU class specification for more details +TU_ATTR_WEAK void tud_dfu_runtime_get_poll_timeout_cb(uint8_t *ms_timeout); + +// Invoked when a DFU_DNLOAD request is received +// This should start a timer for ms_timeout ms +// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called +// NOTE: This callback should return immediately, and not implement the delay +// internally, as this will hold up the class stack from receiving any packets +// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states +void tud_dfu_runtime_start_poll_timeout_cb(uint8_t *ms_timeout); + +// Must be called when the poll_timeout has elapsed +void tud_dfu_runtime_poll_timeout_done(); + +// Invoked when a DFU_DNLOAD request is received +// This callback takes the wBlockNum chunk of length length and provides it +// to the application at the data pointer. This data is only valid for this +// call, so the app must use it not or copy it. +void tud_dfu_runtime_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); + +// Invoked during the last DFU_DNLOAD request, signifying that the host believes +// it is done transmitting data. +// Return true if the application agrees there is no more data +// Return false if the device disagrees, which will stall the pipe, and the Host +// should initiate a recovery procedure +bool tud_dfu_runtime_device_data_done_check_cb(); + +// Invoked when the Host has terminated a download or upload transfer +TU_ATTR_WEAK void tud_dfu_runtime_abort_cb(); + +// Invoked when a DFU_UPLOAD request is received +// This callback must populate data with up to length bytes +// Return the number of bytes to write +uint16_t tud_dfu_runtime_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); //--------------------------------------------------------------------+ // Internal Class Driver API @@ -67,8 +137,11 @@ void dfu_rtd_init(void); void dfu_rtd_reset(uint8_t rhport); uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +//--------------------------------------------------------------------+ +void dfu_mode_init(void); +void dfu_mode_reset(uint8_t rhport); +void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); #ifdef __cplusplus } #endif diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ba3fe2c41..a462b498f 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -421,6 +421,25 @@ typedef struct TU_ATTR_PACKED char url[]; } tusb_desc_webusb_url_t; +// DFU Functional Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength; + uint8_t bDescriptorType; + + struct TU_ATTR_PACKED { + uint8_t bitCanDnload : 1; + uint8_t bitCanUpload : 1; + uint8_t bitManifestationTolerant : 1; + uint8_t bitWillDetach : 1; + uint8_t reserved : 4; + } bmAttributes; + + uint16_t wDetachTimeOut; + uint16_t wTransferSize; + uint16_t bcdDFUVersion; +} tusb_desc_dfu_functional_t; + /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ diff --git a/src/device/usbd.c b/src/device/usbd.c index 4fc221888..28c9acdd2 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -182,7 +182,7 @@ static usbd_class_driver_t const _usbd_driver[] = .reset = dfu_rtd_reset, .open = dfu_rtd_open, .control_xfer_cb = dfu_rtd_control_xfer_cb, - .xfer_cb = dfu_rtd_xfer_cb, + .xfer_cb = NULL, .sof = NULL }, #endif @@ -1270,9 +1270,9 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) /** * 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) { diff --git a/src/device/usbd.h b/src/device/usbd.h index b5f7dceba..f9700811f 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -529,7 +529,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb //------------- DFU Runtime -------------// #define TUD_DFU_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) -#define TUD_DFU_APP_SUBCLASS 0x01u +#define TUD_DFU_APP_SUBCLASS (APP_SUBCLASS_DFU_RUNTIME) // Length of template descriptr: 18 bytes #define TUD_DFU_RT_DESC_LEN (9 + 9) @@ -542,6 +542,17 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +// Length of template descriptr: 18 bytes +#define TUD_DFU_MODE_DESC_LEN (9 + 9) + +// DFU runtime descriptor +// Interface number, string index, alternate setting, attributes, detach timeout, transfer size +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _stridx, _alt_setting, _attr, _timeout, _xfer_size) \ + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt_setting, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + /* Function */ \ + 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) + //------------- CDC-ECM -------------// diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index d15380199..724c652e6 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -107,7 +107,7 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo _ctrl_xfer.buffer = (uint8_t*) buffer; _ctrl_xfer.total_xferred = 0U; _ctrl_xfer.data_len = tu_min16(len, request->wLength); - + if (request->wLength > 0U) { if(_ctrl_xfer.data_len > 0U) diff --git a/src/tusb_option.h b/src/tusb_option.h index 6cbdefbf1..1af3ee672 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -237,6 +237,10 @@ #define CFG_TUD_DFU_RUNTIME 0 #endif +#ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE + #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 64 +#endif + #ifndef CFG_TUD_NET #define CFG_TUD_NET 0 #endif -- cgit v1.3.1 From fb7b47cf07a7a39d39d22502164fec5925fb163e Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Fri, 26 Mar 2021 17:32:03 -0400 Subject: Minor cleanup --- src/class/dfu/dfu_rt_device.c | 20 +++++++++----------- src/class/dfu/dfu_rt_device.h | 4 ---- 2 files changed, 9 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 965d1661e..0cbc8eeda 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -66,6 +66,7 @@ CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx; static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); +static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); //--------------------------------------------------------------------+ @@ -280,6 +281,7 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request return true; } + void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) { _dfu_state_ctx.status = status; @@ -325,21 +327,17 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * tud_control_xfer(rhport, request, &_dfu_state_ctx.epout_buf, request->wLength); } -static void dfu_runtime_start_status_poll_timeout() +static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { - uint8_t bwPollTimeout[3] = {0,0,0}; + uint8_t bwPollTimeout[3] = {0,0,0}; - if ( tud_dfu_runtime_get_poll_timeout_cb ) - { - tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); - } + if ( tud_dfu_runtime_get_poll_timeout_cb ) + { + tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); + } - tud_dfu_runtime_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); -} + tud_dfu_runtime_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); -void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - dfu_runtime_start_status_poll_timeout(); tud_dfu_runtime_req_dnload_data_cb(request->wValue, (uint8_t *)&_dfu_state_ctx.epout_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; } diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 0d8f67a9b..9e7ae029e 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -138,10 +138,6 @@ void dfu_rtd_reset(uint8_t rhport); uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -//--------------------------------------------------------------------+ -void dfu_mode_init(void); -void dfu_mode_reset(uint8_t rhport); -void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); #ifdef __cplusplus } #endif -- cgit v1.3.1 From e010ea30e57e0f8561f8aa7b66afefb01a9bc42d Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Sat, 27 Mar 2021 14:42:19 +0900 Subject: using BRDY interruption for handling IN transfers. --- src/portable/renesas/usba/dcd_usba.c | 228 ++++++++++------------------------- 1 file changed, 62 insertions(+), 166 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index cc25a3a84..e7518b01f 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -200,9 +200,9 @@ static volatile uint16_t* ep_addr_to_pipectr(uint8_t rhport, unsigned ep_addr) { (void)rhport; volatile uint16_t *ctr = NULL; - const unsigned epn = ep_addr & 0xFu; + const unsigned epn = tu_edpt_number(ep_addr); if (epn) { - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned dir = tu_edpt_dir(ep_addr); const unsigned num = _dcd.ep[dir][epn]; if (num) { ctr = (volatile uint16_t*)&USB0.PIPE1CTR.WORD; @@ -234,39 +234,11 @@ static unsigned select_pipe(unsigned num, unsigned attr) /* 1 less than 64 bytes were written * 2 no bytes were written * 0 mps bytes were written */ -static int write_fifo(volatile void *fifo, pipe_state_t* pipe, unsigned mps, unsigned ofs) -{ - unsigned rem = pipe->remaining - ofs; - if (!rem) return 2; - unsigned len = (rem < mps) ? rem: mps; - - hw_fifo_t *reg = (hw_fifo_t*)fifo; - uintptr_t addr = pipe->addr + pipe->length - rem; - if (addr & 1u) { - /* addr is not 2-byte aligned */ - reg->u8 = *(const uint8_t *)addr; - ++addr; - --len; - } - while (len >= 2) { - reg->u16 = *(const uint16_t *)addr; - addr += 2; - len -= 2; - } - if (len) { - reg->u8 = *(const uint8_t *)addr; - ++addr; - } - if (rem < mps) return 1; - return 0; -} -#if 1 -static int write_fifo2(volatile void *fifo, pipe_state_t* pipe, unsigned mps) +static int write_fifo(volatile void *fifo, pipe_state_t* pipe, unsigned mps) { unsigned rem = pipe->remaining; if (!rem) return 2; - unsigned len = (rem < mps) ? rem: mps; - pipe->remaining = rem - len; + unsigned len = TU_MIN(rem, mps); hw_fifo_t *reg = (hw_fifo_t*)fifo; uintptr_t addr = pipe->addr + pipe->length - rem; @@ -288,7 +260,6 @@ static int write_fifo2(volatile void *fifo, pipe_state_t* pipe, unsigned mps) if (rem < mps) return 1; return 0; } -#endif /* 1 if the number of bytes read is less than 64 bytes * 0 otherwise */ @@ -359,7 +330,7 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, pipe->data = USB0.DCPCTR.BIT.SQMON; if (ep_addr) { /* IN */ TU_ASSERT(USB0.DCPCTR.BIT.BSTS && (USB0.USBREQ.WORD & 0x80)); - if (write_fifo(&USB0.CFIFO.WORD, pipe, 64, 0)) { + if (write_fifo(&USB0.CFIFO.WORD, pipe, 64)) { USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; } } @@ -372,7 +343,6 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, pipe->remaining = 0; pipe->data = USB0.DCPCTR.BIT.SQMON; USB0.DCPCTR.WORD = USB_PIPECTR_CCPL | USB_PIPECTR_PID_BUF; - // TU_LOG1("Z %x\r\n", USB0.DCPCTR.WORD); } return true; } @@ -382,9 +352,8 @@ static void process_edpt0_bemp(uint8_t rhport) pipe_state_t *pipe = &_dcd.pipe[0]; unsigned data = pipe->data; if (USB0.DCPCTR.BIT.SQMON == data) { - TU_LOG1("W %x\r\n", USB0.DCPCTR.WORD); /* retry transfer */ - int r = write_fifo(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, 0); + int r = write_fifo(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); if (r) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; return; } @@ -392,16 +361,14 @@ static void process_edpt0_bemp(uint8_t rhport) if (rem > 64) { pipe->remaining = rem - 64; pipe->data = data ^ 1; - TU_LOG1("Y %d %x\r\n", rem - 64, USB0.DCPCTR.WORD); - int r = write_fifo(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, 0); + int r = write_fifo(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); if (r) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; return; } pipe->addr = 0; pipe->remaining = 0; dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN), - pipe->length, XFER_RESULT_SUCCESS, true); - // TU_LOG1("c\r\n"); + pipe->length, XFER_RESULT_SUCCESS, true); } static void process_edpt0_brdy(uint8_t rhport) @@ -414,8 +381,7 @@ static void process_edpt0_brdy(uint8_t rhport) } dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), _dcd.pipe[0].length - _dcd.pipe[0].remaining, - XFER_RESULT_SUCCESS, true); - // TU_LOG1("c\r\n"); + XFER_RESULT_SUCCESS, true); } } @@ -423,8 +389,8 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, { (void)rhport; - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned dir = tu_edpt_dir(ep_addr); const unsigned num = _dcd.ep[dir][epn]; TU_ASSERT(num); @@ -439,120 +405,61 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, if (dir) { /* IN */ USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16; while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; -#if 0 - unsigned ofs = 0; - if (USB0.PIPECFG.BIT.DBLB && (total_bytes > mps)) { - write_fifo(&USB0.D0FIFO.WORD, pipe, mps, 0); - } - if (write_fifo(&USB0.D0FIFO.WORD, pipe, mps, ofs)) { - USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; - } -#else - if (USB0.PIPECFG.BIT.DBLB && (total_bytes > mps)) { - write_fifo2(&USB0.D0FIFO.WORD, pipe, mps); - wait_for_pipe_ready(); - } - if (write_fifo2(&USB0.D0FIFO.WORD, pipe, mps)) { - USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; - } -#endif + int r = write_fifo(&USB0.D0FIFO.WORD, pipe, mps); + if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; USB0.D0FIFOSEL.WORD = 0; } else { volatile reg_pipetre_t *pt = get_pipetre(num); if (pt) { volatile uint16_t *ctr = get_pipectr(num); if (*ctr & 0x3) *ctr = USB_PIPECTR_PID_NAK; - pt->TRE = 1u << 8; + pt->TRE = TU_BIT(8); pt->TRN = (total_bytes + mps - 1) / mps; pt->TRENB = 1; *ctr = USB_PIPECTR_PID_BUF; } } - TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); + //TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); return true; } -#if 0 -static void process_pipe_bemp(uint8_t rhport, unsigned num) -{ - pipe_state_t *pipe = &_dcd.pipe[num]; - unsigned rem = pipe->remaining; - USB0.PIPESEL.WORD = num; - const unsigned mps = USB0.PIPEMAXP.WORD; - - if (rem > mps) { - rem -= mps; - pipe->remaining = rem; - if (USB0.PIPECFG.BIT.DBLB) { - if (rem > mps) { - unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_16); - int r = write_fifo(&USB0.D0FIFO.WORD, pipe, mps, mps); - if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; - USB0.D0FIFOSEL.WORD = 0; - TU_LOG1("< %d %x %x %d\r\n", rem, ctr, *get_pipectr(num), r); - } - } else { - unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_16); - int r = write_fifo(&USB0.D0FIFO.WORD, pipe, mps, 0); - if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; - USB0.D0FIFOSEL.WORD = 0; - TU_LOG1("< %d %x %x %d\r\n", rem, ctr, *get_pipectr(num), r); - } - return; - } - pipe->addr = 0; - pipe->remaining = 0; - USB0.D0FIFOSEL.WORD = 0; - dcd_event_xfer_complete(rhport, pipe->ep, pipe->length, - XFER_RESULT_SUCCESS, true); - TU_LOG1("cE\r\n"); -} -#else -static void process_pipe_bemp(uint8_t rhport, unsigned num) -{ - pipe_state_t *pipe = &_dcd.pipe[num]; - const unsigned rem = pipe->remaining; - if (rem) { - USB0.PIPESEL.WORD = num; - const unsigned mps = USB0.PIPEMAXP.WORD; - unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_16); - int r = write_fifo2(&USB0.D0FIFO.WORD, pipe, mps); - if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; - USB0.D0FIFOSEL.WORD = 0; - TU_LOG1("< %d %x %x %d\r\n", rem, ctr, *get_pipectr(num), r); - return; - } - if (*get_pipectr(num) & USB_PIPECTR_INBUFM) { - TU_LOG1("< SKIP\r\n"); - return; - } - pipe->addr = 0; - pipe->remaining = 0; - USB0.D0FIFOSEL.WORD = 0; - dcd_event_xfer_complete(rhport, pipe->ep, pipe->length, - XFER_RESULT_SUCCESS, true); - TU_LOG1("cE\r\n"); -} -#endif static void process_pipe_brdy(uint8_t rhport, unsigned num) { - const unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_8); - const unsigned len = ctr & USB_FIFOCTR_DTLN; - const unsigned mps = USB0.PIPEMAXP.WORD; pipe_state_t *pipe = &_dcd.pipe[num]; - // TU_LOG1("> %d %x %x\r\n", num, USB0.D0FIFOSEL.WORD, ctr); - int cplt = read_fifo(&USB0.D0FIFO.WORD, pipe, mps, len); - if (cplt || (len < mps)) { - if (2 != cplt) { - USB0.D0FIFO.WORD = USB_FIFOCTR_BCLR; + if (!tu_edpt_dir(pipe->ep)) { + const unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_8); + const unsigned len = ctr & USB_FIFOCTR_DTLN; + const unsigned mps = USB0.PIPEMAXP.WORD; + int cplt = read_fifo(&USB0.D0FIFO.WORD, pipe, mps, len); + if (cplt || (len < mps)) { + if (2 != cplt) { + USB0.D0FIFO.WORD = USB_FIFOCTR_BCLR; + } + USB0.D0FIFOSEL.WORD = 0; + dcd_event_xfer_complete(rhport, pipe->ep, + pipe->length - pipe->remaining, + XFER_RESULT_SUCCESS, true); + return; } USB0.D0FIFOSEL.WORD = 0; - dcd_event_xfer_complete(rhport, pipe->ep, - pipe->length - pipe->remaining, - XFER_RESULT_SUCCESS, true); - // TU_LOG1("c\r\n"); } else { + select_pipe(num, USB_FIFOSEL_MBW_16); + const unsigned mps = USB0.PIPEMAXP.WORD; + unsigned rem = pipe->remaining; + rem -= TU_MIN(rem, mps); + pipe->remaining = rem; + if (rem) { + int r = 0; + r = write_fifo(&USB0.D0FIFO.WORD, pipe, mps); + if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; + USB0.D0FIFOSEL.WORD = 0; + return; + } USB0.D0FIFOSEL.WORD = 0; + pipe->addr = 0; + pipe->remaining = 0; + dcd_event_xfer_complete(rhport, pipe->ep, pipe->length, + XFER_RESULT_SUCCESS, true); } } @@ -571,7 +478,7 @@ static void process_bus_reset(uint8_t rhport) *ctr = USB_PIPECTR_ACLRM; *ctr = 0; ++ctr; - *tre = (1u<<8); + *tre = TU_BIT(8); tre += 2; } for (int i = 6; i <= 9; ++i) { @@ -583,7 +490,7 @@ static void process_bus_reset(uint8_t rhport) } tu_varclr(&_dcd); dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); - TU_LOG1("R\r\n"); + // TU_LOG1("R\r\n"); } static void process_set_address(uint8_t rhport) @@ -626,7 +533,6 @@ void dcd_init(uint8_t rhport) USB0.BEMPENB.WORD = 1; USB0.BRDYENB.WORD = 1; - TU_LOG1("INIT\r\n"); if (USB0.INTSTS0.BIT.VBSTS) { dcd_connect(rhport); } @@ -676,8 +582,8 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) (void)rhport; const unsigned ep_addr = ep_desc->bEndpointAddress; - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned dir = tu_edpt_dir(ep_addr); const unsigned xfer = ep_desc->bmAttributes.xfer; const unsigned mps = ep_desc->wMaxPacketSize.size; @@ -692,6 +598,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) _dcd.ep[dir][epn] = num; /* setup pipe */ + dcd_int_disable(rhport); USB0.PIPESEL.WORD = num; USB0.PIPEMAXP.WORD = mps; volatile uint16_t *ctr = get_pipectr(num); @@ -705,17 +612,14 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) } else { cfg |= USB_PIPECFG_ISO | USB_PIPECFG_DBLB; } - USB0.PIPECFG.WORD = cfg; - if (dir) { - USB0.BEMPENB.WORD |= 1u << num; + USB0.PIPECFG.WORD = cfg; + USB0.BRDYSTS.WORD = 0x1FFu ^ TU_BIT(num); + USB0.BRDYENB.WORD |= TU_BIT(num); + if (dir || (xfer != TUSB_XFER_BULK)) { *ctr = USB_PIPECTR_PID_BUF; - } else { - USB0.BRDYENB.WORD |= 1u << num; - if (xfer != TUSB_XFER_BULK) { - *ctr = USB_PIPECTR_PID_BUF; - } } - TU_LOG1("O %d %x %x\r\n", USB0.PIPESEL.WORD, USB0.PIPECFG.WORD, USB0.PIPEMAXP.WORD); + // TU_LOG1("O %d %x %x\r\n", USB0.PIPESEL.WORD, USB0.PIPECFG.WORD, USB0.PIPEMAXP.WORD); + dcd_int_enable(rhport); return true; } @@ -723,12 +627,11 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { (void)rhport; - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned dir = tu_edpt_dir(ep_addr); const unsigned num = _dcd.ep[dir][epn]; - USB0.BEMPENB.WORD &= ~(1u << num); - USB0.BRDYENB.WORD &= ~(1u << num); + USB0.BRDYENB.WORD &= ~TU_BIT(num); volatile uint16_t *ctr = get_pipectr(num); *ctr = 0; USB0.PIPESEL.WORD = num; @@ -740,7 +643,7 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { bool r; - const unsigned epn = ep_addr & 0xFu; + const unsigned epn = tu_edpt_number(ep_addr); dcd_int_disable(rhport); if (0 == epn) { r = process_edpt0_xfer(rhport, ep_addr, buffer, total_bytes); @@ -816,17 +719,10 @@ void dcd_int_handler(uint8_t rhport) } } if (is0 & USB_IS0_BEMP) { - const unsigned m = USB0.BEMPENB.WORD; - unsigned s = USB0.BEMPSTS.WORD & m; + const unsigned s = USB0.BEMPSTS.WORD; USB0.BEMPSTS.WORD = 0; if (s & 1) { process_edpt0_bemp(rhport); - s &= ~1; - } - while (s) { - const unsigned num = __builtin_ctz(s); - process_pipe_bemp(rhport, num); - s &= ~(1< Date: Sat, 27 Mar 2021 16:03:04 +0900 Subject: fixed a OUT transfer did not completed multiple of the max packet size --- src/portable/renesas/usba/dcd_usba.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index e7518b01f..844fa3856 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -261,7 +261,7 @@ static int write_fifo(volatile void *fifo, pipe_state_t* pipe, unsigned mps) return 0; } -/* 1 if the number of bytes read is less than 64 bytes +/* 1 if the number of bytes read is less than mps bytes * 0 otherwise */ static int read_fifo(volatile void *fifo, pipe_state_t* pipe, unsigned mps, size_t len) { @@ -272,12 +272,14 @@ static int read_fifo(volatile void *fifo, pipe_state_t* pipe, unsigned mps, size hw_fifo_t *reg = (hw_fifo_t*)fifo; uintptr_t addr = pipe->addr; - while (len--) { + unsigned loop = len; + while (loop--) { *(uint8_t *)addr = reg->u8; ++addr; } pipe->addr = addr; - if (rem < mps) return 1; + if (rem < mps) return 1; + if (rem == len) return 2; return 0; } @@ -419,7 +421,7 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, *ctr = USB_PIPECTR_PID_BUF; } } - //TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); + // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); return true; } -- cgit v1.3.1 From 4a597c969844d9b279279db0f678aa6732bae1a5 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Sun, 28 Mar 2021 12:42:28 +0900 Subject: cleanup --- src/portable/renesas/usba/dcd_usba.c | 98 ++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 844fa3856..06ea1a3f9 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -112,12 +112,11 @@ typedef union { typedef struct TU_ATTR_PACKED { - uintptr_t addr; - uint16_t length; - uint16_t remaining; + uintptr_t addr; /* the start address of a transfer data buffer */ + uint16_t length; /* the number of bytes in the buffer */ + uint16_t remaining; /* the number of bytes remaining in the buffer */ struct { - uint32_t ep : 8; - uint32_t data: 1; + uint32_t ep : 8; /* an assigned endpoint address */ uint32_t : 0; }; } pipe_state_t; @@ -125,7 +124,7 @@ typedef struct TU_ATTR_PACKED typedef struct { pipe_state_t pipe[9]; - uint8_t ep[2][16]; /* index for pipe number */ + uint8_t ep[2][16]; /* a lookup table for a pipe index from an endpoint address */ } dcd_data_t; //--------------------------------------------------------------------+ @@ -231,10 +230,10 @@ static unsigned select_pipe(unsigned num, unsigned attr) return wait_for_pipe_ready(); } -/* 1 less than 64 bytes were written - * 2 no bytes were written - * 0 mps bytes were written */ -static int write_fifo(volatile void *fifo, pipe_state_t* pipe, unsigned mps) +/* 1 less than mps bytes were written to FIFO + * 2 no bytes were written to FIFO + * 0 mps bytes were written to FIFO */ +static int fifo_write(volatile void *fifo, pipe_state_t* pipe, unsigned mps) { unsigned rem = pipe->remaining; if (!rem) return 2; @@ -261,9 +260,10 @@ static int write_fifo(volatile void *fifo, pipe_state_t* pipe, unsigned mps) return 0; } -/* 1 if the number of bytes read is less than mps bytes - * 0 otherwise */ -static int read_fifo(volatile void *fifo, pipe_state_t* pipe, unsigned mps, size_t len) +/* 1 less than mps bytes were read from FIFO + * 2 the end of the buffer reached. + * 0 mps bytes were read from FIFO */ +static int fifo_read(volatile void *fifo, pipe_state_t* pipe, unsigned mps, size_t len) { unsigned rem = pipe->remaining; if (!rem) return 2; @@ -294,7 +294,6 @@ static void process_setup_packet(uint8_t rhport) setup_packet[3] = USB0.USBLENG; USB0.INTSTS0.WORD = ~USB_IS0_VALID; dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet[0], true); - // TU_LOG1("S\r\n"); } static void process_status_completion(uint8_t rhport) @@ -309,7 +308,6 @@ static void process_status_completion(uint8_t rhport) ep_addr = tu_edpt_addr(0, TUSB_DIR_OUT); } dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, true); - // TU_LOG1("C\r\n"); } static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) @@ -317,11 +315,11 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, (void)rhport; pipe_state_t *pipe = &_dcd.pipe[0]; - /* set fifo direction */ - if (ep_addr) { /* IN */ + /* configure fifo direction and access unit settings */ + if (ep_addr) { /* IN, 2 bytes */ USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16; while (!(USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX)) ; - } else { /* OUT */ + } else { /* OUT, a byte */ USB0.CFIFOSEL.WORD = USB_FIFOSEL_MBW_8; while (USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX) ; } @@ -329,21 +327,18 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, pipe->addr = (uintptr_t)buffer; pipe->length = total_bytes; pipe->remaining = total_bytes; - pipe->data = USB0.DCPCTR.BIT.SQMON; if (ep_addr) { /* IN */ TU_ASSERT(USB0.DCPCTR.BIT.BSTS && (USB0.USBREQ.WORD & 0x80)); - if (write_fifo(&USB0.CFIFO.WORD, pipe, 64)) { + if (fifo_write(&USB0.CFIFO.WORD, pipe, 64)) { USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; } } USB0.DCPCTR.WORD = USB_PIPECTR_PID_BUF; - // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); } else { /* ZLP */ pipe->addr = 0; pipe->length = 0; pipe->remaining = 0; - pipe->data = USB0.DCPCTR.BIT.SQMON; USB0.DCPCTR.WORD = USB_PIPECTR_CCPL | USB_PIPECTR_PID_BUF; } return true; @@ -352,18 +347,10 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, static void process_edpt0_bemp(uint8_t rhport) { pipe_state_t *pipe = &_dcd.pipe[0]; - unsigned data = pipe->data; - if (USB0.DCPCTR.BIT.SQMON == data) { - /* retry transfer */ - int r = write_fifo(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); - if (r) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; - return; - } const unsigned rem = pipe->remaining; if (rem > 64) { pipe->remaining = rem - 64; - pipe->data = data ^ 1; - int r = write_fifo(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); + int r = fifo_write(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); if (r) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; return; } @@ -376,7 +363,7 @@ static void process_edpt0_bemp(uint8_t rhport) static void process_edpt0_brdy(uint8_t rhport) { size_t len = USB0.CFIFOCTR.BIT.DTLN; - int cplt = read_fifo(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, len); + int cplt = fifo_read(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, len); if (cplt || (len < 64)) { if (2 != cplt) { USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; @@ -407,7 +394,7 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, if (dir) { /* IN */ USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16; while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; - int r = write_fifo(&USB0.D0FIFO.WORD, pipe, mps); + int r = fifo_write(&USB0.D0FIFO.WORD, pipe, mps); if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; USB0.D0FIFOSEL.WORD = 0; } else { @@ -428,23 +415,7 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, static void process_pipe_brdy(uint8_t rhport, unsigned num) { pipe_state_t *pipe = &_dcd.pipe[num]; - if (!tu_edpt_dir(pipe->ep)) { - const unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_8); - const unsigned len = ctr & USB_FIFOCTR_DTLN; - const unsigned mps = USB0.PIPEMAXP.WORD; - int cplt = read_fifo(&USB0.D0FIFO.WORD, pipe, mps, len); - if (cplt || (len < mps)) { - if (2 != cplt) { - USB0.D0FIFO.WORD = USB_FIFOCTR_BCLR; - } - USB0.D0FIFOSEL.WORD = 0; - dcd_event_xfer_complete(rhport, pipe->ep, - pipe->length - pipe->remaining, - XFER_RESULT_SUCCESS, true); - return; - } - USB0.D0FIFOSEL.WORD = 0; - } else { + if (tu_edpt_dir(pipe->ep)) { /* IN */ select_pipe(num, USB_FIFOSEL_MBW_16); const unsigned mps = USB0.PIPEMAXP.WORD; unsigned rem = pipe->remaining; @@ -452,7 +423,7 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) pipe->remaining = rem; if (rem) { int r = 0; - r = write_fifo(&USB0.D0FIFO.WORD, pipe, mps); + r = fifo_write(&USB0.D0FIFO.WORD, pipe, mps); if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; USB0.D0FIFOSEL.WORD = 0; return; @@ -462,6 +433,22 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) pipe->remaining = 0; dcd_event_xfer_complete(rhport, pipe->ep, pipe->length, XFER_RESULT_SUCCESS, true); + } else { + const unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_8); + const unsigned len = ctr & USB_FIFOCTR_DTLN; + const unsigned mps = USB0.PIPEMAXP.WORD; + int cplt = fifo_read(&USB0.D0FIFO.WORD, pipe, mps, len); + if (cplt || (len < mps)) { + if (2 != cplt) { + USB0.D0FIFO.WORD = USB_FIFOCTR_BCLR; + } + USB0.D0FIFOSEL.WORD = 0; + dcd_event_xfer_complete(rhport, pipe->ep, + pipe->length - pipe->remaining, + XFER_RESULT_SUCCESS, true); + return; + } + USB0.D0FIFOSEL.WORD = 0; } } @@ -492,7 +479,6 @@ static void process_bus_reset(uint8_t rhport) } tu_varclr(&_dcd); dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); - // TU_LOG1("R\r\n"); } static void process_set_address(uint8_t rhport) @@ -674,10 +660,14 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) dcd_int_disable(rhport); *ctr = USB_PIPECTR_SQCLR; - if (ep_addr & TUSB_DIR_IN_MASK) { + if (tu_edpt_dir(ep_addr)) { /* IN */ *ctr = USB_PIPECTR_PID_BUF; } else { - /* TODO */ + const unsigned num = _dcd.ep[0][tu_edpt_number(ep_addr)]; + USB0.PIPESEL.WORD = num; + if (USB0.PIPECFG.BIT.TYPE != 1) { + *ctr = USB_PIPECTR_PID_BUF; + } } dcd_int_enable(rhport); } -- cgit v1.3.1 From d135825e9ca36bcf50b3476e5dfdc1f74ae1c101 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Mar 2021 21:12:56 +0700 Subject: add hid keys from 0x6B to 0xA4 --- src/class/hid/hid.h | 283 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 171 insertions(+), 112 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index a7db087a7..79b4f48bf 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -303,118 +303,177 @@ typedef enum //--------------------------------------------------------------------+ // HID KEYCODE //--------------------------------------------------------------------+ -#define HID_KEY_NONE 0x00 -#define HID_KEY_A 0x04 -#define HID_KEY_B 0x05 -#define HID_KEY_C 0x06 -#define HID_KEY_D 0x07 -#define HID_KEY_E 0x08 -#define HID_KEY_F 0x09 -#define HID_KEY_G 0x0A -#define HID_KEY_H 0x0B -#define HID_KEY_I 0x0C -#define HID_KEY_J 0x0D -#define HID_KEY_K 0x0E -#define HID_KEY_L 0x0F -#define HID_KEY_M 0x10 -#define HID_KEY_N 0x11 -#define HID_KEY_O 0x12 -#define HID_KEY_P 0x13 -#define HID_KEY_Q 0x14 -#define HID_KEY_R 0x15 -#define HID_KEY_S 0x16 -#define HID_KEY_T 0x17 -#define HID_KEY_U 0x18 -#define HID_KEY_V 0x19 -#define HID_KEY_W 0x1A -#define HID_KEY_X 0x1B -#define HID_KEY_Y 0x1C -#define HID_KEY_Z 0x1D -#define HID_KEY_1 0x1E -#define HID_KEY_2 0x1F -#define HID_KEY_3 0x20 -#define HID_KEY_4 0x21 -#define HID_KEY_5 0x22 -#define HID_KEY_6 0x23 -#define HID_KEY_7 0x24 -#define HID_KEY_8 0x25 -#define HID_KEY_9 0x26 -#define HID_KEY_0 0x27 -#define HID_KEY_RETURN 0x28 -#define HID_KEY_ESCAPE 0x29 -#define HID_KEY_BACKSPACE 0x2A -#define HID_KEY_TAB 0x2B -#define HID_KEY_SPACE 0x2C -#define HID_KEY_MINUS 0x2D -#define HID_KEY_EQUAL 0x2E -#define HID_KEY_BRACKET_LEFT 0x2F -#define HID_KEY_BRACKET_RIGHT 0x30 -#define HID_KEY_BACKSLASH 0x31 -#define HID_KEY_EUROPE_1 0x32 -#define HID_KEY_SEMICOLON 0x33 -#define HID_KEY_APOSTROPHE 0x34 -#define HID_KEY_GRAVE 0x35 -#define HID_KEY_COMMA 0x36 -#define HID_KEY_PERIOD 0x37 -#define HID_KEY_SLASH 0x38 -#define HID_KEY_CAPS_LOCK 0x39 -#define HID_KEY_F1 0x3A -#define HID_KEY_F2 0x3B -#define HID_KEY_F3 0x3C -#define HID_KEY_F4 0x3D -#define HID_KEY_F5 0x3E -#define HID_KEY_F6 0x3F -#define HID_KEY_F7 0x40 -#define HID_KEY_F8 0x41 -#define HID_KEY_F9 0x42 -#define HID_KEY_F10 0x43 -#define HID_KEY_F11 0x44 -#define HID_KEY_F12 0x45 -#define HID_KEY_PRINT_SCREEN 0x46 -#define HID_KEY_SCROLL_LOCK 0x47 -#define HID_KEY_PAUSE 0x48 -#define HID_KEY_INSERT 0x49 -#define HID_KEY_HOME 0x4A -#define HID_KEY_PAGE_UP 0x4B -#define HID_KEY_DELETE 0x4C -#define HID_KEY_END 0x4D -#define HID_KEY_PAGE_DOWN 0x4E -#define HID_KEY_ARROW_RIGHT 0x4F -#define HID_KEY_ARROW_LEFT 0x50 -#define HID_KEY_ARROW_DOWN 0x51 -#define HID_KEY_ARROW_UP 0x52 -#define HID_KEY_NUM_LOCK 0x53 -#define HID_KEY_KEYPAD_DIVIDE 0x54 -#define HID_KEY_KEYPAD_MULTIPLY 0x55 -#define HID_KEY_KEYPAD_SUBTRACT 0x56 -#define HID_KEY_KEYPAD_ADD 0x57 -#define HID_KEY_KEYPAD_ENTER 0x58 -#define HID_KEY_KEYPAD_1 0x59 -#define HID_KEY_KEYPAD_2 0x5A -#define HID_KEY_KEYPAD_3 0x5B -#define HID_KEY_KEYPAD_4 0x5C -#define HID_KEY_KEYPAD_5 0x5D -#define HID_KEY_KEYPAD_6 0x5E -#define HID_KEY_KEYPAD_7 0x5F -#define HID_KEY_KEYPAD_8 0x60 -#define HID_KEY_KEYPAD_9 0x61 -#define HID_KEY_KEYPAD_0 0x62 -#define HID_KEY_KEYPAD_DECIMAL 0x63 -#define HID_KEY_EUROPE_2 0x64 -#define HID_KEY_APPLICATION 0x65 -#define HID_KEY_POWER 0x66 -#define HID_KEY_KEYPAD_EQUAL 0x67 -#define HID_KEY_F13 0x68 -#define HID_KEY_F14 0x69 -#define HID_KEY_F15 0x6A -#define HID_KEY_CONTROL_LEFT 0xE0 -#define HID_KEY_SHIFT_LEFT 0xE1 -#define HID_KEY_ALT_LEFT 0xE2 -#define HID_KEY_GUI_LEFT 0xE3 -#define HID_KEY_CONTROL_RIGHT 0xE4 -#define HID_KEY_SHIFT_RIGHT 0xE5 -#define HID_KEY_ALT_RIGHT 0xE6 -#define HID_KEY_GUI_RIGHT 0xE7 +#define HID_KEY_NONE 0x00 +#define HID_KEY_A 0x04 +#define HID_KEY_B 0x05 +#define HID_KEY_C 0x06 +#define HID_KEY_D 0x07 +#define HID_KEY_E 0x08 +#define HID_KEY_F 0x09 +#define HID_KEY_G 0x0A +#define HID_KEY_H 0x0B +#define HID_KEY_I 0x0C +#define HID_KEY_J 0x0D +#define HID_KEY_K 0x0E +#define HID_KEY_L 0x0F +#define HID_KEY_M 0x10 +#define HID_KEY_N 0x11 +#define HID_KEY_O 0x12 +#define HID_KEY_P 0x13 +#define HID_KEY_Q 0x14 +#define HID_KEY_R 0x15 +#define HID_KEY_S 0x16 +#define HID_KEY_T 0x17 +#define HID_KEY_U 0x18 +#define HID_KEY_V 0x19 +#define HID_KEY_W 0x1A +#define HID_KEY_X 0x1B +#define HID_KEY_Y 0x1C +#define HID_KEY_Z 0x1D +#define HID_KEY_1 0x1E +#define HID_KEY_2 0x1F +#define HID_KEY_3 0x20 +#define HID_KEY_4 0x21 +#define HID_KEY_5 0x22 +#define HID_KEY_6 0x23 +#define HID_KEY_7 0x24 +#define HID_KEY_8 0x25 +#define HID_KEY_9 0x26 +#define HID_KEY_0 0x27 +#define HID_KEY_RETURN 0x28 +#define HID_KEY_ESCAPE 0x29 +#define HID_KEY_BACKSPACE 0x2A +#define HID_KEY_TAB 0x2B +#define HID_KEY_SPACE 0x2C +#define HID_KEY_MINUS 0x2D +#define HID_KEY_EQUAL 0x2E +#define HID_KEY_BRACKET_LEFT 0x2F +#define HID_KEY_BRACKET_RIGHT 0x30 +#define HID_KEY_BACKSLASH 0x31 +#define HID_KEY_EUROPE_1 0x32 +#define HID_KEY_SEMICOLON 0x33 +#define HID_KEY_APOSTROPHE 0x34 +#define HID_KEY_GRAVE 0x35 +#define HID_KEY_COMMA 0x36 +#define HID_KEY_PERIOD 0x37 +#define HID_KEY_SLASH 0x38 +#define HID_KEY_CAPS_LOCK 0x39 +#define HID_KEY_F1 0x3A +#define HID_KEY_F2 0x3B +#define HID_KEY_F3 0x3C +#define HID_KEY_F4 0x3D +#define HID_KEY_F5 0x3E +#define HID_KEY_F6 0x3F +#define HID_KEY_F7 0x40 +#define HID_KEY_F8 0x41 +#define HID_KEY_F9 0x42 +#define HID_KEY_F10 0x43 +#define HID_KEY_F11 0x44 +#define HID_KEY_F12 0x45 +#define HID_KEY_PRINT_SCREEN 0x46 +#define HID_KEY_SCROLL_LOCK 0x47 +#define HID_KEY_PAUSE 0x48 +#define HID_KEY_INSERT 0x49 +#define HID_KEY_HOME 0x4A +#define HID_KEY_PAGE_UP 0x4B +#define HID_KEY_DELETE 0x4C +#define HID_KEY_END 0x4D +#define HID_KEY_PAGE_DOWN 0x4E +#define HID_KEY_ARROW_RIGHT 0x4F +#define HID_KEY_ARROW_LEFT 0x50 +#define HID_KEY_ARROW_DOWN 0x51 +#define HID_KEY_ARROW_UP 0x52 +#define HID_KEY_NUM_LOCK 0x53 +#define HID_KEY_KEYPAD_DIVIDE 0x54 +#define HID_KEY_KEYPAD_MULTIPLY 0x55 +#define HID_KEY_KEYPAD_SUBTRACT 0x56 +#define HID_KEY_KEYPAD_ADD 0x57 +#define HID_KEY_KEYPAD_ENTER 0x58 +#define HID_KEY_KEYPAD_1 0x59 +#define HID_KEY_KEYPAD_2 0x5A +#define HID_KEY_KEYPAD_3 0x5B +#define HID_KEY_KEYPAD_4 0x5C +#define HID_KEY_KEYPAD_5 0x5D +#define HID_KEY_KEYPAD_6 0x5E +#define HID_KEY_KEYPAD_7 0x5F +#define HID_KEY_KEYPAD_8 0x60 +#define HID_KEY_KEYPAD_9 0x61 +#define HID_KEY_KEYPAD_0 0x62 +#define HID_KEY_KEYPAD_DECIMAL 0x63 +#define HID_KEY_EUROPE_2 0x64 +#define HID_KEY_APPLICATION 0x65 +#define HID_KEY_POWER 0x66 +#define HID_KEY_KEYPAD_EQUAL 0x67 +#define HID_KEY_F13 0x68 +#define HID_KEY_F14 0x69 +#define HID_KEY_F15 0x6A +#define HID_KEY_F16 0x6B +#define HID_KEY_F17 0x6C +#define HID_KEY_F18 0x6D +#define HID_KEY_F19 0x6E +#define HID_KEY_F20 0x6F +#define HID_KEY_F21 0x70 +#define HID_KEY_F22 0x71 +#define HID_KEY_F23 0x72 +#define HID_KEY_F24 0x73 +#define HID_KEY_EXECUTE 0x74 +#define HID_KEY_HELP 0x75 +#define HID_KEY_MENU 0x76 +#define HID_KEY_SELECT 0x77 +#define HID_KEY_STOP 0x78 +#define HID_KEY_AGAIN 0x79 +#define HID_KEY_UNDO 0x7A +#define HID_KEY_CUT 0x7B +#define HID_KEY_COPY 0x7C +#define HID_KEY_PASTE 0x7D +#define HID_KEY_FIND 0x7E +#define HID_KEY_MUTE 0x7F +#define HID_KEY_VOLUME_UP 0x80 +#define HID_KEY_VOLUME_DOWN 0x81 +#define HID_KEY_LOCKING_CAPS_LOCK 0x82 +#define HID_KEY_LOCKING_NUM_LOCK 0x83 +#define HID_KEY_LOCKING_SCROLL_LOCK 0x84 +#define HID_KEY_KEYPAD_COMMA 0x85 +#define HID_KEY_KEYPAD_EQUAL_SIGN 0x86 +#define HID_KEY_KANJI1 0x87 +#define HID_KEY_KANJI2 0x88 +#define HID_KEY_KANJI3 0x89 +#define HID_KEY_KANJI4 0x8A +#define HID_KEY_KANJI5 0x8B +#define HID_KEY_KANJI6 0x8C +#define HID_KEY_KANJI7 0x8D +#define HID_KEY_KANJI8 0x8E +#define HID_KEY_KANJI9 0x8F +#define HID_KEY_LANG1 0x90 +#define HID_KEY_LANG2 0x91 +#define HID_KEY_LANG3 0x92 +#define HID_KEY_LANG4 0x93 +#define HID_KEY_LANG5 0x94 +#define HID_KEY_LANG6 0x95 +#define HID_KEY_LANG7 0x96 +#define HID_KEY_LANG8 0x97 +#define HID_KEY_LANG9 0x98 +#define HID_KEY_ALTERNATE_ERASE 0x99 +#define HID_KEY_SYSREQ_ATTENTION 0x9A +#define HID_KEY_CANCEL 0x9B +#define HID_KEY_CLEAR 0x9C +#define HID_KEY_PRIOR 0x9D +#define HID_KEY_RETURN 0x9E +#define HID_KEY_SEPARATOR 0x9F +#define HID_KEY_OUT 0xA0 +#define HID_KEY_OPER 0xA1 +#define HID_KEY_CLEAR_AGAIN 0xA2 +#define HID_KEY_CRSEL_PROPS 0xA3 +#define HID_KEY_EXSEL 0xA4 +// RESERVED 0xA5-DF +#define HID_KEY_CONTROL_LEFT 0xE0 +#define HID_KEY_SHIFT_LEFT 0xE1 +#define HID_KEY_ALT_LEFT 0xE2 +#define HID_KEY_GUI_LEFT 0xE3 +#define HID_KEY_CONTROL_RIGHT 0xE4 +#define HID_KEY_SHIFT_RIGHT 0xE5 +#define HID_KEY_ALT_RIGHT 0xE6 +#define HID_KEY_GUI_RIGHT 0xE7 //--------------------------------------------------------------------+ -- cgit v1.3.1 From 89a911ee43f2c7a17303b58739dc8b22cbd56294 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Mar 2021 21:26:35 +0700 Subject: correct hid key enter = 0x28, return = 0x9E --- src/class/hid/hid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 79b4f48bf..351a4d600 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -340,7 +340,7 @@ typedef enum #define HID_KEY_8 0x25 #define HID_KEY_9 0x26 #define HID_KEY_0 0x27 -#define HID_KEY_RETURN 0x28 +#define HID_KEY_ENTER 0x28 #define HID_KEY_ESCAPE 0x29 #define HID_KEY_BACKSPACE 0x2A #define HID_KEY_TAB 0x2B -- cgit v1.3.1 From c5aa661c892159b2eced9b2e3c1a4a1d8f92b1f6 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Mar 2021 23:54:17 +0700 Subject: rename tud_midi_receive/send to tud_midi_packet_read/write --- src/class/midi/midi_device.c | 6 +++--- src/class/midi/midi_device.h | 17 +++++++++-------- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 29019cc1d..3772c4759 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -127,7 +127,7 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t // Fill empty buffer if (midi->read_buffer_length == 0) { - if (!tud_midi_n_receive(itf, midi->read_buffer)) return 0; + if (!tud_midi_n_packet_read(itf, midi->read_buffer)) return 0; uint8_t code_index = midi->read_buffer[0] & 0x0f; // We always copy over the first byte. @@ -166,7 +166,7 @@ void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num) _prep_out_transaction(p_midi); } -bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]) +bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) { midid_interface_t* p_midi = &_midid_itf[itf]; uint32_t num_read = tu_fifo_read_n(&p_midi->rx_ff, packet, 4); @@ -278,7 +278,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, return i; } -bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]) +bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) { midid_interface_t* midi = &_midid_itf[itf]; if (midi->itf_num == 0) { diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 5e7df80ae..f76554c70 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -68,8 +68,8 @@ uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* b static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); -bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]); -bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]); +bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); +bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); //--------------------------------------------------------------------+ // Application API (Single Interface) @@ -80,8 +80,9 @@ static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); static inline void tud_midi_read_flush (void); static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); -static inline bool tud_midi_receive (uint8_t packet[4]); -static inline bool tud_midi_send (uint8_t const packet[4]); + +static inline bool tud_midi_packet_read (uint8_t packet[4]); +static inline bool tud_midi_packet_write(uint8_t const packet[4]); //--------------------------------------------------------------------+ // Application Callback API (weak is optional) @@ -129,14 +130,14 @@ static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t return tud_midi_write(cable_num, msg, 3); } -static inline bool tud_midi_receive (uint8_t packet[4]) +static inline bool tud_midi_packet_read (uint8_t packet[4]) { - return tud_midi_n_receive(0, packet); + return tud_midi_n_packet_read(0, packet); } -static inline bool tud_midi_send (uint8_t const packet[4]) +static inline bool tud_midi_packet_write (uint8_t const packet[4]) { - return tud_midi_n_send(0, packet); + return tud_midi_n_packet_write(0, packet); } //--------------------------------------------------------------------+ -- cgit v1.3.1 From b05084e406b50c6378572974e47d7e2ec15f2045 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Mar 2021 23:56:55 +0700 Subject: remove tud_midi_read_flush() --- src/class/midi/midi_device.c | 8 -------- src/class/midi/midi_device.h | 7 ------- 2 files changed, 15 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 3772c4759..48e5a8e68 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -158,14 +158,6 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t return n; } -void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num) -{ - (void) cable_num; - midid_interface_t* p_midi = &_midid_itf[itf]; - tu_fifo_clear(&p_midi->rx_ff); - _prep_out_transaction(p_midi); -} - bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) { midid_interface_t* p_midi = &_midid_itf[itf]; diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index f76554c70..1060fd77a 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -62,7 +62,6 @@ bool tud_midi_n_mounted (uint8_t itf); uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); -void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num); uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); static inline @@ -77,7 +76,6 @@ bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); static inline bool tud_midi_mounted (void); static inline uint32_t tud_midi_available (void); static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); -static inline void tud_midi_read_flush (void); static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); @@ -114,11 +112,6 @@ static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) return tud_midi_n_read(0, 0, buffer, bufsize); } -static inline void tud_midi_read_flush (void) -{ - tud_midi_n_read_flush(0, 0); -} - static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { return tud_midi_n_write(0, cable_num, buffer, bufsize); -- cgit v1.3.1 From 949ff791e0222d9d89fe54b7cab036125997b66e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Mar 2021 00:34:09 +0700 Subject: code format --- src/class/midi/midi_device.c | 131 +++++++++++++++++++++++++------------------ 1 file changed, 77 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 48e5a8e68..1ff81c39a 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -200,67 +200,90 @@ static uint32_t write_flush(midid_interface_t* midi) uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { midid_interface_t* midi = &_midid_itf[itf]; - if (midi->itf_num == 0) { - return 0; - } + TU_VERIFY(midi->itf_num, 0); uint32_t i = 0; - while (i < bufsize) { + while ( i < bufsize ) + { uint8_t data = buffer[i]; - if (midi->write_buffer_length == 0) { - uint8_t msg = data >> 4; - midi->write_buffer[1] = data; - midi->write_buffer_length = 2; - // Check to see if we're still in a SysEx transmit. - if (midi->write_buffer[0] == 0x4) { - if (data == 0xf7) { - midi->write_buffer[0] = 0x5; - midi->write_target_length = 2; - } else { - midi->write_target_length = 4; - } - } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { - midi->write_buffer[0] = cable_num << 4 | msg; - midi->write_target_length = 4; - } else if (msg == 0xf) { - if (data == 0xf0) { - midi->write_buffer[0] = 0x4; - midi->write_target_length = 4; - } else if (data == 0xf1 || data == 0xf3) { - midi->write_buffer[0] = 0x2; - midi->write_target_length = 3; - } else if (data == 0xf2) { - midi->write_buffer[0] = 0x3; - midi->write_target_length = 4; - } else { - midi->write_buffer[0] = 0x5; - midi->write_target_length = 2; - } - } else { - // Pack individual bytes if we don't support packing them into words. - midi->write_buffer[0] = cable_num << 4 | 0xf; - midi->write_buffer[2] = 0; - midi->write_buffer[3] = 0; - midi->write_buffer_length = 2; - midi->write_target_length = 2; + if ( midi->write_buffer_length == 0 ) + { + uint8_t msg = data >> 4; + midi->write_buffer[1] = data; + midi->write_buffer_length = 2; + // Check to see if we're still in a SysEx transmit. + if ( midi->write_buffer[0] == 0x4 ) + { + if ( data == 0xf7 ) + { + midi->write_buffer[0] = 0x5; + midi->write_target_length = 2; } - } else { - midi->write_buffer[midi->write_buffer_length] = data; - midi->write_buffer_length += 1; - // See if this byte ends a SysEx. - if (midi->write_buffer[0] == 0x4 && data == 0xf7) { - midi->write_buffer[0] = 0x4 + (midi->write_buffer_length - 1); - midi->write_target_length = midi->write_buffer_length; + else + { + midi->write_target_length = 4; + } + } + else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) + { + midi->write_buffer[0] = cable_num << 4 | msg; + midi->write_target_length = 4; + } + else if ( msg == 0xf ) + { + if ( data == 0xf0 ) + { + midi->write_buffer[0] = 0x4; + midi->write_target_length = 4; + } + else if ( data == 0xf1 || data == 0xf3 ) + { + midi->write_buffer[0] = 0x2; + midi->write_target_length = 3; } + else if ( data == 0xf2 ) + { + midi->write_buffer[0] = 0x3; + midi->write_target_length = 4; + } + else + { + midi->write_buffer[0] = 0x5; + midi->write_target_length = 2; + } + } + else + { + // Pack individual bytes if we don't support packing them into words. + midi->write_buffer[0] = cable_num << 4 | 0xf; + midi->write_buffer[2] = 0; + midi->write_buffer[3] = 0; + midi->write_buffer_length = 2; + midi->write_target_length = 2; + } + } + else + { + TU_ASSERT(midi->write_buffer_length < 4, 0); + midi->write_buffer[midi->write_buffer_length] = data; + midi->write_buffer_length += 1; + // See if this byte ends a SysEx. + if ( midi->write_buffer[0] == 0x4 && data == 0xf7 ) + { + midi->write_buffer[0] = 0x4 + (midi->write_buffer_length - 1); + midi->write_target_length = midi->write_buffer_length; + } } - if (midi->write_buffer_length == midi->write_target_length) { - uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); - if (written < 4) { - TU_ASSERT( written == 0 ); - break; - } - midi->write_buffer_length = 0; + if ( midi->write_buffer_length == midi->write_target_length ) + { + uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); + if ( written < 4 ) + { + TU_ASSERT(written == 0); + break; + } + midi->write_buffer_length = 0; } i++; } -- cgit v1.3.1 From 080b14b292251e46b43aac9e1cf7807dc2d3eb2c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 13:26:55 +0700 Subject: fix midi tx fifo overflow cause data corruption rename --- examples/device/dynamic_configuration/src/main.c | 2 +- examples/device/midi_test/src/main.c | 8 +- examples/make.mk | 2 +- src/class/midi/midi.h | 45 ++++++++++ src/class/midi/midi_device.c | 103 ++++++++++++++--------- src/class/midi/midi_device.h | 16 +++- 6 files changed, 127 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/examples/device/dynamic_configuration/src/main.c b/examples/device/dynamic_configuration/src/main.c index acee295f6..ce1f752d0 100644 --- a/examples/device/dynamic_configuration/src/main.c +++ b/examples/device/dynamic_configuration/src/main.c @@ -172,7 +172,7 @@ void midi_task(void) // regardless of these being used or not. Therefore incoming traffic should be read // (possibly just discarded) to avoid the sender blocking in IO uint8_t packet[4]; - while(tud_midi_available()) tud_midi_receive(packet); + while( tud_midi_available() ) tud_midi_packet_read(packet); // send note every 1000 ms if (board_millis() - start_ms < 286) return; // not enough time diff --git a/examples/device/midi_test/src/main.c b/examples/device/midi_test/src/main.c index 858a096b6..af10350df 100644 --- a/examples/device/midi_test/src/main.c +++ b/examples/device/midi_test/src/main.c @@ -132,7 +132,7 @@ void midi_task(void) // regardless of these being used or not. Therefore incoming traffic should be read // (possibly just discarded) to avoid the sender blocking in IO uint8_t packet[4]; - while(tud_midi_available()) tud_midi_receive(packet); + while ( tud_midi_available() ) tud_midi_packet_read(packet); // send note every 1000 ms if (board_millis() - start_ms < 286) return; // not enough time @@ -146,10 +146,12 @@ void midi_task(void) if (previous < 0) previous = sizeof(note_sequence) - 1; // Send Note On for current position at full velocity (127) on channel 1. - tud_midi_write24(cable_num, 0x90 | channel, note_sequence[note_pos], 127); + uint8_t note_on[3] = { 0x90 | channel, note_sequence[note_pos], 127 }; + tud_midi_write(cable_num, note_on, 3); // Send Note Off for previous note. - tud_midi_write24(cable_num, 0x80 | channel, note_sequence[previous], 0); + uint8_t note_off[3] = { 0x80 | channel, note_sequence[previous], 0}; + tud_midi_write(cable_num, note_off, 3); // Increment position note_pos++; diff --git a/examples/make.mk b/examples/make.mk index e04a2592a..ffcb8ee5c 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -103,7 +103,7 @@ CFLAGS += \ # Debugging/Optimization ifeq ($(DEBUG), 1) - CFLAGS += -Og + CFLAGS += -O0 else CFLAGS += -Os endif diff --git a/src/class/midi/midi.h b/src/class/midi/midi.h index f758b6e1c..74dc41749 100644 --- a/src/class/midi/midi.h +++ b/src/class/midi/midi.h @@ -61,6 +61,51 @@ typedef enum MIDI_JACK_EXTERNAL = 0x02 } midi_jack_type_t; +typedef enum +{ + MIDI_CIN_MISC = 0, + MIDI_CIN_CABLE_EVENT = 1, + MIDI_CIN_SYSCOM_2BYTE = 2, // 2 byte system common message e.g MTC, SongSelect + MIDI_CIN_SYSCOM_3BYTE = 3, // 3 byte system common message e.g SPP + MIDI_CIN_SYSEX_START = 4, // SysEx starts or continue + MIDI_CIN_SYSEX_END_1BYTE = 5, // SysEx ends with 1 data, or 1 byte system common message + MIDI_CIN_SYSEX_END_2BYTE = 6, // SysEx ends with 2 data + MIDI_CIN_SYSEX_END_3BYTE = 7, // SysEx ends with 3 data + MIDI_CIN_NOTE_ON = 8, + MIDI_CIN_NOTE_OFF = 9, + MIDI_CIN_POLY_KEYPRESS = 10, + MIDI_CIN_CONTROL_CHANGE = 11, + MIDI_CIN_PROGRAM_CHANGE = 12, + MIDI_CIN_CHANNEL_PRESSURE = 13, + MIDI_CIN_PITCH_BEND_CHANGE = 14, + MIDI_CIN_1BYTE_DATA = 15 +} midi_code_index_number_t; + +// MIDI 1.0 status byte +enum +{ + //------------- System Exclusive -------------// + MIDI_STATUS_SYSEX_START = 0xF0, + MIDI_STATUS_SYSEX_END = 0xF7, + + //------------- System Common -------------// + MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME = 0xF1, + MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER = 0xF2, + MIDI_STATUS_SYSCOM_SONG_SELECT = 0xF3, + // F4, F5 is undefined + MIDI_STATUS_SYSCOM_TUNE_REQUEST = 0xF6, + + //------------- System RealTime -------------// + MIDI_STATUS_SYSREAL_TIMING_CLOCK = 0xF8, + // 0xF9 is undefined + MIDI_STATUS_SYSREAL_START = 0xFA, + MIDI_STATUS_SYSREAL_CONTINUE = 0xFB, + MIDI_STATUS_SYSREAL_STOP = 0xFC, + // 0xFD is undefined + MIDI_STATUS_SYSREAL_ACTIVE_SENSING = 0xFE, + MIDI_STATUS_SYSREAL_SYSTEM_RESET = 0xFF, +}; + /// MIDI Interface Header Descriptor typedef struct TU_ATTR_PACKED { diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 1ff81c39a..cba1dcca0 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -38,6 +38,7 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ + typedef struct { uint8_t itf_num; @@ -126,16 +127,19 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t midid_interface_t* midi = &_midid_itf[itf]; // Fill empty buffer - if (midi->read_buffer_length == 0) { - if (!tud_midi_n_packet_read(itf, midi->read_buffer)) return 0; + if ( midi->read_buffer_length == 0 ) + { + if ( !tud_midi_n_packet_read(itf, midi->read_buffer) ) return 0; uint8_t code_index = midi->read_buffer[0] & 0x0f; // We always copy over the first byte. uint8_t count = 1; // Ignore subsequent bytes based on the code. - if (code_index != 0x5 && code_index != 0xf) { + if ( code_index != 0x5 && code_index != 0xf ) + { count = 2; - if (code_index != 0x2 && code_index != 0x6 && code_index != 0xc && code_index != 0xd) { + if ( code_index != 0x2 && code_index != 0x6 && code_index != 0xc && code_index != 0xd ) + { count = 3; } } @@ -150,7 +154,8 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t memcpy(buffer, midi->read_buffer + 1 + midi->read_target_length, n); midi->read_target_length += n; - if (midi->read_target_length == midi->read_buffer_length) { + if ( midi->read_target_length == midi->read_buffer_length ) + { midi->read_buffer_length = 0; midi->read_target_length = 0; } @@ -166,10 +171,6 @@ bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) return (num_read == 4); } -void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) { - tu_fifo_write_n(&midi->rx_ff, buffer, bufsize); -} - //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ @@ -185,7 +186,8 @@ static uint32_t write_flush(midid_interface_t* midi) TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 ); uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); - if (count > 0) + + if (count) { TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, midi->epin_buf, count), 0 ); return count; @@ -202,21 +204,26 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, midid_interface_t* midi = &_midid_itf[itf]; TU_VERIFY(midi->itf_num, 0); + uint32_t written = 0; uint32_t i = 0; while ( i < bufsize ) { - uint8_t data = buffer[i]; + uint8_t const data = buffer[i]; + if ( midi->write_buffer_length == 0 ) { - uint8_t msg = data >> 4; + // new packet + + uint8_t const msg = data >> 4; midi->write_buffer[1] = data; midi->write_buffer_length = 2; + // Check to see if we're still in a SysEx transmit. - if ( midi->write_buffer[0] == 0x4 ) + if ( midi->write_buffer[0] == MIDI_CIN_SYSEX_START ) { - if ( data == 0xf7 ) + if ( data == MIDI_STATUS_SYSEX_END ) { - midi->write_buffer[0] = 0x5; + midi->write_buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; midi->write_target_length = 2; } else @@ -226,29 +233,31 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, } else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) { - midi->write_buffer[0] = cable_num << 4 | msg; + // Channel Voice Messages + midi->write_buffer[0] = (cable_num << 4) | msg; midi->write_target_length = 4; } else if ( msg == 0xf ) { - if ( data == 0xf0 ) + // System message + if ( data == MIDI_STATUS_SYSEX_START ) { - midi->write_buffer[0] = 0x4; + midi->write_buffer[0] = MIDI_CIN_SYSEX_START; midi->write_target_length = 4; } - else if ( data == 0xf1 || data == 0xf3 ) + else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) { - midi->write_buffer[0] = 0x2; + midi->write_buffer[0] = MIDI_CIN_SYSCOM_2BYTE; midi->write_target_length = 3; } - else if ( data == 0xf2 ) + else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) { - midi->write_buffer[0] = 0x3; + midi->write_buffer[0] = MIDI_CIN_SYSCOM_3BYTE; midi->write_target_length = 4; } else { - midi->write_buffer[0] = 0x5; + midi->write_buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; midi->write_target_length = 2; } } @@ -264,33 +273,44 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, } else { + // On-going packet + TU_ASSERT(midi->write_buffer_length < 4, 0); midi->write_buffer[midi->write_buffer_length] = data; - midi->write_buffer_length += 1; + midi->write_buffer_length++; + // See if this byte ends a SysEx. - if ( midi->write_buffer[0] == 0x4 && data == 0xf7 ) + if ( midi->write_buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) { - midi->write_buffer[0] = 0x4 + (midi->write_buffer_length - 1); + midi->write_buffer[0] = MIDI_CIN_SYSEX_START + (midi->write_buffer_length - 1); midi->write_target_length = midi->write_buffer_length; } } + // Send out packet if ( midi->write_buffer_length == midi->write_target_length ) { - uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); - if ( written < 4 ) - { - TU_ASSERT(written == 0); - break; - } - midi->write_buffer_length = 0; + // zeroes unused bytes + for(uint8_t idx = midi->write_target_length; idx < 4; idx++) midi->write_buffer[idx] = 0; + + uint16_t const count = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); + + // reset buffer + midi->write_buffer_length = midi->write_target_length = 0; + + // fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing + if ( count != 4 ) break; + + // updated written if succeeded + written = i; } + i++; } write_flush(midi); - return i; + return written; } bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) @@ -300,8 +320,7 @@ bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) return 0; } - if (tu_fifo_remaining(&midi->tx_ff) < 4) - return false; + if (tu_fifo_remaining(&midi->tx_ff) < 4) return false; tu_fifo_write_n(&midi->tx_ff, packet, 4); write_flush(midi); @@ -347,9 +366,9 @@ void midid_reset(uint8_t rhport) uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) { // 1st Interface is Audio Control v1 - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0); uint16_t drv_len = tu_desc_len(desc_itf); uint8_t const * p_desc = tu_desc_next(desc_itf); @@ -365,9 +384,9 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); 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_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && + AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); // Find available interface midid_interface_t * p_midi = NULL; diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 1060fd77a..aaceaf62a 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -59,16 +59,28 @@ // Application API (Multiple Interfaces) // CFG_TUD_MIDI > 1 //--------------------------------------------------------------------+ + +// Check if midi interface is mounted bool tud_midi_n_mounted (uint8_t itf); + +// Get the number of bytes available for reading uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); + +// Read byte stream (legacy) uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); + +// Write byte Stream (legacy) uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); +// Write good-old 3 bytes data, this use write packet static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); +// Read event packet (4 bytes) +bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); + +// Write event packet (4 bytes) +bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); //--------------------------------------------------------------------+ // Application API (Single Interface) -- cgit v1.3.1 From 6b04efd443c3299131135849b736a2f2ce5877ac Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 13:55:51 +0700 Subject: refactor midi stream read --- src/class/midi/midi_device.c | 51 +++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index cba1dcca0..14748f18b 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -39,6 +39,13 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +typedef struct +{ + uint8_t buffer[4]; + uint8_t index; + uint8_t total; +}midid_stream_t; + typedef struct { uint8_t itf_num; @@ -57,12 +64,15 @@ typedef struct osal_mutex_def_t tx_ff_mutex; #endif + // For Stream read()/write() API // Messages are always 4 bytes long, queue them for reading and writing so the // callers can use the Stream interface with single-byte read/write calls. uint8_t write_buffer[4]; uint8_t write_buffer_length; uint8_t write_target_length; +// midid_stream_t stream_write; + uint8_t read_buffer[4]; uint8_t read_buffer_length; uint8_t read_target_length; @@ -129,26 +139,41 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t // Fill empty buffer if ( midi->read_buffer_length == 0 ) { - if ( !tud_midi_n_packet_read(itf, midi->read_buffer) ) return 0; + TU_VERIFY(tud_midi_n_packet_read(itf, midi->read_buffer), 0); - uint8_t code_index = midi->read_buffer[0] & 0x0f; - // We always copy over the first byte. - uint8_t count = 1; - // Ignore subsequent bytes based on the code. - if ( code_index != 0x5 && code_index != 0xf ) + uint8_t const code_index = midi->read_buffer[0] & 0x0f; + uint8_t count; + + // MIDI 1.0 Table 4-1: Code Index Number Classifications + switch(code_index) { - count = 2; - if ( code_index != 0x2 && code_index != 0x6 && code_index != 0xc && code_index != 0xd ) - { + case MIDI_CIN_MISC: + case MIDI_CIN_CABLE_EVENT: + // These are reserved and unused, possibly issue somewhere, skip this packet + return 0; + break; + + case MIDI_CIN_SYSEX_END_1BYTE: + case MIDI_CIN_1BYTE_DATA: + count = 1; + break; + + case MIDI_CIN_SYSCOM_2BYTE : + case MIDI_CIN_SYSEX_END_2BYTE : + case MIDI_CIN_PROGRAM_CHANGE : + case MIDI_CIN_CHANNEL_PRESSURE : + count = 2; + break; + + default: count = 3; - } + break; } midi->read_buffer_length = count; } - uint32_t n = midi->read_buffer_length - midi->read_target_length; - if (bufsize < n) n = bufsize; + uint32_t n = tu_min32(midi->read_buffer_length - midi->read_target_length, bufsize); // Skip the header in the buffer memcpy(buffer, midi->read_buffer + 1 + midi->read_target_length, n); @@ -204,6 +229,8 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, midid_interface_t* midi = &_midid_itf[itf]; TU_VERIFY(midi->itf_num, 0); +// midid_stream_t* stream = &midi->stream_write; + uint32_t written = 0; uint32_t i = 0; while ( i < bufsize ) -- cgit v1.3.1 From 08fe16840fcc39e4cb7c1f55fa56762427734753 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 14:26:55 +0700 Subject: refactor midi write into stream --- src/class/midi/midi_device.c | 77 +++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 14748f18b..49bf2a27a 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -67,11 +67,7 @@ typedef struct // For Stream read()/write() API // Messages are always 4 bytes long, queue them for reading and writing so the // callers can use the Stream interface with single-byte read/write calls. - uint8_t write_buffer[4]; - uint8_t write_buffer_length; - uint8_t write_target_length; - -// midid_stream_t stream_write; + midid_stream_t stream_write; uint8_t read_buffer[4]; uint8_t read_buffer_length; @@ -229,7 +225,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, midid_interface_t* midi = &_midid_itf[itf]; TU_VERIFY(midi->itf_num, 0); -// midid_stream_t* stream = &midi->stream_write; + midid_stream_t* stream = &midi->stream_write; uint32_t written = 0; uint32_t i = 0; @@ -237,93 +233,94 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, { uint8_t const data = buffer[i]; - if ( midi->write_buffer_length == 0 ) + if ( stream->index == 0 ) { - // new packet + // new event packet uint8_t const msg = data >> 4; - midi->write_buffer[1] = data; - midi->write_buffer_length = 2; + + stream->index = 2; + stream->buffer[1] = data; // Check to see if we're still in a SysEx transmit. - if ( midi->write_buffer[0] == MIDI_CIN_SYSEX_START ) + if ( stream->buffer[0] == MIDI_CIN_SYSEX_START ) { if ( data == MIDI_STATUS_SYSEX_END ) { - midi->write_buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - midi->write_target_length = 2; + stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; + stream->total = 2; } else { - midi->write_target_length = 4; + stream->total = 4; } } else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) { // Channel Voice Messages - midi->write_buffer[0] = (cable_num << 4) | msg; - midi->write_target_length = 4; + stream->buffer[0] = (cable_num << 4) | msg; + stream->total = 4; } else if ( msg == 0xf ) { // System message if ( data == MIDI_STATUS_SYSEX_START ) { - midi->write_buffer[0] = MIDI_CIN_SYSEX_START; - midi->write_target_length = 4; + stream->buffer[0] = MIDI_CIN_SYSEX_START; + stream->total = 4; } else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) { - midi->write_buffer[0] = MIDI_CIN_SYSCOM_2BYTE; - midi->write_target_length = 3; + stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; + stream->total = 3; } else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) { - midi->write_buffer[0] = MIDI_CIN_SYSCOM_3BYTE; - midi->write_target_length = 4; + stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; + stream->total = 4; } else { - midi->write_buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - midi->write_target_length = 2; + stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; + stream->total = 2; } } else { // Pack individual bytes if we don't support packing them into words. - midi->write_buffer[0] = cable_num << 4 | 0xf; - midi->write_buffer[2] = 0; - midi->write_buffer[3] = 0; - midi->write_buffer_length = 2; - midi->write_target_length = 2; + stream->buffer[0] = cable_num << 4 | 0xf; + stream->buffer[2] = 0; + stream->buffer[3] = 0; + stream->index = 2; + stream->total = 2; } } else { - // On-going packet + // On-going (buffering) packet - TU_ASSERT(midi->write_buffer_length < 4, 0); - midi->write_buffer[midi->write_buffer_length] = data; - midi->write_buffer_length++; + TU_ASSERT(stream->index < 4, written); + stream->buffer[stream->index] = data; + stream->index++; // See if this byte ends a SysEx. - if ( midi->write_buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) + if ( stream->buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) { - midi->write_buffer[0] = MIDI_CIN_SYSEX_START + (midi->write_buffer_length - 1); - midi->write_target_length = midi->write_buffer_length; + stream->buffer[0] = MIDI_CIN_SYSEX_START + (stream->index - 1); + stream->total = stream->index; } } // Send out packet - if ( midi->write_buffer_length == midi->write_target_length ) + if ( stream->index == stream->total ) { // zeroes unused bytes - for(uint8_t idx = midi->write_target_length; idx < 4; idx++) midi->write_buffer[idx] = 0; + for(uint8_t idx = stream->total; idx < 4; idx++) stream->buffer[idx] = 0; - uint16_t const count = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); + uint16_t const count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4); // reset buffer - midi->write_buffer_length = midi->write_target_length = 0; + stream->index = stream->total = 0; // fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing if ( count != 4 ) break; -- cgit v1.3.1 From 99b78e62f2172988ffa3835b7d6bcaaf455cef10 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 14:34:13 +0700 Subject: removed tud_midi_write24() --- src/class/midi/midi_device.h | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index aaceaf62a..c875748fd 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -72,10 +72,6 @@ uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, ui // Write byte Stream (legacy) uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); -// Write good-old 3 bytes data, this use write packet -static inline -uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); - // Read event packet (4 bytes) bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); @@ -87,13 +83,26 @@ bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); //--------------------------------------------------------------------+ static inline bool tud_midi_mounted (void); static inline uint32_t tud_midi_available (void); + static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); -static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); static inline bool tud_midi_packet_read (uint8_t packet[4]); static inline bool tud_midi_packet_write(uint8_t const packet[4]); +// TODO remove after 0.10.0 release +TU_ATTR_DEPRECATED("tud_midi_send() is renamed to tud_midi_packet_write()") +static inline bool tud_midi_send(uint8_t packet[4]) +{ + return tud_midi_packet_write(packet); +} + +TU_ATTR_DEPRECATED("tud_midi_receive() is renamed to tud_midi_packet_read()") +static inline bool tud_midi_receive(uint8_t packet[4]) +{ + return tud_midi_packet_read(packet); +} + //--------------------------------------------------------------------+ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ @@ -103,12 +112,6 @@ TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf); // Inline Functions //--------------------------------------------------------------------+ -static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3) -{ - uint8_t msg[3] = { b1, b2, b3 }; - return tud_midi_n_write(itf, cable_num, msg, 3); -} - static inline bool tud_midi_mounted (void) { return tud_midi_n_mounted(0); @@ -129,12 +132,6 @@ static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, return tud_midi_n_write(0, cable_num, buffer, bufsize); } -static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3) -{ - uint8_t msg[3] = { b1, b2, b3 }; - return tud_midi_write(cable_num, msg, 3); -} - static inline bool tud_midi_packet_read (uint8_t packet[4]) { return tud_midi_n_packet_read(0, packet); -- cgit v1.3.1 From da59c4ad4434b64691aa7a93e03381702633964d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 14:43:38 +0700 Subject: rename midi write()/read() to stream_write() stream_read() also add deprecated for warning and rename hint --- examples/device/dynamic_configuration/src/main.c | 6 ++- examples/device/midi_test/src/main.c | 4 +- src/class/midi/midi_device.c | 4 +- src/class/midi/midi_device.h | 55 +++++++++++++++--------- 4 files changed, 43 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/examples/device/dynamic_configuration/src/main.c b/examples/device/dynamic_configuration/src/main.c index ce1f752d0..4c10f55b0 100644 --- a/examples/device/dynamic_configuration/src/main.c +++ b/examples/device/dynamic_configuration/src/main.c @@ -186,10 +186,12 @@ void midi_task(void) if (previous < 0) previous = sizeof(note_sequence) - 1; // Send Note On for current position at full velocity (127) on channel 1. - tud_midi_write24(cable_num, 0x90 | channel, note_sequence[note_pos], 127); + uint8_t note_on[3] = { 0x90 | channel, note_sequence[note_pos], 127 }; + tud_midi_stream_write(cable_num, note_on, 3); // Send Note Off for previous note. - tud_midi_write24(cable_num, 0x80 | channel, note_sequence[previous], 0); + uint8_t note_off[3] = { 0x80 | channel, note_sequence[previous], 0}; + tud_midi_stream_write(cable_num, note_off, 3); // Increment position note_pos++; diff --git a/examples/device/midi_test/src/main.c b/examples/device/midi_test/src/main.c index af10350df..9e0e82a10 100644 --- a/examples/device/midi_test/src/main.c +++ b/examples/device/midi_test/src/main.c @@ -147,11 +147,11 @@ void midi_task(void) // Send Note On for current position at full velocity (127) on channel 1. uint8_t note_on[3] = { 0x90 | channel, note_sequence[note_pos], 127 }; - tud_midi_write(cable_num, note_on, 3); + tud_midi_stream_write(cable_num, note_on, 3); // Send Note Off for previous note. uint8_t note_off[3] = { 0x80 | channel, note_sequence[previous], 0}; - tud_midi_write(cable_num, note_off, 3); + tud_midi_stream_write(cable_num, note_off, 3); // Increment position note_pos++; diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 49bf2a27a..e76f01db2 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -127,7 +127,7 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) return tu_fifo_count(&_midid_itf[itf].rx_ff); } -uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) +uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) { (void) cable_num; midid_interface_t* midi = &_midid_itf[itf]; @@ -220,7 +220,7 @@ static uint32_t write_flush(midid_interface_t* midi) } } -uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) +uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { midid_interface_t* midi = &_midid_itf[itf]; TU_VERIFY(midi->itf_num, 0); diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index c875748fd..67f03930c 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -61,36 +61,51 @@ //--------------------------------------------------------------------+ // Check if midi interface is mounted -bool tud_midi_n_mounted (uint8_t itf); +bool tud_midi_n_mounted (uint8_t itf); // Get the number of bytes available for reading -uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); +uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); -// Read byte stream (legacy) -uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); +// Read byte stream (legacy) +uint32_t tud_midi_n_stream_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); -// Write byte Stream (legacy) -uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); +// Write byte Stream (legacy) +uint32_t tud_midi_n_stream_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); -// Read event packet (4 bytes) -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); +// Read event packet (4 bytes) +bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); -// Write event packet (4 bytes) -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); +// Write event packet (4 bytes) +bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); //--------------------------------------------------------------------+ // Application API (Single Interface) //--------------------------------------------------------------------+ -static inline bool tud_midi_mounted (void); -static inline uint32_t tud_midi_available (void); +static inline bool tud_midi_mounted (void); +static inline uint32_t tud_midi_available (void); -static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); -static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); +static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize); +static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); -static inline bool tud_midi_packet_read (uint8_t packet[4]); -static inline bool tud_midi_packet_write(uint8_t const packet[4]); +static inline bool tud_midi_packet_read (uint8_t packet[4]); +static inline bool tud_midi_packet_write (uint8_t const packet[4]); +//------------- Deprecated API name -------------// // TODO remove after 0.10.0 release + +TU_ATTR_DEPRECATED("tud_midi_read() is renamed to tud_midi_stream_read()") +static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) +{ + return tud_midi_stream_read(buffer, bufsize); +} + +TU_ATTR_DEPRECATED("tud_midi_write() is renamed to tud_midi_stream_write()") +static inline uint32_t tud_midi_write(uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) +{ + return tud_midi_stream_write(cable_num, buffer, bufsize); +} + + TU_ATTR_DEPRECATED("tud_midi_send() is renamed to tud_midi_packet_write()") static inline bool tud_midi_send(uint8_t packet[4]) { @@ -122,14 +137,14 @@ static inline uint32_t tud_midi_available (void) return tud_midi_n_available(0, 0); } -static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) +static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize) { - return tud_midi_n_read(0, 0, buffer, bufsize); + return tud_midi_n_stream_read(0, 0, buffer, bufsize); } -static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) +static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { - return tud_midi_n_write(0, cable_num, buffer, bufsize); + return tud_midi_n_stream_write(0, cable_num, buffer, bufsize); } static inline bool tud_midi_packet_read (uint8_t packet[4]) -- cgit v1.3.1 From 350eb1127755f3ee0dd3dd186cc31e9492916a0c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 14:52:44 +0700 Subject: refactor midi read buffer to stream --- src/class/midi/midi_device.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index e76f01db2..a4cc104a8 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -68,10 +68,7 @@ typedef struct // Messages are always 4 bytes long, queue them for reading and writing so the // callers can use the Stream interface with single-byte read/write calls. midid_stream_t stream_write; - - uint8_t read_buffer[4]; - uint8_t read_buffer_length; - uint8_t read_target_length; + midid_stream_t stream_read; // Endpoint Transfer buffer CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE]; @@ -131,14 +128,16 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui { (void) cable_num; midid_interface_t* midi = &_midid_itf[itf]; + midid_stream_t* stream = &midi->stream_read; + + TU_VERIFY(bufsize, 0); - // Fill empty buffer - if ( midi->read_buffer_length == 0 ) + // Get new packet from fifo + if ( stream->total == 0 ) { - TU_VERIFY(tud_midi_n_packet_read(itf, midi->read_buffer), 0); + TU_VERIFY(tud_midi_n_packet_read(itf, stream->buffer), 0); - uint8_t const code_index = midi->read_buffer[0] & 0x0f; - uint8_t count; + uint8_t const code_index = stream->buffer[0] & 0x0f; // MIDI 1.0 Table 4-1: Code Index Number Classifications switch(code_index) @@ -151,34 +150,32 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui case MIDI_CIN_SYSEX_END_1BYTE: case MIDI_CIN_1BYTE_DATA: - count = 1; + stream->total = 1; break; case MIDI_CIN_SYSCOM_2BYTE : case MIDI_CIN_SYSEX_END_2BYTE : case MIDI_CIN_PROGRAM_CHANGE : case MIDI_CIN_CHANNEL_PRESSURE : - count = 2; + stream->total = 2; break; default: - count = 3; + stream->total = 3; break; } - - midi->read_buffer_length = count; } - uint32_t n = tu_min32(midi->read_buffer_length - midi->read_target_length, bufsize); + uint32_t const n = tu_min32(stream->total - stream->index, bufsize); - // Skip the header in the buffer - memcpy(buffer, midi->read_buffer + 1 + midi->read_target_length, n); - midi->read_target_length += n; + // Skip the header (1st byte) in the buffer + memcpy(buffer, stream->buffer + 1 + stream->index, n); + stream->index += n; - if ( midi->read_target_length == midi->read_buffer_length ) + if ( stream->total == stream->index ) { - midi->read_buffer_length = 0; - midi->read_target_length = 0; + stream->index = 0; + stream->total = 0; } return n; -- cgit v1.3.1 From 48bb96f5072a173189d9076c5c2b1f5066327bf6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 15:08:36 +0700 Subject: correct midi stream read behavior to read until user buffer is full or no more data from usb fifo --- src/class/midi/midi_device.c | 111 ++++++++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index a4cc104a8..9ccbb733c 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -52,6 +52,12 @@ typedef struct uint8_t ep_in; uint8_t ep_out; + // For Stream read()/write() API + // Messages are always 4 bytes long, queue them for reading and writing so the + // callers can use the Stream interface with single-byte read/write calls. + midid_stream_t stream_write; + midid_stream_t stream_read; + /*------------- From this point, data is not cleared by bus reset -------------*/ // FIFO tu_fifo_t rx_ff; @@ -64,12 +70,6 @@ typedef struct osal_mutex_def_t tx_ff_mutex; #endif - // For Stream read()/write() API - // Messages are always 4 bytes long, queue them for reading and writing so the - // callers can use the Stream interface with single-byte read/write calls. - midid_stream_t stream_write; - midid_stream_t stream_read; - // Endpoint Transfer buffer CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE]; CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EP_BUFSIZE]; @@ -127,58 +127,71 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) { (void) cable_num; - midid_interface_t* midi = &_midid_itf[itf]; - midid_stream_t* stream = &midi->stream_read; - TU_VERIFY(bufsize, 0); - // Get new packet from fifo - if ( stream->total == 0 ) - { - TU_VERIFY(tud_midi_n_packet_read(itf, stream->buffer), 0); + uint8_t* buf8 = (uint8_t*) buffer; - uint8_t const code_index = stream->buffer[0] & 0x0f; + midid_interface_t* midi = &_midid_itf[itf]; + midid_stream_t* stream = &midi->stream_read; - // MIDI 1.0 Table 4-1: Code Index Number Classifications - switch(code_index) + uint32_t total_read = 0; + while( bufsize ) + { + // Get new packet from fifo, then set packet expected bytes + if ( stream->total == 0 ) { - case MIDI_CIN_MISC: - case MIDI_CIN_CABLE_EVENT: - // These are reserved and unused, possibly issue somewhere, skip this packet - return 0; - break; + // return if there is no more data from fifo + if ( !tud_midi_n_packet_read(itf, stream->buffer) ) return total_read; - case MIDI_CIN_SYSEX_END_1BYTE: - case MIDI_CIN_1BYTE_DATA: - stream->total = 1; - break; + uint8_t const code_index = stream->buffer[0] & 0x0f; - case MIDI_CIN_SYSCOM_2BYTE : - case MIDI_CIN_SYSEX_END_2BYTE : - case MIDI_CIN_PROGRAM_CHANGE : - case MIDI_CIN_CHANNEL_PRESSURE : - stream->total = 2; - break; + // MIDI 1.0 Table 4-1: Code Index Number Classifications + switch(code_index) + { + case MIDI_CIN_MISC: + case MIDI_CIN_CABLE_EVENT: + // These are reserved and unused, possibly issue somewhere, skip this packet + return 0; + break; + + case MIDI_CIN_SYSEX_END_1BYTE: + case MIDI_CIN_1BYTE_DATA: + stream->total = 1; + break; + + case MIDI_CIN_SYSCOM_2BYTE : + case MIDI_CIN_SYSEX_END_2BYTE : + case MIDI_CIN_PROGRAM_CHANGE : + case MIDI_CIN_CHANNEL_PRESSURE : + stream->total = 2; + break; - default: - stream->total = 3; - break; + default: + stream->total = 3; + break; + } } - } - uint32_t const n = tu_min32(stream->total - stream->index, bufsize); + // Copy data up to bufsize + uint32_t const count = tu_min32(stream->total - stream->index, bufsize); - // Skip the header (1st byte) in the buffer - memcpy(buffer, stream->buffer + 1 + stream->index, n); - stream->index += n; + // Skip the header (1st byte) in the buffer + memcpy(buf8, stream->buffer + 1 + stream->index, count); - if ( stream->total == stream->index ) - { - stream->index = 0; - stream->total = 0; + total_read += count; + stream->index += count; + buf8 += count; + bufsize -= count; + + // complete current event packet, reset stream + if ( stream->total == stream->index ) + { + stream->index = 0; + stream->total = 0; + } } - return n; + return total_read; } bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) @@ -224,7 +237,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* midid_stream_t* stream = &midi->stream_write; - uint32_t written = 0; + uint32_t total_written = 0; uint32_t i = 0; while ( i < bufsize ) { @@ -296,7 +309,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* { // On-going (buffering) packet - TU_ASSERT(stream->index < 4, written); + TU_ASSERT(stream->index < 4, total_written); stream->buffer[stream->index] = data; stream->index++; @@ -316,14 +329,14 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* uint16_t const count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4); - // reset buffer + // complete current event packet, reset stream stream->index = stream->total = 0; // fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing if ( count != 4 ) break; // updated written if succeeded - written = i; + total_written = i; } i++; @@ -331,7 +344,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* write_flush(midi); - return written; + return total_written; } bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) -- cgit v1.3.1 From 9b2ddd9cc6401b80350179d26e842557f9b60aaf Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 09:49:27 +0200 Subject: Generalize audio driver for 3 audio functions plus a lot more. - Audio format and parameters are parsed from descriptors thus user no longer needs to give them explicitely - Tested for 4 channel software type I PCM encoding with 16 bit with 1 channel per FIFO and 2 channels per FIFO (this is I2S specific) --- examples/device/audio_test/src/main.c | 8 +- examples/device/audio_test/src/tusb_config.h | 22 +- examples/device/audio_test/src/usb_descriptors.c | 11 +- examples/device/uac2_headset/src/tusb_config.h | 34 +- examples/device/uac2_headset/src/usb_descriptors.c | 2 +- src/class/audio/audio.h | 76 +- src/class/audio/audio_device.c | 1088 ++++++++++++++++---- src/class/audio/audio_device.h | 313 ++++-- src/common/tusb_fifo.c | 4 +- src/device/usbd.h | 59 +- 10 files changed, 1214 insertions(+), 403 deletions(-) (limited to 'src') diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index a631f37b6..7cbf57946 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -53,17 +53,17 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states -bool mute[CFG_TUD_AUDIO_N_CHANNELS_TX + 1]; // +1 for master channel 0 -uint16_t volume[CFG_TUD_AUDIO_N_CHANNELS_TX + 1]; // +1 for master channel 0 +bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 uint32_t sampFreq; uint8_t clkValid; // Range states -audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_N_CHANNELS_TX+1]; // Volume range state +audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state // Audio test data -uint16_t test_buffer_audio[CFG_TUD_AUDIO_EPSIZE_IN/2]; +uint16_t test_buffer_audio[CFG_TUD_AUDIO_EP_SZ_IN/2]; uint16_t startVal = 0; void led_blinking_task(void); diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index 557a8b15e..d3b617319 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -91,6 +91,21 @@ extern "C" { // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- +// Have a look into audio_device.h for all configurations + +#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_ONE_CH_DESC_LEN +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) +#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 // Size of control request buffer + +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! +#define CFG_TUD_AUDIO_EP_SZ_IN 48 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x 1 Channel +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN + 1 + + + // Audio format type #define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_I @@ -100,14 +115,11 @@ extern "C" { #define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 2 // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 #define CFG_TUD_AUDIO_EPSIZE_IN 48 * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX // ceil(f_s/1000) * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN + CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX // Just for safety one sample more space +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EPSIZE_IN + CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_N_CHANNELS_TX // Just for safety one sample more space -// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) -#define CFG_TUD_AUDIO_N_AS_INT 1 -// Size of control request buffer -#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 #ifdef __cplusplus } diff --git a/examples/device/audio_test/src/usb_descriptors.c b/examples/device/audio_test/src/usb_descriptors.c index d4869a940..67dd34d2a 100644 --- a/examples/device/audio_test/src/usb_descriptors.c +++ b/examples/device/audio_test/src/usb_descriptors.c @@ -79,7 +79,7 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_ONE_CH_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 @@ -89,20 +89,13 @@ enum #define EPNUM_AUDIO 0x01 #endif -// These variables are required by the audio driver in audio_device.c - -// List of audio descriptor lengths which is required by audio driver - you need as many entries as CFG_TUD_AUDIO - unfortunately this is not possible to determine otherwise -const uint16_t tud_audio_desc_lengths[] = {TUD_AUDIO_MIC_DESC_LEN}; - -// TAKE CARE - THE NUMBER OF AUDIO STREAMING INTERFACES PER AUDIO FUNCTION MUST NOT EXCEED CFG_TUD_AUDIO_N_AS_INT - IF IT DOES INCREASE CFG_TUD_AUDIO_N_AS_INT IN tusb_config.h! - uint8_t const desc_configuration[] = { // 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), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_MIC_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ 16, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EPSIZE_IN) + TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 7795d8405..511e4e558 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -91,35 +91,31 @@ extern "C" { //-------------------------------------------------------------------- // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUD_AUDIO_IN_PATH (CFG_TUD_AUDIO) -#define CFG_TUD_AUDIO_OUT_PATH (CFG_TUD_AUDIO) - -// Audio format type -#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_I -#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_I +#define CFG_TUD_AUDIO_IN_PATH (CFG_TUD_AUDIO) +#define CFG_TUD_AUDIO_OUT_PATH (CFG_TUD_AUDIO) // Audio format type I specifications -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM -#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 2 -#define CFG_TUD_AUDIO_N_CHANNELS_RX 2 -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 2 -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX 2 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX 2 +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_EPSIZE_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels -#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 +#define CFG_TUD_AUDIO_EP_SZ_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EPSIZE_IN // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_EPSIZE_OUT (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels -#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_OUT*3 +#define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 +#define CFG_TUD_AUDIO_EP_OUT_SZ (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ CFG_TUD_AUDIO_EP_OUT_SZ*3 // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) -#define CFG_TUD_AUDIO_N_AS_INT 1 +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 // Size of control request buffer -#define CFG_TUD_AUDIO_CTRL_BUF_SIZE 64 +#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 #ifdef __cplusplus } diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index 940f0fe2b..b69e5a5e0 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -98,7 +98,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, 2, 16, EPNUM_AUDIO, CFG_TUD_AUDIO_EPSIZE_OUT, EPNUM_AUDIO | 0x80, CFG_TUD_AUDIO_EPSIZE_IN) + TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, 2, 16, EPNUM_AUDIO, CFG_TUD_AUDIO_EP_OUT_SZ, EPNUM_AUDIO | 0x80, CFG_TUD_AUDIO_EP_SZ_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index af0e86e21..2c6cd260a 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -469,44 +469,44 @@ typedef enum /// Additional Audio Device Class Codes - Source: Audio Data Formats /// A.1 - Audio Class-Format Type Codes UAC2 -//typedef enum -//{ -// AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, -// AUDIO_FORMAT_TYPE_I = 0x01, -// AUDIO_FORMAT_TYPE_II = 0x02, -// AUDIO_FORMAT_TYPE_III = 0x03, -// AUDIO_FORMAT_TYPE_IV = 0x04, -// AUDIO_EXT_FORMAT_TYPE_I = 0x81, -// AUDIO_EXT_FORMAT_TYPE_II = 0x82, -// AUDIO_EXT_FORMAT_TYPE_III = 0x83, -//} audio_format_type_t; - -#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00 -#define AUDIO_FORMAT_TYPE_I 0x01 -#define AUDIO_FORMAT_TYPE_II 0x02 -#define AUDIO_FORMAT_TYPE_III 0x03 -#define AUDIO_FORMAT_TYPE_IV 0x04 -#define AUDIO_EXT_FORMAT_TYPE_I 0x81 -#define AUDIO_EXT_FORMAT_TYPE_II 0x82 -#define AUDIO_EXT_FORMAT_TYPE_III 0x83 - -/// A.2.1 - Audio Class-Audio Data Format Type I UAC2 -//typedef enum -//{ -// AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), -// AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), -// AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), -// AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), -// AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), -// AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, -//} audio_data_format_type_I_t; - -#define AUDIO_DATA_FORMAT_TYPE_I_PCM ((uint32_t) (1 << 0)) -#define AUDIO_DATA_FORMAT_TYPE_I_PCM8 ((uint32_t) (1 << 1)) -#define AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT ((uint32_t) (1 << 2)) -#define AUDIO_DATA_FORMAT_TYPE_I_ALAW ((uint32_t) (1 << 3)) -#define AUDIO_DATA_FORMAT_TYPE_I_MULAW ((uint32_t) (1 << 4)) -#define AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA 0x100000000 +typedef enum +{ + AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, + AUDIO_FORMAT_TYPE_I = 0x01, + AUDIO_FORMAT_TYPE_II = 0x02, + AUDIO_FORMAT_TYPE_III = 0x03, + AUDIO_FORMAT_TYPE_IV = 0x04, + AUDIO_EXT_FORMAT_TYPE_I = 0x81, + AUDIO_EXT_FORMAT_TYPE_II = 0x82, + AUDIO_EXT_FORMAT_TYPE_III = 0x83, +} audio_format_type_t; + +//#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00 +//#define AUDIO_FORMAT_TYPE_I 0x01 +//#define AUDIO_FORMAT_TYPE_II 0x02 +//#define AUDIO_FORMAT_TYPE_III 0x03 +//#define AUDIO_FORMAT_TYPE_IV 0x04 +//#define AUDIO_EXT_FORMAT_TYPE_I 0x81 +//#define AUDIO_EXT_FORMAT_TYPE_II 0x82 +//#define AUDIO_EXT_FORMAT_TYPE_III 0x83 + +// A.2.1 - Audio Class-Audio Data Format Type I UAC2 +typedef enum +{ + AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), + AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), + AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), + AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), + AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, +} audio_data_format_type_I_t; + +//#define AUDIO_DATA_FORMAT_TYPE_I_PCM ((uint32_t) (1 << 0)) +//#define AUDIO_DATA_FORMAT_TYPE_I_PCM8 ((uint32_t) (1 << 1)) +//#define AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT ((uint32_t) (1 << 2)) +//#define AUDIO_DATA_FORMAT_TYPE_I_ALAW ((uint32_t) (1 << 3)) +//#define AUDIO_DATA_FORMAT_TYPE_I_MULAW ((uint32_t) (1 << 4)) +//#define AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA 0x100000000 /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 73f265a8f..5df32c30f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -63,7 +63,7 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ - // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically +// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically #if ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || /* Intermediate software buffer required */ \ CFG_TUSB_MCU == OPT_MCU_DA1469X || /* Intermediate software buffer required */ \ CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ @@ -92,18 +92,170 @@ #define USE_LINEAR_BUFFER 0 #endif +// Declaration of buffers + +// Check for maximum supported numbers +#if CFG_TUD_AUDIO > 3 +#error Maximum number of audio functions restricted to three! +#endif + +// EP IN software buffers and mutexes +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + +// Linear buffer TX in case: +// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR +// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into +#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) + +// EP OUT software buffers and mutexes +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + +// Linear buffer RX in case: +// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR +// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 +CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) + +// Control buffers +CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; +#if CFG_TUD_AUDIO > 1 +CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; +#endif +#if CFG_TUD_AUDIO > 2 +CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; +#endif + +// Active alternate setting of interfaces +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 +CFG_TUSB_MEM_ALIGN uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 +CFG_TUSB_MEM_ALIGN uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 +CFG_TUSB_MEM_ALIGN uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; +#endif + +// Software encoding/decoding support FIFOs +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; +tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; +tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; +tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO +#endif +#endif +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; +tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; +tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 +CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; +tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; +#if CFG_FIFO_MUTEX +osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO +#endif +#endif +#endif + typedef struct { uint8_t rhport; uint8_t const * p_desc; // Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN uint8_t ep_in; // TX audio data EP. + uint16_t ep_in_sz; // Current size of TX EP uint8_t ep_in_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT uint8_t ep_out; // Incoming (into uC) audio data EP. + uint16_t ep_out_sz; // Current size of RX EP uint8_t ep_out_as_intf_num; // Corresponding Standard AS Interface Descriptor (4.9.1) belonging to input terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -116,74 +268,83 @@ typedef struct uint8_t ep_int_ctr; // Audio control interrupt EP. #endif -#if CFG_TUD_AUDIO_N_AS_INT - uint8_t altSetting[CFG_TUD_AUDIO_N_AS_INT]; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 + uint8_t * alt_setting_ptr; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! #endif /*------------- From this point, data is not cleared by bus reset -------------*/ + // + uint16_t desc_length; // Length of audio function descriptor + // Buffer for control requests - CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_AUDIO_CTRL_BUF_SIZE]; + uint8_t * ctrl_buf; + uint8_t ctrl_buf_sz; // EP Transfer buffers and FIFOs -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE - -#if !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - CFG_TUSB_MEM_ALIGN uint8_t ep_out_buf[CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE]; +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +#if !CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_t ep_out_ff; - -#if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd; // No need for write mutex as only USB driver writes into FIFO -#endif - #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format). #endif - #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - CFG_TUSB_MEM_ALIGN uint8_t ep_in_buf[CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE]; +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING tu_fifo_t ep_in_ff; - -#if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr; // No need for read mutex as only USB driver reads from FIFO #endif -#endif - - // Audio control interrupt buffer - no FIFO + // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74) #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; #endif - // Support FIFOs -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - tu_fifo_t tx_supp_ff[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO]; - CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO][CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX]; -#if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr[CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO + // Decoding parameters - parameters are set when alternate AS interface is set by host + // Coding is currently only supported for EP. Software coding corresponding to AS interfaces without EPs are not supported currently. +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + audio_format_type_t format_type_rx; + uint8_t n_channels_rx; + +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + audio_data_format_type_I_t format_type_I_rx; + uint8_t n_bytes_per_sampe_rx; #endif #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - tu_fifo_t rx_supp_ff[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO]; - CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO][CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX]; -#if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd[CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO + // Encoding parameters - parameters are set when alternate AS interface is set by host +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + audio_format_type_t format_type_tx; + uint8_t n_channels_tx; + +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + audio_data_format_type_I_t format_type_I_tx; + uint8_t n_bytes_per_sampe_tx; + uint8_t n_channels_per_ff_tx; +#endif #endif + + // Support FIFOs for software encoding and decoding +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + tu_fifo_t * rx_supp_ff; + uint8_t n_rx_supp_ff; + uint8_t n_channels_per_ff_rx; +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + tu_fifo_t * tx_supp_ff; + uint8_t n_tx_supp_ff; #endif // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used -#if CFG_TUD_AUDIO_EPSIZE_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE) - CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out[CFG_TUD_AUDIO_EPSIZE_OUT]; +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) + uint8_t * lin_buf_out; #define USE_LINEAR_BUFFER_RX 1 #endif -#if CFG_TUD_AUDIO_EPSIZE_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE) - CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in[CFG_TUD_AUDIO_EPSIZE_IN]; +#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) + uint8_t * lin_buf_in; #define USE_LINEAR_BUFFER_TX 1 #endif @@ -204,30 +365,19 @@ typedef struct //--------------------------------------------------------------------+ CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; -extern const uint16_t tud_audio_desc_lengths[]; - -// bSubslotSize for PCM encoding/decoding using support FIFOs -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -extern const tud_audio_n_bytes_per_sample_tx[CFG_TUD_AUDIO][CFG_TUD_AUDIO_N_AS_INT]; -#endif - -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -extern const tud_audio_n_bytes_per_sample_rx[CFG_TUD_AUDIO][CFG_TUD_AUDIO_N_AS_INT]; -#endif - -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio); #endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); #endif @@ -238,17 +388,23 @@ static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8 static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver); static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver); static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); +static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf); + +static inline uint8_t tu_desc_subtype(void const* desc) +{ + return ((uint8_t const*) desc)[2]; +} bool tud_audio_n_mounted(uint8_t itf) { TU_VERIFY(itf < CFG_TUD_AUDIO); audiod_interface_t* audio = &_audiod_itf[itf]; -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT if (audio->ep_out == 0) return false; #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN if (audio->ep_in == 0) return false; #endif @@ -267,7 +423,7 @@ bool tud_audio_n_mounted(uint8_t itf) // READ API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING uint16_t tud_audio_n_available(uint8_t itf) { @@ -289,50 +445,46 @@ bool tud_audio_n_clear_ep_out_ff(uint8_t itf) #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT // Delete all content in the support RX FIFOs bool tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); return tu_fifo_clear(&_audiod_itf[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); return tu_fifo_count(&_audiod_itf[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); return tu_fifo_read_n(&_audiod_itf[itf].rx_supp_ff[channelId], buffer, bufsize); } #endif // This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO (or support FIFOs + decoding of received stream into audio channels). -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE = 0. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_DECODING = 0. -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) { uint8_t idxDriver, idxItf; uint8_t const *dummy2; - // If a callback is used determine current alternate setting of - if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) - { - // Find index of audio streaming interface and index of interface - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); - } + // Find index of audio streaming interface and index of interface + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) - if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); + if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting_ptr[idxItf])); -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT - switch (CFG_TUD_AUDIO_FORMAT_TYPE_RX) + switch (audio->format_type_rx) { case AUDIO_FORMAT_TYPE_UNDEFINED: // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! @@ -342,7 +494,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ case AUDIO_FORMAT_TYPE_I: - switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_RX) + switch (audio->format_type_I_tx) { case AUDIO_DATA_FORMAT_TYPE_I_PCM: TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio, n_bytes_received)); @@ -364,7 +516,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ } // Prepare for next transmission - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else @@ -373,34 +525,108 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); // Schedule for next receive - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else // Data is already placed in EP FIFO, schedule for next receive - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); #endif #endif // Call a weak callback here - a possibility for user to get informed decoding was completed - if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->altSetting[idxItf])); + if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting_ptr[idxItf])); return true; } -#endif //CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#endif //CFG_TUD_AUDIO_ENABLE_EP_OUT -// The following functions are used in case CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE != 0 -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +// The following functions are used in case CFG_TUD_AUDIO_ENABLE_DECODING != 0 +#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT // Decoding according to 2.3.1.5 Audio Streams + +// Helper function +static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used) +{ + + // This function is an optimized version of +// while((uint8_t *)dst < dst_end) +// { +// memcpy(dst, src, nBytesToCopy); +// dst = (uint8_t *)dst + nBytesToCopy; +// src += nBytesToCopy * n_ff_used; +// } + + // Optimize for fast half word copies + typedef struct{ + uint16_t val; + } __attribute((__packed__)) unaligned_uint16_t; + + // Optimize for fast word copies + typedef struct{ + uint32_t val; + } __attribute((__packed__)) unaligned_uint32_t; + + switch (nBytesToCopy) + { + case 1: + while((uint8_t *)dst < dst_end) + { + *(uint8_t *)dst++ = *src; + src += n_ff_used; + } + break; + + case 2: + while((uint8_t *)dst < dst_end) + { + *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; + dst += 2; + src += 2 * n_ff_used; + } + break; + + case 3: + while((uint8_t *)dst < dst_end) + { +// memcpy(dst, src, 3); +// dst = (uint8_t *)dst + 3; +// src += 3 * n_ff_used; + + // TODO: Is there a faster way to copy 3 bytes? + *(uint8_t *)dst++ = *src++; + *(uint8_t *)dst++ = *src++; + *(uint8_t *)dst++ = *src++; + + src += 3 * (n_ff_used - 1); + } + break; + + case 4: + while((uint8_t *)dst < dst_end) + { + *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; + dst += 4; + src += 4 * n_ff_used; + } + break; + } + + return src; +} + static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) { (void) rhport; // Determine amount of samples - uint16_t const nChannelsPerFF = CFG_TUD_AUDIO_N_CHANNELS_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; - uint16_t const nBytesToCopy = nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; - uint16_t const nSamplesPerFFToRead = n_bytes_received / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; + uint8_t const n_ff_used = audio->n_channels_rx / audio->n_channels_per_ff_rx; + + TU_ASSERT( n_ff_used <= audio->n_rx_supp_ff ); + + uint16_t const nBytesToCopy = audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx; + uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used; uint8_t cnt_ff; // Decode @@ -409,36 +635,26 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint8_t * dst_end; uint16_t len; - for (cnt_ff = 0; cnt_ff < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt_ff++) + for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - src = &audio->lin_buf_out[cnt_ff*nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX]; + src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nSamplesPerFFToRead); + len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nBytesPerFFToRead); tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); - dst_end = dst + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; + dst_end = dst + len; - while((uint8_t *)dst < dst_end) - { - memcpy(dst, src, nBytesToCopy); - dst = (uint8_t *)dst + nBytesToCopy; - src += nBytesToCopy * CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; - } + src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); // Handle wrapped part of FIFO - if (len < nSamplesPerFFToRead) + if (len < nBytesPerFFToRead) { - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nSamplesPerFFToRead - len); + len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nBytesPerFFToRead - len); tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); - dst_end = dst + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX; + dst_end = dst + len; - while((uint8_t *)dst < dst_end) - { - memcpy(dst, src, nBytesToCopy); - dst = (uint8_t *)dst + nBytesToCopy; - src += nBytesToCopy * CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; - } + audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); } } @@ -447,13 +663,13 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, return true; } -#endif //CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#endif //CFG_TUD_AUDIO_ENABLE_DECODING //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING /** * \brief Write data to EP in buffer @@ -480,7 +696,7 @@ bool tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete #endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit { TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); @@ -498,13 +714,13 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force a bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_tx_supp_ff); return tu_fifo_clear(&_audiod_itf[itf].tx_supp_ff[channelId]); } uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_tx_supp_ff); return tu_fifo_write_n(&_audiod_itf[itf].tx_supp_ff[channelId], data, len); } #endif @@ -534,42 +750,44 @@ uint16_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint16_t // This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE = 0 and use tud_audio_n_write. +// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_ENCODING = 0 and use tud_audio_n_write. // n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) { uint8_t idxDriver, idxItf; uint8_t const *dummy2; - // If a callback is used determine current alternate setting of - if (tud_audio_tx_done_pre_load_cb || tud_audio_tx_done_post_load_cb) - { - // Find index of audio streaming interface and index of interface - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); - } +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I + // Required in any case regardless if call backs are used - find index of audio streaming interface and index of interface + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); +#else + // If a callback is used determine current alternate setting of - find index of audio streaming interface and index of interface + if (tud_audio_tx_done_pre_load_cb || tud_audio_tx_done_post_load_cb) TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); +#endif // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->altSetting[idxItf])); + if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->alt_setting_ptr[idxItf])); // Send everything in ISO EP FIFO uint16_t n_bytes_tx; // If support FIFOs are used, encode and schedule transmit -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN - switch (CFG_TUD_AUDIO_FORMAT_TYPE_TX) +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN + switch (audio->format_type_tx) { case AUDIO_FORMAT_TYPE_UNDEFINED: // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); TU_BREAKPOINT(); + n_bytes_tx = 0; break; case AUDIO_FORMAT_TYPE_I: - switch (CFG_TUD_AUDIO_FORMAT_TYPE_I_TX) + switch (audio->format_type_I_tx) { case AUDIO_DATA_FORMAT_TYPE_I_PCM: @@ -580,6 +798,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) // YOUR ENCODING IS REQUIRED HERE! TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); TU_BREAKPOINT(); + n_bytes_tx = 0; break; } break; @@ -588,6 +807,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented!\r\n"); TU_BREAKPOINT(); + n_bytes_tx = 0; break; } @@ -596,27 +816,27 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) #else // No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule - n_bytes_tx = tu_fifo_count(&audio->ep_in_ff); + n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); // Limit up to max packet size, more can not be done for ISO - #if USE_LINEAR_BUFFER_TX - tu_fifo_write_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); - #else - // Send everything in ISO EP FIFO - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); - #endif +#if USE_LINEAR_BUFFER_TX + tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); +#else + // Send everything in ISO EP FIFO + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); +#endif #endif // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->altSetting[idxItf])); + if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->alt_setting_ptr[idxItf])); return true; } -#endif //CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#endif //CFG_TUD_AUDIO_ENABLE_EP_IN -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN // Take samples from the support buffer and encode them into the IN EP software FIFO // Returns number of bytes written into linear buffer @@ -626,7 +846,7 @@ data streams. The audio data is not compressed and uses a signed two’s-complem is left-justified (the sign bit is the Msb) and data is padded with trailing zeros to fill the remaining unused bits of the subslot. The binary point is located to the right of the sign bit so that all values lie within the range [-1, +1) -*/ + */ /* * This function encodes channels saved within the support FIFOs into one stream by interleaving the PCM samples @@ -634,35 +854,99 @@ range [-1, +1) * does not change the number of bytes per sample. * */ +// Helper function +static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, void * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) +{ + // Optimize for fast half word copies + typedef struct{ + uint16_t val; + } __attribute((__packed__)) unaligned_uint16_t; + + // Optimize for fast word copies + typedef struct{ + uint32_t val; + } __attribute((__packed__)) unaligned_uint32_t; + + switch (nBytesToCopy) + { + case 1: + while((uint8_t *)src < src_end) + { + *dst = *(uint8_t *)src++; + dst += n_ff_used; + } + break; + + case 2: + while((uint8_t *)src < src_end) + { + *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; + src += 2; + dst += 2 * n_ff_used; + } + break; + + case 3: + while((uint8_t *)src < src_end) + { +// memcpy(dst, src, 3); +// src = (uint8_t *)src + 3; +// dst += 3 * n_ff_used; + + // TODO: Is there a faster way to copy 3 bytes? + *dst++ = *(uint8_t *)src++; + *dst++ = *(uint8_t *)src++; + *dst++ = *(uint8_t *)src++; + + dst += 3 * (n_ff_used - 1); + } + break; + + case 4: + while((uint8_t *)src < src_end) + { + *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; + src += 4; + dst += 4 * n_ff_used; + } + break; + } + + return dst; +} + static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { // We encode directly into IN EP's linear buffer - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples - uint16_t const nChannelsPerFF = CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; - uint16_t const nBytesToCopy = nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; - uint16_t const capSamplesPerFF = CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE / CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; - uint16_t nSamplesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); + uint8_t const n_ff_used = audio->n_channels_tx / audio->n_channels_per_ff_tx; + + TU_ASSERT( n_ff_used <= audio->n_tx_supp_ff ); + + uint16_t const nBytesToCopy = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx; + uint16_t const capPerFF = audio->ep_in_sz / n_ff_used; // Sample capacity per FIFO in bytes + uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); uint8_t cnt_ff; - for (cnt_ff = 1; cnt_ff < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt_ff++) + for (cnt_ff = 1; cnt_ff < n_ff_used; cnt_ff++) { uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cnt_ff]); - if (count < nSamplesPerFFToSend) + if (count < nBytesPerFFToSend) { - nSamplesPerFFToSend = count; + nBytesPerFFToSend = count; } } // Check if there is enough - if (nSamplesPerFFToSend == 0) return 0; + if (nBytesPerFFToSend == 0) return 0; // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - nSamplesPerFFToSend = tu_min16(nSamplesPerFFToSend, capSamplesPerFF); + nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, capPerFF); // Round to full number of samples (flooring) - nSamplesPerFFToSend = (nSamplesPerFFToSend / nChannelsPerFF) * nChannelsPerFF; + nBytesPerFFToSend = (nBytesPerFFToSend / audio->n_channels_per_ff_tx) * audio->n_channels_per_ff_tx; // Encode void * src; @@ -670,46 +954,36 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* aud uint8_t * src_end; uint16_t len; - for (cnt_ff = 0; cnt_ff < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt_ff++) + for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - dst = &audio->lin_buf_in[cnt_ff*nChannelsPerFF*CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX]; + dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nSamplesPerFFToSend); + len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nBytesPerFFToSend); tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); - src_end = src + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + src_end = src + len; - while((uint8_t *)src < src_end) - { - memcpy(dst, src, nBytesToCopy); - src = (uint8_t *)src + nBytesToCopy; - dst += nBytesToCopy * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; - } + dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); // Handle wrapped part of FIFO - if (len < nSamplesPerFFToSend) + if (len < nBytesPerFFToSend) { - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nSamplesPerFFToSend - len); + len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nBytesPerFFToSend - len); tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); - src_end = src + len * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX; + src_end = src + len; - while((uint8_t *)src < src_end) - { - memcpy(dst, src, nBytesToCopy); - src = (uint8_t *)src + nBytesToCopy; - dst += nBytesToCopy * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; - } + audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); } } - return nSamplesPerFFToSend * CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; + return nBytesPerFFToSend * n_ff_used; } -#endif //CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#endif //CFG_TUD_AUDIO_ENABLE_ENCODING // This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static inline bool audiod_fb_send(uint8_t rhport, audiod_interface_t *audio) { return usbd_edpt_xfer(rhport, audio->ep_fb, (uint8_t *) &audio->fb_val, 4); @@ -727,43 +1001,304 @@ void audiod_init(void) { audiod_interface_t* audio = &_audiod_itf[i]; + // Initialize control buffers + switch (i) + { + case 0: + audio->ctrl_buf = ctrl_buf_1; + audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ; + break; +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ > 0 + case 1: + audio->ctrl_buf = ctrl_buf_2; + audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ > 0 + case 2: + audio->ctrl_buf = ctrl_buf_3; + audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ; + break; +#endif + } + + // Initialize active alternate interface buffers +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 + case 0: + audio->alt_setting_ptr = alt_setting_1; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 + case 1: + audio->alt_setting_ptr = alt_setting_2; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 + case 2: + audio->alt_setting_ptr = alt_setting_3; + break; +#endif + } +#endif + // Initialize IN EP FIFO if required -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - tu_fifo_config(&audio->ep_in_ff, &audio->ep_in_buf, CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE, 1, true); +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 + case 0: + tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_1), NULL); +#endif + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 + case 1: + tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_2), NULL); +#endif + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 + case 2: + tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&audio->ep_in_ff_mutex_wr), NULL); + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_3), NULL); #endif + break; #endif + } +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + + // Initialize linear buffers +#if USE_LINEAR_BUFFER_TX + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 + case 0: + audio->lin_buf_in = lin_buf_in_1; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 + case 1: + audio->lin_buf_in = lin_buf_in_2; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 + case 2: + audio->lin_buf_in = lin_buf_in_3; + break; +#endif + } +#endif // USE_LINEAR_BUFFER_TX // Initialize OUT EP FIFO if required -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - tu_fifo_config(&audio->ep_out_ff, &audio->ep_out_buf, CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE, 1, true); +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 + case 0: + tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&audio->ep_out_ff_mutex_rd)); + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_1)); #endif + break; #endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 + case 1: + tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_2)); +#endif + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 + case 2: + tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_3)); +#endif + break; +#endif + } +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING + + // Initialize linear buffers +#if USE_LINEAR_BUFFER_RX + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 + case 0: + audio->lin_buf_out = lin_buf_out_1; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 + case 1: + audio->lin_buf_out = lin_buf_out_2; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 + case 2: + audio->lin_buf_out = lin_buf_out_3; + break; +#endif + } +#endif // USE_LINEAR_BUFFER_TX // Initialize TX support FIFOs if required -#if CFG_TUD_AUDIO_EPSIZE_IN && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt++) +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + + switch (i) { - tu_fifo_config(&audio->tx_supp_ff[cnt], &audio->tx_supp_ff_buf[cnt], CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX, true); +#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->tx_supp_ff = tx_supp_ff_1; + audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_1[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->tx_supp_ff = tx_supp_ff_2; + audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_2[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->tx_supp_ff = tx_supp_ff_3; + audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->tx_supp_ff[cnt], osal_mutex_create(&audio->tx_supp_ff_mutex_wr[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_3[cnt]), NULL); #endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 } +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + + // Set encoding parameters for Type_I formats +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX; + break; +#endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX; + break; #endif + } +#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING // Initialize RX support FIFOs if required -#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt++) +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + + switch (i) { - tu_fifo_config(&audio->rx_supp_ff[cnt], &audio->rx_supp_ff_buf[cnt], CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE, CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX, true); +#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->rx_supp_ff = rx_supp_ff_1; + audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_1[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->rx_supp_ff = rx_supp_ff_2; + audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_2[cnt]), NULL); +#endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 + +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->rx_supp_ff = rx_supp_ff_3; + audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; + for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; cnt++) + { + tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->rx_supp_ff[cnt], NULL, osal_mutex_create(&audio->rx_supp_ff_mutex_rd[cnt])); + tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_3[cnt]), NULL); #endif + } + + break; +#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 } +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + + // Set encoding parameters for Type_I formats +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + switch (i) + { +#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 + case 0: + audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX; + break; #endif +#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 + case 1: + audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX; + break; +#endif +#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 + case 2: + audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX; + break; +#endif + } +#endif // CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING } } @@ -776,23 +1311,23 @@ void audiod_reset(uint8_t rhport) audiod_interface_t* audio = &_audiod_itf[i]; tu_memclr(audio, ITF_MEM_RESET_SIZE); -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING tu_fifo_clear(&audio->ep_in_ff); #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_clear(&audio->ep_out_ff); #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO; cnt++) +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING + for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) { tu_fifo_clear(&audio->tx_supp_ff[cnt]); } #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO; cnt++) +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING + for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) { tu_fifo_clear(&audio->rx_supp_ff[cnt]); } @@ -827,6 +1362,25 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin { _audiod_itf[i].p_desc = (uint8_t const *)itf_desc; // Save pointer to AC descriptor which is by specification always the first one _audiod_itf[i].rhport = rhport; + + // Setup descriptor lengths + switch (i) + { + case 0: + _audiod_itf[i].desc_length = CFG_TUD_AUDIO_FUNC_1_DESC_LEN; + break; +#if CFG_TUD_AUDIO > 1 + case 1: + _audiod_itf[i].desc_length = CFG_TUD_AUDIO_FUNC_2_DESC_LEN; + break; +#endif +#if CFG_TUD_AUDIO > 2 + case 2: + _audiod_itf[i].desc_length = CFG_TUD_AUDIO_FUNC_3_DESC_LEN; + break; +#endif + } + break; } } @@ -835,14 +1389,14 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin TU_ASSERT( i < CFG_TUD_AUDIO ); // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - uint16_t drv_len = tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor + uint16_t drv_len = _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor return drv_len; } static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) { -#if CFG_TUD_AUDIO_N_AS_INT > 0 +#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 uint8_t const itf = tu_u16_low(p_request->wIndex); // Find index of audio streaming interface @@ -850,9 +1404,9 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const *dummy; TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].altSetting[idxItf], 1)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].alt_setting_ptr[idxItf], 1)); - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].altSetting[idxItf]); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].alt_setting_ptr[idxItf]); return true; @@ -888,41 +1442,60 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const *p_desc; TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); + audiod_interface_t* audio = &_audiod_itf[idxDriver]; + // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE - if (_audiod_itf[idxDriver].ep_in_as_intf_num == itf) +#if CFG_TUD_AUDIO_ENABLE_EP_IN + if (audio->ep_in_as_intf_num == itf) { - _audiod_itf[idxDriver].ep_in_as_intf_num = 0; - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_in); + audio->ep_in_as_intf_num = 0; + usbd_edpt_close(rhport, audio->ep_in); // Invoke callback - can be used to stop data sampling if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); - _audiod_itf[idxDriver].ep_in = 0; // Necessary? + audio->ep_in = 0; // Necessary? + + // Clear support FIFOs if used +#if CFG_TUD_AUDIO_ENABLE_ENCODING + for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) + { + tu_fifo_clear(&audio->tx_supp_ff[cnt]); + } +#endif + } #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE - if (_audiod_itf[idxDriver].ep_out_as_intf_num == itf) +#if CFG_TUD_AUDIO_ENABLE_EP_OUT + if (audio->ep_out_as_intf_num == itf) { - _audiod_itf[idxDriver].ep_out_as_intf_num = 0; - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_out); - _audiod_itf[idxDriver].ep_out = 0; // Necessary? + audio->ep_out_as_intf_num = 0; + usbd_edpt_close(rhport, audio->ep_out); + audio->ep_out = 0; // Necessary? + + // Clear support FIFOs if used +#if CFG_TUD_AUDIO_ENABLE_DECODING + for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) + { + tu_fifo_clear(&audio->rx_supp_ff[cnt]); + } +#endif // Close corresponding feedback EP #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - usbd_edpt_close(rhport, _audiod_itf[idxDriver].ep_fb); - _audiod_itf[idxDriver].ep_fb = 0; // Necessary? + usbd_edpt_close(rhport, audio->ep_fb); + audio->ep_fb = 0; // Necessary? #endif } #endif // Save current alternative interface setting - _audiod_itf[idxDriver].altSetting[idxItf] = alt; + audio->alt_setting_ptr[idxItf] = alt; // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[idxDriver].p_desc + tud_audio_desc_lengths[idxDriver] - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; // p_desc starts at required interface with alternate setting zero while (p_desc < p_desc_end) @@ -930,6 +1503,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Find correct interface if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) { +#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING + uint8_t const * p_desc_parse_for_params = p_desc; +#endif // From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints; while (foundEPs < nEps && p_desc < p_desc_end) @@ -943,52 +1519,61 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * //TODO: We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! usbd_edpt_clear_stall(rhport, ep_addr); -#if CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x00) // Check if usage is data EP { // Save address - _audiod_itf[idxDriver].ep_in = ep_addr; - _audiod_itf[idxDriver].ep_in_as_intf_num = itf; + audio->ep_in = ep_addr; + audio->ep_in_as_intf_num = itf; + audio->ep_in_sz = ((tusb_desc_endpoint_t const *) p_desc)->wMaxPacketSize.size; + // If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters +#if CFG_TUD_AUDIO_ENABLE_ENCODING + audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); +#endif // Invoke callback - can be used to trigger data sampling if not already running if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Schedule first transmit - in case no sample data is available a ZLP is loaded - // It is necessary to trigger this here since the refill is done with an TX FIFO empty interrupt which can only trigger if something was in there + // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver])); } -#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN -#if CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) // Checking usage not necessary { // Save address - _audiod_itf[idxDriver].ep_out = ep_addr; - _audiod_itf[idxDriver].ep_out_as_intf_num = itf; + audio->ep_out = ep_addr; + audio->ep_out_as_intf_num = itf; + audio->ep_out_sz = ((tusb_desc_endpoint_t const *) p_desc)->wMaxPacketSize.size; +#if CFG_TUD_AUDIO_ENABLE_DECODING + audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); +#endif // Invoke callback if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); // Prepare for incoming data #if USE_LINEAR_BUFFER_RX - TU_VERIFY(usbd_edpt_xfer(rhport, _audiod_itf[idxDriver].ep_out, _audiod_itf[idxDriver].lin_buf_out, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else - TU_VERIFY(usbd_edpt_iso_xfer(rhport, _audiod_itf[idxDriver].ep_out, &_audiod_itf[idxDriver].ep_out_ff, CFG_TUD_AUDIO_EPSIZE_OUT), false); + TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); #endif } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 1) // Check if usage is explicit data feedback { - _audiod_itf[idxDriver].ep_fb = ep_addr; + audio->ep_fb = ep_addr; // Invoke callback if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); } #endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT -#endif foundEPs += 1; } p_desc = tu_desc_next(p_desc); @@ -1188,7 +1773,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const } // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf, CFG_TUD_AUDIO_CTRL_BUF_SIZE)); + TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf, _audiod_itf[idxDriver].ctrl_buf_sz)); return true; } @@ -1238,7 +1823,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN // Data transmission of audio packet finished if (_audiod_itf[idxDriver].ep_in == ep_addr) @@ -1259,7 +1844,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 } #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT // New audio packet received if (_audiod_itf[idxDriver].ep_out == ep_addr) @@ -1327,7 +1912,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req } // Crop length - if (len > CFG_TUD_AUDIO_CTRL_BUF_SIZE) len = CFG_TUD_AUDIO_CTRL_BUF_SIZE; + if (len > _audiod_itf[idxDriver].ctrl_buf_sz) len = _audiod_itf[idxDriver].ctrl_buf_sz; // Copy into buffer memcpy((void *)_audiod_itf[idxDriver].ctrl_buf, data, (size_t)len); @@ -1348,7 +1933,7 @@ static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8 if (_audiod_itf[i].p_desc) { // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // Advance past AC descriptors uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); @@ -1413,7 +1998,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) { // Get pointer at beginning and end uint8_t const *p_desc = _audiod_itf[i].p_desc; - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i] - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; while (p_desc < p_desc_end) { @@ -1437,7 +2022,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) if (_audiod_itf[i].p_desc) { // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + tud_audio_desc_lengths[i]; + uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length; // Advance past AC descriptors - EP we look for are streaming EPs uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); @@ -1457,6 +2042,69 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) return false; } +#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING +// p_desc points to the AS interface of alternate setting zero +// itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter +// Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for! +static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf) +{ + p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor of current alternate interface descriptor + + while (p_desc < p_desc_end) + { + // Abort if follow up descriptor is a new standard interface descriptor - indicates the last AS descriptor was already finished + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) break; + + // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify format type and format and also to get number of physical channels + if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) + { + if (itf != audio->ep_in_as_intf_num && itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently + + if (itf == audio->ep_in_as_intf_num) + { + audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; + audio->format_type_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; + +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + audio->format_type_I_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; +#endif + } + + if (itf == audio->ep_out_as_intf_num) + { + audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; + audio->format_type_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + audio->format_type_I_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; +#endif + } + } + + // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats) +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) + { + if (itf != audio->ep_in_as_intf_num && itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently + + if (itf == audio->ep_in_as_intf_num) + { + audio->n_bytes_per_sampe_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; + } + + if (itf == audio->ep_out_as_intf_num) + { + audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; + } + } +#endif + + // Other format types are not supported yet + + p_desc = tu_desc_next(p_desc); + } +} +#endif + #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 730d42c38..e68c437ad 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -40,49 +40,151 @@ // All sizes are in bytes! -// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just waste a few bytes) -#ifndef CFG_TUD_AUDIO_N_AS_INT -#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the descriptors! +#ifndef CFG_TUD_AUDIO_FUNC_1_DESC_LEN +#error You must tell the driver the length of the audio function descriptor including IAD descriptor +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_DESC_LEN +#error You must tell the driver the length of the audio function descriptor including IAD descriptor +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_DESC_LEN +#error You must tell the driver the length of the audio function descriptor including IAD descriptor +#endif +#endif + +// Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces +#ifndef CFG_TUD_AUDIO_FUNC_1_N_AS_INT +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_N_AS_INT +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_N_AS_INT +#error You must tell the driver the number of Standard AS Interface Descriptors you have defined in the audio function descriptor! +#endif #endif // Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors -#ifndef CFG_TUD_AUDIO_CTRL_BUF_SIZE +#ifndef CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ #error You must define an audio class control request buffer size! #endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ +#error You must define an audio class control request buffer size! +#endif +#endif + +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ +#error You must define an audio class control request buffer size! +#endif +#endif + // End point sizes IN BYTES - Limits: Full Speed <= 1023, High Speed <= 1024 -#ifndef CFG_TUD_AUDIO_EPSIZE_IN -#define CFG_TUD_AUDIO_EPSIZE_IN 0 // TX +#ifndef CFG_TUD_AUDIO_ENABLE_EP_IN +#define CFG_TUD_AUDIO_ENABLE_EP_IN 0 // TX +#endif + +#ifndef CFG_TUD_AUDIO_ENABLE_EP_OUT +#define CFG_TUD_AUDIO_ENABLE_EP_OUT 0 // RX +#endif + +// Maximum EP sizes for all alternate AS interface settings - used for checks and buffer allocation +#if CFG_TUD_AUDIO_ENABLE_EP_IN +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX +#error You must tell the driver the biggest EP IN size! +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX +#error You must tell the driver the biggest EP IN size! +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX +#error You must tell the driver the biggest EP IN size! +#endif +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_IN + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX +#error You must tell the driver the biggest EP OUT size! +#endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX +#error You must tell the driver the biggest EP OUT size! +#endif +#endif +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX +#error You must tell the driver the biggest EP OUT size! +#endif +#endif +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT + +// Software EP FIFO buffer sizes - must be >= max EP SIZEs! +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ 0 +#endif + +#ifndef CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ +#define CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ 0 +#endif + +#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -#ifndef CFG_TUD_AUDIO_EPSIZE_OUT -#define CFG_TUD_AUDIO_EPSIZE_OUT 0 // RX +#if CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -// Software EP FIFO buffer sizes - must be >= EP SIZEs! -#if CFG_TUD_AUDIO_EPSIZE_IN -#ifndef CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE -#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_IN // TX +#if CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -#else -#define CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE 0 + +#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -#if CFG_TUD_AUDIO_EPSIZE_OUT -#ifndef CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE -#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE CFG_TUD_AUDIO_EPSIZE_OUT // RX +#if CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -#else -#define CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE 0 + +#if CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX +#error EP software buffer size MUST BE at least as big as maximum EP size #endif -// General information of number of TX and/or RX channels - is used in combination with support FIFOs (see below) and can be used for descriptor definitions -#ifndef CFG_TUD_AUDIO_N_CHANNELS_TX -#define CFG_TUD_AUDIO_N_CHANNELS_TX 1 +// Enable/disable feedback EP (required for asynchronous RX applications) +#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 #endif -#ifndef CFG_TUD_AUDIO_N_CHANNELS_RX -#define CFG_TUD_AUDIO_N_CHANNELS_RX 1 +// Audio interrupt control EP size - disabled if 0 +#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN +#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) +#endif + +#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE +#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) #endif // Use of TX/RX support FIFOs @@ -120,83 +222,100 @@ // - audio_rx_done_cb() // functions. -// The number of support FIFOs and number of channels is decoupled. The PCM encoding/decoding works depending on the ratio CFG_TUD_AUDIO_N_CHANNELS_XX / CFG_TUD_AUDIO_N_XX_SUPPORT_SW_FIFO, where currently 1:1 and 2:1 is implemented. The version 2:1 is useful in case of I2S for which usually 2 are channels already interleaved available. +// Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size +// The actual parameters of active encoding is parsed from the descriptors -// Size of support FIFOs IN SAMPLES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO and CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO -#ifndef CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE 0 // FIFO size - minimum size: // ceil(f_s/1000) * CFG_TUD_AUDIO_N_CHANNELS_TX / CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO +// For PCM encoding/decoding + +#ifndef CFG_TUD_AUDIO_ENABLE_ENCODING +#define CFG_TUD_AUDIO_ENABLE_ENCODING 0 #endif -#ifndef CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE 0 // FIFO size - minimum size: ceil(f_s/1000) * CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX / CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO +#ifndef CFG_TUD_AUDIO_ENABLE_DECODING +#define CFG_TUD_AUDIO_ENABLE_DECODING 0 #endif -#ifndef CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO CFG_TUD_AUDIO_N_CHANNELS_TX // default size is equal to number of channels -#else -#define CFG_TUD_AUDIO_N_TX_SUPPORT_SW_FIFO 0 +// This enabling allows to save the current coding parameters e.g. # of bytes per sample etc. - TYPE_I includes common PCM encoding +#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING +#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 0 #endif + +#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING +#define CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING 0 #endif -#ifndef CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE -#define CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO CFG_TUD_AUDIO_N_CHANNELS_RX // default size is equal to number of channels -#else -#define CFG_TUD_AUDIO_N_RX_SUPPORT_SW_FIFO 0 +// Type I Coding parameters not given within UAC2 descriptors +// It would be possible to allow for a more flexible setting and not fix this parameter as done below. However, this is most often not needed and kept for later if really necessary. The more flexible setting could be implemented within set_interface(), however, how the values are saved per alternate setting is to be determined! +#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif - -// Enable/disable feedback EP (required for asynchronous RX applications) -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 #endif - -// Audio interrupt control EP size - disabled if 0 -#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74) +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO +#endif #endif -#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE -#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) +#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif +#if CFG_TUD_AUDIO > 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif - -// Audio data format types - look in audio.h for existing types -// Used in case support FIFOs are used -#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_TX -#define CFG_TUD_AUDIO_FORMAT_TYPE_TX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, an encoding function has to be implemented in audio_device.c #endif - -#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_RX -#define CFG_TUD_AUDIO_FORMAT_TYPE_RX AUDIO_FORMAT_TYPE_UNDEFINED // If this option is used, a decoding function has to be implemented in audio_device.c +#if CFG_TUD_AUDIO > 2 +#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX +#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO +#endif #endif -// Audio data format type I specifications -#if CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I +// Remaining types not support so far -// Type definitions - for possible formats see: audio_data_format_type_I_t and further in UAC2 specifications. -#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_TX -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_TX AUDIO_DATA_FORMAT_TYPE_I_PCM +// Number of support FIFOs to set up - multiple channels can be handled by one FIFO - very common is two channels per FIFO stemming from one I2S interface +#ifndef CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO 0 #endif - -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX 1 +#ifndef CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO 0 #endif - +#ifndef CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO 0 #endif -#if CFG_TUD_AUDIO_FORMAT_TYPE_RX == AUDIO_FORMAT_TYPE_I - -#ifndef CFG_TUD_AUDIO_FORMAT_TYPE_I_RX -#define CFG_TUD_AUDIO_FORMAT_TYPE_I_RX AUDIO_DATA_FORMAT_TYPE_I_PCM +#ifndef CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO +#define CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO 0 #endif -#ifndef CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX // bSubslotSize -#define CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX 1 +// Size of support FIFOs IN BYTES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_FUNC_X_N_TX_SUPP_SW_FIFO and CFG_TUD_AUDIO_FUNC_X_N_RX_SUPP_SW_FIFO +#ifndef CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of TX channels) / (# of TX support FIFOs) * max(# of bytes per sample) +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ 0 #endif +#ifndef CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of RX channels) / (# of RX support FIFOs) * max(# of bytes per sample) +#endif +#ifndef CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ 0 +#endif +#ifndef CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ +#define CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ 0 #endif //static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); @@ -219,33 +338,29 @@ extern "C" { //--------------------------------------------------------------------+ bool tud_audio_n_mounted (uint8_t itf); -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING uint16_t tud_audio_n_available (uint8_t itf); uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); bool tud_audio_n_clear_ep_out_ff (uint8_t itf); // Delete all content in the EP OUT FIFO - #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING bool tud_audio_n_clear_rx_support_ff (uint8_t itf, uint8_t channelId); // Delete all content in the support RX FIFOs uint16_t tud_audio_n_available_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_read_support_ff (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); #endif -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE - +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); bool tud_audio_n_clear_ep_in_ff (uint8_t itf); // Delete all content in the EP IN FIFO +#endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING uint16_t tud_audio_n_flush_tx_support_ff (uint8_t itf); // Force all content in the support TX FIFOs to be written into EP SW FIFO -bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); +bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); uint16_t tud_audio_n_write_support_ff (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); #endif -#endif - #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t len); #endif @@ -258,15 +373,13 @@ static inline bool tud_audio_mounted (void); // RX API -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE - +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING static inline uint16_t tud_audio_available (void); static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); - #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId); static inline uint16_t tud_audio_available_support_ff (uint8_t channelId); static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize); @@ -274,14 +387,12 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, // TX API -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE - +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_write (const void * data, uint16_t len); static inline bool tud_audio_clear_ep_in_ff (void); - #endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_flush_tx_support_ff (void); static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId); static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len); @@ -290,7 +401,7 @@ static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, // INT CTR API #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); +static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len); #endif // Buffer control EP data and schedule a transmit @@ -305,17 +416,17 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); // User code should call this function with feedback value in 16.16 format for FS and HS. // Value will be corrected for FS to 10.14 format automatically. @@ -364,7 +475,7 @@ static inline bool tud_audio_mounted(void) // RX API -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING static inline uint16_t tud_audio_available (void) { @@ -383,7 +494,7 @@ static inline bool tud_audio_clear_ep_out_ff (void) #endif -#if CFG_TUD_AUDIO_RX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_OUT +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId) { @@ -404,7 +515,7 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, // TX API -#if CFG_TUD_AUDIO_EP_IN_SW_BUFFER_SIZE && !CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_write (const void * data, uint16_t len) { @@ -418,7 +529,7 @@ static inline bool tud_audio_clear_ep_in_ff (void) #endif -#if CFG_TUD_AUDIO_TX_SUPPORT_SW_FIFO_SIZE && CFG_TUD_AUDIO_EPSIZE_IN +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_flush_tx_support_ff (void) { @@ -444,7 +555,7 @@ static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t l } #endif -#if CFG_TUD_AUDIO_EP_OUT_SW_BUFFER_SIZE && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static inline bool tud_audio_fb_set(uint32_t feedback) { return tud_audio_n_fb_set(0, feedback); diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index d05549e3e..1b7f64447 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -138,9 +138,7 @@ static void _tu_fifo_read_from_const_src_ptr_in_full_words(void * dst, const voi } } -// Intended to be used to write to hardware USB FIFO in e.g. STM32 where all data is written to a constant address -// Code adapted from dcd_synopsis.c -// TODO generalize with configurable 1 byte or 4 byte each write +// Intended to be used to write to hardware USB FIFO in e.g. STM32 where all data is written to a constant address in full word copies static void _tu_fifo_write_to_const_dst_ptr_in_full_words(void * dst, const void * src, uint16_t len) { volatile uint32_t * tx_fifo = (volatile uint32_t *) dst; diff --git a/src/device/usbd.h b/src/device/usbd.h index 56615b081..7c50a6db0 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -353,6 +353,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN (6+(2+1)*4) #define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _stridx) \ TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), _stridx +// 4 - Channels +#define TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN (6+(4+1)*4) +#define TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _ctrlch3, _ctrlch4, _stridx) \ + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), U32_TO_U8S_LE(_ctrlch3), U32_TO_U8S_LE(_ctrlch4), _stridx // For more channels, add definitions here @@ -389,7 +393,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source -#define TUD_AUDIO_MIC_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ +#define TUD_AUDIO_MIC_ONE_CH_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ + TUD_AUDIO_DESC_STD_AC_LEN\ + TUD_AUDIO_DESC_CS_AC_LEN\ + TUD_AUDIO_DESC_CLK_SRC_LEN\ @@ -403,9 +407,9 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) -#define TUD_AUDIO_MIC_DESC_N_AS_INT 1 // Number of AS interfaces +#define TUD_AUDIO_MIC_ONE_CH_DESC_N_AS_INT 1 // Number of AS interfaces -#define TUD_AUDIO_MIC_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ +#define TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ /* Standard Interface Association Descriptor (IAD) */\ TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ @@ -435,6 +439,55 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) +// AUDIO simple descriptor (UAC2) for 4 microphone input +// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source + +#define TUD_AUDIO_MIC_FOUR_CH_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ + + TUD_AUDIO_DESC_STD_AC_LEN\ + + TUD_AUDIO_DESC_CS_AC_LEN\ + + TUD_AUDIO_DESC_CLK_SRC_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) + +#define TUD_AUDIO_MIC_FOUR_CH_DESC_N_AS_INT 1 // Number of AS interfaces + +#define TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ + TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + /* Clock Source Descriptor(4.7.2.1) */\ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x04, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.7.2.8) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch2*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch3*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch4*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.9.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x04, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ + TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ + TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + // AUDIO simple descriptor (UAC2) for mono speaker // - 1 Input Terminal, 2 Feature Unit (Mute and Volume Control), 3 Output Terminal, 4 Clock Source -- cgit v1.3.1 From 8b90c08b357ce04aebe093856b954e02624ff0fe Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 15:24:38 +0200 Subject: Fix #define errors in audio_device.h --- src/class/audio/audio_device.h | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index e68c437ad..9ff74d6c7 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -153,25 +153,33 @@ #error EP software buffer size MUST BE at least as big as maximum EP size #endif +#if CFG_TUD_AUDIO > 1 #if CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX #error EP software buffer size MUST BE at least as big as maximum EP size #endif +#endif +#if CFG_TUD_AUDIO > 2 #if CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX #error EP software buffer size MUST BE at least as big as maximum EP size #endif +#endif #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX #error EP software buffer size MUST BE at least as big as maximum EP size #endif +#if CFG_TUD_AUDIO > 1 #if CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX #error EP software buffer size MUST BE at least as big as maximum EP size #endif +#endif +#if CFG_TUD_AUDIO > 2 #if CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX #error EP software buffer size MUST BE at least as big as maximum EP size #endif +#endif // Enable/disable feedback EP (required for asynchronous RX applications) #ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -187,13 +195,16 @@ #define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) #endif -// Use of TX/RX support FIFOs +// Use software encoding/decoding -// Support FIFOs are not mandatory for the audio driver, rather they are intended to be of use in -// - TX case: CFG_TUD_AUDIO_N_CHANNELS_TX channels need to be encoded into one USB output stream (currently PCM type I is implemented) -// - RX case: CFG_TUD_AUDIO_N_CHANNELS_RX channels need to be decoded from a single USB input stream (currently PCM type I is implemented) +// The software coding feature of the driver is not mandatory. It is useful if, for instance, you have two I2S streams which need to be interleaved +// into a single PCM stream as SAMPLE_1 | SAMPLE_2 | SAMPLE_3 | SAMPLE_4. // -// This encoding/decoding is done in software and thus time consuming. If you can encode/decode your stream more efficiently do not use the +// Currently, only PCM type I encoding/decoding is supported! +// +// If the coding feature is to be used, support FIFOs need to be configured. Their sizes and numbers are defined below. + +// Encoding/decoding is done in software and thus time consuming. If you can encode/decode your stream more efficiently do not use the // support FIFOs but write/read directly into/from the EP_X_SW_BUFFER_FIFOs using // - tud_audio_n_write() or // - tud_audio_n_read(). @@ -223,7 +234,7 @@ // functions. // Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size -// The actual parameters of active encoding is parsed from the descriptors +// The actual coding parameters of active AS alternate interface is parsed from the descriptors // For PCM encoding/decoding -- cgit v1.3.1 From 6236effb1415ea509e6283d33f2779eeae7d425e Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 15:29:39 +0200 Subject: Fix #define error in audio_device.h --- src/class/audio/audio_device.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 9ff74d6c7..e2208629f 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -149,6 +149,7 @@ #define CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ 0 #endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX #error EP software buffer size MUST BE at least as big as maximum EP size #endif @@ -164,7 +165,9 @@ #error EP software buffer size MUST BE at least as big as maximum EP size #endif #endif +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_OUT #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ < CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX #error EP software buffer size MUST BE at least as big as maximum EP size #endif @@ -180,6 +183,7 @@ #error EP software buffer size MUST BE at least as big as maximum EP size #endif #endif +#endif // Enable/disable feedback EP (required for asynchronous RX applications) #ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -- cgit v1.3.1 From ec6b240de299e24a7fabb54aa2f2d9c72d0eaad4 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 15:44:44 +0200 Subject: Fix #define error in audio_device.h --- src/class/audio/audio_device.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index e2208629f..d4793c9d8 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -261,6 +261,7 @@ // Type I Coding parameters not given within UAC2 descriptors // It would be possible to allow for a more flexible setting and not fix this parameter as done below. However, this is most often not needed and kept for later if really necessary. The more flexible setting could be implemented within set_interface(), however, how the values are saved per alternate setting is to be determined! +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING #ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX #error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif @@ -274,7 +275,9 @@ #error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif #endif +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING #ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX #error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif @@ -288,6 +291,7 @@ #error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO #endif #endif +#endif // Remaining types not support so far -- cgit v1.3.1 From fc65f39ff224cdfe3c486c95e0c04f1f979fa1b2 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 15:58:41 +0200 Subject: Fix error in #defines in uac2_headset --- examples/device/uac2_headset/src/tusb_config.h | 2 ++ examples/device/uac2_headset/src/usb_descriptors.c | 5 ----- src/class/audio/audio_device.c | 3 +++ 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 511e4e558..cbdd7b3df 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -94,6 +94,8 @@ extern "C" { #define CFG_TUD_AUDIO_IN_PATH (CFG_TUD_AUDIO) #define CFG_TUD_AUDIO_OUT_PATH (CFG_TUD_AUDIO) +#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN + // Audio format type I specifications #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index b69e5a5e0..cd749eb65 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -87,11 +87,6 @@ uint8_t const * tud_descriptor_device_cb(void) #define EPNUM_AUDIO 0x01 #endif -// These variables are required by the audio driver in audio_device.c - -// List of audio descriptor lengths which is required by audio driver - you need as many entries as CFG_TUD_AUDIO -const uint16_t tud_audio_desc_lengths[] = {TUD_AUDIO_HEADSET_STEREO_DESC_LEN}; - uint8_t const desc_configuration[] = { // Interface count, string index, total length, attribute, power in mA diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 5df32c30f..a39a030e6 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -388,7 +388,10 @@ static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8 static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver); static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver); static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); + +#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf); +#endif static inline uint8_t tu_desc_subtype(void const* desc) { -- cgit v1.3.1 From 475badd0873dda58b507d3dfe5ab74957fcaa3c0 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 16:10:46 +0200 Subject: Add missing #defines in uac2_headset example --- examples/device/uac2_headset/src/tusb_config.h | 2 ++ src/class/audio/audio_device.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index ee6bdd519..5f86ee1a8 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -107,11 +107,13 @@ extern "C" { #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 #define CFG_TUD_AUDIO_EP_SZ_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN // Maximum EP IN size for all AS alternate settings used // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 #define CFG_TUD_AUDIO_EP_OUT_SZ (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels #define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ CFG_TUD_AUDIO_EP_OUT_SZ*3 +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX CFG_TUD_AUDIO_EP_SZ_OUT // Maximum EP IN size for all AS alternate settings used // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) #define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index a39a030e6..8e4f9d218 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -949,7 +949,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* aud nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, capPerFF); // Round to full number of samples (flooring) - nBytesPerFFToSend = (nBytesPerFFToSend / audio->n_channels_per_ff_tx) * audio->n_channels_per_ff_tx; + nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy; // Encode void * src; -- cgit v1.3.1 From 4af5189492f850615581d3310e20c98f69cf6138 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 16:53:29 +0200 Subject: Fix potential bug in support FIFO sizes --- examples/device/uac2_headset/src/tusb_config.h | 2 -- examples/device/uac2_headset/src/usb_descriptors.c | 2 ++ src/class/audio/audio_device.c | 32 +++++++++++++++++++++- 3 files changed, 33 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 514728ac4..00620d9ed 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -94,8 +94,6 @@ extern "C" { #define CFG_TUD_AUDIO_IN_PATH (CFG_TUD_AUDIO) #define CFG_TUD_AUDIO_OUT_PATH (CFG_TUD_AUDIO) -#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN - // Audio format type I specifications #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index cd749eb65..404863dba 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -87,6 +87,8 @@ uint8_t const * tud_descriptor_device_cb(void) #define EPNUM_AUDIO 0x01 #endif +#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN + uint8_t const desc_configuration[] = { // Interface count, string index, total length, attribute, power in mA diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8e4f9d218..8bd15a8c1 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -310,6 +310,7 @@ typedef struct #if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING audio_data_format_type_I_t format_type_I_rx; uint8_t n_bytes_per_sampe_rx; + uint8_t n_channels_per_ff_rx; #endif #endif @@ -329,12 +330,13 @@ typedef struct #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_t * rx_supp_ff; uint8_t n_rx_supp_ff; - uint8_t n_channels_per_ff_rx; + uint16_t rx_supp_ff_sz_max; #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING tu_fifo_t * tx_supp_ff; uint8_t n_tx_supp_ff; + uint16_t tx_supp_ff_sz_max; #endif // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used @@ -920,6 +922,9 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) { + // This function relies on the fact that the length of the support FIFOs was configured to be a multiple of the active sample size in bytes s.t. no sample is split within a wrap + // This is ensured within set_interface, where the FIFOs are reconfigured according to this size + // We encode directly into IN EP's linear buffer - abort if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); @@ -1164,6 +1169,7 @@ void audiod_init(void) case 0: audio->tx_supp_ff = tx_supp_ff_1; audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; + audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ; for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) { tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); @@ -1179,6 +1185,7 @@ void audiod_init(void) case 1: audio->tx_supp_ff = tx_supp_ff_2; audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; + audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ; for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; cnt++) { tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); @@ -1194,6 +1201,7 @@ void audiod_init(void) case 2: audio->tx_supp_ff = tx_supp_ff_3; audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; + audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ; for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; cnt++) { tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); @@ -1238,6 +1246,7 @@ void audiod_init(void) case 0: audio->rx_supp_ff = rx_supp_ff_1; audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; + audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ; for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; cnt++) { tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); @@ -1253,6 +1262,7 @@ void audiod_init(void) case 1: audio->rx_supp_ff = rx_supp_ff_2; audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; + audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ; for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; cnt++) { tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); @@ -1268,6 +1278,7 @@ void audiod_init(void) case 2: audio->rx_supp_ff = rx_supp_ff_3; audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; + audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ; for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; cnt++) { tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); @@ -1533,6 +1544,16 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters #if CFG_TUD_AUDIO_ENABLE_ENCODING audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); + + // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + const uint16_t active_fifo_depth = (audio->tx_supp_ff_sz_max / audio->n_bytes_per_sampe_tx) * audio->n_bytes_per_sampe_tx; + for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) + { + tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); + } +#endif + #endif // Invoke callback - can be used to trigger data sampling if not already running if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); @@ -1554,6 +1575,15 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #if CFG_TUD_AUDIO_ENABLE_DECODING audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); + + // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + const uint16_t active_fifo_depth = (audio->rx_supp_ff_sz_max / audio->n_bytes_per_sampe_rx) * audio->n_bytes_per_sampe_rx; + for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) + { + tu_fifo_config(&audio->rx_supp_ff[cnt], audio->rx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); + } +#endif #endif // Invoke callback if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); -- cgit v1.3.1 From f6ba58e370cd67b78dcd1758aa9fe010035f13bc Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 17:50:30 +0200 Subject: Fix wrong pointer type in audio_device.c --- examples/device/uac2_headset/src/usb_descriptors.c | 2 -- src/class/audio/audio_device.c | 12 ++++++------ 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index 404863dba..cd749eb65 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -87,8 +87,6 @@ uint8_t const * tud_descriptor_device_cb(void) #define EPNUM_AUDIO 0x01 #endif -#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN - uint8_t const desc_configuration[] = { // Interface count, string index, total length, attribute, power in mA diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8bd15a8c1..642688876 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1174,7 +1174,7 @@ void audiod_init(void) { tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_1[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(tx_supp_ff_mutex_wr_1[cnt]), NULL); #endif } @@ -1190,7 +1190,7 @@ void audiod_init(void) { tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_2[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(tx_supp_ff_mutex_wr_2[cnt]), NULL); #endif } @@ -1206,7 +1206,7 @@ void audiod_init(void) { tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_3[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(tx_supp_ff_mutex_wr_3[cnt]), NULL); #endif } @@ -1251,7 +1251,7 @@ void audiod_init(void) { tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_1[cnt]), NULL); + tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(rx_supp_ff_mutex_rd_1[cnt]), NULL); #endif } @@ -1267,7 +1267,7 @@ void audiod_init(void) { tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_2[cnt]), NULL); + tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(rx_supp_ff_mutex_rd_2[cnt]), NULL); #endif } @@ -1283,7 +1283,7 @@ void audiod_init(void) { tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_3[cnt]), NULL); + tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(rx_supp_ff_mutex_rd_3[cnt]), NULL); #endif } -- cgit v1.3.1 From 1ac9e7e3a70b48e73f150d1e7494eaecd2d34822 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Apr 2021 18:22:19 +0200 Subject: Fix wrong read mutexes in audio_device.c --- src/class/audio/audio_device.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 642688876..dadb66caa 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1061,7 +1061,7 @@ void audiod_init(void) case 0: tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_1), NULL); + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_1), NULL); #endif break; #endif @@ -1069,7 +1069,7 @@ void audiod_init(void) case 1: tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_2), NULL); + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_2), NULL); #endif break; #endif @@ -1077,7 +1077,7 @@ void audiod_init(void) case 2: tu_fifo_config(&audio->ep_in_ff, audio_ep_in_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(ep_in_ff_mutex_wr_3), NULL); + tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_3), NULL); #endif break; #endif @@ -1115,7 +1115,7 @@ void audiod_init(void) case 0: tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_1)); + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_1)); #endif break; #endif @@ -1123,7 +1123,7 @@ void audiod_init(void) case 1: tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_2)); + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_2)); #endif break; #endif @@ -1131,7 +1131,7 @@ void audiod_init(void) case 2: tu_fifo_config(&audio->ep_out_ff, audio_ep_out_sw_buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(rx_supp_ff_mutex_rd_3)); + tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_3)); #endif break; #endif @@ -1174,7 +1174,7 @@ void audiod_init(void) { tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(tx_supp_ff_mutex_wr_1[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_1[cnt]), NULL); #endif } @@ -1190,7 +1190,7 @@ void audiod_init(void) { tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(tx_supp_ff_mutex_wr_2[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_2[cnt]), NULL); #endif } @@ -1206,7 +1206,7 @@ void audiod_init(void) { tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(tx_supp_ff_mutex_wr_3[cnt]), NULL); + tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_3[cnt]), NULL); #endif } @@ -1251,7 +1251,7 @@ void audiod_init(void) { tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(rx_supp_ff_mutex_rd_1[cnt]), NULL); + tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_1[cnt]), NULL); #endif } @@ -1267,7 +1267,7 @@ void audiod_init(void) { tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(rx_supp_ff_mutex_rd_2[cnt]), NULL); + tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_2[cnt]), NULL); #endif } @@ -1283,7 +1283,7 @@ void audiod_init(void) { tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(rx_supp_ff_mutex_rd_3[cnt]), NULL); + tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_3[cnt]), NULL); #endif } -- cgit v1.3.1 From 586a46c7d3991b28f9a0a8769c90c4992fcc1539 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 4 Apr 2021 21:33:19 +0700 Subject: revert dcd_edpt_xfer_fifo() implementation for samg samg fifo is accessed byte by byte (although the register is 32 bit). --- src/portable/microchip/samg/dcd_samg.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 8b5bebf85..f8b204508 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -297,34 +297,13 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_desc_t* xfer = &_dcd_xfer[epnum]; - xfer->total_len = total_bytes; - xfer->actual_len = 0; - xfer->buffer = NULL; // Indicates a FIFO shall be used - xfer->ff = ff; - - if (dir == TUSB_DIR_OUT) - { - // Enable interrupt when starting OUT transfer - if (epnum != 0) UDP->UDP_IER |= (1 << epnum); - } - else - { - tu_fifo_read_n(ff, (void *) &UDP->UDP_FDR[epnum], xfer_packet_len(xfer)); - - // TX ready for transfer - csr_set(epnum, UDP_CSR_TXPKTRDY_Msk); - } - return true; } +#endif // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) @@ -435,11 +414,13 @@ void dcd_int_handler(uint8_t rhport) if (xact_len) { // write to EP fifo +#if 0 // TODO support dcd_edpt_xfer_fifo if (xfer->ff) { tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len); } else +#endif { xact_ep_write(epnum, xfer->buffer, xact_len); } @@ -468,11 +449,13 @@ void dcd_int_handler(uint8_t rhport) uint16_t const xact_len = (uint16_t) ((UDP->UDP_CSR[epnum] & UDP_CSR_RXBYTECNT_Msk) >> UDP_CSR_RXBYTECNT_Pos); // Read from EP fifo +#if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len); } else +#endif { xact_ep_read(epnum, xfer->buffer, xact_len); } -- cgit v1.3.1 From bebe2f0bbf68561727a68037bae25f223d284578 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 4 Apr 2021 22:50:26 +0700 Subject: revert dcd_edpt_xfer_fifo() implementation for nuc505 --- src/portable/microchip/samg/dcd_samg.c | 6 +++--- src/portable/nuvoton/nuc505/dcd_nuc505.c | 24 ++++++++++++++++-------- 2 files changed, 19 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index f8b204508..62fab8d17 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -44,7 +44,7 @@ typedef struct { uint8_t* buffer; - tu_fifo_t* ff; + // tu_fifo_t* ff; // TODO support dcd_edpt_xfer_fifo API uint16_t total_len; volatile uint16_t actual_len; uint16_t epsize; @@ -61,7 +61,7 @@ void xfer_epsize_set(xfer_desc_t* xfer, uint16_t epsize) void xfer_begin(xfer_desc_t* xfer, uint8_t * buffer, uint16_t total_bytes) { xfer->buffer = buffer; - xfer->ff = NULL; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->total_len = total_bytes; xfer->actual_len = 0; } @@ -69,7 +69,7 @@ void xfer_begin(xfer_desc_t* xfer, uint8_t * buffer, uint16_t total_bytes) void xfer_end(xfer_desc_t* xfer) { xfer->buffer = NULL; - xfer->ff = NULL; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->total_len = 0; xfer->actual_len = 0; } diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 67693e335..b7bbb020b 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -95,7 +95,7 @@ static uint32_t bufseg_addr; static struct xfer_ctl_t { uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */ - tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_xfer_fifo() */ + // tu_fifo_t* ff; // TODO support dcd_edpt_xfer_fifo API union { uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */ uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */ @@ -165,7 +165,7 @@ static USBD_EP_T *ep_entry(uint8_t ep_addr, bool add) /* perform a non-control IN endpoint transfer; this is called by the ISR */ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) { - uint16_t bytes_now = tu_min16(xfer->in_remaining_bytes, xfer->max_packet_size); + uint16_t const bytes_now = tu_min16(xfer->in_remaining_bytes, xfer->max_packet_size); /* precompute what amount of data will be left */ xfer->in_remaining_bytes -= bytes_now; @@ -181,11 +181,13 @@ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) } /* provided buffers are thankfully 32-bit aligned, allowing most data to be transfered as 32-bit */ +#if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now); } else +#endif { uint16_t countdown = bytes_now; while (countdown > 3) @@ -196,13 +198,12 @@ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) ep->EPDAT = u32; xfer->data_ptr += 4; countdown -= 4; } - while (countdown--) - ep->EPDAT_BYTE = *xfer->data_ptr++; + + while (countdown--) ep->EPDAT_BYTE = *xfer->data_ptr++; } /* for short packets, we must nudge the peripheral to say 'that's all folks' */ - if (bytes_now != xfer->max_packet_size) - ep->EPRSPCTL = USBD_EPRSPCTL_SHORTTXEN_Msk; + if (bytes_now != xfer->max_packet_size) ep->EPRSPCTL = USBD_EPRSPCTL_SHORTTXEN_Msk; } /* called by dcd_init() as well as by the ISR during a USB bus reset */ @@ -394,7 +395,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to /* store away the information we'll needing now and later */ xfer->data_ptr = buffer; - xfer->ff = NULL; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->in_remaining_bytes = total_bytes; xfer->total_bytes = total_bytes; @@ -412,6 +413,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; @@ -441,6 +443,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 return true; } +#endif void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { @@ -655,20 +658,25 @@ void dcd_int_handler(uint8_t rhport) #else uint16_t const available_bytes = ep->EPDATCNT & USBD_EPDATCNT_DATCNT_Msk; /* copy the data from the PC to the previously provided buffer */ +#if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far)); } else +#endif { for (int count = 0; (count < available_bytes) && (xfer->out_bytes_so_far < xfer->total_bytes); count++, xfer->out_bytes_so_far++) + { *xfer->data_ptr++ = ep->EPDAT_BYTE; - + } } /* when the transfer is finished, alert TinyUSB; otherwise, continue accepting more data */ if ( (xfer->total_bytes == xfer->out_bytes_so_far) || (available_bytes < xfer->max_packet_size) ) + { dcd_event_xfer_complete(0, ep_addr, xfer->out_bytes_so_far, XFER_RESULT_SUCCESS, true); + } #endif } -- cgit v1.3.1 From 8d2dfe872ca5e1cdbde629b4bfd072bbca0c0216 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 5 Apr 2021 19:19:49 +0700 Subject: revert dcd_edpt_xfer_fifo() implementation for stm32_fsdev --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index dbd514f86..b8b0fc104 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -166,7 +166,7 @@ TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligne typedef struct { uint8_t * buffer; - tu_fifo_t * ff; + // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API uint16_t total_len; uint16_t queued_len; uint16_t pma_ptr; @@ -197,9 +197,10 @@ 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_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wNBytes); static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes); -static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNBytes); + +//static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wNBytes); +//static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNBytes); // Using a function due to better type checks // This seems better than having to do type casts everywhere else @@ -480,14 +481,15 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) if (count != 0U) { +#if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { dcd_read_packet_memory_ff(xfer->ff, *pcd_ep_rx_address_ptr(USB,EPindex), count); } else +#endif { - dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]), - *pcd_ep_rx_address_ptr(USB,EPindex), count); + dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]), *pcd_ep_rx_address_ptr(USB,EPindex), count); } xfer->queued_len = (uint16_t)(xfer->queued_len + count); @@ -816,11 +818,14 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix) len = xfer->max_packet_size; } uint16_t oldAddr = *pcd_ep_tx_address_ptr(USB,ep_ix); + +#if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { dcd_write_packet_memory_ff(xfer->ff, oldAddr, len); } else +#endif { dcd_write_packet_memory(oldAddr, &(xfer->buffer[xfer->queued_len]), len); } @@ -840,7 +845,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_ctl_t * xfer = xfer_ctl_ptr(epnum,dir); xfer->buffer = buffer; - xfer->ff = NULL; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->total_len = total_bytes; xfer->queued_len = 0; @@ -867,6 +872,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; @@ -877,7 +883,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 xfer_ctl_t * xfer = xfer_ctl_ptr(epnum,dir); xfer->buffer = NULL; - xfer->ff = ff; + // xfer->ff = ff; // TODO support dcd_edpt_xfer_fifo API xfer->total_len = total_bytes; xfer->queued_len = 0; @@ -897,6 +903,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 } return true; } +#endif void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { @@ -971,6 +978,7 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, si return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API /** * @brief Copy from FIFO to packet memory area (PMA). * Uses byte-access of system memory and 16-bit access of packet memory @@ -1015,6 +1023,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN return true; } +#endif /** * @brief Copy a buffer from packet memory area (PMA) to user memory area. @@ -1051,6 +1060,7 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API /** * @brief Copy a buffer from user packet memory area (PMA) to FIFO. * Uses byte-access of system memory and 16-bit access of packet memory @@ -1097,3 +1107,5 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB #endif +#endif + -- cgit v1.3.1 From 164d3e82e32e1039ba8e471fbc949699c396c9fe Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 5 Apr 2021 11:13:42 -0400 Subject: Fix incorrect DNLOAD request len passed to app Fixes bug where the app callback was getting the length of the status request transfer rather than the length of the data stage payload. TODO: Right now this returns the expected length, when it really should be returning the transfer length. --- src/class/dfu/dfu_rt_device.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 0cbc8eeda..7d40d2057 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -46,8 +46,9 @@ typedef struct TU_ATTR_PACKED bool blk_transfer_in_proc; uint8_t itf_num; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; + uint16_t last_block_num; + uint16_t last_transfer_len; + CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; } dfu_state_ctx_t; typedef struct TU_ATTR_PACKED @@ -161,6 +162,8 @@ void dfu_rtd_init(void) _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; dfu_rtd_debug_print_context(); } @@ -204,6 +207,8 @@ void dfu_rtd_reset(uint8_t rhport) _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; dfu_rtd_debug_print_context(); } @@ -290,8 +295,8 @@ void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) { TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); - uint16_t retval = tud_dfu_runtime_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.epin_buf, wLength); - tud_control_xfer(rhport, request, &_dfu_state_ctx.epin_buf, retval); + uint16_t retval = tud_dfu_runtime_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, wLength); + tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, retval); return retval; } @@ -319,12 +324,14 @@ static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) { + _dfu_state_ctx.last_block_num = request->wValue; + _dfu_state_ctx.last_transfer_len = request->wLength; // TODO: add "zero" copy mode so the buffer we read into can be provided by the user // if they wish, there still will be the internal control buffer copy to this buffer // but this mode would provide zero copy from the class driver to the application // setup for data phase - tud_control_xfer(rhport, request, &_dfu_state_ctx.epout_buf, request->wLength); + tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); } static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) @@ -338,8 +345,12 @@ static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t con tud_dfu_runtime_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); - tud_dfu_runtime_req_dnload_data_cb(request->wValue, (uint8_t *)&_dfu_state_ctx.epout_buf, request->wLength); + // TODO: I want the real xferred len, not what is expected. May need to change usbd.c to do this. + tud_dfu_runtime_req_dnload_data_cb(_dfu_state_ctx.last_block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, _dfu_state_ctx.last_transfer_len); _dfu_state_ctx.blk_transfer_in_proc = false; + + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; } void tud_dfu_runtime_poll_timeout_done() -- cgit v1.3.1 From 49b2d8f26cdf0dd832c7f3f752d5fe3cdeb45a77 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Apr 2021 00:07:17 +0700 Subject: revert dcd_edpt_xfer_fifo() implementation for msp430 --- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 40b12eb04..48e9dd592 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -49,7 +49,7 @@ uint8_t _setup_packet[8]; typedef struct { uint8_t * buffer; - tu_fifo_t * ff; + // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API uint16_t total_len; uint16_t queued_len; uint16_t max_size; @@ -308,7 +308,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->buffer = buffer; - xfer->ff = NULL; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->total_len = total_bytes; xfer->queued_len = 0; xfer->short_packet = false; @@ -347,6 +347,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; @@ -374,6 +375,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 return true; } +#endif void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { @@ -474,12 +476,14 @@ static void receive_packet(uint8_t ep_num) to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; } +#if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { - volatile uint8_t * ep_buf = &USBSTABUFF + (ep_regs[BBAX] << 3); + volatile uint8_t * ep_buf = (ep_num == 0) ? &USBOEP0BUF : (&USBSTABUFF + (ep_regs[BBAX] << 3)); tu_fifo_write_n(xfer->ff, (const void *) ep_buf, to_recv_size); } else +#endif { uint8_t * base = (xfer->buffer + xfer->queued_len); @@ -565,11 +569,13 @@ static void transmit_packet(uint8_t ep_num) ep_regs_t ep_regs = EP_REGS(ep_num, TUSB_DIR_IN); volatile uint8_t * ep_buf = &USBSTABUFF + (ep_regs[BBAX] << 3); +#if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { tu_fifo_read_n(xfer->ff, (void *) ep_buf, xfer_size); } else +#endif { uint8_t * base = (xfer->buffer + xfer->queued_len); for(int i = 0; i < xfer_size; i++) -- cgit v1.3.1 From 69ad092fceb635062c20bef5bd03e325a1a5d59a Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Apr 2021 00:13:12 +0700 Subject: revert dcd_edpt_xfer_fifo() implementation for nuc120 121 --- src/portable/nuvoton/nuc120/dcd_nuc120.c | 10 ++++++++-- src/portable/nuvoton/nuc121/dcd_nuc121.c | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 06ffa2965..5dc3bca21 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -77,7 +77,7 @@ static bool active_ep0_xfer; static struct xfer_ctl_t { uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */ - tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_xfer_fifo() */ + // tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_xfer_fifo() */ // TODO support dcd_edpt_xfer_fifo API union { uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */ uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */ @@ -144,11 +144,13 @@ static void dcd_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) { uint16_t bytes_now = tu_min16(xfer->in_remaining_bytes, xfer->max_packet_size); +#if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { tu_fifo_read_n(xfer->ff, (void *) (USBD_BUF_BASE + ep->BUFSEG), bytes_now); } else +#endif { memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); } @@ -277,7 +279,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to /* store away the information we'll needing now and later */ xfer->data_ptr = buffer; - xfer->ff = NULL; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->in_remaining_bytes = total_bytes; xfer->total_bytes = total_bytes; @@ -297,6 +299,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; @@ -324,6 +327,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 return true; } +#endif void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { @@ -428,11 +432,13 @@ void dcd_int_handler(uint8_t rhport) if (out_ep) { /* copy the data from the PC to the previously provided buffer */ +#if 0 // // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { tu_fifo_write_n(xfer->ff, (const void *) (USBD_BUF_BASE + ep->BUFSEG), available_bytes); } else +#endif { memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); xfer->data_ptr += available_bytes; diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 6d98ba08a..d50e82846 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -79,7 +79,7 @@ static bool active_ep0_xfer; static struct xfer_ctl_t { uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */ - tu_fifo_t * ff; + // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API union { uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */ uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */ @@ -146,11 +146,13 @@ static void dcd_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) { uint16_t bytes_now = tu_min16(xfer->in_remaining_bytes, xfer->max_packet_size); +#if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { tu_fifo_read_n(xfer->ff, (void *) (USBD_BUF_BASE + ep->BUFSEG), bytes_now); } else +#endif { memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); } @@ -283,7 +285,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to /* store away the information we'll needing now and later */ xfer->data_ptr = buffer; - xfer->ff = NULL; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->in_remaining_bytes = total_bytes; xfer->total_bytes = total_bytes; @@ -303,6 +305,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void) rhport; @@ -330,6 +333,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 return true; } +#endif void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { @@ -439,11 +443,13 @@ void dcd_int_handler(uint8_t rhport) if (out_ep) { /* copy the data from the PC to the previously provided buffer */ +#if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { tu_fifo_write_n(xfer->ff, (const void *) (USBD_BUF_BASE + ep->BUFSEG), available_bytes); } else +#endif { memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); xfer->data_ptr += available_bytes; -- cgit v1.3.1 From 3acf0c2d73defdc92de02db2456591b8a441a2e0 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Apr 2021 01:00:00 +0700 Subject: revert dcd_edpt_xfer_fifo() implementation for esp32s2 --- src/portable/espressif/esp32s2/dcd_esp32s2.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 28a3bcd07..edbc872fe 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -60,7 +60,7 @@ typedef struct { uint8_t *buffer; - tu_fifo_t * ff; + // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API uint16_t total_len; uint16_t queued_len; uint16_t max_size; @@ -321,7 +321,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->buffer = buffer; - xfer->ff = NULL; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->total_len = total_bytes; xfer->queued_len = 0; xfer->short_packet = false; @@ -357,6 +357,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { (void)rhport; @@ -404,6 +405,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 } return true; } +#endif void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { @@ -514,12 +516,14 @@ static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ } // Common buffer read +#if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { // Ring buffer tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, to_recv_size); } else +#endif { uint8_t to_recv_rem = to_recv_size % 4; uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; @@ -571,11 +575,13 @@ static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; +#if 0 // TODO support dcd_edpt_xfer_fifo API if (xfer->ff) { tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, to_xfer_size); } else +#endif { uint8_t to_xfer_rem = to_xfer_size % 4; uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; -- cgit v1.3.1 From 7ab8da949e6622f59e49d7435a22f52a18940350 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Apr 2021 01:07:32 +0700 Subject: audio driver only use USE_LINEAR_BUFFER = 0 for stm32 synopsys driver --- src/class/audio/audio_device.c | 51 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index dadb66caa..634e9e4d2 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -63,33 +63,32 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically -#if ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX || /* Intermediate software buffer required */ \ - CFG_TUSB_MCU == OPT_MCU_DA1469X || /* Intermediate software buffer required */ \ - CFG_TUSB_MCU == OPT_MCU_LPC18XX || /* No clue how driver works */ \ - CFG_TUSB_MCU == OPT_MCU_LPC43XX || \ - CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_RP2040 || /* Don't want to change driver */ \ - CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI || /* Intermediate software buffer required */ \ - CFG_TUSB_MCU == OPT_MCU_CXD56 || /* No clue how driver works */ \ - CFG_TUSB_MCU == OPT_MCU_NRF5X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ - CFG_TUSB_MCU == OPT_MCU_LPC11UXX || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ - CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC15XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC51UXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC55XX || \ - CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ - CFG_TUSB_MCU == OPT_MCU_LPC40XX || \ - CFG_TUSB_MCU == OPT_MCU_SAMD11 || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ - CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ - CFG_TUSB_MCU == OPT_MCU_SAMD51 || \ - CFG_TUSB_MCU == OPT_MCU_SAME5X ) - -#define USE_LINEAR_BUFFER 1 - +// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer +// is available or driver is would need to be changed dramatically + +// Only STM32 synopsys use non-linear buffer for now +// Synopsys detection copied from dcd_synopsys.c (refactor later on) +#if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ + defined (STM32F107xB) || defined (STM32F107xC) +#define STM32F1_SYNOPSYS +#endif + +#if defined (STM32L475xx) || defined (STM32L476xx) || \ + defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \ + defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define STM32L4_SYNOPSYS +#endif + +#if (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_SYNOPSYS)) || \ + CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ + CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ + (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \ + #define USE_LINEAR_BUFFER 0 #else -#define USE_LINEAR_BUFFER 0 + #define USE_LINEAR_BUFFER 1 #endif // Declaration of buffers -- cgit v1.3.1 From 68687ed0f400adc456cd8e4dbda4eb7d8e32d5cd Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Apr 2021 01:16:51 +0700 Subject: fix build --- src/class/audio/audio_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 634e9e4d2..a85dfddb8 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -85,7 +85,7 @@ CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ - (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \ + (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) #define USE_LINEAR_BUFFER 0 #else #define USE_LINEAR_BUFFER 1 -- cgit v1.3.1 From c5b8ef15299e9d5787602b39805efbb0ca385110 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 5 Apr 2021 16:32:58 -0400 Subject: Separate DFU RT and Mode. Untested --- src/class/dfu/dfu.h | 91 ++++++ src/class/dfu/dfu_mode_device.c | 598 +++++++++++++++++++++++++++++++++++ src/class/dfu/dfu_mode_device.h | 132 ++++++++ src/class/dfu/dfu_rt_device.c | 670 +++------------------------------------- src/class/dfu/dfu_rt_device.h | 70 +---- src/common/tusb_common.h | 2 +- src/device/usbd.c | 12 + src/tusb.h | 6 +- src/tusb_option.h | 6 +- 9 files changed, 903 insertions(+), 684 deletions(-) create mode 100644 src/class/dfu/dfu_mode_device.c create mode 100644 src/class/dfu/dfu_mode_device.h (limited to 'src') diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h index 39ce567da..2040e415c 100644 --- a/src/class/dfu/dfu.h +++ b/src/class/dfu/dfu.h @@ -100,6 +100,97 @@ typedef enum { #define DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK (1 << 2) #define DFU_FUNC_ATTR_WILL_DETACH_BITMASK (1 << 3) +// DFU Status Request Payload +typedef struct TU_ATTR_PACKED +{ + uint8_t bStatus; + uint8_t bwPollTimeout[3]; + uint8_t bState; + uint8_t iString; +} dfu_status_req_payload_t; + +TU_VERIFY_STATIC( sizeof(dfu_status_req_payload_t) == 6, "size is not correct"); + + +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + +static tu_lookup_entry_t const _dfu_request_lookup[] = +{ + { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, + { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, + { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, + { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, + { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, + { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, + { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, +}; + +static tu_lookup_table_t const _dfu_request_table = +{ + .count = TU_ARRAY_SIZE(_dfu_request_lookup), + .items = _dfu_request_lookup +}; + +static tu_lookup_entry_t const _dfu_mode_state_lookup[] = +{ + { .key = APP_IDLE , .data = "APP_IDLE" }, + { .key = APP_DETACH , .data = "APP_DETACH" }, + { .key = DFU_IDLE , .data = "DFU_IDLE" }, + { .key = DFU_DNLOAD_SYNC , .data = "DFU_DNLOAD_SYNC" }, + { .key = DFU_DNBUSY , .data = "DFU_DNBUSY" }, + { .key = DFU_DNLOAD_IDLE , .data = "DFU_DNLOAD_IDLE" }, + { .key = DFU_MANIFEST_SYNC , .data = "DFU_MANIFEST_SYNC" }, + { .key = DFU_MANIFEST , .data = "DFU_MANIFEST" }, + { .key = DFU_MANIFEST_WAIT_RESET , .data = "DFU_MANIFEST_WAIT_RESET" }, + { .key = DFU_UPLOAD_IDLE , .data = "DFU_UPLOAD_IDLE" }, + { .key = DFU_ERROR , .data = "DFU_ERROR" }, +}; + +static tu_lookup_table_t const _dfu_mode_state_table = +{ + .count = TU_ARRAY_SIZE(_dfu_mode_state_lookup), + .items = _dfu_mode_state_lookup +}; + +static tu_lookup_entry_t const _dfu_mode_status_lookup[] = +{ + { .key = DFU_STATUS_OK , .data = "OK" }, + { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, + { .key = DFU_STATUS_ERRFILE , .data = "errFILE" }, + { .key = DFU_STATUS_ERRWRITE , .data = "errWRITE" }, + { .key = DFU_STATUS_ERRERASE , .data = "errERASE" }, + { .key = DFU_STATUS_ERRCHECK_ERASED , .data = "errCHECK_ERASED" }, + { .key = DFU_STATUS_ERRPROG , .data = "errPROG" }, + { .key = DFU_STATUS_ERRVERIFY , .data = "errVERIFY" }, + { .key = DFU_STATUS_ERRADDRESS , .data = "errADDRESS" }, + { .key = DFU_STATUS_ERRNOTDONE , .data = "errNOTDONE" }, + { .key = DFU_STATUS_ERRFIRMWARE , .data = "errFIRMWARE" }, + { .key = DFU_STATUS_ERRVENDOR , .data = "errVENDOR" }, + { .key = DFU_STATUS_ERRUSBR , .data = "errUSBR" }, + { .key = DFU_STATUS_ERRPOR , .data = "errPOR" }, + { .key = DFU_STATUS_ERRUNKNOWN , .data = "errUNKNOWN" }, + { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, +}; + +static tu_lookup_table_t const _dfu_mode_status_table = +{ + .count = TU_ARRAY_SIZE(_dfu_mode_status_lookup), + .items = _dfu_mode_status_lookup +}; + +#endif + +#define dfu_debug_print_context() \ +{ \ + TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ + tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), \ + tu_lookup_find(&_dfu_mode_status_table, _dfu_state_ctx.status) ); \ +} + + #ifdef __cplusplus } #endif diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c new file mode 100644 index 000000000..e66fb823c --- /dev/null +++ b/src/class/dfu/dfu_mode_device.c @@ -0,0 +1,598 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) + +#include "dfu_mode_device.h" +#include "device/usbd_pvt.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +typedef struct TU_ATTR_PACKED +{ + dfu_mode_device_status_t status; + dfu_mode_state_t state; + uint8_t attrs; + bool blk_transfer_in_proc; + + uint8_t itf_num; + uint16_t last_block_num; + uint16_t last_transfer_len; + CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; +} dfu_mode_state_ctx_t; + +// Only a single dfu state is allowed +CFG_TUSB_MEM_SECTION static dfu_mode_state_ctx_t _dfu_state_ctx; + + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); +static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); +static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const * request); + + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void dfu_mode_init(void) +{ + _dfu_state_ctx.state = DFU_IDLE; + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.attrs = tud_dfu_mode_init_attrs_cb(); + _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; + + dfu_debug_print_context(); +} + +void dfu_mode_reset(uint8_t rhport) +{ + if ( tud_dfu_mode_usb_reset_cb ) + { + tud_dfu_mode_usb_reset_cb(rhport, &_dfu_state_ctx.state); + } else { + switch (_dfu_state_ctx.state) + { + case DFU_IDLE: + case DFU_DNLOAD_SYNC: + case DFU_DNBUSY: + case DFU_DNLOAD_IDLE: + case DFU_MANIFEST_SYNC: + case DFU_MANIFEST: + case DFU_MANIFEST_WAIT_RESET: + case DFU_UPLOAD_IDLE: + { + _dfu_state_ctx.state = (tud_dfu_mode_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; + } + break; + + case DFU_ERROR: + default: + { + _dfu_state_ctx.state = APP_IDLE; + } + break; + } + } + + if(_dfu_state_ctx.state == APP_IDLE) + { + tud_dfu_mode_reboot_to_rt_cb(); + } + + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.attrs = tud_dfu_mode_init_attrs_cb(); + _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; + dfu_debug_print_context(); +} + +uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + (void) rhport; + (void) max_len; + + // Ensure this is DFU Mode + TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && + (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); + + uint8_t const * p_desc = tu_desc_next( itf_desc ); + uint16_t drv_len = sizeof(tusb_desc_interface_t); + + if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) + { + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + return drv_len; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) + { + dfu_mode_req_dnload_reply(rhport, request); + return true; + } + + // nothing to do with any other DATA or ACK stage + if ( stage != CONTROL_STAGE_SETUP ) return true; + + TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + + // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request + if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && + TUSB_REQ_SET_INTERFACE == request->bRequest ) + { + tud_control_status(rhport, request); + return true; + } + + // Handle class request only from here + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + switch (request->bRequest) + { + case DFU_REQUEST_DETACH: + case DFU_REQUEST_DNLOAD: + case DFU_REQUEST_UPLOAD: + case DFU_REQUEST_GETSTATUS: + case DFU_REQUEST_CLRSTATUS: + case DFU_REQUEST_GETSTATE: + case DFU_REQUEST_ABORT: + { + return dfu_mode_state_machine(rhport, request); + } + break; + + default: + { + TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); + return ( tud_dfu_mode_req_nonstandard_cb ) ? tud_dfu_mode_req_nonstandard_cb(rhport, stage, request) : false; + } + break; + } + + return true; +} + +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) +{ + TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + uint16_t retval = tud_dfu_mode_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, wLength); + tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, retval); + return retval; +} + +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + dfu_status_req_payload_t resp; + + resp.bStatus = _dfu_state_ctx.status; + if ( tud_dfu_mode_get_poll_timeout_cb ) + { + tud_dfu_mode_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); + } else { + memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); + } + resp.bState = _dfu_state_ctx.state; + resp.iString = ( tud_dfu_mode_get_status_desc_table_index_cb ) ? tud_dfu_mode_get_status_desc_table_index_cb() : 0; + + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); +} + +static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); +} + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) +{ + _dfu_state_ctx.last_block_num = request->wValue; + _dfu_state_ctx.last_transfer_len = request->wLength; + // TODO: add "zero" copy mode so the buffer we read into can be provided by the user + // if they wish, there still will be the internal control buffer copy to this buffer + // but this mode would provide zero copy from the class driver to the application + + // setup for data phase + tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); +} + +static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + uint8_t bwPollTimeout[3] = {0,0,0}; + + if ( tud_dfu_mode_get_poll_timeout_cb ) + { + tud_dfu_mode_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); + } + + tud_dfu_mode_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); + + // TODO: I want the real xferred len, not what is expected. May need to change usbd.c to do this. + tud_dfu_mode_req_dnload_data_cb(_dfu_state_ctx.last_block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, _dfu_state_ctx.last_transfer_len); + _dfu_state_ctx.blk_transfer_in_proc = false; + + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; +} + +void tud_dfu_mode_poll_timeout_done() +{ + if (_dfu_state_ctx.state == DFU_DNBUSY) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + } else if (_dfu_state_ctx.state == DFU_MANIFEST) + { + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; + } +} + +static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const * request) +{ + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state)); + + switch (_dfu_state_ctx.state) + { + case DFU_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + dfu_req_dnload_setup(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_UPLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + { + _dfu_state_ctx.state = DFU_UPLOAD_IDLE; + dfu_req_upload(rhport, request, request->wValue, request->wLength); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + ; // do nothing, but don't stall so continue on + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ( _dfu_state_ctx.blk_transfer_in_proc ) + { + _dfu_state_ctx.state = DFU_DNBUSY; + dfu_req_getstatus_reply(rhport, request); + } else { + _dfu_state_ctx.state = DFU_DNLOAD_IDLE; + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNBUSY: + { + switch (request->bRequest) + { + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + + dfu_req_dnload_setup(rhport, request); + } else { + if ( tud_dfu_mode_device_data_done_check_cb() ) + { + _dfu_state_ctx.state = DFU_MANIFEST_SYNC; + tud_control_status(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall + } + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if ( tud_dfu_mode_abort_cb ) + { + tud_dfu_mode_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + { + _dfu_state_ctx.state = DFU_MANIFEST; + dfu_req_getstatus_reply(rhport, request); + } else { + if ( tud_dfu_mode_firmware_valid_check_cb() ) + { + _dfu_state_ctx.state = DFU_IDLE; + } + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST: + { + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_WAIT_RESET: + { + // technically we should never even get here, but we will handle it just in case + TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_UPLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_UPLOAD: + { + if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) + { + _dfu_state_ctx.state = DFU_IDLE; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if (tud_dfu_mode_abort_cb) + { + tud_dfu_mode_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_ERROR: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_CLRSTATUS: + { + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + default: + _dfu_state_ctx.state = DFU_ERROR; + TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); + return false; // Unexpected state, stall and change to error + } + + return true; +} + + +bool dfu_mode_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) rhport; + (void) ep_addr; + (void) result; + (void) xferred_bytes; + return true; +} + + + #endif diff --git a/src/class/dfu/dfu_mode_device.h b/src/class/dfu/dfu_mode_device.h new file mode 100644 index 000000000..32bf58bbd --- /dev/null +++ b/src/class/dfu/dfu_mode_device.h @@ -0,0 +1,132 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_DFU_MODE_DEVICE_H_ +#define _TUSB_DFU_MODE_DEVICE_H_ + +#include "common/tusb_common.h" +#include "device/usbd.h" +#include "dfu.h" + +#ifdef __cplusplus + extern "C" { +#endif + + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ +// Invoked when a reset is received to check if firmware is valid +bool tud_dfu_mode_firmware_valid_check_cb(); + +// Invoked when the device must reboot to dfu runtime mode +void tud_dfu_mode_reboot_to_rt_cb(); + +// Invoked during initialization of the dfu driver to set attributes +// Return byte set with bitmasks: +// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK +// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK +// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK +// DFU_FUNC_ATTR_WILL_DETACH_BITMASK +// Note: This should match the USB descriptor +uint8_t tud_dfu_mode_init_attrs_cb(); + +// Invoked during a DFU_GETSTATUS request to get for the string index +// to the status description string table. +TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(); + +// Invoked during a USB reset +// Lets the app perform custom behavior on a USB reset. +// If not defined, the default behavior remains the DFU specification of +// Checking the firmware valid and changing to the error state or rebooting to runtime +// Note: If used, the application must perform the reset logic for all states. +// Changing the state to APP_IDLE will result in tud_dfu_mode_reboot_to_rt_cb being called +TU_ATTR_WEAK void tud_dfu_mode_usb_reset_cb(uint8_t rhport, dfu_mode_state_t *state); + +// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use +// before the subsequent DFU_GETSTATUS requests. +// The purpose of this value is to allow the device to tell the host +// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks +// to allow the device to have time to erase, write memory, etc. +// ms_timeout is a pointer to array of length 3. +// Refer to the USB DFU class specification for more details +TU_ATTR_WEAK void tud_dfu_mode_get_poll_timeout_cb(uint8_t *ms_timeout); + +// Invoked when a DFU_DNLOAD request is received +// This should start a timer for ms_timeout ms +// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called +// NOTE: This callback should return immediately, and not implement the delay +// internally, as this will hold up the class stack from receiving any packets +// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states +void tud_dfu_mode_start_poll_timeout_cb(uint8_t *ms_timeout); + +// Must be called when the poll_timeout has elapsed +void tud_dfu_mode_poll_timeout_done(); + +// Invoked when a DFU_DNLOAD request is received +// This callback takes the wBlockNum chunk of length length and provides it +// to the application at the data pointer. This data is only valid for this +// call, so the app must use it not or copy it. +void tud_dfu_mode_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); + +// Invoked during the last DFU_DNLOAD request, signifying that the host believes +// it is done transmitting data. +// Return true if the application agrees there is no more data +// Return false if the device disagrees, which will stall the pipe, and the Host +// should initiate a recovery procedure +bool tud_dfu_mode_device_data_done_check_cb(); + +// Invoked when the Host has terminated a download or upload transfer +TU_ATTR_WEAK void tud_dfu_mode_abort_cb(); + +// Invoked when a DFU_UPLOAD request is received +// This callback must populate data with up to length bytes +// Return the number of bytes to write +uint16_t tud_dfu_mode_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); + +// Invoked when a nonstandard request is received +// Use may be vendor specific. +// Return false to stall +TU_ATTR_WEAK bool tud_dfu_mode_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + +// Invoked during a DFU_GETSTATUS request to get for the string index +// to the status description string table. +TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(); +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void dfu_mode_init(void); +void dfu_mode_reset(uint8_t rhport); +uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool dfu_mode_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DFU_MODE_DEVICE_H_ */ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 7d40d2057..806bfba2e 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -40,176 +40,39 @@ //--------------------------------------------------------------------+ typedef struct TU_ATTR_PACKED { - dfu_mode_device_status_t status; - dfu_mode_state_t state; - uint8_t attrs; - bool blk_transfer_in_proc; - - uint8_t itf_num; - uint16_t last_block_num; - uint16_t last_transfer_len; - CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; -} dfu_state_ctx_t; - -typedef struct TU_ATTR_PACKED -{ - uint8_t bStatus; - uint8_t bwPollTimeout[3]; - uint8_t bState; - uint8_t iString; -} dfu_status_req_payload_t; - -TU_VERIFY_STATIC( sizeof(dfu_status_req_payload_t) == 6, "size is not correct"); + dfu_mode_device_status_t status; + dfu_mode_state_t state; + uint8_t attrs; +} dfu_rt_state_ctx_t; // Only a single dfu state is allowed -CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx; - -static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); -static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); -static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); -static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); -static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - -static tu_lookup_entry_t const _dfu_request_lookup[] = -{ - { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, - { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, - { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, - { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, - { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, - { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, - { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, -}; - -static tu_lookup_table_t const _dfu_request_table = -{ - .count = TU_ARRAY_SIZE(_dfu_request_lookup), - .items = _dfu_request_lookup -}; - -static tu_lookup_entry_t const _dfu_mode_state_lookup[] = -{ - { .key = APP_IDLE , .data = "APP_IDLE" }, - { .key = APP_DETACH , .data = "APP_DETACH" }, - { .key = DFU_IDLE , .data = "DFU_IDLE" }, - { .key = DFU_DNLOAD_SYNC , .data = "DFU_DNLOAD_SYNC" }, - { .key = DFU_DNBUSY , .data = "DFU_DNBUSY" }, - { .key = DFU_DNLOAD_IDLE , .data = "DFU_DNLOAD_IDLE" }, - { .key = DFU_MANIFEST_SYNC , .data = "DFU_MANIFEST_SYNC" }, - { .key = DFU_MANIFEST , .data = "DFU_MANIFEST" }, - { .key = DFU_MANIFEST_WAIT_RESET , .data = "DFU_MANIFEST_WAIT_RESET" }, - { .key = DFU_UPLOAD_IDLE , .data = "DFU_UPLOAD_IDLE" }, - { .key = DFU_ERROR , .data = "DFU_ERROR" }, -}; - -static tu_lookup_table_t const _dfu_mode_state_table = -{ - .count = TU_ARRAY_SIZE(_dfu_mode_state_lookup), - .items = _dfu_mode_state_lookup -}; - -static tu_lookup_entry_t const _dfu_mode_status_lookup[] = -{ - { .key = DFU_STATUS_OK , .data = "OK" }, - { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, - { .key = DFU_STATUS_ERRFILE , .data = "errFILE" }, - { .key = DFU_STATUS_ERRWRITE , .data = "errWRITE" }, - { .key = DFU_STATUS_ERRERASE , .data = "errERASE" }, - { .key = DFU_STATUS_ERRCHECK_ERASED , .data = "errCHECK_ERASED" }, - { .key = DFU_STATUS_ERRPROG , .data = "errPROG" }, - { .key = DFU_STATUS_ERRVERIFY , .data = "errVERIFY" }, - { .key = DFU_STATUS_ERRADDRESS , .data = "errADDRESS" }, - { .key = DFU_STATUS_ERRNOTDONE , .data = "errNOTDONE" }, - { .key = DFU_STATUS_ERRFIRMWARE , .data = "errFIRMWARE" }, - { .key = DFU_STATUS_ERRVENDOR , .data = "errVENDOR" }, - { .key = DFU_STATUS_ERRUSBR , .data = "errUSBR" }, - { .key = DFU_STATUS_ERRPOR , .data = "errPOR" }, - { .key = DFU_STATUS_ERRUNKNOWN , .data = "errUNKNOWN" }, - { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, -}; - -static tu_lookup_table_t const _dfu_mode_status_table = -{ - .count = TU_ARRAY_SIZE(_dfu_mode_status_lookup), - .items = _dfu_mode_status_lookup -}; - -#endif +CFG_TUSB_MEM_SECTION static dfu_rt_state_ctx_t _dfu_state_ctx; -#define dfu_rtd_debug_print_context() \ -{ \ - TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ - tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), \ - tu_lookup_find(&_dfu_mode_status_table, _dfu_state_ctx.status) ); \ -} +static void dfu_rt_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ void dfu_rtd_init(void) { - if ( tud_dfu_runtime_init_cb ) { - _dfu_state_ctx.state = (tud_dfu_runtime_init_cb() == DFU_PROTOCOL_DFU) ? APP_DETACH : APP_IDLE; - } else { - _dfu_state_ctx.state = APP_IDLE; - } - + _dfu_state_ctx.state = APP_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); - _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; - - dfu_rtd_debug_print_context(); + dfu_debug_print_context(); } void dfu_rtd_reset(uint8_t rhport) { - if ( tud_dfu_runtime_usb_reset_cb ) + if (((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 0) + && (_dfu_state_ctx.state == DFU_REQUEST_DETACH)) { - tud_dfu_runtime_usb_reset_cb(rhport, _dfu_state_ctx.state); - } - - switch (_dfu_state_ctx.state) - { - case APP_DETACH: - { - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - case DFU_IDLE: - case DFU_DNLOAD_SYNC: - case DFU_DNBUSY: - case DFU_DNLOAD_IDLE: - case DFU_MANIFEST_SYNC: - case DFU_MANIFEST: - case DFU_MANIFEST_WAIT_RESET: - case DFU_UPLOAD_IDLE: - { - _dfu_state_ctx.state = (tud_dfu_runtime_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; - } - break; - - case DFU_ERROR: - default: - { - _dfu_state_ctx.state = APP_IDLE; - } - break; + tud_dfu_runtime_reboot_to_dfu_cb(); } + _dfu_state_ctx.state = APP_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); - _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; - dfu_rtd_debug_print_context(); + dfu_debug_print_context(); } uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) @@ -217,10 +80,9 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui (void) rhport; (void) max_len; - // Ensure this is DFU Runtime or Mode - TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && - ( (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT) - | (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) ), 0); + // Ensure this is DFU Runtime + TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && + (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT), 0); uint8_t const * p_desc = tu_desc_next( itf_desc ); uint16_t drv_len = sizeof(tusb_desc_interface_t); @@ -239,16 +101,9 @@ uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui // return false to stall control endpoint (e.g unsupported request) bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) - { - dfu_mode_req_dnload_reply(rhport, request); - return true; - } - - // nothing to do with any other DATA or ACK stage + // nothing to do with DATA or ACK stage if ( stage != CONTROL_STAGE_SETUP ) return true; - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request @@ -262,490 +117,67 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request // Handle class request only from here TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); switch (request->bRequest) { case DFU_REQUEST_DETACH: - case DFU_REQUEST_DNLOAD: - case DFU_REQUEST_UPLOAD: - case DFU_REQUEST_GETSTATUS: - case DFU_REQUEST_CLRSTATUS: - case DFU_REQUEST_GETSTATE: - case DFU_REQUEST_ABORT: - { - return dfu_state_machine(rhport, request); - } - break; - - default: - { - TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); - return ( tud_dfu_runtime_req_nonstandard_cb ) ? tud_dfu_runtime_req_nonstandard_cb(rhport, stage, request) : false; - } - break; - } - - return true; -} - -void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) -{ - _dfu_state_ctx.status = status; -} - -static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) -{ - TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); - uint16_t retval = tud_dfu_runtime_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, wLength); - tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, retval); - return retval; -} - -static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - dfu_status_req_payload_t resp; - - resp.bStatus = _dfu_state_ctx.status; - if ( tud_dfu_runtime_get_poll_timeout_cb ) - { - tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); - } else { - memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); - } - resp.bState = _dfu_state_ctx.state; - resp.iString = ( tud_dfu_runtime_get_status_desc_table_index_cb ) ? tud_dfu_runtime_get_status_desc_table_index_cb() : 0; - - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); -} - -static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); -} - -static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) -{ - _dfu_state_ctx.last_block_num = request->wValue; - _dfu_state_ctx.last_transfer_len = request->wLength; - // TODO: add "zero" copy mode so the buffer we read into can be provided by the user - // if they wish, there still will be the internal control buffer copy to this buffer - // but this mode would provide zero copy from the class driver to the application - - // setup for data phase - tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); -} - -static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - uint8_t bwPollTimeout[3] = {0,0,0}; - - if ( tud_dfu_runtime_get_poll_timeout_cb ) - { - tud_dfu_runtime_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); - } - - tud_dfu_runtime_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); - - // TODO: I want the real xferred len, not what is expected. May need to change usbd.c to do this. - tud_dfu_runtime_req_dnload_data_cb(_dfu_state_ctx.last_block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, _dfu_state_ctx.last_transfer_len); - _dfu_state_ctx.blk_transfer_in_proc = false; - - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; -} - -void tud_dfu_runtime_poll_timeout_done() -{ - if (_dfu_state_ctx.state == DFU_DNBUSY) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - } else if (_dfu_state_ctx.state == DFU_MANIFEST) - { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) - ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; - } -} - -static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) -{ - TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); - TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state)); - - switch (_dfu_state_ctx.state) - { - case APP_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DETACH: - { - _dfu_state_ctx.state = APP_DETACH; - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 1) - { - tud_dfu_runtime_reboot_to_dfu_cb(); - } else { - tud_dfu_runtime_detach_start_timer_cb(request->wValue); - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case APP_DETACH: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = APP_IDLE; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DNLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (request->wLength > 0) ) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - _dfu_state_ctx.blk_transfer_in_proc = true; - dfu_req_dnload_setup(rhport, request); - } else { - _dfu_state_ctx.state = DFU_ERROR; - } - } - break; - - case DFU_REQUEST_UPLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) - { - _dfu_state_ctx.state = DFU_UPLOAD_IDLE; - dfu_req_upload(rhport, request, request->wValue, request->wLength); - } else { - _dfu_state_ctx.state = DFU_ERROR; - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - ; // do nothing, but don't stall so continue on - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_DNLOAD_SYNC: { - switch (request->bRequest) + if (_dfu_state_ctx.state == APP_IDLE) { - case DFU_REQUEST_GETSTATUS: + _dfu_state_ctx.state = APP_DETACH; + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 1) { - if ( _dfu_state_ctx.blk_transfer_in_proc ) - { - _dfu_state_ctx.state = DFU_DNBUSY; - dfu_req_getstatus_reply(rhport, request); - } else { - _dfu_state_ctx.state = DFU_DNLOAD_IDLE; - dfu_req_getstatus_reply(rhport, request); - } + tud_dfu_runtime_reboot_to_dfu_cb(); + } else { + tud_dfu_runtime_detach_start_timer_cb(request->wValue); } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_DNBUSY: - { - switch (request->bRequest) - { - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; + } else { + TU_LOG2(" DFU Unexpected request during state %s: %u\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), request->bRequest); + return false; } } break; - case DFU_DNLOAD_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DNLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (request->wLength > 0) ) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - _dfu_state_ctx.blk_transfer_in_proc = true; - - dfu_req_dnload_setup(rhport, request); - } else { - if ( tud_dfu_runtime_device_data_done_check_cb() ) - { - _dfu_state_ctx.state = DFU_MANIFEST_SYNC; - tud_control_status(rhport, request); - } else { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall - } - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - if ( tud_dfu_runtime_abort_cb ) - { - tud_dfu_runtime_abort_cb(); - } - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_MANIFEST_SYNC: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) - { - _dfu_state_ctx.state = DFU_MANIFEST; - dfu_req_getstatus_reply(rhport, request); - } else { - if ( tud_dfu_runtime_firmware_valid_check_cb() ) - { - _dfu_state_ctx.state = DFU_IDLE; - } - dfu_req_getstatus_reply(rhport, request); - } - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_MANIFEST: + case DFU_REQUEST_GETSTATUS: { - switch (request->bRequest) - { - default: - { - return false; // stall on all other requests - } - break; - } - } - break; + dfu_status_req_payload_t resp; + resp.bStatus = _dfu_state_ctx.status; + memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); // Value is ignored + resp.bState = _dfu_state_ctx.state; + resp.iString = ( tud_dfu_runtime_get_status_desc_table_index_cb ) ? tud_dfu_runtime_get_status_desc_table_index_cb() : 0; - case DFU_MANIFEST_WAIT_RESET: - { - // technically we should never even get here, but we will handle it just in case - TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); - switch (request->bRequest) - { - default: - { - return false; // stall on all other requests - } - break; - } + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); } break; - case DFU_UPLOAD_IDLE: + case DFU_REQUEST_GETSTATE: { - switch (request->bRequest) - { - case DFU_REQUEST_UPLOAD: - { - if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) - { - _dfu_state_ctx.state = DFU_IDLE; - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - if (tud_dfu_runtime_abort_cb) - { - tud_dfu_runtime_abort_cb(); - } - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - default: - { - return false; // stall on all other requests - } - break; - } + tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); } break; - case DFU_ERROR: + default: { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_CLRSTATUS: - { - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - return false; // stall on all other requests - } - break; - } + TU_LOG2(" DFU Nonstandard Runtime Request: %u\r\n", request->bRequest); + return ( tud_dfu_runtime_req_nonstandard_cb ) ? tud_dfu_runtime_req_nonstandard_cb(rhport, stage, request) : false; } break; - - default: - _dfu_state_ctx.state = DFU_ERROR; - TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); - return false; // Unexpected state, stall and change to error } return true; } +void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) +{ + _dfu_state_ctx.status = status; +} + +void tud_dfu_runtime_detach_timer_elapsed() +{ + if (_dfu_state_ctx.state == DFU_REQUEST_DETACH) + { + _dfu_state_ctx.state = APP_IDLE; + } +} #endif diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 9e7ae029e..23703862d 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -43,28 +43,26 @@ // Value is not checked to allow for custom statuses to be used void tud_dfu_runtime_set_status(dfu_mode_device_status_t status); -// Invoked when a DFU_DETACH request is received and bitWillDetatch is set +// Invoked when a DFU_DETACH request is received and bitWillDetach is set void tud_dfu_runtime_reboot_to_dfu_cb(); -// Invoked when a DFU_DETACH request is received and bitWillDetatch is not set +// Invoked when a DFU_DETACH request is received and bitWillDetach is not set // This should start a timer for wTimeout ms -// The application should then look for a USB reset signal to occur before -// the timeout has elapsed. The reset signal will invoke tud_dfu_runtime_usb_reset_cb. -// If this reset signal is received before the timeout, then the application must -// switch to DFU mode. -// If the timer expires, the app does not need to do anything. +// When the timer has elapsed, the app must call tud_dfu_runtime_detach_timer_elapsed +// If a USB reset is called while the timer is running, the class will call +// tud_dfu_runtime_reboot_to_dfu_cb. // NOTE: This callback should return immediately, and not implement the delay // internally, as this can will hold up the USB stack TU_ATTR_WEAK void tud_dfu_runtime_detach_start_timer_cb(uint16_t wTimeout); +// Invoke when the dfu runtime detach timer has elapsed +void tud_dfu_runtime_detach_timer_elapsed(); + // Invoked when a nonstandard request is received // Use may be vendor specific. // Return false to stall TU_ATTR_WEAK bool tud_dfu_runtime_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -// Invoked when a reset is received to check if firmware is valid -bool tud_dfu_runtime_firmware_valid_check_cb(); - // Invoked during initialization of the dfu driver to set attributes // Return byte set with bitmasks: // DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK @@ -74,62 +72,10 @@ bool tud_dfu_runtime_firmware_valid_check_cb(); // Note: This should match the USB descriptor uint8_t tud_dfu_runtime_init_attrs_cb(); -// Invoked during initialization of the dfu driver to start as RT or DFU -// This will determine if the internal state machine will begin in -// APP_IDLE or DFU_IDLE -TU_ATTR_WEAK dfu_protocol_type_t tud_dfu_runtime_init_cb(); - // Invoked during a DFU_GETSTATUS request to get for the string index // to the status description string table. TU_ATTR_WEAK uint8_t tud_dfu_runtime_get_status_desc_table_index_cb(); -// Invoked during a USB reset -// Lets the app know that a USB reset has occurred so it can act accordingly, -// See tud_dfu_runtime_detach_start_timer_cb for how to handle the APP_DETACH state -// Other states will be application specific -TU_ATTR_WEAK void tud_dfu_runtime_usb_reset_cb(uint8_t rhport, dfu_mode_state_t state); - -// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use -// before the subsequent DFU_GETSTATUS requests. -// The purpose of this value is to allow the device to tell the host -// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks -// to allow the device to have time to erase, write memory, etc. -// ms_timeout is a pointer to array of length 3. -// Refer to the USB DFU class specification for more details -TU_ATTR_WEAK void tud_dfu_runtime_get_poll_timeout_cb(uint8_t *ms_timeout); - -// Invoked when a DFU_DNLOAD request is received -// This should start a timer for ms_timeout ms -// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called -// NOTE: This callback should return immediately, and not implement the delay -// internally, as this will hold up the class stack from receiving any packets -// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states -void tud_dfu_runtime_start_poll_timeout_cb(uint8_t *ms_timeout); - -// Must be called when the poll_timeout has elapsed -void tud_dfu_runtime_poll_timeout_done(); - -// Invoked when a DFU_DNLOAD request is received -// This callback takes the wBlockNum chunk of length length and provides it -// to the application at the data pointer. This data is only valid for this -// call, so the app must use it not or copy it. -void tud_dfu_runtime_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); - -// Invoked during the last DFU_DNLOAD request, signifying that the host believes -// it is done transmitting data. -// Return true if the application agrees there is no more data -// Return false if the device disagrees, which will stall the pipe, and the Host -// should initiate a recovery procedure -bool tud_dfu_runtime_device_data_done_check_cb(); - -// Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_runtime_abort_cb(); - -// Invoked when a DFU_UPLOAD request is received -// This callback must populate data with up to length bytes -// Return the number of bytes to write -uint16_t tud_dfu_runtime_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index f10be88ab..859d9d47d 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) diff --git a/src/device/usbd.c b/src/device/usbd.c index 28c9acdd2..91838b39c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -187,6 +187,18 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif + #if CFG_TUD_DFU_MODE + { + DRIVER_NAME("DFU-MODE") + .init = dfu_mode_init, + .reset = dfu_mode_reset, + .open = dfu_mode_open, + .control_xfer_cb = dfu_mode_control_xfer_cb, + .xfer_cb = dfu_mode_xfer_cb, + .sof = NULL + }, + #endif + #if CFG_TUD_NET { DRIVER_NAME("NET") diff --git a/src/tusb.h b/src/tusb.h index cc82c440d..c9558515c 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -96,6 +96,10 @@ #include "class/dfu/dfu_rt_device.h" #endif + #if CFG_TUD_DFU_MODE + #include "class/dfu/dfu_mode_device.h" + #endif + #if CFG_TUD_NET #include "class/net/net_device.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 1af3ee672..3cd3df9f2 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -234,7 +234,11 @@ #endif #ifndef CFG_TUD_DFU_RUNTIME - #define CFG_TUD_DFU_RUNTIME 0 + #define CFG_TUD_DFU_RUNTIME 0 +#endif + +#ifndef CFG_TUD_DFU_MODE + #define CFG_TUD_DFU_MODE 0 #endif #ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE -- cgit v1.3.1 From fdc91f8d2c3364a9a5cea2b0efff2167c9bf4786 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 5 Apr 2021 16:48:09 -0400 Subject: Fix bug during initialization of DFU Mode --- src/class/dfu/dfu_mode_device.c | 45 +++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c index e66fb823c..68f55510b 100644 --- a/src/class/dfu/dfu_mode_device.c +++ b/src/class/dfu/dfu_mode_device.c @@ -67,7 +67,7 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const //--------------------------------------------------------------------+ void dfu_mode_init(void) { - _dfu_state_ctx.state = DFU_IDLE; + _dfu_state_ctx.state = APP_DETACH; // After init, reset will occur. We want to be in APP_DETACH to move to DFU_IDLE _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = tud_dfu_mode_init_attrs_cb(); _dfu_state_ctx.blk_transfer_in_proc = false; @@ -79,31 +79,36 @@ void dfu_mode_init(void) void dfu_mode_reset(uint8_t rhport) { - if ( tud_dfu_mode_usb_reset_cb ) + if (_dfu_state_ctx.state == APP_DETACH) { - tud_dfu_mode_usb_reset_cb(rhport, &_dfu_state_ctx.state); + _dfu_state_ctx.state = DFU_IDLE; } else { - switch (_dfu_state_ctx.state) + if ( tud_dfu_mode_usb_reset_cb ) { - case DFU_IDLE: - case DFU_DNLOAD_SYNC: - case DFU_DNBUSY: - case DFU_DNLOAD_IDLE: - case DFU_MANIFEST_SYNC: - case DFU_MANIFEST: - case DFU_MANIFEST_WAIT_RESET: - case DFU_UPLOAD_IDLE: + tud_dfu_mode_usb_reset_cb(rhport, &_dfu_state_ctx.state); + } else { + switch (_dfu_state_ctx.state) { - _dfu_state_ctx.state = (tud_dfu_mode_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; - } - break; + case DFU_IDLE: + case DFU_DNLOAD_SYNC: + case DFU_DNBUSY: + case DFU_DNLOAD_IDLE: + case DFU_MANIFEST_SYNC: + case DFU_MANIFEST: + case DFU_MANIFEST_WAIT_RESET: + case DFU_UPLOAD_IDLE: + { + _dfu_state_ctx.state = (tud_dfu_mode_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; + } + break; - case DFU_ERROR: - default: - { - _dfu_state_ctx.state = APP_IDLE; + case DFU_ERROR: + default: + { + _dfu_state_ctx.state = APP_IDLE; + } + break; } - break; } } -- cgit v1.3.1 From bc2cb99780a0bc0359195a4be8e556f71da5a70b Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 5 Apr 2021 17:06:27 -0400 Subject: Remove unreachable callback --- src/class/dfu/dfu_mode_device.c | 10 ---------- src/class/dfu/dfu_mode_device.h | 1 - src/device/usbd.c | 2 +- 3 files changed, 1 insertion(+), 12 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c index 68f55510b..59cea7673 100644 --- a/src/class/dfu/dfu_mode_device.c +++ b/src/class/dfu/dfu_mode_device.c @@ -590,14 +590,4 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const } -bool dfu_mode_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) rhport; - (void) ep_addr; - (void) result; - (void) xferred_bytes; - return true; -} - - #endif diff --git a/src/class/dfu/dfu_mode_device.h b/src/class/dfu/dfu_mode_device.h index 32bf58bbd..11b748c3b 100644 --- a/src/class/dfu/dfu_mode_device.h +++ b/src/class/dfu/dfu_mode_device.h @@ -122,7 +122,6 @@ void dfu_mode_init(void); void dfu_mode_reset(uint8_t rhport); uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool dfu_mode_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus diff --git a/src/device/usbd.c b/src/device/usbd.c index 91838b39c..de0e7b0b7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -194,7 +194,7 @@ static usbd_class_driver_t const _usbd_driver[] = .reset = dfu_mode_reset, .open = dfu_mode_open, .control_xfer_cb = dfu_mode_control_xfer_cb, - .xfer_cb = dfu_mode_xfer_cb, + .xfer_cb = NULL, .sof = NULL }, #endif -- cgit v1.3.1 From c39b7b8177acbab23e82fee295d5f3205aa9752c Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 5 Apr 2021 17:52:33 -0400 Subject: Add DFU runtime and mode "class" With the runtime and mode portions in separate classes, a single application should only be building with one or the other enabled. In some applications both might be desired at build time. The CFG_TUD_DFU_RUNTIME_AND_MODE option creates a DFU class, which asks the application which mode to initialize to. This allows a runtime change between RT and DFU mode, by just reinitializing tusb. --- src/class/dfu/dfu_mode_device.c | 4 +- src/class/dfu/dfu_rt_and_mode_device.c | 114 +++++++++++++++++++++++++++++++++ src/class/dfu/dfu_rt_and_mode_device.h | 57 +++++++++++++++++ src/class/dfu/dfu_rt_device.c | 2 +- src/device/usbd.c | 12 ++++ src/tusb.h | 6 ++ src/tusb_option.h | 10 +++ 7 files changed, 202 insertions(+), 3 deletions(-) create mode 100644 src/class/dfu/dfu_rt_and_mode_device.c create mode 100644 src/class/dfu/dfu_rt_and_mode_device.h (limited to 'src') diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c index 59cea7673..0b80b103d 100644 --- a/src/class/dfu/dfu_mode_device.c +++ b/src/class/dfu/dfu_mode_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) || (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) #include "dfu_mode_device.h" #include "device/usbd_pvt.h" @@ -590,4 +590,4 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const } - #endif +#endif diff --git a/src/class/dfu/dfu_rt_and_mode_device.c b/src/class/dfu/dfu_rt_and_mode_device.c new file mode 100644 index 000000000..d555a1d58 --- /dev/null +++ b/src/class/dfu/dfu_rt_and_mode_device.c @@ -0,0 +1,114 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) + +#include "dfu_rt_and_mode_device.h" + +#include "dfu_mode_device.h" +#include "dfu_rt_device.h" +#include "device/usbd_pvt.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +typedef struct +{ + void (* init ) (void); + void (* reset ) (uint8_t rhport); + uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); + bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +} dfu_local_driver_t; + +static dfu_local_driver_t ctx = +{ + .init = NULL, + .reset = NULL, + .open = NULL, + .control_xfer_cb = NULL +}; + +static dfu_protocol_type_t mode = 0x00; + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void dfu_init(void) +{ + mode = dfu_init_in_mode_cb(); + + switch (mode) + { + case DFU_PROTOCOL_RT: + { + ctx.init = dfu_rtd_init; + ctx.reset = dfu_rtd_reset; + ctx.open = dfu_rtd_open; + ctx.control_xfer_cb = dfu_rtd_control_xfer_cb; + } + break; + + case DFU_PROTOCOL_DFU: + { + ctx.init = dfu_mode_init; + ctx.reset = dfu_mode_reset; + ctx.open = dfu_mode_open; + ctx.control_xfer_cb = dfu_mode_control_xfer_cb; + } + break; + + default: + { + TU_LOG2(" DFU Unexpected mode: %u\r\n", mode); + } + break; + } + + ctx.init(); +} + +void dfu_reset(uint8_t rhport) +{ + ctx.reset(rhport); +} + +uint16_t dfu_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + return ctx.open(rhport, itf_desc, max_len); +} + +bool dfu_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + return ctx.control_xfer_cb(rhport, stage, request); +} + +#endif diff --git a/src/class/dfu/dfu_rt_and_mode_device.h b/src/class/dfu/dfu_rt_and_mode_device.h new file mode 100644 index 000000000..9734a031c --- /dev/null +++ b/src/class/dfu/dfu_rt_and_mode_device.h @@ -0,0 +1,57 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_DFU_RT_AND_MODE_DEVICE_H_ +#define _TUSB_DFU_RT_AND_MODE_DEVICE_H_ + +#include "common/tusb_common.h" +#include "device/usbd.h" +#include "dfu.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ +// Invoked when the driver needs to determine the callbacks to use +dfu_protocol_type_t dfu_init_in_mode_cb(); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void dfu_init(void); +void dfu_reset(uint8_t rhport); +uint16_t dfu_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DFU_RT_AND_MODE_DEVICE_H_ */ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 806bfba2e..d1d028d69 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) || (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) #include "dfu_rt_device.h" #include "device/usbd_pvt.h" diff --git a/src/device/usbd.c b/src/device/usbd.c index de0e7b0b7..6f2262feb 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -199,6 +199,18 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif + #if CFG_TUD_DFU_RUNTIME_AND_MODE + { + DRIVER_NAME("DFU-RT-MODE") + .init = dfu_init, + .reset = dfu_reset, + .open = dfu_open, + .control_xfer_cb = dfu_control_xfer_cb, + .xfer_cb = NULL, + .sof = NULL + }, + #endif + #if CFG_TUD_NET { DRIVER_NAME("NET") diff --git a/src/tusb.h b/src/tusb.h index c9558515c..6eab4bee2 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -100,6 +100,12 @@ #include "class/dfu/dfu_mode_device.h" #endif + #if CFG_TUD_DFU_RUNTIME_AND_MODE + #include "class/dfu/dfu_rt_and_mode_device.h" + #include "class/dfu/dfu_rt_device.h" + #include "class/dfu/dfu_mode_device.h" + #endif + #if CFG_TUD_NET #include "class/net/net_device.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 3cd3df9f2..4c2204964 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -241,6 +241,10 @@ #define CFG_TUD_DFU_MODE 0 #endif +#ifndef CFG_TUD_DFU_RUNTIME_AND_MODE + #define CFG_TUD_DFU_RUNTIME_AND_MODE 0 +#endif + #ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 64 #endif @@ -285,6 +289,12 @@ #error Control Endpoint Max Packet Size cannot be larger than 64 #endif +#if (CFG_TUD_DFU_RUNTIME_AND_MODE && CFG_TUD_DFU_RUNTIME) \ + || (CFG_TUD_DFU_RUNTIME_AND_MODE && CFG_TUD_DFU_MODE) \ + || (CFG_TUD_DFU_RUNTIME && CFG_TUD_DFU_MODE) + #error Only one of CFG_TUD_DFU_RUNTIME_AND_MODE, CFG_TUD_DFU_RUNTIME, and CFG_TUD_DFU_MODE can be enabled in a single build +#endif + #endif /* _TUSB_OPTION_H_ */ /** @} */ -- cgit v1.3.1 From 8b79040c3864f9d76bba90b8660464f1821209a5 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Apr 2021 15:34:50 +0700 Subject: code format --- examples/device/audio_test/src/main.c | 142 ++++++++++++++++++---------------- src/class/audio/audio.h | 16 ---- 2 files changed, 77 insertions(+), 81 deletions(-) (limited to 'src') diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index f01a5a183..4de515b3b 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -207,7 +207,6 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * mute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); - return true; case AUDIO_FU_CTRL_VOLUME: @@ -217,8 +216,7 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * volume[channelNum] = ((audio_control_cur_2_t*) pBuff)->bCur; TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); - - return true; + return true; // Unknown/Unsupported control default: @@ -275,96 +273,110 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * // Input terminal (Microphone input) if (entityID == 1) { - switch (ctrlSel) + switch ( ctrlSel ) { - case AUDIO_TE_CTRL_CONNECTOR:; - // The terminal connector control only has a get request with only the CUR attribute. - - audio_desc_channel_cluster_t ret; + case AUDIO_TE_CTRL_CONNECTOR: + { + // The terminal connector control only has a get request with only the CUR attribute. + audio_desc_channel_cluster_t ret; - // Those are dummy values for now - ret.bNrChannels = 1; - ret.bmChannelConfig = 0; - ret.iChannelNames = 0; + // Those are dummy values for now + ret.bNrChannels = 1; + ret.bmChannelConfig = 0; + ret.iChannelNames = 0; - TU_LOG2(" Get terminal connector\r\n"); + TU_LOG2(" Get terminal connector\r\n"); - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*)&ret, sizeof(ret)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + } + break; - // Unknown/Unsupported control selector - default: TU_BREAKPOINT(); return false; + // Unknown/Unsupported control selector + default: + TU_BREAKPOINT(); + return false; } } // Feature unit if (entityID == 2) { - switch (ctrlSel) + switch ( ctrlSel ) { case AUDIO_FU_CTRL_MUTE: - // Audio control mute cur parameter block consists of only one byte - we thus can send it right away - // There does not exist a range parameter block for mute - TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); - return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); + // Audio control mute cur parameter block consists of only one byte - we thus can send it right away + // There does not exist a range parameter block for mute + TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); case AUDIO_FU_CTRL_VOLUME: + switch ( p_request->bRequest ) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); - switch (p_request->bRequest) - { - case AUDIO_CS_REQ_CUR: - TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); - return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); - case AUDIO_CS_REQ_RANGE: - TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); - // Copy values - only for testing - better is version below - audio_control_range_2_n_t(1) ret; + // Copy values - only for testing - better is version below + audio_control_range_2_n_t(1) + ret; - ret.wNumSubRanges = 1; - ret.subrange[0].bMin = -90; // -90 dB - ret.subrange[0].bMax = 90; // +90 dB - ret.subrange[0].bRes = 1; // 1 dB steps + ret.wNumSubRanges = 1; + ret.subrange[0].bMin = -90; // -90 dB + ret.subrange[0].bMax = 90; // +90 dB + ret.subrange[0].bRes = 1; // 1 dB steps - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*)&ret, sizeof(ret)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); - // Unknown/Unsupported control - default: TU_BREAKPOINT(); return false; - } + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; - // Unknown/Unsupported control - default: TU_BREAKPOINT(); return false; + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; } } // Clock Source unit - if (entityID == 4) + if ( entityID == 4 ) { - switch (ctrlSel) + switch ( ctrlSel ) { case AUDIO_CS_CTRL_SAM_FREQ: - - // channelNum is always zero in this case - - switch (p_request->bRequest) - { - case AUDIO_CS_REQ_CUR: - TU_LOG2(" Get Sample Freq.\r\n"); - return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); - case AUDIO_CS_REQ_RANGE: - TU_LOG2(" Get Sample Freq. range\r\n"); - return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); - - // Unknown/Unsupported control - default: TU_BREAKPOINT(); return false; - } - - case AUDIO_CS_CTRL_CLK_VALID: - // Only cur attribute exists for this request - TU_LOG2(" Get Sample Freq. valid\r\n"); - return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); - - // Unknown/Unsupported control - default: TU_BREAKPOINT(); return false; + // channelNum is always zero in this case + switch ( p_request->bRequest ) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Sample Freq.\r\n"); + return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); + + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Sample Freq. range\r\n"); + return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; + + case AUDIO_CS_CTRL_CLK_VALID: + // Only cur attribute exists for this request + TU_LOG2(" Get Sample Freq. valid\r\n"); + return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; } } diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 2c6cd260a..936f09104 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -481,15 +481,6 @@ typedef enum AUDIO_EXT_FORMAT_TYPE_III = 0x83, } audio_format_type_t; -//#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00 -//#define AUDIO_FORMAT_TYPE_I 0x01 -//#define AUDIO_FORMAT_TYPE_II 0x02 -//#define AUDIO_FORMAT_TYPE_III 0x03 -//#define AUDIO_FORMAT_TYPE_IV 0x04 -//#define AUDIO_EXT_FORMAT_TYPE_I 0x81 -//#define AUDIO_EXT_FORMAT_TYPE_II 0x82 -//#define AUDIO_EXT_FORMAT_TYPE_III 0x83 - // A.2.1 - Audio Class-Audio Data Format Type I UAC2 typedef enum { @@ -501,13 +492,6 @@ typedef enum AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, } audio_data_format_type_I_t; -//#define AUDIO_DATA_FORMAT_TYPE_I_PCM ((uint32_t) (1 << 0)) -//#define AUDIO_DATA_FORMAT_TYPE_I_PCM8 ((uint32_t) (1 << 1)) -//#define AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT ((uint32_t) (1 << 2)) -//#define AUDIO_DATA_FORMAT_TYPE_I_ALAW ((uint32_t) (1 << 3)) -//#define AUDIO_DATA_FORMAT_TYPE_I_MULAW ((uint32_t) (1 << 4)) -//#define AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA 0x100000000 - /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification /// Isochronous End Point Attributes -- cgit v1.3.1 From 1d20c84798305043c2783725a496070c39d2d966 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Tue, 6 Apr 2021 19:32:01 +0700 Subject: add tu_unaligned_read32/write32 (#772) * add tu_unaligned_read32/write32 * added tu_unaligned_read16/write16 * add TU_ATTR_ALWAYS_INLINE, add to most of simple inline function --- src/common/tusb_common.h | 109 ++++++++++++++++++++++++++++++--------------- src/common/tusb_compiler.h | 8 ++-- src/common/tusb_verify.h | 4 +- src/tusb_option.h | 16 +++++-- 4 files changed, 91 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index f10be88ab..147856d45 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -76,51 +76,55 @@ #include "tusb_timeout.h" #include "tusb_types.h" -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ +//------------- Mem -------------// #define tu_memclr(buffer, size) memset((buffer), 0, (size)) #define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) -static inline uint32_t tu_u32(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) +//------------- Bytes -------------// +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) { - return ( ((uint32_t) b1) << 24) + ( ((uint32_t) b2) << 16) + ( ((uint32_t) b3) << 8) + b4; + return ( ((uint32_t) b1) << 24) | ( ((uint32_t) b2) << 16) | ( ((uint32_t) b3) << 8) | b4; } -static inline uint16_t tu_u16(uint8_t high, uint8_t low) +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) { - return (uint16_t)((((uint16_t) high) << 8) + low); + return (uint16_t) ((((uint16_t) high) << 8) | low); } -static inline uint8_t tu_u16_high(uint16_t u16) { return (uint8_t) (((uint16_t) (u16 >> 8)) & 0x00ff); } -static inline uint8_t tu_u16_low (uint16_t u16) { return (uint8_t) (u16 & 0x00ff); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t u16) { return (uint8_t) (((uint16_t) (u16 >> 8)) & 0x00ff); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t u16) { return (uint8_t) (u16 & 0x00ff); } -// Min -static inline uint8_t tu_min8 (uint8_t x, uint8_t y ) { return (x < y) ? x : y; } -static inline uint16_t tu_min16 (uint16_t x, uint16_t y) { return (x < y) ? x : y; } -static inline uint32_t tu_min32 (uint32_t x, uint32_t y) { return (x < y) ? x : y; } +//------------- Bits -------------// +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_set (uint32_t value, uint8_t pos) { return value | TU_BIT(pos); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_clear(uint32_t value, uint8_t pos) { return value & (~TU_BIT(pos)); } +TU_ATTR_ALWAYS_INLINE static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value & TU_BIT(pos)) ? true : false; } -// Max -static inline uint8_t tu_max8 (uint8_t x, uint8_t y ) { return (x > y) ? x : y; } -static inline uint16_t tu_max16 (uint16_t x, uint16_t y) { return (x > y) ? x : y; } -static inline uint32_t tu_max32 (uint32_t x, uint32_t y) { return (x > y) ? x : y; } +//------------- Min -------------// +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_min8 (uint8_t x, uint8_t y ) { return (x < y) ? x : y; } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_min16 (uint16_t x, uint16_t y) { return (x < y) ? x : y; } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_min32 (uint32_t x, uint32_t y) { return (x < y) ? x : y; } -// Align -static inline uint32_t tu_align(uint32_t value, uint32_t alignment) +//------------- Max -------------// +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_max8 (uint8_t x, uint8_t y ) { return (x > y) ? x : y; } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_max16 (uint16_t x, uint16_t y) { return (x > y) ? x : y; } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_max32 (uint32_t x, uint32_t y) { return (x > y) ? x : y; } + +//------------- Align -------------// +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align(uint32_t value, uint32_t alignment) { return value & ((uint32_t) ~(alignment-1)); } -static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); } -static inline uint32_t tu_align16 (uint32_t value) { return (value & 0xFFFFFFF0UL); } -static inline uint32_t tu_align4k (uint32_t value) { return (value & 0xFFFFF000UL); } -static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align16 (uint32_t value) { return (value & 0xFFFFFFF0UL); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align4k (uint32_t value) { return (value & 0xFFFFF000UL); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); } //------------- Mathematics -------------// -static inline uint32_t tu_abs(int32_t value) { return (uint32_t)((value < 0) ? (-value) : value); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_abs(int32_t value) { return (uint32_t)((value < 0) ? (-value) : value); } -/// inclusive range checking -static inline bool tu_within(uint32_t lower, uint32_t value, uint32_t upper) +/// inclusive range checking TODO remove +TU_ATTR_ALWAYS_INLINE static inline bool tu_within(uint32_t lower, uint32_t value, uint32_t upper) { return (lower <= value) && (value <= upper); } @@ -130,18 +134,49 @@ static inline bool tu_within(uint32_t lower, uint32_t value, uint32_t upper) static inline uint8_t tu_log2(uint32_t value) { uint8_t result = 0; - - while (value >>= 1) - { - result++; - } + while (value >>= 1) { result++; } return result; } -// Bit -static inline uint32_t tu_bit_set (uint32_t value, uint8_t pos) { return value | TU_BIT(pos); } -static inline uint32_t tu_bit_clear(uint32_t value, uint8_t pos) { return value & (~TU_BIT(pos)); } -static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value & TU_BIT(pos)) ? true : false; } +//------------- Unaligned Access -------------// +#if TUP_ARCH_STRICT_ALIGN + +typedef struct { uint16_t val; } TU_ATTR_PACKED tu_unaligned_uint16_t; +typedef struct { uint32_t val; } TU_ATTR_PACKED tu_unaligned_uint32_t; + +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem) +{ + tu_unaligned_uint32_t const* ua32 = (tu_unaligned_uint32_t const*) mem; + return ua32->val; +} + +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value) +{ + tu_unaligned_uint32_t* ua32 = (tu_unaligned_uint32_t*) mem; + ua32->val = value; +} + +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem) +{ + tu_unaligned_uint16_t const* ua16 = (tu_unaligned_uint16_t const*) mem; + return ua16->val; +} + +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value) +{ + tu_unaligned_uint16_t* ua16 = (tu_unaligned_uint16_t*) mem; + ua16->val = value; +} + +#else + +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32 (const void* mem ) { return *((uint32_t*) mem); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16 (const void* mem ) { return *((uint16_t*) mem); } + +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32 (void* mem, uint32_t value ) { *((uint32_t*) mem) = value; } +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16 (void* mem, uint16_t value ) { *((uint16_t*) mem) = value; } + +#endif /*------------------------------------------------------------------*/ /* Count number of arguments of __VA_ARGS__ @@ -153,9 +188,9 @@ static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value *------------------------------------------------------------------*/ #ifndef TU_ARGS_NUM -#define TU_ARGS_NUM(...) NARG_(_0, ##__VA_ARGS__,_RSEQ_N()) +#define TU_ARGS_NUM(...) _TU_NARG(_0, ##__VA_ARGS__,_RSEQ_N()) -#define NARG_(...) _GET_NTH_ARG(__VA_ARGS__) +#define _TU_NARG(...) _GET_NTH_ARG(__VA_ARGS__) #define _GET_NTH_ARG( \ _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 22c8366ab..679060b20 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -61,12 +61,14 @@ //--------------------------------------------------------------------+ // Compiler porting with Attribute and Endian //--------------------------------------------------------------------+ + +// TODO refactor since __attribute__ is supported across many compiler #if defined(__GNUC__) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) #define TU_ATTR_PACKED __attribute__ ((packed)) - #define TU_ATTR_PREPACKED #define TU_ATTR_WEAK __attribute__ ((weak)) + #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used @@ -85,8 +87,8 @@ #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) #define TU_ATTR_PACKED __attribute__ ((packed)) - #define TU_ATTR_PREPACKED #define TU_ATTR_WEAK __attribute__ ((weak)) + #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) @@ -106,8 +108,8 @@ #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) #define TU_ATTR_PACKED __attribute__ ((packed)) - #define TU_ATTR_PREPACKED #define TU_ATTR_WEAK __attribute__ ((weak)) + #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 8b724aef8..542809899 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -36,7 +36,6 @@ * as C++ for the sake of code simplicity. Beware of a headache macro * manipulation that you are told to stay away. * - * * This contains macros for both VERIFY and ASSERT: * * VERIFY: Used when there is an error condition which is not the @@ -50,9 +49,8 @@ * quickly. One example would be adding assertions in library * function calls to confirm a function's (untainted) * parameters are valid. - * * - * The difference in behaviour is that ASSERT triggers a breakpoint while + * The difference in behavior is that ASSERT triggers a breakpoint while * verify does not. * * #define TU_VERIFY(cond) if(cond) return false; diff --git a/src/tusb_option.h b/src/tusb_option.h index 644208ab4..56950d364 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -124,7 +124,6 @@ #define OPT_OS_RTTHREAD 6 ///< RT-Thread /** @} */ - // Allow to use command line to change the config name/location #ifdef CFG_TUSB_CONFIG_FILE #include CFG_TUSB_CONFIG_FILE @@ -132,8 +131,6 @@ #include "tusb_config.h" #endif - - /** \addtogroup group_configuration * @{ */ @@ -277,6 +274,19 @@ //------------- CLASS -------------// #endif // TUSB_OPT_HOST_ENABLED +//--------------------------------------------------------------------+ +// Port Options +// TUP for TinyUSB Port (can be renamed) +//--------------------------------------------------------------------+ + +// TUP_ARCH_STRICT_ALIGN if arch cannot access unaligned memory + +// ARMv7+ (M3-M7, M23-M33) can access unaligned memory +#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) + #define TUP_ARCH_STRICT_ALIGN 0 +#else + #define TUP_ARCH_STRICT_ALIGN 1 +#endif //------------------------------------------------------------------ // Configuration Validation -- cgit v1.3.1 From 58bab86d794aad8979bd2557bdc81f44d0731a97 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Apr 2021 21:09:23 +0700 Subject: minor clean up --- src/class/audio/audio_device.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index d4793c9d8..81e0024d7 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -496,17 +496,17 @@ static inline bool tud_audio_mounted(void) #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -static inline uint16_t tud_audio_available (void) +static inline uint16_t tud_audio_available(void) { return tud_audio_n_available(0); } -static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_read(void* buffer, uint16_t bufsize) { return tud_audio_n_read(0, buffer, bufsize); } -static inline bool tud_audio_clear_ep_out_ff (void) +static inline bool tud_audio_clear_ep_out_ff(void) { return tud_audio_n_clear_ep_out_ff(0); } @@ -515,17 +515,17 @@ static inline bool tud_audio_clear_ep_out_ff (void) #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId) +static inline bool tud_audio_clear_rx_support_ff(uint8_t channelId) { return tud_audio_n_clear_rx_support_ff(0, channelId); } -static inline uint16_t tud_audio_available_support_ff (uint8_t channelId) +static inline uint16_t tud_audio_available_support_ff(uint8_t channelId) { return tud_audio_n_available_support_ff(0, channelId); } -static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_read_support_ff(uint8_t channelId, void* buffer, uint16_t bufsize) { return tud_audio_n_read_support_ff(0, channelId, buffer, bufsize); } @@ -536,12 +536,12 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -static inline uint16_t tud_audio_write (const void * data, uint16_t len) +static inline uint16_t tud_audio_write(const void * data, uint16_t len) { return tud_audio_n_write(0, data, len); } -static inline bool tud_audio_clear_ep_in_ff (void) +static inline bool tud_audio_clear_ep_in_ff(void) { return tud_audio_n_clear_ep_in_ff(0); } @@ -550,17 +550,17 @@ static inline bool tud_audio_clear_ep_in_ff (void) #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -static inline uint16_t tud_audio_flush_tx_support_ff (void) +static inline uint16_t tud_audio_flush_tx_support_ff(void) { return tud_audio_n_flush_tx_support_ff(0); } -static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId) +static inline uint16_t tud_audio_clear_tx_support_ff(uint8_t channelId) { return tud_audio_n_clear_tx_support_ff(0, channelId); } -static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len) +static inline uint16_t tud_audio_write_support_ff(uint8_t channelId, const void * data, uint16_t len) { return tud_audio_n_write_support_ff(0, channelId, data, len); } @@ -584,11 +584,11 @@ static inline bool tud_audio_fb_set(uint32_t feedback) //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void audiod_init (void); -void audiod_reset (uint8_t rhport); -uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool audiod_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void audiod_init (void); +void audiod_reset (uint8_t rhport); +uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus } -- cgit v1.3.1 From d82ee2f8c04342390d2c754f14ad13673a7f6c11 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Apr 2021 23:12:04 +0700 Subject: refactor _ff_pull_n() with const addr --- src/common/tusb_fifo.c | 77 ++++++++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 1b7f64447..184807bef 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -139,37 +139,30 @@ static void _tu_fifo_read_from_const_src_ptr_in_full_words(void * dst, const voi } // Intended to be used to write to hardware USB FIFO in e.g. STM32 where all data is written to a constant address in full word copies -static void _tu_fifo_write_to_const_dst_ptr_in_full_words(void * dst, const void * src, uint16_t len) +static void _ff_pull_const_addr_in_full_words(void * dst, const uint8_t * src, uint16_t len) { volatile uint32_t * tx_fifo = (volatile uint32_t *) dst; - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; - - unaligned_uint32_t* src_una = (unaligned_uint32_t *) src; - // Pushing full available 32 bit words to FIFO uint16_t full_words = len >> 2; while(full_words--) { - *tx_fifo = src_una->val; - src_una++; + *tx_fifo = tu_unaligned_read32(src); + src += 4; } // Write the remaining 1-3 bytes into FIFO uint8_t bytes_rem = len & 0x03; - if(bytes_rem){ - uint8_t * src_u8 = (uint8_t *) src_una; - uint32_t tmp = 0; - uint8_t * dst_u8 = (uint8_t *)&tmp; + if(bytes_rem) + { + uint32_t tmp32 = 0; + uint8_t* dst8 = (uint8_t*) &tmp32; while(bytes_rem--) { - *dst_u8++ = *src_u8++; + *dst8++ = *src++; } - *tx_fifo = tmp; + *tx_fifo = tmp32; } } @@ -270,12 +263,12 @@ static inline void _ff_pull(tu_fifo_t* f, void * p_buffer, uint16_t rRel) } // get n items from FIFO WITHOUT updating read pointer -static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel, tu_fifo_copy_mode_t copy_mode) +static void _ff_pull_n(tu_fifo_t* f, uint8_t* p_buffer, uint16_t n, uint16_t rRel, tu_fifo_copy_mode_t copy_mode) { switch (copy_mode) { case TU_FIFO_COPY_INC: - if(n <= f->depth-rRel) + if ( n <= f->depth - rRel ) { // Linear mode only memcpy(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); @@ -289,68 +282,60 @@ static void _ff_pull_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t rRel, memcpy(p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size); // Read data wrapped part - memcpy((uint8_t*)p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size); + memcpy(p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size); } break; case TU_FIFO_COPY_CST_FULL_WORDS: - - if(n <= f->depth-rRel) + if ( n <= f->depth - rRel ) { // Linear mode only - _tu_fifo_write_to_const_dst_ptr_in_full_words(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); + _ff_pull_const_addr_in_full_words(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); } else { + // since it is const address, we don't increase p_buffer + volatile uint32_t * tx_fifo = (volatile uint32_t *) p_buffer; + uint8_t* src = f->buffer + (rRel * f->item_size); + // Wrap around case uint16_t nLin = (f->depth - rRel) * f->item_size; - uint16_t nWrap = (n - nLin) * f->item_size; - - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; + uint16_t nLin_4n = nLin & 0xFFFC; - unaligned_uint32_t* src = (unaligned_uint32_t*)(f->buffer + (rRel * f->item_size)); + uint16_t nWrap = (n - nLin) * f->item_size; - volatile uint32_t * tx_fifo = (volatile uint32_t *) p_buffer; + // Read data from linear part of buffer + _ff_pull_const_addr_in_full_words(p_buffer, src, nLin_4n); - // Pushing full available 32 bit words to FIFO - uint16_t full_words = nLin >> 2; - while(full_words--) - { - *tx_fifo = src->val; - src++; - } + src += nLin_4n; - uint8_t * src_u8; - uint8_t rem = nLin & 0x03; + // There could be odd 1-3 bytes before the wrap-around boundary // Handle wrap around - do it manually as these are only 4 bytes and its faster without memcpy + uint8_t rem = nLin & 0x03; if (rem > 0) { - src_u8 = (uint8_t *) src; uint8_t remrem = tu_min16(nWrap, 4-rem); nWrap -= remrem; uint32_t tmp; uint8_t * dst_u8 = (uint8_t *)&tmp; while(rem--) { - *dst_u8++ = *src_u8++; + *dst_u8++ = *src++; } - src_u8 = f->buffer; + src = f->buffer; while(remrem--) { - *dst_u8++ = *src_u8++; + *dst_u8++ = *src++; } *tx_fifo = tmp; } else { - src_u8 = f->buffer; + src = f->buffer; // wrap around to beginning } // Final linear part - if (nWrap > 0) _tu_fifo_write_to_const_dst_ptr_in_full_words(p_buffer, src_u8, nWrap); + if (nWrap > 0) _ff_pull_const_addr_in_full_words(p_buffer, src, nWrap); } break; } @@ -482,7 +467,7 @@ static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffe uint16_t rRel = get_relative_pointer(f, rAbs, offset); // Peek data - _ff_pull_n(f, p_buffer, n, rRel, copy_mode); + _ff_pull_n(f, (uint8_t*) p_buffer, n, rRel, copy_mode); return n; } -- cgit v1.3.1 From a3c06aa7bc66c33c2a4801426934ced1ed72ce6e Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Apr 2021 23:39:39 +0700 Subject: more clean up for _ff_pull_const_addr_in_full_words() --- src/common/tusb_fifo.c | 62 ++++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 184807bef..0b5b6854f 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -265,68 +265,68 @@ static inline void _ff_pull(tu_fifo_t* f, void * p_buffer, uint16_t rRel) // get n items from FIFO WITHOUT updating read pointer static void _ff_pull_n(tu_fifo_t* f, uint8_t* p_buffer, uint16_t n, uint16_t rRel, tu_fifo_copy_mode_t copy_mode) { + uint16_t const nLin = f->depth - rRel; + uint16_t const nWrap = n - nLin; // only used if wrapped + switch (copy_mode) { case TU_FIFO_COPY_INC: - if ( n <= f->depth - rRel ) + if ( n <= nLin ) { - // Linear mode only + // Linear only memcpy(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); } else { // Wrap around - uint16_t nLin = f->depth - rRel; // Read data from linear part of buffer memcpy(p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size); // Read data wrapped part - memcpy(p_buffer + nLin*f->item_size, f->buffer, (n - nLin) * f->item_size); + memcpy(p_buffer + nLin*f->item_size, f->buffer, nWrap*f->item_size); } - break; + break; case TU_FIFO_COPY_CST_FULL_WORDS: - if ( n <= f->depth - rRel ) + if ( n <= nLin ) { // Linear mode only _ff_pull_const_addr_in_full_words(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); } else { - // since it is const address, we don't increase p_buffer - volatile uint32_t * tx_fifo = (volatile uint32_t *) p_buffer; - uint8_t* src = f->buffer + (rRel * f->item_size); - // Wrap around case - uint16_t nLin = (f->depth - rRel) * f->item_size; - uint16_t nLin_4n = nLin & 0xFFFC; - uint16_t nWrap = (n - nLin) * f->item_size; + uint16_t nLin_bytes = nLin * f->item_size; + uint16_t nWrap_bytes = nWrap * f->item_size; - // Read data from linear part of buffer - _ff_pull_const_addr_in_full_words(p_buffer, src, nLin_4n); + uint8_t* src = f->buffer + (rRel * f->item_size); - src += nLin_4n; + // Read data from linear part of buffer + uint16_t nLin_4n_bytes = nLin_bytes & 0xFFFC; + _ff_pull_const_addr_in_full_words(p_buffer, src, nLin_4n_bytes); + src += nLin_4n_bytes; // There could be odd 1-3 bytes before the wrap-around boundary // Handle wrap around - do it manually as these are only 4 bytes and its faster without memcpy - uint8_t rem = nLin & 0x03; + volatile uint32_t * tx_fifo = (volatile uint32_t *) p_buffer; + uint8_t rem = nLin_bytes & 0x03; if (rem > 0) { - uint8_t remrem = tu_min16(nWrap, 4-rem); - nWrap -= remrem; + uint8_t remrem = tu_min16(nWrap_bytes, 4-rem); + nWrap_bytes -= remrem; + uint32_t tmp; uint8_t * dst_u8 = (uint8_t *)&tmp; - while(rem--) - { - *dst_u8++ = *src++; - } + + // Get 1-3 bytes before wrapped boundary + while(rem--) *dst_u8++ = *src++; + + // Get more bytes from beginning to form a complete word src = f->buffer; - while(remrem--) - { - *dst_u8++ = *src++; - } + while(remrem--) *dst_u8++ = *src++; + *tx_fifo = tmp; } else @@ -334,10 +334,12 @@ static void _ff_pull_n(tu_fifo_t* f, uint8_t* p_buffer, uint16_t n, uint16_t rRe src = f->buffer; // wrap around to beginning } - // Final linear part - if (nWrap > 0) _ff_pull_const_addr_in_full_words(p_buffer, src, nWrap); + // Read data wrapped part + if (nWrap_bytes > 0) _ff_pull_const_addr_in_full_words(p_buffer, src, nWrap_bytes); } - break; + break; + + default: break; } } // Advance an absolute pointer -- cgit v1.3.1 From 8ac156622d6e1021cc96055da9036d50b55e936d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Apr 2021 00:38:12 +0700 Subject: fix cast-align warning --- src/common/tusb_fifo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 0b5b6854f..4061514a0 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -263,7 +263,7 @@ static inline void _ff_pull(tu_fifo_t* f, void * p_buffer, uint16_t rRel) } // get n items from FIFO WITHOUT updating read pointer -static void _ff_pull_n(tu_fifo_t* f, uint8_t* p_buffer, uint16_t n, uint16_t rRel, tu_fifo_copy_mode_t copy_mode) +static void _ff_pull_n(tu_fifo_t* f, void* p_buffer, uint16_t n, uint16_t rRel, tu_fifo_copy_mode_t copy_mode) { uint16_t const nLin = f->depth - rRel; uint16_t const nWrap = n - nLin; // only used if wrapped @@ -284,7 +284,7 @@ static void _ff_pull_n(tu_fifo_t* f, uint8_t* p_buffer, uint16_t n, uint16_t rRe memcpy(p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size); // Read data wrapped part - memcpy(p_buffer + nLin*f->item_size, f->buffer, nWrap*f->item_size); + memcpy((uint8_t*) p_buffer + nLin*f->item_size, f->buffer, nWrap*f->item_size); } break; @@ -469,7 +469,7 @@ static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffe uint16_t rRel = get_relative_pointer(f, rAbs, offset); // Peek data - _ff_pull_n(f, (uint8_t*) p_buffer, n, rRel, copy_mode); + _ff_pull_n(f, p_buffer, n, rRel, copy_mode); return n; } -- cgit v1.3.1 From d0fa4d5189a6f75a3028897b04e9c30481689b59 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Apr 2021 12:24:24 +0700 Subject: rename --- src/common/tusb_fifo.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 4061514a0..99f107581 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -105,7 +105,7 @@ static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) // Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address // Code adapted from dcd_synopsis.c // TODO generalize with configurable 1 byte or 4 byte each read -static void _tu_fifo_read_from_const_src_ptr_in_full_words(void * dst, const void * src, uint16_t len) +static void _ff_push_const_addr(void * dst, const void * src, uint16_t len) { volatile uint32_t * rx_fifo = (volatile uint32_t *) src; @@ -139,7 +139,7 @@ static void _tu_fifo_read_from_const_src_ptr_in_full_words(void * dst, const voi } // Intended to be used to write to hardware USB FIFO in e.g. STM32 where all data is written to a constant address in full word copies -static void _ff_pull_const_addr_in_full_words(void * dst, const uint8_t * src, uint16_t len) +static void _ff_pull_const_addr(void * dst, const uint8_t * src, uint16_t len) { volatile uint32_t * tx_fifo = (volatile uint32_t *) dst; @@ -200,7 +200,7 @@ static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRe if(n <= f->depth-wRel) { // Linear mode only - _tu_fifo_read_from_const_src_ptr_in_full_words(f->buffer + (wRel * f->item_size), data, n*f->item_size); + _ff_push_const_addr(f->buffer + (wRel * f->item_size), data, n*f->item_size); } else { @@ -250,7 +250,7 @@ static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRe } // Final part - if (nWrap > 0) _tu_fifo_read_from_const_src_ptr_in_full_words(dst_u8, data, nWrap); + if (nWrap > 0) _ff_push_const_addr(dst_u8, data, nWrap); } break; } @@ -292,7 +292,7 @@ static void _ff_pull_n(tu_fifo_t* f, void* p_buffer, uint16_t n, uint16_t rRel, if ( n <= nLin ) { // Linear mode only - _ff_pull_const_addr_in_full_words(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); + _ff_pull_const_addr(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); } else { @@ -305,7 +305,7 @@ static void _ff_pull_n(tu_fifo_t* f, void* p_buffer, uint16_t n, uint16_t rRel, // Read data from linear part of buffer uint16_t nLin_4n_bytes = nLin_bytes & 0xFFFC; - _ff_pull_const_addr_in_full_words(p_buffer, src, nLin_4n_bytes); + _ff_pull_const_addr(p_buffer, src, nLin_4n_bytes); src += nLin_4n_bytes; // There could be odd 1-3 bytes before the wrap-around boundary @@ -335,7 +335,7 @@ static void _ff_pull_n(tu_fifo_t* f, void* p_buffer, uint16_t n, uint16_t rRel, } // Read data wrapped part - if (nWrap_bytes > 0) _ff_pull_const_addr_in_full_words(p_buffer, src, nWrap_bytes); + if (nWrap_bytes > 0) _ff_pull_const_addr(p_buffer, src, nWrap_bytes); } break; -- cgit v1.3.1 From d6737fb5fe9b2f51767c62b6e8d4e9c526d579ae Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Apr 2021 12:34:00 +0700 Subject: use tu_unaligned_write32() for _ff_push_const_addr --- src/common/tusb_fifo.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 99f107581..5f8623786 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -105,35 +105,28 @@ static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) // Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address // Code adapted from dcd_synopsis.c // TODO generalize with configurable 1 byte or 4 byte each read -static void _ff_push_const_addr(void * dst, const void * src, uint16_t len) +static void _ff_push_const_addr(uint8_t * dst, const void * src, uint16_t len) { volatile uint32_t * rx_fifo = (volatile uint32_t *) src; - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; - - unaligned_uint32_t* dst_una = (unaligned_uint32_t*)dst; - // Reading full available 32 bit words from FIFO uint16_t full_words = len >> 2; while(full_words--) { - dst_una->val = *rx_fifo; - dst_una++; + tu_unaligned_write32(dst, *rx_fifo); + dst += 4; } // Read the remaining 1-3 bytes from FIFO uint8_t bytes_rem = len & 0x03; - if(bytes_rem != 0) { - uint8_t * dst_u8 = (uint8_t *)dst_una; - uint32_t tmp = *rx_fifo; - uint8_t * src_u8 = (uint8_t *) &tmp; + if ( bytes_rem ) + { + uint32_t tmp32 = *rx_fifo; + uint8_t *src_u8 = (uint8_t*) &tmp32; - while(bytes_rem--) + while ( bytes_rem-- ) { - *dst_u8++ = *src_u8++; + *dst++ = *src_u8++; } } } @@ -153,12 +146,12 @@ static void _ff_pull_const_addr(void * dst, const uint8_t * src, uint16_t len) // Write the remaining 1-3 bytes into FIFO uint8_t bytes_rem = len & 0x03; - if(bytes_rem) + if ( bytes_rem ) { uint32_t tmp32 = 0; - uint8_t* dst8 = (uint8_t*) &tmp32; + uint8_t *dst8 = (uint8_t*) &tmp32; - while(bytes_rem--) + while ( bytes_rem-- ) { *dst8++ = *src++; } -- cgit v1.3.1 From 9042e973d34fb3c1cf397489aa8953b795dbf930 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Apr 2021 12:52:57 +0700 Subject: clean up _ff_push_n --- src/common/tusb_fifo.c | 91 +++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 5f8623786..6e2ea51e6 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -168,18 +168,20 @@ static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t wRel) // send n items to FIFO WITHOUT updating write pointer static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRel, tu_fifo_copy_mode_t copy_mode) { + uint16_t const nLin = f->depth - wRel; + uint16_t const nWrap = n - nLin; // only used if wrapped + switch (copy_mode) { case TU_FIFO_COPY_INC: - if(n <= f->depth-wRel) + if(n <= nLin) { - // Linear mode only + // Linear only memcpy(f->buffer + (wRel * f->item_size), data, n*f->item_size); } else { // Wrap around - uint16_t nLin = f->depth - wRel; // Write data to linear part of buffer memcpy(f->buffer + (wRel * f->item_size), data, nLin*f->item_size); @@ -189,61 +191,51 @@ static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRe } break; - case TU_FIFO_COPY_CST_FULL_WORDS: // Intended for hardware buffers from which it can be read word by word only - if(n <= f->depth-wRel) + case TU_FIFO_COPY_CST_FULL_WORDS: + // Intended for hardware buffers from which it can be read word by word only + if(n <= nLin) { - // Linear mode only + // Linear only _ff_push_const_addr(f->buffer + (wRel * f->item_size), data, n*f->item_size); } else { // Wrap around case - uint16_t nLin = (f->depth - wRel) * f->item_size; - uint16_t nWrap = (n - nLin) * f->item_size; - - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; + uint16_t nLin_bytes = nLin * f->item_size; + uint16_t nWrap_bytes = nWrap * f->item_size; - unaligned_uint32_t* dst = (unaligned_uint32_t*)(f->buffer + (wRel * f->item_size)); - volatile uint32_t * rx_fifo = (volatile uint32_t *) data; + uint8_t* dst = f->buffer + (wRel * f->item_size); - // Write full words of linear part to buffer - uint16_t full_words = nLin >> 2; - while(full_words--) - { - dst->val = *rx_fifo; - dst++; - } + // Write full words to linear part of buffer + uint16_t nLin_4n_bytes = nLin_bytes & 0xFFFC; + _ff_push_const_addr(dst, data, nLin_4n_bytes); + dst += nLin_4n_bytes; - uint8_t * dst_u8; - uint8_t rem = nLin & 0x03; - // Handle wrap around + // There could be odd 1-3 bytes before the wrap-around boundary + volatile uint32_t * rx_fifo = (volatile uint32_t *) data; + uint8_t rem = nLin_bytes & 0x03; if (rem > 0) { - dst_u8 = (uint8_t *)dst; - uint8_t remrem = tu_min16(nWrap, 4-rem); - nWrap -= remrem; - uint32_t tmp = *rx_fifo; - uint8_t * src_u8 = ((uint8_t *) &tmp); - while(rem--) - { - *dst_u8++ = *src_u8++; - } - dst_u8 = f->buffer; - while(remrem--) - { - *dst_u8++ = *src_u8++; - } + uint8_t remrem = tu_min16(nWrap_bytes, 4-rem); + nWrap_bytes -= remrem; + + uint32_t tmp32 = *rx_fifo; + uint8_t * src_u8 = ((uint8_t *) &tmp32); + + // Write 1-3 bytes before wrapped boundary + while(rem--) *dst++ = *src_u8++; + + // Read more bytes to beginning to complete a word + dst = f->buffer; + while(remrem--) *dst++ = *src_u8++; } else { - dst_u8 = f->buffer; + dst = f->buffer; // wrap around to beginning } - // Final part - if (nWrap > 0) _ff_push_const_addr(dst_u8, data, nWrap); + // Write data wrapped part + if (nWrap_bytes > 0) _ff_push_const_addr(dst, data, nWrap_bytes); } break; } @@ -284,7 +276,7 @@ static void _ff_pull_n(tu_fifo_t* f, void* p_buffer, uint16_t n, uint16_t rRel, case TU_FIFO_COPY_CST_FULL_WORDS: if ( n <= nLin ) { - // Linear mode only + // Linear only _ff_pull_const_addr(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); } else @@ -296,13 +288,12 @@ static void _ff_pull_n(tu_fifo_t* f, void* p_buffer, uint16_t n, uint16_t rRel, uint8_t* src = f->buffer + (rRel * f->item_size); - // Read data from linear part of buffer + // Read full words from linear part of buffer uint16_t nLin_4n_bytes = nLin_bytes & 0xFFFC; _ff_pull_const_addr(p_buffer, src, nLin_4n_bytes); src += nLin_4n_bytes; // There could be odd 1-3 bytes before the wrap-around boundary - // Handle wrap around - do it manually as these are only 4 bytes and its faster without memcpy volatile uint32_t * tx_fifo = (volatile uint32_t *) p_buffer; uint8_t rem = nLin_bytes & 0x03; if (rem > 0) @@ -310,17 +301,17 @@ static void _ff_pull_n(tu_fifo_t* f, void* p_buffer, uint16_t n, uint16_t rRel, uint8_t remrem = tu_min16(nWrap_bytes, 4-rem); nWrap_bytes -= remrem; - uint32_t tmp; - uint8_t * dst_u8 = (uint8_t *)&tmp; + uint32_t tmp32; + uint8_t * dst_u8 = (uint8_t *)&tmp32; - // Get 1-3 bytes before wrapped boundary + // Read 1-3 bytes before wrapped boundary while(rem--) *dst_u8++ = *src++; - // Get more bytes from beginning to form a complete word + // Read more bytes from beginning to complete a word src = f->buffer; while(remrem--) *dst_u8++ = *src++; - *tx_fifo = tmp; + *tx_fifo = tmp32; } else { -- cgit v1.3.1 From 2468f9e26d63313e74d2673437b605af3ea45c74 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Apr 2021 13:15:25 +0700 Subject: more _ff_pull/push clean up --- src/common/tusb_fifo.c | 77 ++++++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 6e2ea51e6..32739f8b7 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -166,10 +166,16 @@ static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t wRel) } // send n items to FIFO WITHOUT updating write pointer -static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRel, tu_fifo_copy_mode_t copy_mode) +static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t wRel, tu_fifo_copy_mode_t copy_mode) { uint16_t const nLin = f->depth - wRel; - uint16_t const nWrap = n - nLin; // only used if wrapped + uint16_t const nWrap = n - nLin; + + uint16_t nLin_bytes = nLin * f->item_size; + uint16_t nWrap_bytes = nWrap * f->item_size; + + // current buffer of fifo + uint8_t* ff_buf = f->buffer + (wRel * f->item_size); switch (copy_mode) { @@ -177,17 +183,17 @@ static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRe if(n <= nLin) { // Linear only - memcpy(f->buffer + (wRel * f->item_size), data, n*f->item_size); + memcpy(ff_buf, app_buf, n*f->item_size); } else { // Wrap around // Write data to linear part of buffer - memcpy(f->buffer + (wRel * f->item_size), data, nLin*f->item_size); + memcpy(ff_buf, app_buf, nLin_bytes); // Write data wrapped around - memcpy(f->buffer, ((uint8_t const*) data) + nLin*f->item_size, (n - nLin) * f->item_size); + memcpy(f->buffer, ((uint8_t const*) app_buf) + nLin_bytes, nWrap_bytes); } break; @@ -196,23 +202,19 @@ static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRe if(n <= nLin) { // Linear only - _ff_push_const_addr(f->buffer + (wRel * f->item_size), data, n*f->item_size); + _ff_push_const_addr(ff_buf, app_buf, n*f->item_size); } else { // Wrap around case - uint16_t nLin_bytes = nLin * f->item_size; - uint16_t nWrap_bytes = nWrap * f->item_size; - - uint8_t* dst = f->buffer + (wRel * f->item_size); // Write full words to linear part of buffer uint16_t nLin_4n_bytes = nLin_bytes & 0xFFFC; - _ff_push_const_addr(dst, data, nLin_4n_bytes); - dst += nLin_4n_bytes; + _ff_push_const_addr(ff_buf, app_buf, nLin_4n_bytes); + ff_buf += nLin_4n_bytes; // There could be odd 1-3 bytes before the wrap-around boundary - volatile uint32_t * rx_fifo = (volatile uint32_t *) data; + volatile uint32_t * rx_fifo = (volatile uint32_t *) app_buf; uint8_t rem = nLin_bytes & 0x03; if (rem > 0) { @@ -223,19 +225,19 @@ static void _ff_push_n(tu_fifo_t* f, void const * data, uint16_t n, uint16_t wRe uint8_t * src_u8 = ((uint8_t *) &tmp32); // Write 1-3 bytes before wrapped boundary - while(rem--) *dst++ = *src_u8++; + while(rem--) *ff_buf++ = *src_u8++; // Read more bytes to beginning to complete a word - dst = f->buffer; - while(remrem--) *dst++ = *src_u8++; + ff_buf = f->buffer; + while(remrem--) *ff_buf++ = *src_u8++; } else { - dst = f->buffer; // wrap around to beginning + ff_buf = f->buffer; // wrap around to beginning } // Write data wrapped part - if (nWrap_bytes > 0) _ff_push_const_addr(dst, data, nWrap_bytes); + if (nWrap_bytes > 0) _ff_push_const_addr(ff_buf, app_buf, nWrap_bytes); } break; } @@ -248,28 +250,34 @@ static inline void _ff_pull(tu_fifo_t* f, void * p_buffer, uint16_t rRel) } // get n items from FIFO WITHOUT updating read pointer -static void _ff_pull_n(tu_fifo_t* f, void* p_buffer, uint16_t n, uint16_t rRel, tu_fifo_copy_mode_t copy_mode) +static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t wRel, tu_fifo_copy_mode_t copy_mode) { - uint16_t const nLin = f->depth - rRel; + uint16_t const nLin = f->depth - wRel; uint16_t const nWrap = n - nLin; // only used if wrapped + uint16_t nLin_bytes = nLin * f->item_size; + uint16_t nWrap_bytes = nWrap * f->item_size; + + // current buffer of fifo + uint8_t* ff_buf = f->buffer + (wRel * f->item_size); + switch (copy_mode) { case TU_FIFO_COPY_INC: if ( n <= nLin ) { // Linear only - memcpy(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); + memcpy(app_buf, ff_buf, n*f->item_size); } else { // Wrap around // Read data from linear part of buffer - memcpy(p_buffer, f->buffer + (rRel * f->item_size), nLin*f->item_size); + memcpy(app_buf, ff_buf, nLin_bytes); // Read data wrapped part - memcpy((uint8_t*) p_buffer + nLin*f->item_size, f->buffer, nWrap*f->item_size); + memcpy((uint8_t*) app_buf + nLin_bytes, f->buffer, nWrap_bytes); } break; @@ -277,24 +285,19 @@ static void _ff_pull_n(tu_fifo_t* f, void* p_buffer, uint16_t n, uint16_t rRel, if ( n <= nLin ) { // Linear only - _ff_pull_const_addr(p_buffer, f->buffer + (rRel * f->item_size), n*f->item_size); + _ff_pull_const_addr(app_buf, ff_buf, n*f->item_size); } else { // Wrap around case - uint16_t nLin_bytes = nLin * f->item_size; - uint16_t nWrap_bytes = nWrap * f->item_size; - - uint8_t* src = f->buffer + (rRel * f->item_size); - // Read full words from linear part of buffer uint16_t nLin_4n_bytes = nLin_bytes & 0xFFFC; - _ff_pull_const_addr(p_buffer, src, nLin_4n_bytes); - src += nLin_4n_bytes; + _ff_pull_const_addr(app_buf, ff_buf, nLin_4n_bytes); + ff_buf += nLin_4n_bytes; // There could be odd 1-3 bytes before the wrap-around boundary - volatile uint32_t * tx_fifo = (volatile uint32_t *) p_buffer; + volatile uint32_t * tx_fifo = (volatile uint32_t *) app_buf; uint8_t rem = nLin_bytes & 0x03; if (rem > 0) { @@ -305,21 +308,21 @@ static void _ff_pull_n(tu_fifo_t* f, void* p_buffer, uint16_t n, uint16_t rRel, uint8_t * dst_u8 = (uint8_t *)&tmp32; // Read 1-3 bytes before wrapped boundary - while(rem--) *dst_u8++ = *src++; + while(rem--) *dst_u8++ = *ff_buf++; // Read more bytes from beginning to complete a word - src = f->buffer; - while(remrem--) *dst_u8++ = *src++; + ff_buf = f->buffer; + while(remrem--) *dst_u8++ = *ff_buf++; *tx_fifo = tmp32; } else { - src = f->buffer; // wrap around to beginning + ff_buf = f->buffer; // wrap around to beginning } // Read data wrapped part - if (nWrap_bytes > 0) _ff_pull_const_addr(p_buffer, src, nWrap_bytes); + if (nWrap_bytes > 0) _ff_pull_const_addr(app_buf, ff_buf, nWrap_bytes); } break; -- cgit v1.3.1 From 893919a848926f453f85fc131d553935554af23b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Apr 2021 13:27:28 +0700 Subject: remove tu_fifo_backward_write/read_pointer API since it is illegal from fifo perspective --- src/common/tusb_fifo.c | 42 ------------------------------------------ src/common/tusb_fifo.h | 2 -- 2 files changed, 44 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 32739f8b7..8de07c819 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -893,48 +893,6 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) f->rd_idx = advance_pointer(f, f->rd_idx, n); } -/******************************************************************************/ -/*! - @brief Move back write pointer - intended to be used in combination with DMA. - It is possible to fill the FIFO by use of a DMA in circular mode. Within - DMA ISRs you may update the write pointer to be able to read from the FIFO. - As long as the DMA is the only process writing into the FIFO this is safe - to use. - - USE WITH CARE - WE DO NOT CONDUCT SAFTY CHECKS HERE! - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] n - Number of items the write pointer moves backward - */ -/******************************************************************************/ -void tu_fifo_backward_write_pointer(tu_fifo_t *f, uint16_t n) -{ - f->wr_idx = backward_pointer(f, f->wr_idx, n); -} - -/******************************************************************************/ -/*! - @brief Move back read pointer - intended to be used in combination with DMA. - It is possible to read from the FIFO by use of a DMA in linear mode. Within - DMA ISRs you may update the read pointer to be able to again write into the - FIFO. As long as the DMA is the only process reading from the FIFO this is - safe to use. - - USE WITH CARE - WE DO NOT CONDUCT SAFTY CHECKS HERE! - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] n - Number of items the read pointer moves backward - */ -/******************************************************************************/ -void tu_fifo_backward_read_pointer(tu_fifo_t *f, uint16_t n) -{ - f->rd_idx = backward_pointer(f, f->rd_idx, n); -} - /******************************************************************************/ /*! @brief Get linear read info diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 93ed6095d..b2d0b5be9 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -128,9 +128,7 @@ void tu_fifo_correct_read_pointer (tu_fifo_t* f); // Pointer modifications intended to be used in combinations with DMAs. // USE WITH CARE - NO SAFTY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED! void tu_fifo_advance_write_pointer (tu_fifo_t *f, uint16_t n); -void tu_fifo_backward_write_pointer (tu_fifo_t *f, uint16_t n); void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); -void tu_fifo_backward_read_pointer (tu_fifo_t *f, uint16_t n); // If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies to handle a possible wrapping part // This functions deliver a pointer to start reading/writing from/to and a valid linear length along which no wrap occurs. -- cgit v1.3.1 From d9a0cc9e9f328db15df6cc31b2a04532d4e8ad35 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Apr 2021 15:56:43 +0700 Subject: more cleanup --- src/common/tusb_fifo.c | 148 +++++++++++++++++++++++-------------------------- 1 file changed, 68 insertions(+), 80 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 8de07c819..098d54801 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -39,26 +39,20 @@ // implement mutex lock and unlock #if CFG_FIFO_MUTEX -static void tu_fifo_lock(tu_fifo_mutex_t mutex) +static inline void _ff_lock(tu_fifo_mutex_t mutex) { - if (mutex) - { - osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); - } + if (mutex) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); } -static void tu_fifo_unlock(tu_fifo_mutex_t mutex) +static inline void _ff_unlock(tu_fifo_mutex_t mutex) { - if (mutex) - { - osal_mutex_unlock(mutex); - } + if (mutex) osal_mutex_unlock(mutex); } #else -#define tu_fifo_lock(_mutex) -#define tu_fifo_unlock(_mutex) +#define _ff_lock(_mutex) +#define _ff_unlock(_mutex) #endif @@ -67,16 +61,16 @@ static void tu_fifo_unlock(tu_fifo_mutex_t mutex) */ typedef enum { - TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode - TU_FIFO_COPY_CST_FULL_WORDS, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO + TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode + TU_FIFO_COPY_CST_FULL_WORDS, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO } tu_fifo_copy_mode_t; bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) { if (depth > 0x8000) return false; // Maximum depth is 2^15 items - tu_fifo_lock(f->mutex_wr); - tu_fifo_lock(f->mutex_rd); + _ff_lock(f->mutex_wr); + _ff_lock(f->mutex_rd); f->buffer = (uint8_t*) buffer; f->depth = depth; @@ -88,14 +82,13 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si f->rd_idx = f->wr_idx = 0; - tu_fifo_unlock(f->mutex_wr); - tu_fifo_unlock(f->mutex_rd); + _ff_unlock(f->mutex_wr); + _ff_unlock(f->mutex_rd); return true; } // Static functions are intended to work on local variables - static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) { while ( idx >= depth) idx -= depth; @@ -105,77 +98,69 @@ static inline uint16_t _ff_mod(uint16_t idx, uint16_t depth) // Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address // Code adapted from dcd_synopsis.c // TODO generalize with configurable 1 byte or 4 byte each read -static void _ff_push_const_addr(uint8_t * dst, const void * src, uint16_t len) +static void _ff_push_const_addr(uint8_t * ff_buf, const void * app_buf, uint16_t len) { - volatile uint32_t * rx_fifo = (volatile uint32_t *) src; + volatile uint32_t * rx_fifo = (volatile uint32_t *) app_buf; - // Reading full available 32 bit words from FIFO + // Reading full available 32 bit words from const app address uint16_t full_words = len >> 2; while(full_words--) { - tu_unaligned_write32(dst, *rx_fifo); - dst += 4; + tu_unaligned_write32(ff_buf, *rx_fifo); + ff_buf += 4; } - // Read the remaining 1-3 bytes from FIFO - uint8_t bytes_rem = len & 0x03; + // Read the remaining 1-3 bytes from const app address + uint8_t const bytes_rem = len & 0x03; if ( bytes_rem ) { uint32_t tmp32 = *rx_fifo; - uint8_t *src_u8 = (uint8_t*) &tmp32; - - while ( bytes_rem-- ) - { - *dst++ = *src_u8++; - } + memcpy(ff_buf, &tmp32, bytes_rem); } } -// Intended to be used to write to hardware USB FIFO in e.g. STM32 where all data is written to a constant address in full word copies -static void _ff_pull_const_addr(void * dst, const uint8_t * src, uint16_t len) +// Intended to be used to write to hardware USB FIFO in e.g. STM32 +// where all data is written to a constant address in full word copies +static void _ff_pull_const_addr(void * app_buf, const uint8_t * ff_buf, uint16_t len) { - volatile uint32_t * tx_fifo = (volatile uint32_t *) dst; + volatile uint32_t * tx_fifo = (volatile uint32_t *) app_buf; - // Pushing full available 32 bit words to FIFO + // Pushing full available 32 bit words to const app address uint16_t full_words = len >> 2; while(full_words--) { - *tx_fifo = tu_unaligned_read32(src); - src += 4; + *tx_fifo = tu_unaligned_read32(ff_buf); + ff_buf += 4; } - // Write the remaining 1-3 bytes into FIFO - uint8_t bytes_rem = len & 0x03; + // Write the remaining 1-3 bytes into const app address + uint8_t const bytes_rem = len & 0x03; if ( bytes_rem ) { uint32_t tmp32 = 0; - uint8_t *dst8 = (uint8_t*) &tmp32; + memcpy(&tmp32, ff_buf, bytes_rem); - while ( bytes_rem-- ) - { - *dst8++ = *src++; - } *tx_fifo = tmp32; } } // send one item to FIFO WITHOUT updating write pointer -static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t wRel) +static inline void _ff_push(tu_fifo_t* f, void const * app_buf, uint16_t rel) { - memcpy(f->buffer + (wRel * f->item_size), data, f->item_size); + memcpy(f->buffer + (rel * f->item_size), app_buf, f->item_size); } // send n items to FIFO WITHOUT updating write pointer -static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t wRel, tu_fifo_copy_mode_t copy_mode) +static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t rel, tu_fifo_copy_mode_t copy_mode) { - uint16_t const nLin = f->depth - wRel; + uint16_t const nLin = f->depth - rel; uint16_t const nWrap = n - nLin; uint16_t nLin_bytes = nLin * f->item_size; uint16_t nWrap_bytes = nWrap * f->item_size; // current buffer of fifo - uint8_t* ff_buf = f->buffer + (wRel * f->item_size); + uint8_t* ff_buf = f->buffer + (rel * f->item_size); switch (copy_mode) { @@ -244,22 +229,22 @@ static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t } // get one item from FIFO WITHOUT updating read pointer -static inline void _ff_pull(tu_fifo_t* f, void * p_buffer, uint16_t rRel) +static inline void _ff_pull(tu_fifo_t* f, void * app_buf, uint16_t rel) { - memcpy(p_buffer, f->buffer + (rRel * f->item_size), f->item_size); + memcpy(app_buf, f->buffer + (rel * f->item_size), f->item_size); } // get n items from FIFO WITHOUT updating read pointer -static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t wRel, tu_fifo_copy_mode_t copy_mode) +static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t rel, tu_fifo_copy_mode_t copy_mode) { - uint16_t const nLin = f->depth - wRel; + uint16_t const nLin = f->depth - rel; uint16_t const nWrap = n - nLin; // only used if wrapped uint16_t nLin_bytes = nLin * f->item_size; uint16_t nWrap_bytes = nWrap * f->item_size; // current buffer of fifo - uint8_t* ff_buf = f->buffer + (wRel * f->item_size); + uint8_t* ff_buf = f->buffer + (rel * f->item_size); switch (copy_mode) { @@ -304,7 +289,7 @@ static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t wRel, t uint8_t remrem = tu_min16(nWrap_bytes, 4-rem); nWrap_bytes -= remrem; - uint32_t tmp32; + uint32_t tmp32=0; uint8_t * dst_u8 = (uint8_t *)&tmp32; // Read 1-3 bytes before wrapped boundary @@ -329,6 +314,7 @@ static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t wRel, t default: break; } } + // Advance an absolute pointer static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) { @@ -471,7 +457,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu { if ( n == 0 ) return 0; - tu_fifo_lock(f->mutex_wr); + _ff_lock(f->mutex_wr); uint16_t w = f->wr_idx, r = f->rd_idx; uint8_t const* buf8 = (uint8_t const*) data; @@ -501,14 +487,14 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu // Advance pointer f->wr_idx = advance_pointer(f, w, n); - tu_fifo_unlock(f->mutex_wr); + _ff_unlock(f->mutex_wr); return n; } static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) { - tu_fifo_lock(f->mutex_rd); + _ff_lock(f->mutex_rd); // Peek the data n = _tu_fifo_peek_at_n(f, 0, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable @@ -516,7 +502,7 @@ static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo // Advance read pointer f->rd_idx = advance_pointer(f, f->rd_idx, n); - tu_fifo_unlock(f->mutex_rd); + _ff_unlock(f->mutex_rd); return n; } @@ -623,9 +609,9 @@ bool tu_fifo_overflowed(tu_fifo_t* f) // Only use in case tu_fifo_overflow() returned true! void tu_fifo_correct_read_pointer(tu_fifo_t* f) { - tu_fifo_lock(f->mutex_rd); + _ff_lock(f->mutex_rd); _tu_fifo_correct_read_pointer(f, f->wr_idx); - tu_fifo_unlock(f->mutex_rd); + _ff_unlock(f->mutex_rd); } /******************************************************************************/ @@ -646,7 +632,7 @@ void tu_fifo_correct_read_pointer(tu_fifo_t* f) /******************************************************************************/ bool tu_fifo_read(tu_fifo_t* f, void * buffer) { - tu_fifo_lock(f->mutex_rd); + _ff_lock(f->mutex_rd); // Peek the data bool ret = _tu_fifo_peek_at(f, 0, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable @@ -654,7 +640,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) // Advance pointer f->rd_idx = advance_pointer(f, f->rd_idx, ret); - tu_fifo_unlock(f->mutex_rd); + _ff_unlock(f->mutex_rd); return ret; } @@ -701,9 +687,9 @@ uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint1 /******************************************************************************/ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) { - tu_fifo_lock(f->mutex_rd); + _ff_lock(f->mutex_rd); bool ret = _tu_fifo_peek_at(f, offset, p_buffer, f->wr_idx, f->rd_idx); - tu_fifo_unlock(f->mutex_rd); + _ff_unlock(f->mutex_rd); return ret; } @@ -726,9 +712,9 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) /******************************************************************************/ uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t n) { - tu_fifo_lock(f->mutex_rd); + _ff_lock(f->mutex_rd); bool ret = _tu_fifo_peek_at_n(f, offset, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); - tu_fifo_unlock(f->mutex_rd); + _ff_unlock(f->mutex_rd); return ret; } @@ -750,7 +736,7 @@ uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint1 /******************************************************************************/ bool tu_fifo_write(tu_fifo_t* f, const void * data) { - tu_fifo_lock(f->mutex_wr); + _ff_lock(f->mutex_wr); uint16_t w = f->wr_idx; @@ -764,7 +750,7 @@ bool tu_fifo_write(tu_fifo_t* f, const void * data) // Advance pointer f->wr_idx = advance_pointer(f, w, 1); - tu_fifo_unlock(f->mutex_wr); + _ff_unlock(f->mutex_wr); return true; } @@ -818,13 +804,15 @@ uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t* f, const void * data, /******************************************************************************/ bool tu_fifo_clear(tu_fifo_t *f) { - tu_fifo_lock(f->mutex_wr); - tu_fifo_lock(f->mutex_rd); + _ff_lock(f->mutex_wr); + _ff_lock(f->mutex_rd); + f->rd_idx = f->wr_idx = 0; f->max_pointer_idx = 2*f->depth-1; f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; - tu_fifo_unlock(f->mutex_wr); - tu_fifo_unlock(f->mutex_rd); + + _ff_unlock(f->mutex_wr); + _ff_unlock(f->mutex_rd); return true; } @@ -840,13 +828,13 @@ bool tu_fifo_clear(tu_fifo_t *f) /******************************************************************************/ bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { - tu_fifo_lock(f->mutex_wr); - tu_fifo_lock(f->mutex_rd); + _ff_lock(f->mutex_wr); + _ff_lock(f->mutex_rd); f->overwritable = overwritable; - tu_fifo_unlock(f->mutex_wr); - tu_fifo_unlock(f->mutex_rd); + _ff_unlock(f->mutex_wr); + _ff_unlock(f->mutex_rd); return true; } @@ -927,9 +915,9 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, // Check overflow and correct if required if (cnt > f->depth) { - tu_fifo_lock(f->mutex_rd); + _ff_lock(f->mutex_rd); _tu_fifo_correct_read_pointer(f, w); - tu_fifo_unlock(f->mutex_rd); + _ff_unlock(f->mutex_rd); r = f->rd_idx; cnt = f->depth; } -- cgit v1.3.1 From 8eacdffebdcc10a6fffdc248ef6086b223f3edf3 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 7 Apr 2021 20:07:28 +0200 Subject: Optimize encode/decode - refactor unnecessary repetitive division --- src/class/audio/audio_device.c | 16 ++++++++-------- src/class/audio/audio_device.h | 3 +++ 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index a85dfddb8..2e9684cb9 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -310,6 +310,7 @@ typedef struct audio_data_format_type_I_t format_type_I_rx; uint8_t n_bytes_per_sampe_rx; uint8_t n_channels_per_ff_rx; + uint8_t n_ff_used_rx; #endif #endif @@ -322,6 +323,7 @@ typedef struct audio_data_format_type_I_t format_type_I_tx; uint8_t n_bytes_per_sampe_tx; uint8_t n_channels_per_ff_tx; + uint8_t n_ff_used_tx; #endif #endif @@ -625,10 +627,7 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, (void) rhport; // Determine amount of samples - uint8_t const n_ff_used = audio->n_channels_rx / audio->n_channels_per_ff_rx; - - TU_ASSERT( n_ff_used <= audio->n_rx_supp_ff ); - + uint8_t const n_ff_used = audio->n_ff_used_rx; uint16_t const nBytesToCopy = audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx; uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used; uint8_t cnt_ff; @@ -928,10 +927,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* aud TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); // Determine amount of samples - uint8_t const n_ff_used = audio->n_channels_tx / audio->n_channels_per_ff_tx; - - TU_ASSERT( n_ff_used <= audio->n_tx_supp_ff ); - + uint8_t const n_ff_used = audio->n_ff_used_tx; uint16_t const nBytesToCopy = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx; uint16_t const capPerFF = audio->ep_in_sz / n_ff_used; // Sample capacity per FIFO in bytes uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); @@ -1551,6 +1547,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); } + audio->n_ff_used_tx = audio->n_channels_tx / audio->n_channels_per_ff_tx; + TU_ASSERT( audio->n_ff_used_tx <= audio->n_tx_supp_ff ); #endif #endif @@ -1582,6 +1580,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { tu_fifo_config(&audio->rx_supp_ff[cnt], audio->rx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); } + audio->n_ff_used_rx = audio->n_channels_rx / audio->n_channels_per_ff_rx; + TU_ASSERT( audio->n_ff_used_rx <= audio->n_rx_supp_ff ); #endif #endif // Invoke callback diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 81e0024d7..f91540b64 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -240,6 +240,9 @@ // Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size // The actual coding parameters of active AS alternate interface is parsed from the descriptors +// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sampe_sz) * sampe_sz)! +// This is important to remind in case you use DMAs! If the sample sizes changes, the DMA MUST BE RECONFIGURED just like the FIFOs for a different depth!!! + // For PCM encoding/decoding #ifndef CFG_TUD_AUDIO_ENABLE_ENCODING -- cgit v1.3.1 From 2e2dc7bdc5928dfa027291ca8c6d6792698e5b9a Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Wed, 7 Apr 2021 17:05:04 -0400 Subject: Revise per initial comments Returns the RT driver to the function state of previous iteration, which did not support the will_detach. Behavior should be fine without this feature. This removes much of the added bloat to track state, and handle requests in the APP_DETACH state which is no longer required. Removes the optional bloat added to the RT driver, such as responding to GETSTATE requests. Fixes the DFU Mode to extract the attr bits from the functional descriptor when opened. Fixes some incorrect bitwise if checks. Also, updates some naming of functions to be consistent with the rest of the library. --- src/class/dfu/dfu_mode_device.c | 19 +++++---- src/class/dfu/dfu_mode_device.h | 8 ++-- src/class/dfu/dfu_rt_and_mode_device.c | 18 ++++---- src/class/dfu/dfu_rt_and_mode_device.h | 10 ++--- src/class/dfu/dfu_rt_device.c | 76 ++++------------------------------ src/class/dfu/dfu_rt_device.h | 35 ---------------- src/class/vendor/vendor_device.c | 2 +- src/common/tusb_types.h | 18 ++++---- src/device/usbd.c | 16 +++---- 9 files changed, 55 insertions(+), 147 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c index 0b80b103d..7ad0f5168 100644 --- a/src/class/dfu/dfu_mode_device.c +++ b/src/class/dfu/dfu_mode_device.c @@ -65,11 +65,11 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ -void dfu_mode_init(void) +void dfu_moded_init(void) { _dfu_state_ctx.state = APP_DETACH; // After init, reset will occur. We want to be in APP_DETACH to move to DFU_IDLE _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = tud_dfu_mode_init_attrs_cb(); + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.last_block_num = 0; _dfu_state_ctx.last_transfer_len = 0; @@ -77,7 +77,7 @@ void dfu_mode_init(void) dfu_debug_print_context(); } -void dfu_mode_reset(uint8_t rhport) +void dfu_moded_reset(uint8_t rhport) { if (_dfu_state_ctx.state == APP_DETACH) { @@ -118,14 +118,13 @@ void dfu_mode_reset(uint8_t rhport) } _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = tud_dfu_mode_init_attrs_cb(); _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.last_block_num = 0; _dfu_state_ctx.last_transfer_len = 0; dfu_debug_print_context(); } -uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { (void) rhport; (void) max_len; @@ -139,6 +138,9 @@ uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, u if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) { + tusb_desc_dfu_functional_t *dfu_desc = (tusb_desc_dfu_functional_t *)p_desc; + _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } @@ -149,7 +151,7 @@ uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, u // Invoked when a control transfer occurred on an interface of this class // Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) { @@ -266,7 +268,7 @@ void tud_dfu_mode_poll_timeout_done() _dfu_state_ctx.state = DFU_DNLOAD_SYNC; } else if (_dfu_state_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -394,7 +396,6 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; _dfu_state_ctx.blk_transfer_in_proc = true; - dfu_req_dnload_setup(rhport, request); } else { if ( tud_dfu_mode_device_data_done_check_cb() ) @@ -447,7 +448,7 @@ static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) { _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); diff --git a/src/class/dfu/dfu_mode_device.h b/src/class/dfu/dfu_mode_device.h index 11b748c3b..aacb1911c 100644 --- a/src/class/dfu/dfu_mode_device.h +++ b/src/class/dfu/dfu_mode_device.h @@ -118,10 +118,10 @@ TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void dfu_mode_init(void); -void dfu_mode_reset(uint8_t rhport); -uint16_t dfu_mode_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_mode_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +void dfu_moded_init(void); +void dfu_moded_reset(uint8_t rhport); +uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); #ifdef __cplusplus diff --git a/src/class/dfu/dfu_rt_and_mode_device.c b/src/class/dfu/dfu_rt_and_mode_device.c index d555a1d58..8b6a8a766 100644 --- a/src/class/dfu/dfu_rt_and_mode_device.c +++ b/src/class/dfu/dfu_rt_and_mode_device.c @@ -62,9 +62,9 @@ static dfu_protocol_type_t mode = 0x00; //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ -void dfu_init(void) +void dfu_d_init(void) { - mode = dfu_init_in_mode_cb(); + mode = tud_dfu_init_in_mode_cb(); switch (mode) { @@ -79,10 +79,10 @@ void dfu_init(void) case DFU_PROTOCOL_DFU: { - ctx.init = dfu_mode_init; - ctx.reset = dfu_mode_reset; - ctx.open = dfu_mode_open; - ctx.control_xfer_cb = dfu_mode_control_xfer_cb; + ctx.init = dfu_moded_init; + ctx.reset = dfu_moded_reset; + ctx.open = dfu_moded_open; + ctx.control_xfer_cb = dfu_moded_control_xfer_cb; } break; @@ -96,17 +96,17 @@ void dfu_init(void) ctx.init(); } -void dfu_reset(uint8_t rhport) +void dfu_d_reset(uint8_t rhport) { ctx.reset(rhport); } -uint16_t dfu_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +uint16_t dfu_d_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { return ctx.open(rhport, itf_desc, max_len); } -bool dfu_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +bool dfu_d_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { return ctx.control_xfer_cb(rhport, stage, request); } diff --git a/src/class/dfu/dfu_rt_and_mode_device.h b/src/class/dfu/dfu_rt_and_mode_device.h index 9734a031c..b6eafbba4 100644 --- a/src/class/dfu/dfu_rt_and_mode_device.h +++ b/src/class/dfu/dfu_rt_and_mode_device.h @@ -39,15 +39,15 @@ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ // Invoked when the driver needs to determine the callbacks to use -dfu_protocol_type_t dfu_init_in_mode_cb(); +dfu_protocol_type_t tud_dfu_init_in_mode_cb(); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void dfu_init(void); -void dfu_reset(uint8_t rhport); -uint16_t dfu_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +void dfu_d_init(void); +void dfu_d_reset(uint8_t rhport); +uint16_t dfu_d_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_d_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); #ifdef __cplusplus diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index d1d028d69..729b8e3e0 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -38,41 +38,17 @@ //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED -{ - dfu_mode_device_status_t status; - dfu_mode_state_t state; - uint8_t attrs; -} dfu_rt_state_ctx_t; - -// Only a single dfu state is allowed -CFG_TUSB_MEM_SECTION static dfu_rt_state_ctx_t _dfu_state_ctx; - -static void dfu_rt_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ void dfu_rtd_init(void) { - _dfu_state_ctx.state = APP_IDLE; - _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); - dfu_debug_print_context(); } void dfu_rtd_reset(uint8_t rhport) { - if (((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 0) - && (_dfu_state_ctx.state == DFU_REQUEST_DETACH)) - { - tud_dfu_runtime_reboot_to_dfu_cb(); - } - - _dfu_state_ctx.state = APP_IDLE; - _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = tud_dfu_runtime_init_attrs_cb(); - dfu_debug_print_context(); + (void) rhport; } uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) @@ -117,67 +93,29 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request // Handle class request only from here TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + TU_LOG2(" DFU RT Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); switch (request->bRequest) { case DFU_REQUEST_DETACH: { - if (_dfu_state_ctx.state == APP_IDLE) - { - _dfu_state_ctx.state = APP_DETACH; - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_WILL_DETACH_BITMASK) == 1) - { - tud_dfu_runtime_reboot_to_dfu_cb(); - } else { - tud_dfu_runtime_detach_start_timer_cb(request->wValue); - } - } else { - TU_LOG2(" DFU Unexpected request during state %s: %u\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), request->bRequest); - return false; - } + tud_control_status(rhport, request); + tud_dfu_runtime_reboot_to_dfu_cb(); } break; case DFU_REQUEST_GETSTATUS: { dfu_status_req_payload_t resp; - resp.bStatus = _dfu_state_ctx.status; - memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); // Value is ignored - resp.bState = _dfu_state_ctx.state; - resp.iString = ( tud_dfu_runtime_get_status_desc_table_index_cb ) ? tud_dfu_runtime_get_status_desc_table_index_cb() : 0; - + // Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0 + memset(&resp, 0x00, sizeof(dfu_status_req_payload_t)); tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); } break; - case DFU_REQUEST_GETSTATE: - { - tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); - } - break; - - default: - { - TU_LOG2(" DFU Nonstandard Runtime Request: %u\r\n", request->bRequest); - return ( tud_dfu_runtime_req_nonstandard_cb ) ? tud_dfu_runtime_req_nonstandard_cb(rhport, stage, request) : false; - } - break; + default: return false; // stall unsupported request } return true; } -void tud_dfu_runtime_set_status(dfu_mode_device_status_t status) -{ - _dfu_state_ctx.status = status; -} - -void tud_dfu_runtime_detach_timer_elapsed() -{ - if (_dfu_state_ctx.state == DFU_REQUEST_DETACH) - { - _dfu_state_ctx.state = APP_IDLE; - } -} - #endif diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 23703862d..465bf9d99 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -38,44 +38,9 @@ //--------------------------------------------------------------------+ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -// Allow the application to update the status as required. -// Is set to DFU_STATUS_OK during internal initialization and USB reset -// Value is not checked to allow for custom statuses to be used -void tud_dfu_runtime_set_status(dfu_mode_device_status_t status); - // Invoked when a DFU_DETACH request is received and bitWillDetach is set void tud_dfu_runtime_reboot_to_dfu_cb(); -// Invoked when a DFU_DETACH request is received and bitWillDetach is not set -// This should start a timer for wTimeout ms -// When the timer has elapsed, the app must call tud_dfu_runtime_detach_timer_elapsed -// If a USB reset is called while the timer is running, the class will call -// tud_dfu_runtime_reboot_to_dfu_cb. -// NOTE: This callback should return immediately, and not implement the delay -// internally, as this can will hold up the USB stack -TU_ATTR_WEAK void tud_dfu_runtime_detach_start_timer_cb(uint16_t wTimeout); - -// Invoke when the dfu runtime detach timer has elapsed -void tud_dfu_runtime_detach_timer_elapsed(); - -// Invoked when a nonstandard request is received -// Use may be vendor specific. -// Return false to stall -TU_ATTR_WEAK bool tud_dfu_runtime_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -// Invoked during initialization of the dfu driver to set attributes -// Return byte set with bitmasks: -// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK -// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK -// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK -// DFU_FUNC_ATTR_WILL_DETACH_BITMASK -// Note: This should match the USB descriptor -uint8_t tud_dfu_runtime_init_attrs_cb(); - -// Invoked during a DFU_GETSTATUS request to get for the string index -// to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_runtime_get_status_desc_table_index_cb(); - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 3fcea89c4..d39830a6a 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index a462b498f..7703ebb7b 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -427,13 +427,17 @@ typedef struct TU_ATTR_PACKED uint8_t bLength; uint8_t bDescriptorType; - struct TU_ATTR_PACKED { - uint8_t bitCanDnload : 1; - uint8_t bitCanUpload : 1; - uint8_t bitManifestationTolerant : 1; - uint8_t bitWillDetach : 1; - uint8_t reserved : 4; - } bmAttributes; + union { + struct TU_ATTR_PACKED { + uint8_t bitCanDnload : 1; + uint8_t bitCanUpload : 1; + uint8_t bitManifestationTolerant : 1; + uint8_t bitWillDetach : 1; + uint8_t reserved : 4; + } bmAttributes; + + uint8_t bAttributes; + }; uint16_t wDetachTimeOut; uint16_t wTransferSize; diff --git a/src/device/usbd.c b/src/device/usbd.c index 6f2262feb..92e521ec9 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -190,10 +190,10 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_DFU_MODE { DRIVER_NAME("DFU-MODE") - .init = dfu_mode_init, - .reset = dfu_mode_reset, - .open = dfu_mode_open, - .control_xfer_cb = dfu_mode_control_xfer_cb, + .init = dfu_moded_init, + .reset = dfu_moded_reset, + .open = dfu_moded_open, + .control_xfer_cb = dfu_moded_control_xfer_cb, .xfer_cb = NULL, .sof = NULL }, @@ -202,10 +202,10 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_DFU_RUNTIME_AND_MODE { DRIVER_NAME("DFU-RT-MODE") - .init = dfu_init, - .reset = dfu_reset, - .open = dfu_open, - .control_xfer_cb = dfu_control_xfer_cb, + .init = dfu_d_init, + .reset = dfu_d_reset, + .open = dfu_d_open, + .control_xfer_cb = dfu_d_control_xfer_cb, .xfer_cb = NULL, .sof = NULL }, -- cgit v1.3.1 From ae851bba31781eacfadc7e69b414cd1da6960314 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Wed, 7 Apr 2021 17:15:26 -0400 Subject: Resolve gcc warnings for no parameter functions --- src/class/dfu/dfu_mode_device.h | 16 ++++++++-------- src/class/dfu/dfu_rt_and_mode_device.h | 2 +- src/class/dfu/dfu_rt_device.h | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_mode_device.h b/src/class/dfu/dfu_mode_device.h index aacb1911c..c25910b23 100644 --- a/src/class/dfu/dfu_mode_device.h +++ b/src/class/dfu/dfu_mode_device.h @@ -40,10 +40,10 @@ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ // Invoked when a reset is received to check if firmware is valid -bool tud_dfu_mode_firmware_valid_check_cb(); +bool tud_dfu_mode_firmware_valid_check_cb(void); // Invoked when the device must reboot to dfu runtime mode -void tud_dfu_mode_reboot_to_rt_cb(); +void tud_dfu_mode_reboot_to_rt_cb(void); // Invoked during initialization of the dfu driver to set attributes // Return byte set with bitmasks: @@ -52,11 +52,11 @@ void tud_dfu_mode_reboot_to_rt_cb(); // DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK // DFU_FUNC_ATTR_WILL_DETACH_BITMASK // Note: This should match the USB descriptor -uint8_t tud_dfu_mode_init_attrs_cb(); +uint8_t tud_dfu_mode_init_attrs_cb(void); // Invoked during a DFU_GETSTATUS request to get for the string index // to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(); +TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(void); // Invoked during a USB reset // Lets the app perform custom behavior on a USB reset. @@ -84,7 +84,7 @@ TU_ATTR_WEAK void tud_dfu_mode_get_poll_timeout_cb(uint8_t *ms_timeout); void tud_dfu_mode_start_poll_timeout_cb(uint8_t *ms_timeout); // Must be called when the poll_timeout has elapsed -void tud_dfu_mode_poll_timeout_done(); +void tud_dfu_mode_poll_timeout_done(void); // Invoked when a DFU_DNLOAD request is received // This callback takes the wBlockNum chunk of length length and provides it @@ -97,10 +97,10 @@ void tud_dfu_mode_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t // Return true if the application agrees there is no more data // Return false if the device disagrees, which will stall the pipe, and the Host // should initiate a recovery procedure -bool tud_dfu_mode_device_data_done_check_cb(); +bool tud_dfu_mode_device_data_done_check_cb(void); // Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_mode_abort_cb(); +TU_ATTR_WEAK void tud_dfu_mode_abort_cb(void); // Invoked when a DFU_UPLOAD request is received // This callback must populate data with up to length bytes @@ -114,7 +114,7 @@ TU_ATTR_WEAK bool tud_dfu_mode_req_nonstandard_cb(uint8_t rhport, uint8_t stage, // Invoked during a DFU_GETSTATUS request to get for the string index // to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(); +TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(void); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_rt_and_mode_device.h b/src/class/dfu/dfu_rt_and_mode_device.h index b6eafbba4..b311bb7a5 100644 --- a/src/class/dfu/dfu_rt_and_mode_device.h +++ b/src/class/dfu/dfu_rt_and_mode_device.h @@ -39,7 +39,7 @@ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ // Invoked when the driver needs to determine the callbacks to use -dfu_protocol_type_t tud_dfu_init_in_mode_cb(); +dfu_protocol_type_t tud_dfu_init_in_mode_cb(void); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 465bf9d99..0e5fd005a 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -39,7 +39,7 @@ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ // Invoked when a DFU_DETACH request is received and bitWillDetach is set -void tud_dfu_runtime_reboot_to_dfu_cb(); +void tud_dfu_runtime_reboot_to_dfu_cb(void); //--------------------------------------------------------------------+ // Internal Class Driver API -- cgit v1.3.1 From 4bebb9ca49bc6fc7ae281d284e009afe276a2948 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 8 Apr 2021 20:11:51 +0200 Subject: Remove depracted defines in audio_device.c --- src/class/audio/audio_device.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 2e9684cb9..8c0d563e6 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -762,13 +762,8 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) uint8_t idxDriver, idxItf; uint8_t const *dummy2; -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_FORMAT_TYPE_TX == AUDIO_FORMAT_TYPE_I - // Required in any case regardless if call backs are used - find index of audio streaming interface and index of interface - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); -#else // If a callback is used determine current alternate setting of - find index of audio streaming interface and index of interface if (tud_audio_tx_done_pre_load_cb || tud_audio_tx_done_post_load_cb) TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); -#endif // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). -- cgit v1.3.1 From 2134c1a875d57c79cd431a982d67420101d3c656 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 8 Apr 2021 21:48:36 +0200 Subject: Fix defines in audio_device.c --- examples/device/audio_4_channel_mic/src/main.c | 1 - src/class/audio/audio_device.c | 28 ++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index 58fbd401e..6e1ea1e6a 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -429,7 +429,6 @@ bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const { (void) rhport; (void) p_request; - startVal = 0; return true; } diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8c0d563e6..753c0ef6c 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -2085,43 +2085,67 @@ static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify format type and format and also to get number of physical channels if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) { +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT if (itf != audio->ep_in_as_intf_num && itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT + if (itf != audio->ep_in_as_intf_num) break; +#endif +#if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT + if (itf != audio->ep_out_as_intf_num) break; +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN if (itf == audio->ep_in_as_intf_num) { audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; audio->format_type_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING audio->format_type_I_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; #endif } +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_OUT if (itf == audio->ep_out_as_intf_num) { audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; audio->format_type_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING audio->format_type_I_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; #endif } +#endif } // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats) #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) { +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT if (itf != audio->ep_in_as_intf_num && itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT + if (itf != audio->ep_in_as_intf_num) break; +#endif +#if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT + if (itf != audio->ep_out_as_intf_num) break; +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN if (itf == audio->ep_in_as_intf_num) { audio->n_bytes_per_sampe_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; } +#endif +#if CFG_TUD_AUDIO_ENABLE_EP_OUT if (itf == audio->ep_out_as_intf_num) { audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; } +#endif } #endif -- cgit v1.3.1 From 7c8b4991f17809ec924e86914868a3043d13d34d Mon Sep 17 00:00:00 2001 From: Joey Castillo Date: Mon, 5 Apr 2021 00:02:51 -0400 Subject: Add support for SAM L22 family --- hw/bsp/board_mcu.h | 3 +- hw/bsp/saml22/boards/saml22_feather/board.h | 47 ++++++ hw/bsp/saml22/boards/saml22_feather/board.mk | 9 ++ .../saml22/boards/saml22_feather/saml22_feather.ld | 145 ++++++++++++++++++ hw/bsp/saml22/boards/sensorwatch_m0/board.h | 47 ++++++ hw/bsp/saml22/boards/sensorwatch_m0/board.mk | 9 ++ .../saml22/boards/sensorwatch_m0/sensorwatch_m0.ld | 145 ++++++++++++++++++ hw/bsp/saml22/family.c | 163 +++++++++++++++++++++ hw/bsp/saml22/family.mk | 50 +++++++ hw/mcu/microchip | 2 +- src/portable/microchip/samd/dcd_samd.c | 6 +- src/tusb_option.h | 1 + 12 files changed, 623 insertions(+), 4 deletions(-) create mode 100644 hw/bsp/saml22/boards/saml22_feather/board.h create mode 100644 hw/bsp/saml22/boards/saml22_feather/board.mk create mode 100644 hw/bsp/saml22/boards/saml22_feather/saml22_feather.ld create mode 100644 hw/bsp/saml22/boards/sensorwatch_m0/board.h create mode 100644 hw/bsp/saml22/boards/sensorwatch_m0/board.mk create mode 100644 hw/bsp/saml22/boards/sensorwatch_m0/sensorwatch_m0.ld create mode 100644 hw/bsp/saml22/family.c create mode 100644 hw/bsp/saml22/family.mk (limited to 'src') diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index 362e3289e..b00958e5e 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -53,7 +53,8 @@ #include "nrf.h" #elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ - CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X + CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \ + CFG_TUSB_MCU == OPT_MCU_SAML22 #include "sam.h" #elif CFG_TUSB_MCU == OPT_MCU_SAMG diff --git a/hw/bsp/saml22/boards/saml22_feather/board.h b/hw/bsp/saml22/boards/saml22_feather/board.h new file mode 100644 index 000000000..13a326000 --- /dev/null +++ b/hw/bsp/saml22/boards/saml22_feather/board.h @@ -0,0 +1,47 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PIN PIN_PA08 +#define LED_STATE_ON 1 + +// Button +#define BUTTON_PIN PIN_PA06 +#define BUTTON_STATE_ACTIVE 0 + + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/saml22/boards/saml22_feather/board.mk b/hw/bsp/saml22/boards/saml22_feather/board.mk new file mode 100644 index 000000000..a6a773137 --- /dev/null +++ b/hw/bsp/saml22/boards/saml22_feather/board.mk @@ -0,0 +1,9 @@ +CFLAGS += -D__SAML22J18A__ + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/$(BOARD).ld + +# For flash-jlink target +JLINK_DEVICE = ATSAML22J18 + +flash: flash-bossac diff --git a/hw/bsp/saml22/boards/saml22_feather/saml22_feather.ld b/hw/bsp/saml22/boards/saml22_feather/saml22_feather.ld new file mode 100644 index 000000000..2e0e1b256 --- /dev/null +++ b/hw/bsp/saml22/boards/saml22_feather/saml22_feather.ld @@ -0,0 +1,145 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAML22J18A + * + * Copyright (c) 2018 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the Licence at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +ENTRY(Reset_Handler) + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/saml22/boards/sensorwatch_m0/board.h b/hw/bsp/saml22/boards/sensorwatch_m0/board.h new file mode 100644 index 000000000..7fc690ab2 --- /dev/null +++ b/hw/bsp/saml22/boards/sensorwatch_m0/board.h @@ -0,0 +1,47 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PIN PIN_PA21 +#define LED_STATE_ON 1 + +// Button +#define BUTTON_PIN PIN_PA22 +#define BUTTON_STATE_ACTIVE 1 + + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/saml22/boards/sensorwatch_m0/board.mk b/hw/bsp/saml22/boards/sensorwatch_m0/board.mk new file mode 100644 index 000000000..a6a773137 --- /dev/null +++ b/hw/bsp/saml22/boards/sensorwatch_m0/board.mk @@ -0,0 +1,9 @@ +CFLAGS += -D__SAML22J18A__ + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/$(BOARD).ld + +# For flash-jlink target +JLINK_DEVICE = ATSAML22J18 + +flash: flash-bossac diff --git a/hw/bsp/saml22/boards/sensorwatch_m0/sensorwatch_m0.ld b/hw/bsp/saml22/boards/sensorwatch_m0/sensorwatch_m0.ld new file mode 100644 index 000000000..2e0e1b256 --- /dev/null +++ b/hw/bsp/saml22/boards/sensorwatch_m0/sensorwatch_m0.ld @@ -0,0 +1,145 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAML22J18A + * + * Copyright (c) 2018 Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the Licence at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +ENTRY(Reset_Handler) + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/saml22/family.c b/hw/bsp/saml22/family.c new file mode 100644 index 000000000..fff11cbe5 --- /dev/null +++ b/hw/bsp/saml22/family.c @@ -0,0 +1,163 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "sam.h" +#include "bsp/board.h" +#include "board.h" + +#include "hal/include/hal_gpio.h" +#include "hal/include/hal_init.h" +#include "hpl/gclk/hpl_gclk_base.h" +#include "hpl_mclk_config.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_Handler(void) +{ + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +/* Referenced GCLKs (out of 0~4), should be initialized firstly */ +#define _GCLK_INIT_1ST 0x00000000 +/* Not referenced GCLKs, initialized last */ +#define _GCLK_INIT_LAST 0x0000001F + +void board_init(void) +{ + // Clock init ( follow hpl_init.c ) + hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, CONF_NVM_WAIT_STATE); + + _set_performance_level(2); + + _osc32kctrl_init_sources(); + _oscctrl_init_sources(); + _mclk_init(); +#if _GCLK_INIT_1ST + _gclk_init_generators_by_fref(_GCLK_INIT_1ST); +#endif + _oscctrl_init_referenced_generators(); + _gclk_init_generators_by_fref(_GCLK_INIT_LAST); + +#if (CONF_PORT_EVCTRL_PORT_0 | CONF_PORT_EVCTRL_PORT_1 | CONF_PORT_EVCTRL_PORT_2 | CONF_PORT_EVCTRL_PORT_3) + hri_port_set_EVCTRL_reg(PORT, 0, CONF_PORTA_EVCTRL); + hri_port_set_EVCTRL_reg(PORT, 1, CONF_PORTB_EVCTRL); +#endif + + // Update SystemCoreClock since it is hard coded with asf4 and not correct + // Init 1ms tick timer (samd SystemCoreClock may not correct) + SystemCoreClock = CONF_CPU_FREQUENCY; + SysTick_Config(CONF_CPU_FREQUENCY / 1000); + + // Led init + gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_level(LED_PIN, !LED_STATE_ON); + + // Button init + gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULL_DOWN : GPIO_PULL_UP); + +#if CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); +#endif + + /* USB Clock init + * The USB module requires a GCLK_USB of 48 MHz ~ 0.25% clock + * for low speed and full speed operation. */ + hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); + hri_mclk_set_AHBMASK_USB_bit(MCLK); + hri_mclk_set_APBBMASK_USB_bit(MCLK); + + // USB Pin Init + gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PIN_PA24, false); + gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF); + gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PIN_PA25, false); + gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF); + + gpio_set_pin_function(PIN_PA24, PINMUX_PA24G_USB_DM); + gpio_set_pin_function(PIN_PA25, PINMUX_PA25G_USB_DP); + + // Output 500hz PWM on PB23 (TCC0 WO[3]) so we can validate the GCLK1 clock speed + hri_mclk_set_APBCMASK_TCC0_bit(MCLK); + TCC0->PER.bit.PER = 48000000 / 1000; + TCC0->CC[3].bit.CC = 48000000 / 2000; + TCC0->CTRLA.bit.ENABLE = true; + + gpio_set_pin_function(PIN_PB23, PINMUX_PB23F_TCC0_WO3); + hri_gclk_write_PCHCTRL_reg(GCLK, TCC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + gpio_set_pin_level(LED_PIN, state); +} + +uint32_t board_button_read(void) +{ + // button is active low + return gpio_get_pin_level(BUTTON_PIN) ? 0 : 1; +} + +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +int board_uart_write(void const * buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; + +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif +void _init(void) +{ + +} \ No newline at end of file diff --git a/hw/bsp/saml22/family.mk b/hw/bsp/saml22/family.mk new file mode 100644 index 000000000..fbe4e66f8 --- /dev/null +++ b/hw/bsp/saml22/family.mk @@ -0,0 +1,50 @@ +UF2_FAMILY_ID = 0x68ed2b88 +DEPS_SUBMODULES += hw/mcu/microchip + +include $(TOP)/$(BOARD_PATH)/board.mk + +CFLAGS += \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m0plus \ + -nostdlib -nostartfiles \ + -DCONF_OSC32K_CALIB_ENABLE=0 \ + -DCFG_TUSB_MCU=OPT_MCU_SAML22 + +SRC_C += \ + src/portable/microchip/samd/dcd_samd.c \ + hw/mcu/microchip/saml22/gcc/gcc/startup_saml22.c \ + hw/mcu/microchip/saml22/gcc/system_saml22.c \ + hw/mcu/microchip/saml22/hpl/gclk/hpl_gclk.c \ + hw/mcu/microchip/saml22/hpl/mclk/hpl_mclk.c \ + hw/mcu/microchip/saml22/hpl/pm/hpl_pm.c \ + hw/mcu/microchip/saml22/hpl/osc32kctrl/hpl_osc32kctrl.c \ + hw/mcu/microchip/saml22/hpl/oscctrl/hpl_oscctrl.c \ + hw/mcu/microchip/saml22/hal/src/hal_atomic.c + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/hw/mcu/microchip/saml22/ \ + $(TOP)/hw/mcu/microchip/saml22/config \ + $(TOP)/hw/mcu/microchip/saml22/include \ + $(TOP)/hw/mcu/microchip/saml22/hal/include \ + $(TOP)/hw/mcu/microchip/saml22/hal/utils/include \ + $(TOP)/hw/mcu/microchip/saml22/hpl/port \ + $(TOP)/hw/mcu/microchip/saml22/hri \ + $(TOP)/hw/mcu/microchip/saml22/CMSIS/Core/Include + +# For TinyUSB port source +VENDOR = microchip +CHIP_FAMILY = samd + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM0 + +# flash using bossac at least version 1.8 +# can be found in arduino15/packages/arduino/tools/bossac/ +# Add it to your PATH or change BOSSAC variable to match your installation +BOSSAC = bossac + +flash-bossac: $(BUILD)/$(PROJECT).bin + @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) + $(BOSSAC) --port=$(SERIAL) -U -i --offset=0x2000 -e -w $^ -R diff --git a/hw/mcu/microchip b/hw/mcu/microchip index d75bb2d8c..f7087f047 160000 --- a/hw/mcu/microchip +++ b/hw/mcu/microchip @@ -1 +1 @@ -Subproject commit d75bb2d8c877043218de104257203bcba6e11cc8 +Subproject commit f7087f04783c896627061fc151fa3527b73733c7 diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 3cff92fcd..13e56453d 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -28,7 +28,8 @@ #if TUSB_OPT_DEVICE_ENABLED && \ (CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ - CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X) + CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \ + CFG_TUSB_MCU == OPT_MCU_SAML22) #include "sam.h" #include "device/dcd.h" @@ -123,7 +124,8 @@ void dcd_int_disable(uint8_t rhport) NVIC_DisableIRQ(USB_0_IRQn); } -#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 +#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ + CFG_TUSB_MCU == OPT_MCU_SAML22 void dcd_int_enable(uint8_t rhport) { diff --git a/src/tusb_option.h b/src/tusb_option.h index 56950d364..7585a9ff6 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -60,6 +60,7 @@ #define OPT_MCU_SAMD51 201 ///< MicroChip SAMD51 #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMG 202 ///< MicroChip SAMDG series +#define OPT_MCU_SAML22 205 ///< MicroChip SAML22 // STM32 #define OPT_MCU_STM32F0 300 ///< ST STM32F0 -- cgit v1.3.1 From 7b45b38fe4b7d2ebd197463cf12f091a6f68ac91 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Mon, 12 Apr 2021 11:17:01 -0400 Subject: Remove DFU mode and rt --- src/class/dfu/dfu_mode_device.c | 2 +- src/class/dfu/dfu_rt_and_mode_device.c | 114 --------------------------------- src/class/dfu/dfu_rt_and_mode_device.h | 57 ----------------- src/class/dfu/dfu_rt_device.c | 2 +- src/device/usbd.c | 12 ---- src/tusb.h | 6 -- src/tusb_option.h | 10 --- 7 files changed, 2 insertions(+), 201 deletions(-) delete mode 100644 src/class/dfu/dfu_rt_and_mode_device.c delete mode 100644 src/class/dfu/dfu_rt_and_mode_device.h (limited to 'src') diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c index 7ad0f5168..5f8c714c0 100644 --- a/src/class/dfu/dfu_mode_device.c +++ b/src/class/dfu/dfu_mode_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) || (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) #include "dfu_mode_device.h" #include "device/usbd_pvt.h" diff --git a/src/class/dfu/dfu_rt_and_mode_device.c b/src/class/dfu/dfu_rt_and_mode_device.c deleted file mode 100644 index 8b6a8a766..000000000 --- a/src/class/dfu/dfu_rt_and_mode_device.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * 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. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) - -#include "dfu_rt_and_mode_device.h" - -#include "dfu_mode_device.h" -#include "dfu_rt_device.h" -#include "device/usbd_pvt.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -typedef struct -{ - void (* init ) (void); - void (* reset ) (uint8_t rhport); - uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); - bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -} dfu_local_driver_t; - -static dfu_local_driver_t ctx = -{ - .init = NULL, - .reset = NULL, - .open = NULL, - .control_xfer_cb = NULL -}; - -static dfu_protocol_type_t mode = 0x00; - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void dfu_d_init(void) -{ - mode = tud_dfu_init_in_mode_cb(); - - switch (mode) - { - case DFU_PROTOCOL_RT: - { - ctx.init = dfu_rtd_init; - ctx.reset = dfu_rtd_reset; - ctx.open = dfu_rtd_open; - ctx.control_xfer_cb = dfu_rtd_control_xfer_cb; - } - break; - - case DFU_PROTOCOL_DFU: - { - ctx.init = dfu_moded_init; - ctx.reset = dfu_moded_reset; - ctx.open = dfu_moded_open; - ctx.control_xfer_cb = dfu_moded_control_xfer_cb; - } - break; - - default: - { - TU_LOG2(" DFU Unexpected mode: %u\r\n", mode); - } - break; - } - - ctx.init(); -} - -void dfu_d_reset(uint8_t rhport) -{ - ctx.reset(rhport); -} - -uint16_t dfu_d_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - return ctx.open(rhport, itf_desc, max_len); -} - -bool dfu_d_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - return ctx.control_xfer_cb(rhport, stage, request); -} - -#endif diff --git a/src/class/dfu/dfu_rt_and_mode_device.h b/src/class/dfu/dfu_rt_and_mode_device.h deleted file mode 100644 index b311bb7a5..000000000 --- a/src/class/dfu/dfu_rt_and_mode_device.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * 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. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_RT_AND_MODE_DEVICE_H_ -#define _TUSB_DFU_RT_AND_MODE_DEVICE_H_ - -#include "common/tusb_common.h" -#include "device/usbd.h" -#include "dfu.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ -// Invoked when the driver needs to determine the callbacks to use -dfu_protocol_type_t tud_dfu_init_in_mode_cb(void); - -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void dfu_d_init(void); -void dfu_d_reset(uint8_t rhport); -uint16_t dfu_d_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_d_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_RT_AND_MODE_DEVICE_H_ */ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 729b8e3e0..9da2e1e4f 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) || (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME_AND_MODE) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) #include "dfu_rt_device.h" #include "device/usbd_pvt.h" diff --git a/src/device/usbd.c b/src/device/usbd.c index 92e521ec9..af34e53ac 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -199,18 +199,6 @@ static usbd_class_driver_t const _usbd_driver[] = }, #endif - #if CFG_TUD_DFU_RUNTIME_AND_MODE - { - DRIVER_NAME("DFU-RT-MODE") - .init = dfu_d_init, - .reset = dfu_d_reset, - .open = dfu_d_open, - .control_xfer_cb = dfu_d_control_xfer_cb, - .xfer_cb = NULL, - .sof = NULL - }, - #endif - #if CFG_TUD_NET { DRIVER_NAME("NET") diff --git a/src/tusb.h b/src/tusb.h index 6eab4bee2..c9558515c 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -100,12 +100,6 @@ #include "class/dfu/dfu_mode_device.h" #endif - #if CFG_TUD_DFU_RUNTIME_AND_MODE - #include "class/dfu/dfu_rt_and_mode_device.h" - #include "class/dfu/dfu_rt_device.h" - #include "class/dfu/dfu_mode_device.h" - #endif - #if CFG_TUD_NET #include "class/net/net_device.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 4c2204964..3cd3df9f2 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -241,10 +241,6 @@ #define CFG_TUD_DFU_MODE 0 #endif -#ifndef CFG_TUD_DFU_RUNTIME_AND_MODE - #define CFG_TUD_DFU_RUNTIME_AND_MODE 0 -#endif - #ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 64 #endif @@ -289,12 +285,6 @@ #error Control Endpoint Max Packet Size cannot be larger than 64 #endif -#if (CFG_TUD_DFU_RUNTIME_AND_MODE && CFG_TUD_DFU_RUNTIME) \ - || (CFG_TUD_DFU_RUNTIME_AND_MODE && CFG_TUD_DFU_MODE) \ - || (CFG_TUD_DFU_RUNTIME && CFG_TUD_DFU_MODE) - #error Only one of CFG_TUD_DFU_RUNTIME_AND_MODE, CFG_TUD_DFU_RUNTIME, and CFG_TUD_DFU_MODE can be enabled in a single build -#endif - #endif /* _TUSB_OPTION_H_ */ /** @} */ -- cgit v1.3.1 From 8d9f60ca5e1b095fd8ab5541bf3190a2035eaf6f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 14 Apr 2021 21:52:54 +0200 Subject: Improve user feedback in case of wrong configuration of audio driver --- src/class/audio/audio_device.c | 71 +++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 753c0ef6c..4057f5f64 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -81,14 +81,14 @@ #endif #if (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_SYNOPSYS)) || \ - CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ - CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ - CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F2 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ + CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ + CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) - #define USE_LINEAR_BUFFER 0 +#define USE_LINEAR_BUFFER 0 #else - #define USE_LINEAR_BUFFER 1 +#define USE_LINEAR_BUFFER 1 #endif // Declaration of buffers @@ -182,9 +182,7 @@ CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; #endif // Active alternate setting of interfaces -#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 CFG_TUSB_MEM_ALIGN uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; -#endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 CFG_TUSB_MEM_ALIGN uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; #endif @@ -267,9 +265,7 @@ typedef struct uint8_t ep_int_ctr; // Audio control interrupt EP. #endif -#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 - uint8_t * alt_setting_ptr; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! -#endif + uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! /*------------- From this point, data is not cleared by bus reset -------------*/ @@ -486,7 +482,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) - if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting_ptr[idxItf])); + if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting[idxItf])); #if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT @@ -540,7 +536,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ #endif // Call a weak callback here - a possibility for user to get informed decoding was completed - if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting_ptr[idxItf])); + if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting[idxItf])); return true; } @@ -557,12 +553,12 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const { // This function is an optimized version of -// while((uint8_t *)dst < dst_end) -// { -// memcpy(dst, src, nBytesToCopy); -// dst = (uint8_t *)dst + nBytesToCopy; -// src += nBytesToCopy * n_ff_used; -// } + // while((uint8_t *)dst < dst_end) + // { + // memcpy(dst, src, nBytesToCopy); + // dst = (uint8_t *)dst + nBytesToCopy; + // src += nBytesToCopy * n_ff_used; + // } // Optimize for fast half word copies typedef struct{ @@ -596,9 +592,9 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const case 3: while((uint8_t *)dst < dst_end) { -// memcpy(dst, src, 3); -// dst = (uint8_t *)dst + 3; -// src += 3 * n_ff_used; + // memcpy(dst, src, 3); + // dst = (uint8_t *)dst + 3; + // src += 3 * n_ff_used; // TODO: Is there a faster way to copy 3 bytes? *(uint8_t *)dst++ = *src++; @@ -767,7 +763,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->alt_setting_ptr[idxItf])); + if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->alt_setting[idxItf])); // Send everything in ISO EP FIFO uint16_t n_bytes_tx; @@ -827,7 +823,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) #endif // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->alt_setting_ptr[idxItf])); + if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->alt_setting[idxItf])); return true; } @@ -887,9 +883,9 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const case 3: while((uint8_t *)src < src_end) { -// memcpy(dst, src, 3); -// src = (uint8_t *)src + 3; -// dst += 3 * n_ff_used; + // memcpy(dst, src, 3); + // src = (uint8_t *)src + 3; + // dst += 3 * n_ff_used; // TODO: Is there a faster way to copy 3 bytes? *dst++ = *(uint8_t *)src++; @@ -1021,26 +1017,24 @@ void audiod_init(void) } // Initialize active alternate interface buffers -#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 switch (i) { #if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 case 0: - audio->alt_setting_ptr = alt_setting_1; + audio->alt_setting = alt_setting_1; break; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 case 1: - audio->alt_setting_ptr = alt_setting_2; + audio->alt_setting = alt_setting_2; break; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 case 2: - audio->alt_setting_ptr = alt_setting_3; + audio->alt_setting = alt_setting_3; break; #endif } -#endif // Initialize IN EP FIFO if required #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING @@ -1400,7 +1394,6 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request) { -#if CFG_TUD_AUDIO_FUNC_1_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 || CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 uint8_t const itf = tu_u16_low(p_request->wIndex); // Find index of audio streaming interface @@ -1408,17 +1401,11 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const *dummy; TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].alt_setting_ptr[idxItf], 1)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].alt_setting[idxItf], 1)); - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].alt_setting_ptr[idxItf]); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].alt_setting[idxItf]); return true; - -#else - (void) rhport; - (void) p_request; - return false; -#endif } static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request) @@ -1495,7 +1482,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #endif // Save current alternative interface setting - audio->alt_setting_ptr[idxItf] = alt; + audio->alt_setting[idxItf] = alt; // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface // Get pointer at end -- cgit v1.3.1 From 3c84776e0ac926cedfcbda4a3ecf72e2a7c1cde8 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 Apr 2021 12:09:12 +0700 Subject: minor clean up --- src/portable/st/synopsys/dcd_synopsys.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index aa927d5a4..0fe7c2a3c 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -1007,16 +1007,16 @@ static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OT uint16_t remaining_packets = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_PKTCNT_Msk) >> USB_OTG_DIEPTSIZ_PKTCNT_Pos; // Process every single packet (only whole packets can be written to fifo) - for(uint16_t i = 0; i < remaining_packets; i++){ - volatile uint16_t remaining_bytes = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos; + for(uint16_t i = 0; i < remaining_packets; i++) + { + uint16_t const remaining_bytes = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos; + // Packet can not be larger than ep max size - uint16_t packet_size = tu_min16(remaining_bytes, xfer->max_size); + uint16_t const packet_size = tu_min16(remaining_bytes, xfer->max_size); // It's only possible to write full packets into FIFO. Therefore DTXFSTS register of current // EP has to be checked if the buffer can take another WHOLE packet - if(packet_size > ((in_ep[n].DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV_Msk) << 2)){ - break; - } + if(packet_size > ((in_ep[n].DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV_Msk) << 2)) break; // Push packet to Tx-FIFO if (xfer->ff) -- cgit v1.3.1 From 9ecb91e1bd0ac54c759ac1e91a0714c5a8c49172 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 Apr 2021 23:47:28 +0700 Subject: fix build with LOG=2 --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 8b126a9f6..8a3d8ec2f 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1250,7 +1250,7 @@ bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, count); + TU_LOG2(" Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes); // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); -- cgit v1.3.1 From 2f0cb8b5f1a944187635a58a748ed08738d324a5 Mon Sep 17 00:00:00 2001 From: Alex Lisitsyn Date: Tue, 9 Mar 2021 11:29:07 +0100 Subject: tinyusb: add support of esp32s3 target add support of new esp32s3 target and the board update the roles.mk wrapper to allow dfu flashing of espressif chip update examples to allow compilation for esp32s3_addax_1 board once the code is tested the PR to original tinyusb repo will be submitted --- .github/workflows/build.yml | 7 +- README.md | 2 +- examples/device/board_test/CMakeLists.txt | 2 +- examples/device/board_test/sdkconfig.defaults | 3 +- examples/device/board_test/src/CMakeLists.txt | 12 +- examples/device/board_test/src/main.c | 2 +- examples/device/cdc_msc/CMakeLists.txt | 2 +- examples/device/cdc_msc_freertos/CMakeLists.txt | 2 +- .../device/cdc_msc_freertos/sdkconfig.defaults | 2 - .../device/cdc_msc_freertos/src/CMakeLists.txt | 15 +- examples/device/cdc_msc_freertos/src/main.c | 6 +- .../device/hid_composite_freertos/CMakeLists.txt | 4 +- .../hid_composite_freertos/sdkconfig.defaults | 2 - .../hid_composite_freertos/src/CMakeLists.txt | 15 +- examples/device/hid_composite_freertos/src/main.c | 6 +- examples/host/cdc_msc_hid/CMakeLists.txt | 2 +- examples/make.mk | 3 + examples/rules.mk | 4 +- hw/bsp/board_mcu.h | 3 + hw/bsp/esp32s2/boards/CMakeLists.txt | 16 - .../boards/adafruit_feather_esp32s2/board.h | 45 -- .../esp32s2/boards/adafruit_magtag_29gray/board.h | 45 -- .../esp32s2/boards/adafruit_metro_esp32s2/board.h | 43 - hw/bsp/esp32s2/boards/esp32s2.c | 143 ---- hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h | 44 -- hw/bsp/esp32s2/boards/espressif_saola_1/board.h | 45 -- hw/bsp/esp32s2/components/led_strip/CMakeLists.txt | 8 - .../components/led_strip/include/led_strip.h | 126 --- .../led_strip/src/led_strip_rmt_ws2812.c | 171 ---- hw/bsp/esp32s2/family.cmake | 6 - hw/bsp/esp32s2/family.mk | 36 - hw/bsp/esp32sx/boards/CMakeLists.txt | 14 + .../boards/adafruit_feather_esp32s2/CMakeLists.txt | 15 + .../boards/adafruit_feather_esp32s2/board.h | 45 ++ .../boards/adafruit_feather_esp32s2/board.mk | 3 + .../boards/adafruit_magtag_29gray/CMakeLists.txt | 15 + .../esp32sx/boards/adafruit_magtag_29gray/board.h | 45 ++ .../esp32sx/boards/adafruit_magtag_29gray/board.mk | 3 + .../boards/adafruit_metro_esp32s2/CMakeLists.txt | 15 + .../esp32sx/boards/adafruit_metro_esp32s2/board.h | 43 + .../esp32sx/boards/adafruit_metro_esp32s2/board.mk | 3 + hw/bsp/esp32sx/boards/esp32sx.c | 143 ++++ .../boards/espressif_addax_1/CMakeLists.txt | 15 + hw/bsp/esp32sx/boards/espressif_addax_1/board.h | 44 ++ hw/bsp/esp32sx/boards/espressif_addax_1/board.mk | 3 + .../boards/espressif_kaluga_1/CMakeLists.txt | 14 + hw/bsp/esp32sx/boards/espressif_kaluga_1/board.h | 44 ++ hw/bsp/esp32sx/boards/espressif_kaluga_1/board.mk | 3 + .../boards/espressif_saola_1/CMakeLists.txt | 14 + hw/bsp/esp32sx/boards/espressif_saola_1/board.h | 45 ++ hw/bsp/esp32sx/boards/espressif_saola_1/board.mk | 3 + hw/bsp/esp32sx/components/led_strip/CMakeLists.txt | 8 + .../components/led_strip/include/led_strip.h | 126 +++ .../led_strip/src/led_strip_rmt_ws2812.c | 171 ++++ hw/bsp/esp32sx/family.cmake | 6 + hw/bsp/esp32sx/family.mk | 26 + src/osal/osal_freertos.h | 4 +- src/portable/espressif/esp32s2/dcd_esp32s2.c | 867 -------------------- src/portable/espressif/esp32sx/dcd_esp32sx.c | 868 +++++++++++++++++++++ src/tusb_option.h | 1 + tools/build_esp32s2.py | 99 --- tools/build_esp32sx.py | 99 +++ tools/build_family.py | 2 +- 63 files changed, 1900 insertions(+), 1728 deletions(-) delete mode 100644 hw/bsp/esp32s2/boards/CMakeLists.txt delete mode 100644 hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h delete mode 100644 hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h delete mode 100644 hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h delete mode 100644 hw/bsp/esp32s2/boards/esp32s2.c delete mode 100644 hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h delete mode 100644 hw/bsp/esp32s2/boards/espressif_saola_1/board.h delete mode 100644 hw/bsp/esp32s2/components/led_strip/CMakeLists.txt delete mode 100644 hw/bsp/esp32s2/components/led_strip/include/led_strip.h delete mode 100644 hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c delete mode 100644 hw/bsp/esp32s2/family.cmake delete mode 100644 hw/bsp/esp32s2/family.mk create mode 100644 hw/bsp/esp32sx/boards/CMakeLists.txt create mode 100644 hw/bsp/esp32sx/boards/adafruit_feather_esp32s2/CMakeLists.txt create mode 100644 hw/bsp/esp32sx/boards/adafruit_feather_esp32s2/board.h create mode 100644 hw/bsp/esp32sx/boards/adafruit_feather_esp32s2/board.mk create mode 100644 hw/bsp/esp32sx/boards/adafruit_magtag_29gray/CMakeLists.txt create mode 100644 hw/bsp/esp32sx/boards/adafruit_magtag_29gray/board.h create mode 100644 hw/bsp/esp32sx/boards/adafruit_magtag_29gray/board.mk create mode 100644 hw/bsp/esp32sx/boards/adafruit_metro_esp32s2/CMakeLists.txt create mode 100644 hw/bsp/esp32sx/boards/adafruit_metro_esp32s2/board.h create mode 100644 hw/bsp/esp32sx/boards/adafruit_metro_esp32s2/board.mk create mode 100644 hw/bsp/esp32sx/boards/esp32sx.c create mode 100644 hw/bsp/esp32sx/boards/espressif_addax_1/CMakeLists.txt create mode 100644 hw/bsp/esp32sx/boards/espressif_addax_1/board.h create mode 100644 hw/bsp/esp32sx/boards/espressif_addax_1/board.mk create mode 100644 hw/bsp/esp32sx/boards/espressif_kaluga_1/CMakeLists.txt create mode 100644 hw/bsp/esp32sx/boards/espressif_kaluga_1/board.h create mode 100644 hw/bsp/esp32sx/boards/espressif_kaluga_1/board.mk create mode 100644 hw/bsp/esp32sx/boards/espressif_saola_1/CMakeLists.txt create mode 100644 hw/bsp/esp32sx/boards/espressif_saola_1/board.h create mode 100644 hw/bsp/esp32sx/boards/espressif_saola_1/board.mk create mode 100644 hw/bsp/esp32sx/components/led_strip/CMakeLists.txt create mode 100644 hw/bsp/esp32sx/components/led_strip/include/led_strip.h create mode 100644 hw/bsp/esp32sx/components/led_strip/src/led_strip_rmt_ws2812.c create mode 100644 hw/bsp/esp32sx/family.cmake create mode 100644 hw/bsp/esp32sx/family.mk delete mode 100644 src/portable/espressif/esp32s2/dcd_esp32s2.c create mode 100644 src/portable/espressif/esp32sx/dcd_esp32sx.c delete mode 100644 tools/build_esp32s2.py create mode 100644 tools/build_esp32sx.py (limited to 'src') diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cccf8eacc..41ce430ad 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -180,9 +180,9 @@ jobs: asset_content_type: application/zip # --------------------------------------- - # Build ESP32S2 family + # Build ESP32SX family # --------------------------------------- - build-esp32s2: + build-esp32sx: runs-on: ubuntu-latest strategy: fail-fast: false @@ -192,6 +192,7 @@ jobs: - 'adafruit_feather_esp32s2' - 'adafruit_magtag_29gray' - 'adafruit_metro_esp32s2' + - 'espressif_addax_1' - 'espressif_kaluga_1' - 'espressif_saola_1' @@ -206,7 +207,7 @@ jobs: uses: actions/checkout@v2 - name: Build - run: docker run --rm -v $PWD:/project -w /project espressif/idf:latest python3 tools/build_esp32s2.py ${{ matrix.board }} + run: docker run --rm -v $PWD:/project -w /project espressif/idf:latest python3 tools/build_esp32sx.py ${{ matrix.board }} # --------------------------------------- # Build msp430 family diff --git a/README.md b/README.md index ddbd8a7fb..b77ddb662 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Special thanks to all the people who spent their precious time and effort to hel The stack supports the following MCUs: - **Dialog:** DA1469x -- **Espressif:** ESP32-S2 +- **Espressif:** ESP32-S2, ESP32-S3 - **MicroChip:** SAMD11, SAMD21, SAMD51, SAME5x, SAMG55 - **NordicSemi:** nRF52833, nRF52840 - **Nuvoton:** NUC120, NUC121/NUC125, NUC126, NUC505 diff --git a/examples/device/board_test/CMakeLists.txt b/examples/device/board_test/CMakeLists.txt index 32c0329ea..7658fae49 100644 --- a/examples/device/board_test/CMakeLists.txt +++ b/examples/device/board_test/CMakeLists.txt @@ -7,7 +7,7 @@ set(TOP "../../..") get_filename_component(TOP "${TOP}" REALPATH) # Check for -DFAMILY= -if(FAMILY STREQUAL "esp32s2") +if(FAMILY STREQUAL "esp32sx") cmake_minimum_required(VERSION 3.5) include(${TOP}/hw/bsp/${FAMILY}/family.cmake) diff --git a/examples/device/board_test/sdkconfig.defaults b/examples/device/board_test/sdkconfig.defaults index cede66031..83871619e 100644 --- a/examples/device/board_test/sdkconfig.defaults +++ b/examples/device/board_test/sdkconfig.defaults @@ -1,4 +1,3 @@ CONFIG_IDF_CMAKE=y -CONFIG_IDF_TARGET="esp32s2" -CONFIG_IDF_TARGET_ESP32S2=y +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y diff --git a/examples/device/board_test/src/CMakeLists.txt b/examples/device/board_test/src/CMakeLists.txt index e59661069..e44863609 100644 --- a/examples/device/board_test/src/CMakeLists.txt +++ b/examples/device/board_test/src/CMakeLists.txt @@ -1,10 +1,18 @@ -# FAMILY = "esp32s2" +# FAMILY = esp32sx idf_component_register(SRCS "main.c" INCLUDE_DIRS "." REQUIRES freertos soc) +string(REGEX MATCH "^(esp32s[2-3])*" chip_target "$ENV{IDF_TARGET}") + +if(NOT chip_target) + message(FATAL_ERROR "Incorrect target: $ENV{IDF_TARGET}" ) +endif() + +string(TOUPPER ${chip_target} upper_case_target) + target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + "-DCFG_TUSB_MCU=OPT_MCU_${upper_case_target}" "-DCFG_TUSB_OS=OPT_OS_FREERTOS" ) diff --git a/examples/device/board_test/src/main.c b/examples/device/board_test/src/main.c index d94b24650..c77dd5647 100644 --- a/examples/device/board_test/src/main.c +++ b/examples/device/board_test/src/main.c @@ -70,7 +70,7 @@ int main(void) return 0; } -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 void app_main(void) { main(); diff --git a/examples/device/cdc_msc/CMakeLists.txt b/examples/device/cdc_msc/CMakeLists.txt index d4ee8c050..5f515c825 100644 --- a/examples/device/cdc_msc/CMakeLists.txt +++ b/examples/device/cdc_msc/CMakeLists.txt @@ -7,7 +7,7 @@ set(TOP "../../..") get_filename_component(TOP "${TOP}" REALPATH) # Check for -DFAMILY= -if(FAMILY STREQUAL "esp32s2") +if(FAMILY STREQUAL "esp32sx") cmake_minimum_required(VERSION 3.5) include(${TOP}/hw/bsp/${FAMILY}/family.cmake) project(${PROJECT}) diff --git a/examples/device/cdc_msc_freertos/CMakeLists.txt b/examples/device/cdc_msc_freertos/CMakeLists.txt index dabb4bc80..643cebebe 100644 --- a/examples/device/cdc_msc_freertos/CMakeLists.txt +++ b/examples/device/cdc_msc_freertos/CMakeLists.txt @@ -9,7 +9,7 @@ set(TOP "../../..") get_filename_component(TOP "${TOP}" REALPATH) # Check for -DFAMILY= -if(FAMILY STREQUAL "esp32s2") +if(FAMILY STREQUAL "esp32sx") include(${TOP}/hw/bsp/${FAMILY}/family.cmake) project(${PROJECT}) diff --git a/examples/device/cdc_msc_freertos/sdkconfig.defaults b/examples/device/cdc_msc_freertos/sdkconfig.defaults index 3253f605c..83871619e 100644 --- a/examples/device/cdc_msc_freertos/sdkconfig.defaults +++ b/examples/device/cdc_msc_freertos/sdkconfig.defaults @@ -1,5 +1,3 @@ CONFIG_IDF_CMAKE=y -CONFIG_IDF_TARGET="esp32s2" -CONFIG_IDF_TARGET_ESP32S2=y CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y diff --git a/examples/device/cdc_msc_freertos/src/CMakeLists.txt b/examples/device/cdc_msc_freertos/src/CMakeLists.txt index a7ece92c9..17bc0b3eb 100644 --- a/examples/device/cdc_msc_freertos/src/CMakeLists.txt +++ b/examples/device/cdc_msc_freertos/src/CMakeLists.txt @@ -2,8 +2,19 @@ idf_component_register(SRCS "main.c" "usb_descriptors.c" "msc_disk.c" INCLUDE_DIRS "." REQUIRES freertos soc) +string(REGEX MATCH "^(esp32s[2-3])*" chip_target "$ENV{IDF_TARGET}") + +if(NOT chip_target) + message(FATAL_ERROR "Incorrect target: $ENV{IDF_TARGET}" ) +else() + set(chip_family "esp32sx") +endif() + +string(TOUPPER ${chip_target} upper_case_target) + target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + "-DCFG_TUSB_MCU=OPT_MCU_${upper_case_target}" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" ) idf_component_get_property( FREERTOS_ORIG_INCLUDE_PATH freertos ORIG_INCLUDE_PATH) @@ -26,5 +37,5 @@ target_sources(${COMPONENT_TARGET} PUBLIC "${TOP}/src/class/net/net_device.c" "${TOP}/src/class/usbtmc/usbtmc_device.c" "${TOP}/src/class/vendor/vendor_device.c" - "${TOP}/src/portable/espressif/esp32s2/dcd_esp32s2.c" + "${TOP}/src/portable/espressif/${chip_family}/dcd_${chip_family}.c" ) diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index ccff2e0fb..c27b7feda 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -94,15 +94,15 @@ int main(void) // Create CDC task (void) xTaskCreateStatic( cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); - // skip starting scheduler (and return) for ESP32-S2 -#if CFG_TUSB_MCU != OPT_MCU_ESP32S2 + // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 +#if CFG_TUSB_MCU != OPT_MCU_ESP32S2 && CFG_TUSB_MCU != OPT_MCU_ESP32S3 vTaskStartScheduler(); #endif return 0; } -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 void app_main(void) { main(); diff --git a/examples/device/hid_composite_freertos/CMakeLists.txt b/examples/device/hid_composite_freertos/CMakeLists.txt index dabb4bc80..a3c7697aa 100644 --- a/examples/device/hid_composite_freertos/CMakeLists.txt +++ b/examples/device/hid_composite_freertos/CMakeLists.txt @@ -9,10 +9,10 @@ set(TOP "../../..") get_filename_component(TOP "${TOP}" REALPATH) # Check for -DFAMILY= -if(FAMILY STREQUAL "esp32s2") +if(FAMILY STREQUAL "esp32sx") include(${TOP}/hw/bsp/${FAMILY}/family.cmake) project(${PROJECT}) else() - message(FATAL_ERROR "Invalid FAMILY specified") + message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}") endif() diff --git a/examples/device/hid_composite_freertos/sdkconfig.defaults b/examples/device/hid_composite_freertos/sdkconfig.defaults index 3253f605c..83871619e 100644 --- a/examples/device/hid_composite_freertos/sdkconfig.defaults +++ b/examples/device/hid_composite_freertos/sdkconfig.defaults @@ -1,5 +1,3 @@ CONFIG_IDF_CMAKE=y -CONFIG_IDF_TARGET="esp32s2" -CONFIG_IDF_TARGET_ESP32S2=y CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y diff --git a/examples/device/hid_composite_freertos/src/CMakeLists.txt b/examples/device/hid_composite_freertos/src/CMakeLists.txt index f79e8f845..ae213a3c8 100644 --- a/examples/device/hid_composite_freertos/src/CMakeLists.txt +++ b/examples/device/hid_composite_freertos/src/CMakeLists.txt @@ -2,8 +2,19 @@ idf_component_register(SRCS "main.c" "usb_descriptors.c" INCLUDE_DIRS "." REQUIRES freertos soc) +string(REGEX MATCH "^(esp32s[2-3])*" chip_target "$ENV{IDF_TARGET}") + +if(NOT chip_target) + message(FATAL_ERROR "Incorrect target: $ENV{IDF_TARGET}" ) +else() + set(chip_family "esp32sx") +endif() + +string(TOUPPER ${chip_target} upper_case_target) + target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + "-DCFG_TUSB_MCU=OPT_MCU_${upper_case_target}" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" ) idf_component_get_property( FREERTOS_ORIG_INCLUDE_PATH freertos ORIG_INCLUDE_PATH) @@ -26,5 +37,5 @@ target_sources(${COMPONENT_TARGET} PUBLIC "${TOP}/src/class/net/net_device.c" "${TOP}/src/class/usbtmc/usbtmc_device.c" "${TOP}/src/class/vendor/vendor_device.c" - "${TOP}/src/portable/espressif/esp32s2/dcd_esp32s2.c" + "${TOP}/src/portable/espressif/${chip_family}/dcd_${chip_family}.c" ) diff --git a/examples/device/hid_composite_freertos/src/main.c b/examples/device/hid_composite_freertos/src/main.c index 37b4a0cf7..47f976427 100644 --- a/examples/device/hid_composite_freertos/src/main.c +++ b/examples/device/hid_composite_freertos/src/main.c @@ -95,15 +95,15 @@ int main(void) // Create HID task (void) xTaskCreateStatic( hid_task, "hid", HID_STACK_SZIE, NULL, configMAX_PRIORITIES-2, hid_stack, &hid_taskdef); - // skip starting scheduler (and return) for ESP32-S2 -#if CFG_TUSB_MCU != OPT_MCU_ESP32S2 + // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 +#if CFG_TUSB_MCU != OPT_MCU_ESP32S2 && CFG_TUSB_MCU != OPT_MCU_ESP32S3 vTaskStartScheduler(); #endif return 0; } -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 void app_main(void) { main(); diff --git a/examples/host/cdc_msc_hid/CMakeLists.txt b/examples/host/cdc_msc_hid/CMakeLists.txt index 30b6c713e..e9360a731 100644 --- a/examples/host/cdc_msc_hid/CMakeLists.txt +++ b/examples/host/cdc_msc_hid/CMakeLists.txt @@ -7,7 +7,7 @@ set(TOP "../../..") get_filename_component(TOP "${TOP}" REALPATH) # Check for -DFAMILY= -if(FAMILY STREQUAL "esp32s2") +if(FAMILY STREQUAL "esp32sx") cmake_minimum_required(VERSION 3.5) include(${TOP}/hw/bsp/${FAMILY}/family.cmake) project(${PROJECT}) diff --git a/examples/make.mk b/examples/make.mk index e04a2592a..47879c66f 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -27,6 +27,9 @@ endif # Board within family ifeq ($(BOARD_PATH),) BOARD_PATH := $(subst $(TOP)/,,$(wildcard $(TOP)/hw/bsp/*/boards/$(BOARD))) +ifneq ($(wildcard $(TOP)/hw/bsp/*/boards/$(BOARD)/board.mk),) + include $(TOP)/hw/bsp/*/boards/$(BOARD)/board.mk +endif FAMILY := $(word 3, $(subst /, ,$(BOARD_PATH))) FAMILY_PATH = hw/bsp/$(FAMILY) endif diff --git a/examples/rules.mk b/examples/rules.mk index a19cd678e..461683fad 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -5,8 +5,8 @@ # Set all as default goal .DEFAULT_GOAL := all -# ESP32-S2 and RP2040 has its own CMake build system -ifneq ($(FAMILY),esp32s2) +# ESP32-SX and RP2040 has its own CMake build system +ifneq ($(FAMILY),esp32sx) ifneq ($(FAMILY),rp2040) # --------------------------------------- # GNU Make build system diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index b00958e5e..1a659c410 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -115,6 +115,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_ESP32S2 // no header needed +#elif CFG_TUSB_MCU == OPT_MCU_ESP32S3 + // no header needed + #elif CFG_TUSB_MCU == OPT_MCU_DA1469X #include "DA1469xAB.h" diff --git a/hw/bsp/esp32s2/boards/CMakeLists.txt b/hw/bsp/esp32s2/boards/CMakeLists.txt deleted file mode 100644 index 98c929ef3..000000000 --- a/hw/bsp/esp32s2/boards/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -idf_component_register(SRCS esp32s2.c - INCLUDE_DIRS "." "${BOARD}" - PRIV_REQUIRES "driver" - REQUIRES freertos src led_strip) - -target_compile_options(${COMPONENT_TARGET} PUBLIC - "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" -) - -idf_component_get_property( FREERTOS_ORIG_INCLUDE_PATH freertos ORIG_INCLUDE_PATH) -target_include_directories(${COMPONENT_TARGET} PUBLIC - "${FREERTOS_ORIG_INCLUDE_PATH}" - "${TOP}/hw" - "${TOP}/src" -) diff --git a/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h b/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h deleted file mode 100644 index 43e00901d..000000000 --- a/hw/bsp/esp32s2/boards/adafruit_feather_esp32s2/board.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, 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. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#define NEOPIXEL_PIN 33 -#define NEOPIXEL_POWER_PIN 21 -#define NEOPIXEL_POWER_STATE 1 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h b/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h deleted file mode 100644 index 16e30b685..000000000 --- a/hw/bsp/esp32s2/boards/adafruit_magtag_29gray/board.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, 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. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#define NEOPIXEL_PIN 1 -#define NEOPIXEL_POWER_PIN 21 -#define NEOPIXEL_POWER_STATE 0 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h b/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h deleted file mode 100644 index 49a2474bc..000000000 --- a/hw/bsp/esp32s2/boards/adafruit_metro_esp32s2/board.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, 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. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#define NEOPIXEL_PIN 45 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/esp32s2/boards/esp32s2.c b/hw/bsp/esp32s2/boards/esp32s2.c deleted file mode 100644 index 358c0c803..000000000 --- a/hw/bsp/esp32s2/boards/esp32s2.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, 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. - * - * This file is part of the TinyUSB stack. - */ - -#include "../../board.h" -#include "board.h" - -#include "esp_rom_gpio.h" -#include "hal/gpio_ll.h" -#include "hal/usb_hal.h" -#include "soc/usb_periph.h" - -#include "driver/periph_ctrl.h" -#include "driver/rmt.h" - -#ifdef NEOPIXEL_PIN -#include "led_strip.h" -static led_strip_t *strip; -#endif - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -static void configure_pins(usb_hal_context_t *usb); - -// Initialize on-board peripherals : led, button, uart and USB -void board_init(void) -{ - -#ifdef NEOPIXEL_PIN - #ifdef NEOPIXEL_POWER_PIN - gpio_reset_pin(NEOPIXEL_POWER_PIN); - gpio_set_direction(NEOPIXEL_POWER_PIN, GPIO_MODE_OUTPUT); - gpio_set_level(NEOPIXEL_POWER_PIN, NEOPIXEL_POWER_STATE); - #endif - - // WS2812 Neopixel driver with RMT peripheral - rmt_config_t config = RMT_DEFAULT_CONFIG_TX(NEOPIXEL_PIN, RMT_CHANNEL_0); - config.clk_div = 2; // set counter clock to 40MHz - - rmt_config(&config); - rmt_driver_install(config.channel, 0, 0); - - led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(1, (led_strip_dev_t) config.channel); - strip = led_strip_new_rmt_ws2812(&strip_config); - strip->clear(strip, 100); // off led -#endif - - // Button - gpio_pad_select_gpio(BUTTON_PIN); - gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT); - gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY); - - // USB Controller Hal init - periph_module_reset(PERIPH_USB_MODULE); - periph_module_enable(PERIPH_USB_MODULE); - - usb_hal_context_t hal = { - .use_external_phy = false // use built-in PHY - }; - usb_hal_init(&hal); - configure_pins(&hal); -} - -static void configure_pins(usb_hal_context_t *usb) -{ - /* usb_periph_iopins currently configures USB_OTG as USB Device. - * Introduce additional parameters in usb_hal_context_t when adding support - * for USB Host. - */ - for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) { - if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) { - esp_rom_gpio_pad_select_gpio(iopin->pin); - if (iopin->is_output) { - esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false); - } else { - esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false); - if ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) { - gpio_ll_input_enable(&GPIO, iopin->pin); - } - } - esp_rom_gpio_pad_unhold(iopin->pin); - } - } - if (!usb->use_external_phy) { - gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); - gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); - } -} - -// Turn LED on or off -void board_led_write(bool state) -{ -#ifdef NEOPIXEL_PIN - strip->set_pixel(strip, 0, (state ? 0x88 : 0x00), 0x00, 0x00); - strip->refresh(strip, 100); -#endif -} - -// Get the current state of button -// a '1' means active (pressed), a '0' means inactive. -uint32_t board_button_read(void) -{ - return gpio_get_level(BUTTON_PIN) == BUTTON_STATE_ACTIVE; -} - -// Get characters from UART -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; - return 0; -} - -// Send characters to UART -int board_uart_write(void const * buf, int len) -{ - (void) buf; (void) len; - return 0; -} - diff --git a/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h b/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h deleted file mode 100644 index 6bb44f76d..000000000 --- a/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, 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. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// Note: need to insert jumper next to WS2812 pixel -#define NEOPIXEL_PIN 45 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/esp32s2/boards/espressif_saola_1/board.h b/hw/bsp/esp32s2/boards/espressif_saola_1/board.h deleted file mode 100644 index f450b9a8b..000000000 --- a/hw/bsp/esp32s2/boards/espressif_saola_1/board.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, 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. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// Note: On the production version (v1.2) WS2812 is connected to GPIO 18, -// however earlier revision v1.1 WS2812 is connected to GPIO 17 -#define NEOPIXEL_PIN 18 - -#define BUTTON_PIN 0 -#define BUTTON_STATE_ACTIVE 0 - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt b/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt deleted file mode 100644 index 6d0fcbc86..000000000 --- a/hw/bsp/esp32s2/components/led_strip/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(component_srcs "src/led_strip_rmt_ws2812.c") - -idf_component_register(SRCS "${component_srcs}" - INCLUDE_DIRS "include" - PRIV_INCLUDE_DIRS "" - PRIV_REQUIRES "driver" - REQUIRES "") - diff --git a/hw/bsp/esp32s2/components/led_strip/include/led_strip.h b/hw/bsp/esp32s2/components/led_strip/include/led_strip.h deleted file mode 100644 index a9dffc325..000000000 --- a/hw/bsp/esp32s2/components/led_strip/include/led_strip.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include "esp_err.h" - -/** -* @brief LED Strip Type -* -*/ -typedef struct led_strip_s led_strip_t; - -/** -* @brief LED Strip Device Type -* -*/ -typedef void *led_strip_dev_t; - -/** -* @brief Declare of LED Strip Type -* -*/ -struct led_strip_s { - /** - * @brief Set RGB for a specific pixel - * - * @param strip: LED strip - * @param index: index of pixel to set - * @param red: red part of color - * @param green: green part of color - * @param blue: blue part of color - * - * @return - * - ESP_OK: Set RGB for a specific pixel successfully - * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters - * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred - */ - esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue); - - /** - * @brief Refresh memory colors to LEDs - * - * @param strip: LED strip - * @param timeout_ms: timeout value for refreshing task - * - * @return - * - ESP_OK: Refresh successfully - * - ESP_ERR_TIMEOUT: Refresh failed because of timeout - * - ESP_FAIL: Refresh failed because some other error occurred - * - * @note: - * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip. - */ - esp_err_t (*refresh)(led_strip_t *strip, uint32_t timeout_ms); - - /** - * @brief Clear LED strip (turn off all LEDs) - * - * @param strip: LED strip - * @param timeout_ms: timeout value for clearing task - * - * @return - * - ESP_OK: Clear LEDs successfully - * - ESP_ERR_TIMEOUT: Clear LEDs failed because of timeout - * - ESP_FAIL: Clear LEDs failed because some other error occurred - */ - esp_err_t (*clear)(led_strip_t *strip, uint32_t timeout_ms); - - /** - * @brief Free LED strip resources - * - * @param strip: LED strip - * - * @return - * - ESP_OK: Free resources successfully - * - ESP_FAIL: Free resources failed because error occurred - */ - esp_err_t (*del)(led_strip_t *strip); -}; - -/** -* @brief LED Strip Configuration Type -* -*/ -typedef struct { - uint32_t max_leds; /*!< Maximum LEDs in a single strip */ - led_strip_dev_t dev; /*!< LED strip device (e.g. RMT channel, PWM channel, etc) */ -} led_strip_config_t; - -/** - * @brief Default configuration for LED strip - * - */ -#define LED_STRIP_DEFAULT_CONFIG(number, dev_hdl) \ - { \ - .max_leds = number, \ - .dev = dev_hdl, \ - } - -/** -* @brief Install a new ws2812 driver (based on RMT peripheral) -* -* @param config: LED strip configuration -* @return -* LED strip instance or NULL -*/ -led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config); - -#ifdef __cplusplus -} -#endif diff --git a/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c b/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c deleted file mode 100644 index 025d3c590..000000000 --- a/hw/bsp/esp32s2/components/led_strip/src/led_strip_rmt_ws2812.c +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include -#include -#include -#include "esp_log.h" -#include "esp_attr.h" -#include "led_strip.h" -#include "driver/rmt.h" - -static const char *TAG = "ws2812"; -#define STRIP_CHECK(a, str, goto_tag, ret_value, ...) \ - do \ - { \ - if (!(a)) \ - { \ - ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - ret = ret_value; \ - goto goto_tag; \ - } \ - } while (0) - -#define WS2812_T0H_NS (350) -#define WS2812_T0L_NS (1000) -#define WS2812_T1H_NS (1000) -#define WS2812_T1L_NS (350) -#define WS2812_RESET_US (280) - -static uint32_t ws2812_t0h_ticks = 0; -static uint32_t ws2812_t1h_ticks = 0; -static uint32_t ws2812_t0l_ticks = 0; -static uint32_t ws2812_t1l_ticks = 0; - -typedef struct { - led_strip_t parent; - rmt_channel_t rmt_channel; - uint32_t strip_len; - uint8_t buffer[0]; -} ws2812_t; - -/** - * @brief Conver RGB data to RMT format. - * - * @note For WS2812, R,G,B each contains 256 different choices (i.e. uint8_t) - * - * @param[in] src: source data, to converted to RMT format - * @param[in] dest: place where to store the convert result - * @param[in] src_size: size of source data - * @param[in] wanted_num: number of RMT items that want to get - * @param[out] translated_size: number of source data that got converted - * @param[out] item_num: number of RMT items which are converted from source data - */ -static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size, - size_t wanted_num, size_t *translated_size, size_t *item_num) -{ - if (src == NULL || dest == NULL) { - *translated_size = 0; - *item_num = 0; - return; - } - const rmt_item32_t bit0 = {{{ ws2812_t0h_ticks, 1, ws2812_t0l_ticks, 0 }}}; //Logical 0 - const rmt_item32_t bit1 = {{{ ws2812_t1h_ticks, 1, ws2812_t1l_ticks, 0 }}}; //Logical 1 - size_t size = 0; - size_t num = 0; - uint8_t *psrc = (uint8_t *)src; - rmt_item32_t *pdest = dest; - while (size < src_size && num < wanted_num) { - for (int i = 0; i < 8; i++) { - // MSB first - if (*psrc & (1 << (7 - i))) { - pdest->val = bit1.val; - } else { - pdest->val = bit0.val; - } - num++; - pdest++; - } - size++; - psrc++; - } - *translated_size = size; - *item_num = num; -} - -static esp_err_t ws2812_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue) -{ - esp_err_t ret = ESP_OK; - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - STRIP_CHECK(index < ws2812->strip_len, "index out of the maximum number of leds", err, ESP_ERR_INVALID_ARG); - uint32_t start = index * 3; - // In thr order of GRB - ws2812->buffer[start + 0] = green & 0xFF; - ws2812->buffer[start + 1] = red & 0xFF; - ws2812->buffer[start + 2] = blue & 0xFF; - return ESP_OK; -err: - return ret; -} - -static esp_err_t ws2812_refresh(led_strip_t *strip, uint32_t timeout_ms) -{ - esp_err_t ret = ESP_OK; - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - STRIP_CHECK(rmt_write_sample(ws2812->rmt_channel, ws2812->buffer, ws2812->strip_len * 3, true) == ESP_OK, - "transmit RMT samples failed", err, ESP_FAIL); - return rmt_wait_tx_done(ws2812->rmt_channel, pdMS_TO_TICKS(timeout_ms)); -err: - return ret; -} - -static esp_err_t ws2812_clear(led_strip_t *strip, uint32_t timeout_ms) -{ - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - // Write zero to turn off all leds - memset(ws2812->buffer, 0, ws2812->strip_len * 3); - return ws2812_refresh(strip, timeout_ms); -} - -static esp_err_t ws2812_del(led_strip_t *strip) -{ - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - free(ws2812); - return ESP_OK; -} - -led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config) -{ - led_strip_t *ret = NULL; - STRIP_CHECK(config, "configuration can't be null", err, NULL); - - // 24 bits per led - uint32_t ws2812_size = sizeof(ws2812_t) + config->max_leds * 3; - ws2812_t *ws2812 = calloc(1, ws2812_size); - STRIP_CHECK(ws2812, "request memory for ws2812 failed", err, NULL); - - uint32_t counter_clk_hz = 0; - STRIP_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev, &counter_clk_hz) == ESP_OK, - "get rmt counter clock failed", err, NULL); - // ns -> ticks - float ratio = (float)counter_clk_hz / 1e9; - ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS); - ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS); - ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS); - ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS); - - // set ws2812 to rmt adapter - rmt_translator_init((rmt_channel_t)config->dev, ws2812_rmt_adapter); - - ws2812->rmt_channel = (rmt_channel_t)config->dev; - ws2812->strip_len = config->max_leds; - - ws2812->parent.set_pixel = ws2812_set_pixel; - ws2812->parent.refresh = ws2812_refresh; - ws2812->parent.clear = ws2812_clear; - ws2812->parent.del = ws2812_del; - - return &ws2812->parent; -err: - return ret; -} diff --git a/hw/bsp/esp32s2/family.cmake b/hw/bsp/esp32s2/family.cmake deleted file mode 100644 index c19221b14..000000000 --- a/hw/bsp/esp32s2/family.cmake +++ /dev/null @@ -1,6 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -# Add example src and bsp directories -set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s2/boards" "${TOP}/hw/bsp/esp32s2/components") -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -set(SUPPORTED_TARGETS esp32s2) diff --git a/hw/bsp/esp32s2/family.mk b/hw/bsp/esp32s2/family.mk deleted file mode 100644 index 8bd290eb3..000000000 --- a/hw/bsp/esp32s2/family.mk +++ /dev/null @@ -1,36 +0,0 @@ -#DEPS_SUBMODULES += - -.PHONY: all clean flash - -all: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) build - -build: all - -clean: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) clean - -fullclean: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) fullclean - -flash: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) flash - -bootloader-flash: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) bootloader-flash - -app-flash: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) app-flash - -erase: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) erase_flash - -monitor: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) monitor - -uf2: $(BUILD)/$(PROJECT).uf2 - -UF2_FAMILY_ID = 0xbfdd4eee -$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).bin - @echo CREATE $@ - $(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -b 0x0 -c -o $@ $^ diff --git a/hw/bsp/esp32sx/boards/CMakeLists.txt b/hw/bsp/esp32sx/boards/CMakeLists.txt new file mode 100644 index 000000000..0d8de0895 --- /dev/null +++ b/hw/bsp/esp32sx/boards/CMakeLists.txt @@ -0,0 +1,14 @@ +idf_component_register(SRCS esp32sx.c + INCLUDE_DIRS "." "${BOARD}" + PRIV_REQUIRES "driver" + REQUIRES freertos src led_strip) + +# Apply board specific content +add_subdirectory(${BOARD}) + +idf_component_get_property( FREERTOS_ORIG_INCLUDE_PATH freertos ORIG_INCLUDE_PATH) +target_include_directories(${COMPONENT_TARGET} PUBLIC + "${FREERTOS_ORIG_INCLUDE_PATH}" + "${TOP}/hw" + "${TOP}/src" +) diff --git a/hw/bsp/esp32sx/boards/adafruit_feather_esp32s2/CMakeLists.txt b/hw/bsp/esp32sx/boards/adafruit_feather_esp32s2/CMakeLists.txt new file mode 100644 index 000000000..fc7f5a43a --- /dev/null +++ b/hw/bsp/esp32sx/boards/adafruit_feather_esp32s2/CMakeLists.txt @@ -0,0 +1,15 @@ +# Apply board specific context here +target_include_directories(${COMPONENT_LIB} PRIVATE .) + +message(STATUS "Apply board specific content ${BOARD}: $ENV{IDF_TARGET} " ) +idf_build_get_property(idf_target IDF_TARGET) + +if(NOT ${idf_target} STREQUAL "esp32s2") + message(STATUS "Incorrect target for board ${BOARD}: $ENV{IDF_TARGET} " ) + set(IDF_TARGET "esp32s2" FORCE) +endif() + +target_compile_options(${COMPONENT_TARGET} PUBLIC + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" +) \ No newline at end of file diff --git a/hw/bsp/esp32sx/boards/adafruit_feather_esp32s2/board.h b/hw/bsp/esp32sx/boards/adafruit_feather_esp32s2/board.h new file mode 100644 index 000000000..43e00901d --- /dev/null +++ b/hw/bsp/esp32sx/boards/adafruit_feather_esp32s2/board.h @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define NEOPIXEL_PIN 33 +#define NEOPIXEL_POWER_PIN 21 +#define NEOPIXEL_POWER_STATE 1 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/esp32sx/boards/adafruit_feather_esp32s2/board.mk b/hw/bsp/esp32sx/boards/adafruit_feather_esp32s2/board.mk new file mode 100644 index 000000000..7308a9f62 --- /dev/null +++ b/hw/bsp/esp32sx/boards/adafruit_feather_esp32s2/board.mk @@ -0,0 +1,3 @@ +IDF_TARGET = esp32s2 + +$(info Processing of board.mk for board: $(BOARD){$(BOARD_PATH)}, family: $(FAMILY), target: $(IDF_TARGET)) \ No newline at end of file diff --git a/hw/bsp/esp32sx/boards/adafruit_magtag_29gray/CMakeLists.txt b/hw/bsp/esp32sx/boards/adafruit_magtag_29gray/CMakeLists.txt new file mode 100644 index 000000000..fc7f5a43a --- /dev/null +++ b/hw/bsp/esp32sx/boards/adafruit_magtag_29gray/CMakeLists.txt @@ -0,0 +1,15 @@ +# Apply board specific context here +target_include_directories(${COMPONENT_LIB} PRIVATE .) + +message(STATUS "Apply board specific content ${BOARD}: $ENV{IDF_TARGET} " ) +idf_build_get_property(idf_target IDF_TARGET) + +if(NOT ${idf_target} STREQUAL "esp32s2") + message(STATUS "Incorrect target for board ${BOARD}: $ENV{IDF_TARGET} " ) + set(IDF_TARGET "esp32s2" FORCE) +endif() + +target_compile_options(${COMPONENT_TARGET} PUBLIC + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" +) \ No newline at end of file diff --git a/hw/bsp/esp32sx/boards/adafruit_magtag_29gray/board.h b/hw/bsp/esp32sx/boards/adafruit_magtag_29gray/board.h new file mode 100644 index 000000000..16e30b685 --- /dev/null +++ b/hw/bsp/esp32sx/boards/adafruit_magtag_29gray/board.h @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define NEOPIXEL_PIN 1 +#define NEOPIXEL_POWER_PIN 21 +#define NEOPIXEL_POWER_STATE 0 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/esp32sx/boards/adafruit_magtag_29gray/board.mk b/hw/bsp/esp32sx/boards/adafruit_magtag_29gray/board.mk new file mode 100644 index 000000000..7308a9f62 --- /dev/null +++ b/hw/bsp/esp32sx/boards/adafruit_magtag_29gray/board.mk @@ -0,0 +1,3 @@ +IDF_TARGET = esp32s2 + +$(info Processing of board.mk for board: $(BOARD){$(BOARD_PATH)}, family: $(FAMILY), target: $(IDF_TARGET)) \ No newline at end of file diff --git a/hw/bsp/esp32sx/boards/adafruit_metro_esp32s2/CMakeLists.txt b/hw/bsp/esp32sx/boards/adafruit_metro_esp32s2/CMakeLists.txt new file mode 100644 index 000000000..fc7f5a43a --- /dev/null +++ b/hw/bsp/esp32sx/boards/adafruit_metro_esp32s2/CMakeLists.txt @@ -0,0 +1,15 @@ +# Apply board specific context here +target_include_directories(${COMPONENT_LIB} PRIVATE .) + +message(STATUS "Apply board specific content ${BOARD}: $ENV{IDF_TARGET} " ) +idf_build_get_property(idf_target IDF_TARGET) + +if(NOT ${idf_target} STREQUAL "esp32s2") + message(STATUS "Incorrect target for board ${BOARD}: $ENV{IDF_TARGET} " ) + set(IDF_TARGET "esp32s2" FORCE) +endif() + +target_compile_options(${COMPONENT_TARGET} PUBLIC + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" +) \ No newline at end of file diff --git a/hw/bsp/esp32sx/boards/adafruit_metro_esp32s2/board.h b/hw/bsp/esp32sx/boards/adafruit_metro_esp32s2/board.h new file mode 100644 index 000000000..49a2474bc --- /dev/null +++ b/hw/bsp/esp32sx/boards/adafruit_metro_esp32s2/board.h @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define NEOPIXEL_PIN 45 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/esp32sx/boards/adafruit_metro_esp32s2/board.mk b/hw/bsp/esp32sx/boards/adafruit_metro_esp32s2/board.mk new file mode 100644 index 000000000..7308a9f62 --- /dev/null +++ b/hw/bsp/esp32sx/boards/adafruit_metro_esp32s2/board.mk @@ -0,0 +1,3 @@ +IDF_TARGET = esp32s2 + +$(info Processing of board.mk for board: $(BOARD){$(BOARD_PATH)}, family: $(FAMILY), target: $(IDF_TARGET)) \ No newline at end of file diff --git a/hw/bsp/esp32sx/boards/esp32sx.c b/hw/bsp/esp32sx/boards/esp32sx.c new file mode 100644 index 000000000..358c0c803 --- /dev/null +++ b/hw/bsp/esp32sx/boards/esp32sx.c @@ -0,0 +1,143 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "../../board.h" +#include "board.h" + +#include "esp_rom_gpio.h" +#include "hal/gpio_ll.h" +#include "hal/usb_hal.h" +#include "soc/usb_periph.h" + +#include "driver/periph_ctrl.h" +#include "driver/rmt.h" + +#ifdef NEOPIXEL_PIN +#include "led_strip.h" +static led_strip_t *strip; +#endif + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +static void configure_pins(usb_hal_context_t *usb); + +// Initialize on-board peripherals : led, button, uart and USB +void board_init(void) +{ + +#ifdef NEOPIXEL_PIN + #ifdef NEOPIXEL_POWER_PIN + gpio_reset_pin(NEOPIXEL_POWER_PIN); + gpio_set_direction(NEOPIXEL_POWER_PIN, GPIO_MODE_OUTPUT); + gpio_set_level(NEOPIXEL_POWER_PIN, NEOPIXEL_POWER_STATE); + #endif + + // WS2812 Neopixel driver with RMT peripheral + rmt_config_t config = RMT_DEFAULT_CONFIG_TX(NEOPIXEL_PIN, RMT_CHANNEL_0); + config.clk_div = 2; // set counter clock to 40MHz + + rmt_config(&config); + rmt_driver_install(config.channel, 0, 0); + + led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(1, (led_strip_dev_t) config.channel); + strip = led_strip_new_rmt_ws2812(&strip_config); + strip->clear(strip, 100); // off led +#endif + + // Button + gpio_pad_select_gpio(BUTTON_PIN); + gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT); + gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY); + + // USB Controller Hal init + periph_module_reset(PERIPH_USB_MODULE); + periph_module_enable(PERIPH_USB_MODULE); + + usb_hal_context_t hal = { + .use_external_phy = false // use built-in PHY + }; + usb_hal_init(&hal); + configure_pins(&hal); +} + +static void configure_pins(usb_hal_context_t *usb) +{ + /* usb_periph_iopins currently configures USB_OTG as USB Device. + * Introduce additional parameters in usb_hal_context_t when adding support + * for USB Host. + */ + for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) { + if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) { + esp_rom_gpio_pad_select_gpio(iopin->pin); + if (iopin->is_output) { + esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false); + } else { + esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false); + if ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) { + gpio_ll_input_enable(&GPIO, iopin->pin); + } + } + esp_rom_gpio_pad_unhold(iopin->pin); + } + } + if (!usb->use_external_phy) { + gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); + gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); + } +} + +// Turn LED on or off +void board_led_write(bool state) +{ +#ifdef NEOPIXEL_PIN + strip->set_pixel(strip, 0, (state ? 0x88 : 0x00), 0x00, 0x00); + strip->refresh(strip, 100); +#endif +} + +// Get the current state of button +// a '1' means active (pressed), a '0' means inactive. +uint32_t board_button_read(void) +{ + return gpio_get_level(BUTTON_PIN) == BUTTON_STATE_ACTIVE; +} + +// Get characters from UART +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +// Send characters to UART +int board_uart_write(void const * buf, int len) +{ + (void) buf; (void) len; + return 0; +} + diff --git a/hw/bsp/esp32sx/boards/espressif_addax_1/CMakeLists.txt b/hw/bsp/esp32sx/boards/espressif_addax_1/CMakeLists.txt new file mode 100644 index 000000000..b64efa399 --- /dev/null +++ b/hw/bsp/esp32sx/boards/espressif_addax_1/CMakeLists.txt @@ -0,0 +1,15 @@ +# Apply board specific content here +target_include_directories(${COMPONENT_LIB} PRIVATE .) + +message(STATUS "Apply board specific content ${BOARD}: $ENV{IDF_TARGET} " ) +idf_build_get_property(idf_target IDF_TARGET) + +if(NOT ${idf_target} STREQUAL "esp32s3") + message(STATUS "Incorrect target for board ${BOARD}: $ENV{IDF_TARGET} " ) + set(IDF_TARGET "esp32s3" FORCE) +endif() + +target_compile_options(${COMPONENT_TARGET} PUBLIC + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S3" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" +) \ No newline at end of file diff --git a/hw/bsp/esp32sx/boards/espressif_addax_1/board.h b/hw/bsp/esp32sx/boards/espressif_addax_1/board.h new file mode 100644 index 000000000..fff24ba44 --- /dev/null +++ b/hw/bsp/esp32sx/boards/espressif_addax_1/board.h @@ -0,0 +1,44 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// Note: On the production version (v1.1) WS2812 is connected to GPIO 47 +#define NEOPIXEL_PIN 47 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/esp32sx/boards/espressif_addax_1/board.mk b/hw/bsp/esp32sx/boards/espressif_addax_1/board.mk new file mode 100644 index 000000000..6c5bda9b1 --- /dev/null +++ b/hw/bsp/esp32sx/boards/espressif_addax_1/board.mk @@ -0,0 +1,3 @@ +IDF_TARGET = esp32s3 + +$(info Processing of board.mk for board: $(BOARD){$(BOARD_PATH)}, family: $(FAMILY), target: $(IDF_TARGET)) \ No newline at end of file diff --git a/hw/bsp/esp32sx/boards/espressif_kaluga_1/CMakeLists.txt b/hw/bsp/esp32sx/boards/espressif_kaluga_1/CMakeLists.txt new file mode 100644 index 000000000..9b76625a7 --- /dev/null +++ b/hw/bsp/esp32sx/boards/espressif_kaluga_1/CMakeLists.txt @@ -0,0 +1,14 @@ +# Apply board specific context here +target_include_directories(${COMPONENT_LIB} PRIVATE .) + +idf_build_get_property(idf_target IDF_TARGET) + +if( NOT ${idf_target} STREQUAL "esp32s2") + message(STATUS "Incorrect target for board ${BOARD}: $ENV{IDF_TARGET} " ) + set(IDF_TARGET "esp32s2" FORCE) +endif() + +target_compile_options(${COMPONENT_TARGET} PUBLIC + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" +) \ No newline at end of file diff --git a/hw/bsp/esp32sx/boards/espressif_kaluga_1/board.h b/hw/bsp/esp32sx/boards/espressif_kaluga_1/board.h new file mode 100644 index 000000000..6bb44f76d --- /dev/null +++ b/hw/bsp/esp32sx/boards/espressif_kaluga_1/board.h @@ -0,0 +1,44 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// Note: need to insert jumper next to WS2812 pixel +#define NEOPIXEL_PIN 45 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/esp32sx/boards/espressif_kaluga_1/board.mk b/hw/bsp/esp32sx/boards/espressif_kaluga_1/board.mk new file mode 100644 index 000000000..7308a9f62 --- /dev/null +++ b/hw/bsp/esp32sx/boards/espressif_kaluga_1/board.mk @@ -0,0 +1,3 @@ +IDF_TARGET = esp32s2 + +$(info Processing of board.mk for board: $(BOARD){$(BOARD_PATH)}, family: $(FAMILY), target: $(IDF_TARGET)) \ No newline at end of file diff --git a/hw/bsp/esp32sx/boards/espressif_saola_1/CMakeLists.txt b/hw/bsp/esp32sx/boards/espressif_saola_1/CMakeLists.txt new file mode 100644 index 000000000..c034a11a6 --- /dev/null +++ b/hw/bsp/esp32sx/boards/espressif_saola_1/CMakeLists.txt @@ -0,0 +1,14 @@ +# Apply board specific context here +target_include_directories(${COMPONENT_LIB} PUBLIC .) + +idf_build_get_property(idf_target IDF_TARGET) + +if(NOT ${idf_target} STREQUAL "esp32s2") + message(STATUS "Incorrect target for board ${BOARD}: $ENV{IDF_TARGET} " ) + set(IDF_TARGET "esp32s2" FORCE) +endif() + +target_compile_options(${COMPONENT_TARGET} PUBLIC + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + "-DCFG_TUSB_OS=OPT_OS_FREERTOS" +) \ No newline at end of file diff --git a/hw/bsp/esp32sx/boards/espressif_saola_1/board.h b/hw/bsp/esp32sx/boards/espressif_saola_1/board.h new file mode 100644 index 000000000..f450b9a8b --- /dev/null +++ b/hw/bsp/esp32sx/boards/espressif_saola_1/board.h @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// Note: On the production version (v1.2) WS2812 is connected to GPIO 18, +// however earlier revision v1.1 WS2812 is connected to GPIO 17 +#define NEOPIXEL_PIN 18 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/esp32sx/boards/espressif_saola_1/board.mk b/hw/bsp/esp32sx/boards/espressif_saola_1/board.mk new file mode 100644 index 000000000..7308a9f62 --- /dev/null +++ b/hw/bsp/esp32sx/boards/espressif_saola_1/board.mk @@ -0,0 +1,3 @@ +IDF_TARGET = esp32s2 + +$(info Processing of board.mk for board: $(BOARD){$(BOARD_PATH)}, family: $(FAMILY), target: $(IDF_TARGET)) \ No newline at end of file diff --git a/hw/bsp/esp32sx/components/led_strip/CMakeLists.txt b/hw/bsp/esp32sx/components/led_strip/CMakeLists.txt new file mode 100644 index 000000000..6d0fcbc86 --- /dev/null +++ b/hw/bsp/esp32sx/components/led_strip/CMakeLists.txt @@ -0,0 +1,8 @@ +set(component_srcs "src/led_strip_rmt_ws2812.c") + +idf_component_register(SRCS "${component_srcs}" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "" + PRIV_REQUIRES "driver" + REQUIRES "") + diff --git a/hw/bsp/esp32sx/components/led_strip/include/led_strip.h b/hw/bsp/esp32sx/components/led_strip/include/led_strip.h new file mode 100644 index 000000000..a9dffc325 --- /dev/null +++ b/hw/bsp/esp32sx/components/led_strip/include/led_strip.h @@ -0,0 +1,126 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" + +/** +* @brief LED Strip Type +* +*/ +typedef struct led_strip_s led_strip_t; + +/** +* @brief LED Strip Device Type +* +*/ +typedef void *led_strip_dev_t; + +/** +* @brief Declare of LED Strip Type +* +*/ +struct led_strip_s { + /** + * @brief Set RGB for a specific pixel + * + * @param strip: LED strip + * @param index: index of pixel to set + * @param red: red part of color + * @param green: green part of color + * @param blue: blue part of color + * + * @return + * - ESP_OK: Set RGB for a specific pixel successfully + * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters + * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred + */ + esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue); + + /** + * @brief Refresh memory colors to LEDs + * + * @param strip: LED strip + * @param timeout_ms: timeout value for refreshing task + * + * @return + * - ESP_OK: Refresh successfully + * - ESP_ERR_TIMEOUT: Refresh failed because of timeout + * - ESP_FAIL: Refresh failed because some other error occurred + * + * @note: + * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip. + */ + esp_err_t (*refresh)(led_strip_t *strip, uint32_t timeout_ms); + + /** + * @brief Clear LED strip (turn off all LEDs) + * + * @param strip: LED strip + * @param timeout_ms: timeout value for clearing task + * + * @return + * - ESP_OK: Clear LEDs successfully + * - ESP_ERR_TIMEOUT: Clear LEDs failed because of timeout + * - ESP_FAIL: Clear LEDs failed because some other error occurred + */ + esp_err_t (*clear)(led_strip_t *strip, uint32_t timeout_ms); + + /** + * @brief Free LED strip resources + * + * @param strip: LED strip + * + * @return + * - ESP_OK: Free resources successfully + * - ESP_FAIL: Free resources failed because error occurred + */ + esp_err_t (*del)(led_strip_t *strip); +}; + +/** +* @brief LED Strip Configuration Type +* +*/ +typedef struct { + uint32_t max_leds; /*!< Maximum LEDs in a single strip */ + led_strip_dev_t dev; /*!< LED strip device (e.g. RMT channel, PWM channel, etc) */ +} led_strip_config_t; + +/** + * @brief Default configuration for LED strip + * + */ +#define LED_STRIP_DEFAULT_CONFIG(number, dev_hdl) \ + { \ + .max_leds = number, \ + .dev = dev_hdl, \ + } + +/** +* @brief Install a new ws2812 driver (based on RMT peripheral) +* +* @param config: LED strip configuration +* @return +* LED strip instance or NULL +*/ +led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config); + +#ifdef __cplusplus +} +#endif diff --git a/hw/bsp/esp32sx/components/led_strip/src/led_strip_rmt_ws2812.c b/hw/bsp/esp32sx/components/led_strip/src/led_strip_rmt_ws2812.c new file mode 100644 index 000000000..025d3c590 --- /dev/null +++ b/hw/bsp/esp32sx/components/led_strip/src/led_strip_rmt_ws2812.c @@ -0,0 +1,171 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include +#include "esp_log.h" +#include "esp_attr.h" +#include "led_strip.h" +#include "driver/rmt.h" + +static const char *TAG = "ws2812"; +#define STRIP_CHECK(a, str, goto_tag, ret_value, ...) \ + do \ + { \ + if (!(a)) \ + { \ + ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ret = ret_value; \ + goto goto_tag; \ + } \ + } while (0) + +#define WS2812_T0H_NS (350) +#define WS2812_T0L_NS (1000) +#define WS2812_T1H_NS (1000) +#define WS2812_T1L_NS (350) +#define WS2812_RESET_US (280) + +static uint32_t ws2812_t0h_ticks = 0; +static uint32_t ws2812_t1h_ticks = 0; +static uint32_t ws2812_t0l_ticks = 0; +static uint32_t ws2812_t1l_ticks = 0; + +typedef struct { + led_strip_t parent; + rmt_channel_t rmt_channel; + uint32_t strip_len; + uint8_t buffer[0]; +} ws2812_t; + +/** + * @brief Conver RGB data to RMT format. + * + * @note For WS2812, R,G,B each contains 256 different choices (i.e. uint8_t) + * + * @param[in] src: source data, to converted to RMT format + * @param[in] dest: place where to store the convert result + * @param[in] src_size: size of source data + * @param[in] wanted_num: number of RMT items that want to get + * @param[out] translated_size: number of source data that got converted + * @param[out] item_num: number of RMT items which are converted from source data + */ +static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size, + size_t wanted_num, size_t *translated_size, size_t *item_num) +{ + if (src == NULL || dest == NULL) { + *translated_size = 0; + *item_num = 0; + return; + } + const rmt_item32_t bit0 = {{{ ws2812_t0h_ticks, 1, ws2812_t0l_ticks, 0 }}}; //Logical 0 + const rmt_item32_t bit1 = {{{ ws2812_t1h_ticks, 1, ws2812_t1l_ticks, 0 }}}; //Logical 1 + size_t size = 0; + size_t num = 0; + uint8_t *psrc = (uint8_t *)src; + rmt_item32_t *pdest = dest; + while (size < src_size && num < wanted_num) { + for (int i = 0; i < 8; i++) { + // MSB first + if (*psrc & (1 << (7 - i))) { + pdest->val = bit1.val; + } else { + pdest->val = bit0.val; + } + num++; + pdest++; + } + size++; + psrc++; + } + *translated_size = size; + *item_num = num; +} + +static esp_err_t ws2812_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue) +{ + esp_err_t ret = ESP_OK; + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + STRIP_CHECK(index < ws2812->strip_len, "index out of the maximum number of leds", err, ESP_ERR_INVALID_ARG); + uint32_t start = index * 3; + // In thr order of GRB + ws2812->buffer[start + 0] = green & 0xFF; + ws2812->buffer[start + 1] = red & 0xFF; + ws2812->buffer[start + 2] = blue & 0xFF; + return ESP_OK; +err: + return ret; +} + +static esp_err_t ws2812_refresh(led_strip_t *strip, uint32_t timeout_ms) +{ + esp_err_t ret = ESP_OK; + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + STRIP_CHECK(rmt_write_sample(ws2812->rmt_channel, ws2812->buffer, ws2812->strip_len * 3, true) == ESP_OK, + "transmit RMT samples failed", err, ESP_FAIL); + return rmt_wait_tx_done(ws2812->rmt_channel, pdMS_TO_TICKS(timeout_ms)); +err: + return ret; +} + +static esp_err_t ws2812_clear(led_strip_t *strip, uint32_t timeout_ms) +{ + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + // Write zero to turn off all leds + memset(ws2812->buffer, 0, ws2812->strip_len * 3); + return ws2812_refresh(strip, timeout_ms); +} + +static esp_err_t ws2812_del(led_strip_t *strip) +{ + ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); + free(ws2812); + return ESP_OK; +} + +led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config) +{ + led_strip_t *ret = NULL; + STRIP_CHECK(config, "configuration can't be null", err, NULL); + + // 24 bits per led + uint32_t ws2812_size = sizeof(ws2812_t) + config->max_leds * 3; + ws2812_t *ws2812 = calloc(1, ws2812_size); + STRIP_CHECK(ws2812, "request memory for ws2812 failed", err, NULL); + + uint32_t counter_clk_hz = 0; + STRIP_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev, &counter_clk_hz) == ESP_OK, + "get rmt counter clock failed", err, NULL); + // ns -> ticks + float ratio = (float)counter_clk_hz / 1e9; + ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS); + ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS); + ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS); + ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS); + + // set ws2812 to rmt adapter + rmt_translator_init((rmt_channel_t)config->dev, ws2812_rmt_adapter); + + ws2812->rmt_channel = (rmt_channel_t)config->dev; + ws2812->strip_len = config->max_leds; + + ws2812->parent.set_pixel = ws2812_set_pixel; + ws2812->parent.refresh = ws2812_refresh; + ws2812->parent.clear = ws2812_clear; + ws2812->parent.del = ws2812_del; + + return &ws2812->parent; +err: + return ret; +} diff --git a/hw/bsp/esp32sx/family.cmake b/hw/bsp/esp32sx/family.cmake new file mode 100644 index 000000000..54f36e5d0 --- /dev/null +++ b/hw/bsp/esp32sx/family.cmake @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.5) + +# Add example src and bsp directories +set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32sx/boards" "${TOP}/hw/bsp/esp32sx/components") +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(SUPPORTED_TARGETS esp32s2 esp32s3) diff --git a/hw/bsp/esp32sx/family.mk b/hw/bsp/esp32sx/family.mk new file mode 100644 index 000000000..46df596ea --- /dev/null +++ b/hw/bsp/esp32sx/family.mk @@ -0,0 +1,26 @@ +#DEPS_SUBMODULES += + +.PHONY: all clean flash bootloader-flash app-flash erase monitor dfu-flash dfu + +all: + idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) -DIDF_TARGET=$(IDF_TARGET) build + +build: all + +clean: + idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) clean + +fullclean: + if test -f sdkconfig; then $(RM) -f sdkconfig ; fi + if test -d $(BUILD); then $(RM) -rf $(BUILD) ; fi + +flash bootloader-flash app-flash erase monitor dfu-flash dfu: + idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@ + +uf2: $(BUILD)/$(PROJECT).uf2 + +UF2_FAMILY_ID = 0xbfdd4eee +$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).bin + @echo CREATE $@ + $(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -b 0x0 -c -o $@ $^ + diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 004bd1b6b..66070c273 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -67,7 +67,7 @@ static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) BaseType_t xHigherPriorityTaskWoken; BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken); -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); #else portYIELD_FROM_ISR(xHigherPriorityTaskWoken); @@ -150,7 +150,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in BaseType_t xHigherPriorityTaskWoken; BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken); -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); #else portYIELD_FROM_ISR(xHigherPriorityTaskWoken); diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c deleted file mode 100644 index edbc872fe..000000000 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ /dev/null @@ -1,867 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Additions Copyright (c) 2020, Espressif Systems (Shanghai) Co. Ltd. - * - * 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. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" -#include "common/tusb_fifo.h" - -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 && TUSB_OPT_DEVICE_ENABLED - -// Espressif -#include "driver/periph_ctrl.h" -#include "freertos/xtensa_api.h" -#include "esp_intr_alloc.h" -#include "esp_log.h" -#include "esp32s2/rom/gpio.h" -#include "soc/dport_reg.h" -#include "soc/gpio_sig_map.h" -#include "soc/usb_periph.h" - -#include "device/dcd.h" - -// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) -// We disable SOF for now until needed later on -#define USE_SOF 0 - -// Max number of bi-directional endpoints including EP0 -// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0 -// We should probably prohibit enabling Endpoint IN > 4 (not done yet) -#define EP_MAX USB_OUT_EP_NUM - -// FIFO size in bytes -#define EP_FIFO_SIZE 1024 - -// Max number of IN EP FIFOs -#define EP_FIFO_NUM 5 - -typedef struct { - uint8_t *buffer; - // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API - uint16_t total_len; - uint16_t queued_len; - uint16_t max_size; - bool short_packet; -} xfer_ctl_t; - -static const char *TAG = "TUSB:DCD"; -static intr_handle_t usb_ih; - - -static uint32_t _setup_packet[2]; - -#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] -static xfer_ctl_t xfer_status[EP_MAX][2]; - -// Keep count of how many FIFOs are in use -static uint8_t _allocated_fifos = 1; //FIFO0 is always in use - -// Will either return an unused FIFO number, or 0 if all are used. -static uint8_t get_free_fifo(void) -{ - if (_allocated_fifos < EP_FIFO_NUM) return _allocated_fifos++; - return 0; -} - -// Setup the control endpoint 0. -static void bus_reset(void) -{ - for (int ep_num = 0; ep_num < USB_OUT_EP_NUM; ep_num++) { - USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK - } - - USB0.dcfg &= ~USB_DEVADDR_M; // reset address - - USB0.daintmsk |= USB_OUTEPMSK0_M | USB_INEPMSK0_M; - USB0.doepmsk |= USB_SETUPMSK_M | USB_XFERCOMPLMSK; - USB0.diepmsk |= USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; - - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | - // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits): - // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN - // - // - All EP OUT shared a unique OUT FIFO which uses - // * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets). - // * 2 locations for OUT endpoint control words. - // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) - // * 1 location for global NAK (not required/used here). - // * It is recommended to allocate 2 times the largest packet size, therefore - // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 - USB0.grstctl |= 0x10 << USB_TXFNUM_S; // fifo 0x10, - USB0.grstctl |= USB_TXFFLSH_M; // Flush fifo - USB0.grxfsiz = 52; - - // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); - - // Ready to receive SETUP packet - USB0.out_ep_reg[0].doeptsiz |= USB_SUPCNT0_M; - - USB0.gintmsk |= USB_IEPINTMSK_M | USB_OEPINTMSK_M; -} - -static void enum_done_processing(void) -{ - ESP_EARLY_LOGV(TAG, "dcd_int_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); - // On current silicon on the Full Speed core, speed is fixed to Full Speed. - // However, keep for debugging and in case Low Speed is ever supported. - uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); - - // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL - if (enum_spd == 0x03) { // Full-Speed (PHY on 48 MHz) - USB0.in_ep_reg[0].diepctl &= ~USB_D_MPS0_V; // 64 bytes - USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; - } else { - USB0.in_ep_reg[0].diepctl |= USB_D_MPS0_V; // 8 bytes - USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall - xfer_status[0][TUSB_DIR_OUT].max_size = 8; - xfer_status[0][TUSB_DIR_IN].max_size = 8; - } -} - - -/*------------------------------------------------------------------*/ -/* Controller API - *------------------------------------------------------------------*/ -void dcd_init(uint8_t rhport) -{ - ESP_LOGV(TAG, "DCD init - Start"); - - // A. Disconnect - ESP_LOGV(TAG, "DCD init - Soft DISCONNECT and Setting up"); - USB0.dctl |= USB_SFTDISCON_M; // Soft disconnect - - // B. Programming DCFG - /* If USB host misbehaves during status portion of control xfer - (non zero-length packet), send STALL back and discard. Full speed. */ - USB0.dcfg |= USB_NZSTSOUTHSHK_M | // NonZero .... STALL - (3 << 0); // dev speed: fullspeed 1.1 on 48 mhz // TODO no value in usb_reg.h (IDF-1476) - - USB0.gahbcfg |= USB_NPTXFEMPLVL_M | USB_GLBLLNTRMSK_M; // Global interruptions ON - USB0.gusbcfg |= USB_FORCEDEVMODE_M; // force devmode - USB0.gotgctl &= ~(USB_BVALIDOVVAL_M | USB_BVALIDOVEN_M | USB_VBVALIDOVVAL_M); //no overrides - - // C. Setting SNAKs, then connect - for (int n = 0; n < USB_OUT_EP_NUM; n++) { - USB0.out_ep_reg[n].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK - } - - // D. Interruption masking - USB0.gintmsk = 0; //mask all - USB0.gotgint = ~0U; //clear OTG ints - USB0.gintsts = ~0U; //clear pending ints - USB0.gintmsk = USB_OTGINTMSK_M | - USB_MODEMISMSK_M | - #if USE_SOF - USB_SOFMSK_M | - #endif - USB_RXFLVIMSK_M | - USB_ERLYSUSPMSK_M | - USB_USBSUSPMSK_M | - USB_USBRSTMSK_M | - USB_ENUMDONEMSK_M | - USB_RESETDETMSK_M | - USB_DISCONNINTMSK_M; // host most only - - dcd_connect(rhport); -} - -void dcd_set_address(uint8_t rhport, uint8_t dev_addr) -{ - (void)rhport; - ESP_LOGV(TAG, "DCD init - Set address : %u", dev_addr); - USB0.dcfg |= ((dev_addr & USB_DEVADDR_V) << USB_DEVADDR_S); - // Response with status after changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); -} - -void dcd_remote_wakeup(uint8_t rhport) -{ - (void)rhport; - - // TODO must manually clear this bit after 1-15 ms - // USB0.DCTL |= USB_RMTWKUPSIG_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 - *------------------------------------------------------------------*/ - -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) -{ - ESP_LOGV(TAG, "DCD endpoint opened"); - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - - TU_ASSERT(epnum < EP_MAX); - - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); - xfer->max_size = desc_edpt->wMaxPacketSize.size; - - if (dir == TUSB_DIR_OUT) { - out_ep[epnum].doepctl |= USB_USBACTEP0_M | - desc_edpt->bmAttributes.xfer << USB_EPTYPE0_S | - desc_edpt->wMaxPacketSize.size << USB_MPS0_S; - USB0.daintmsk |= (1 << (16 + epnum)); - } else { - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | - // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints - // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1) - // - Offset: GRXFSIZ + 16 + Size*(epnum-1) - // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". - - uint8_t fifo_num = get_free_fifo(); - TU_ASSERT(fifo_num != 0); - - in_ep[epnum].diepctl &= ~(USB_D_TXFNUM1_M | USB_D_EPTYPE1_M | USB_DI_SETD0PID1 | USB_D_MPS1_M); - in_ep[epnum].diepctl |= USB_D_USBACTEP1_M | - fifo_num << USB_D_TXFNUM1_S | - desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | - desc_edpt->wMaxPacketSize.size << 0; - - USB0.daintmsk |= (1 << (0 + epnum)); - - // Both TXFD and TXSA are in unit of 32-bit words. - // IN FIFO 0 was configured during enumeration, hence the "+ 16". - uint16_t const allocated_size = (USB0.grxfsiz & 0x0000ffff) + 16; - uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_FIFO_NUM-1); - uint32_t const fifo_offset = allocated_size + fifo_size*(fifo_num-1); - - // DIEPTXF starts at FIFO #1. - USB0.dieptxf[epnum - 1] = (fifo_size << USB_NPTXFDEP_S) | fifo_offset; - } - return true; -} - -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) -{ - (void)rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = buffer; - // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API - xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->short_packet = false; - - uint16_t num_packets = (total_bytes / xfer->max_size); - uint8_t short_packet_size = total_bytes % xfer->max_size; - - // Zero-size packet is special case. - if (short_packet_size > 0 || (total_bytes == 0)) { - num_packets++; - } - - ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", - epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), - num_packets, total_bytes); - - // IN and OUT endpoint xfers are interrupt-driven, we just schedule them - // here. - if (dir == TUSB_DIR_IN) { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; - USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK - - // Enable fifo empty interrupt only if there are something to put in the fifo. - if(total_bytes != 0) { - USB0.dtknqr4_fifoemptymsk |= (1 << epnum); - } - } else { - // Each complete packet for OUT xfers triggers XFRC. - USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; - } - return true; -} - -#if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) -{ - (void)rhport; - - // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 - TU_ASSERT(ff->item_size == 1); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = NULL; - xfer->ff = ff; - xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->short_packet = false; - - uint16_t num_packets = (total_bytes / xfer->max_size); - uint8_t short_packet_size = total_bytes % xfer->max_size; - - // Zero-size packet is special case. - if (short_packet_size > 0 || (total_bytes == 0)) { - num_packets++; - } - - ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", - epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), - num_packets, total_bytes); - - // IN and OUT endpoint xfers are interrupt-driven, we just schedule them - // here. - if (dir == TUSB_DIR_IN) { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; - USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK - - // Enable fifo empty interrupt only if there are something to put in the fifo. - if(total_bytes != 0) { - USB0.dtknqr4_fifoemptymsk |= (1 << epnum); - } - } else { - // Each complete packet for OUT xfers triggers XFRC. - USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; - } - return true; -} -#endif - -void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - if (dir == TUSB_DIR_IN) { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(in_ep[epnum].diepctl & USB_D_EPENA1_M)) { - in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M); - } else { - // Stop transmitting packets and NAK IN xfers. - in_ep[epnum].diepctl |= USB_DI_SNAK1_M; - while ((in_ep[epnum].diepint & USB_DI_SNAK1_M) == 0) ; - - // Disable the endpoint. Note that both SNAK and STALL are set here. - in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M | USB_D_EPDIS1_M); - while ((in_ep[epnum].diepint & USB_D_EPDISBLD0_M) == 0) ; - in_ep[epnum].diepint = USB_D_EPDISBLD0_M; - } - - // Flush the FIFO, and wait until we have confirmed it cleared. - uint8_t const fifo_num = ((in_ep[epnum].diepctl >> USB_D_TXFNUM1_S) & USB_D_TXFNUM1_V); - USB0.grstctl |= (fifo_num << USB_TXFNUM_S); - USB0.grstctl |= USB_TXFFLSH_M; - while ((USB0.grstctl & USB_TXFFLSH_M) != 0) ; - } else { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(out_ep[epnum].doepctl & USB_EPENA0_M)) { - out_ep[epnum].doepctl |= USB_STALL0_M; - } else { - // Asserting GONAK is required to STALL an OUT endpoint. - // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt - // anyway, and it can't be cleared by user code. If this while loop never - // finishes, we have bigger problems than just the stack. - USB0.dctl |= USB_SGOUTNAK_M; - while ((USB0.gintsts & USB_GOUTNAKEFF_M) == 0) ; - - // Ditto here- disable the endpoint. Note that only STALL and not SNAK - // is set here. - out_ep[epnum].doepctl |= (USB_STALL0_M | USB_EPDIS0_M); - while ((out_ep[epnum].doepint & USB_EPDISBLD0_M) == 0) ; - out_ep[epnum].doepint = USB_EPDISBLD0_M; - - // Allow other OUT endpoints to keep receiving. - USB0.dctl |= USB_CGOUTNAK_M; - } - } -} - -void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - if (dir == TUSB_DIR_IN) { - in_ep[epnum].diepctl &= ~USB_D_STALL1_M; - - uint8_t eptype = (in_ep[epnum].diepctl & USB_D_EPTYPE1_M) >> USB_D_EPTYPE1_S; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt - // and bulk endpoints. - if (eptype == 2 || eptype == 3) { - in_ep[epnum].diepctl |= USB_DI_SETD0PID1_M; - } - } else { - out_ep[epnum].doepctl &= ~USB_STALL1_M; - - uint8_t eptype = (out_ep[epnum].doepctl & USB_EPTYPE1_M) >> USB_EPTYPE1_S; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt - // and bulk endpoints. - if (eptype == 2 || eptype == 3) { - out_ep[epnum].doepctl |= USB_DO_SETD0PID1_M; - } - } -} - -/*------------------------------------------------------------------*/ - -static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ uint16_t xfer_size) -{ - ESP_EARLY_LOGV(TAG, "USB - receive_packet"); - volatile uint32_t *rx_fifo = USB0.fifo[0]; - - // See above TODO - // uint16_t remaining = (out_ep->DOEPTSIZ & UsbDOEPTSIZ_XFRSIZ_Msk) >> UsbDOEPTSIZ_XFRSIZ_Pos; - // xfer->queued_len = xfer->total_len - remaining; - - uint16_t remaining = xfer->total_len - xfer->queued_len; - uint16_t to_recv_size; - - if (remaining <= xfer->max_size) { - // Avoid buffer overflow. - to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; - } else { - // Room for full packet, choose recv_size based on what the microcontroller - // claims. - to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; - } - - // Common buffer read -#if 0 // TODO support dcd_edpt_xfer_fifo API - if (xfer->ff) - { - // Ring buffer - tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, to_recv_size); - } - else -#endif - { - uint8_t to_recv_rem = to_recv_size % 4; - uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; - - // Do not assume xfer buffer is aligned. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to collect. - if (to_recv_size >= 4) { - for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { - uint32_t tmp = (*rx_fifo); - base[i] = tmp & 0x000000FF; - base[i + 1] = (tmp & 0x0000FF00) >> 8; - base[i + 2] = (tmp & 0x00FF0000) >> 16; - base[i + 3] = (tmp & 0xFF000000) >> 24; - } - } - - // Do not read invalid bytes from RX FIFO. - if (to_recv_rem != 0) { - uint32_t tmp = (*rx_fifo); - uint8_t *last_32b_bound = base + to_recv_size_aligned; - - last_32b_bound[0] = tmp & 0x000000FF; - if (to_recv_rem > 1) { - last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; - } - if (to_recv_rem > 2) { - last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; - } - } - } - - xfer->queued_len += xfer_size; - - // Per USB spec, a short OUT packet (including length 0) is always - // indicative of the end of a transfer (at least for ctl, bulk, int). - xfer->short_packet = (xfer_size < xfer->max_size); -} - -static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, uint8_t fifo_num) -{ - ESP_EARLY_LOGV(TAG, "USB - transmit_packet"); - volatile uint32_t *tx_fifo = USB0.fifo[fifo_num]; - - uint16_t remaining = (in_ep->dieptsiz & 0x7FFFFU) >> USB_D_XFERSIZE0_S; - xfer->queued_len = xfer->total_len - remaining; - - uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; - -#if 0 // TODO support dcd_edpt_xfer_fifo API - if (xfer->ff) - { - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, to_xfer_size); - } - else -#endif - { - uint8_t to_xfer_rem = to_xfer_size % 4; - uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; - - // Buffer might not be aligned to 32b, so we need to force alignment - // by copying to a temp var. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to send off. - if (to_xfer_size >= 4) { - for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { - uint32_t tmp = base[i] | (base[i + 1] << 8) | - (base[i + 2] << 16) | (base[i + 3] << 24); - (*tx_fifo) = tmp; - } - } - - // Do not read beyond end of buffer if not divisible by 4. - if (to_xfer_rem != 0) { - uint32_t tmp = 0; - uint8_t *last_32b_bound = base + to_xfer_size_aligned; - - tmp |= last_32b_bound[0]; - if (to_xfer_rem > 1) { - tmp |= (last_32b_bound[1] << 8); - } - if (to_xfer_rem > 2) { - tmp |= (last_32b_bound[2] << 16); - } - - (*tx_fifo) = tmp; - } - } -} - -static void read_rx_fifo(void) -{ - // Pop control word off FIFO (completed xfers will have 2 control words, - // we only pop one ctl word each interrupt). - uint32_t const ctl_word = USB0.grxstsp; - uint8_t const pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S; - uint8_t const epnum = (ctl_word & USB_CHNUM_M ) >> USB_CHNUM_S; - uint16_t const bcnt = (ctl_word & USB_BCNT_M ) >> USB_BCNT_S; - - switch (pktsts) { - case 0x01: // Global OUT NAK (Interrupt) - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Global OUT NAK"); - break; - - case 0x02: { // Out packet recvd - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet"); - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - receive_packet(xfer, bcnt); - } - break; - - case 0x03: // Out packet done (Interrupt) - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet done"); - break; - - case 0x04: // Step 2: Setup transaction completed (Interrupt) - // After this event, OEPINT interrupt will occur with SETUP bit set - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); - USB0.out_ep_reg[epnum].doeptsiz |= USB_SUPCNT0_M; - break; - - case 0x06: { // Step1: Setup data packet received - volatile uint32_t *rx_fifo = USB0.fifo[0]; - - // We can receive up to three setup packets in succession, but - // only the last one is valid. Therefore we just overwrite it - _setup_packet[0] = (*rx_fifo); - _setup_packet[1] = (*rx_fifo); - - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", _setup_packet[0], _setup_packet[1]); - } - break; - - default: // Invalid, do something here, like breakpoint? - TU_BREAKPOINT(); - break; - } -} - -static void handle_epout_ints(void) -{ - // GINTSTS will be cleared with DAINT == 0 - // DAINT for a given EP clears when DOEPINTx is cleared. - // DOEPINT will be cleared when DAINT's out bits are cleared. - for (int n = 0; n < USB_OUT_EP_NUM; n++) { - xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); - - if (USB0.daint & (1 << (16 + n))) { - // SETUP packet Setup Phase done. - if ((USB0.out_ep_reg[n].doepint & USB_SETUP0_M)) { - USB0.out_ep_reg[n].doepint = USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear - dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); - } - - // OUT XFER complete (single packet).q - if (USB0.out_ep_reg[n].doepint & USB_XFERCOMPL0_M) { - - ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP OUT - XFER complete (single packet)"); - USB0.out_ep_reg[n].doepint = USB_XFERCOMPL0_M; - - // Transfer complete if short packet or total len is transferred - if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { - xfer->short_packet = false; - dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); - } else { - // Schedule another packet to be received. - USB0.out_ep_reg[n].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[n].doepctl |= USB_EPENA0_M | USB_CNAK0_M; - } - } - } - } -} - -static void handle_epin_ints(void) -{ - // GINTSTS will be cleared with DAINT == 0 - // DAINT for a given EP clears when DIEPINTx is cleared. - // IEPINT will be cleared when DAINT's out bits are cleared. - for (uint32_t n = 0; n < USB_IN_EP_NUM; n++) { - xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN]; - - if (USB0.daint & (1 << (0 + n))) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP IN %u", n); - // IN XFER complete (entire xfer). - if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER complete!"); - USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M; - dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - - // XFER FIFO empty - if (USB0.in_ep_reg[n].diepint & USB_D_TXFEMP0_M) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER FIFO empty!"); - USB0.in_ep_reg[n].diepint = USB_D_TXFEMP0_M; - transmit_packet(xfer, &USB0.in_ep_reg[n], n); - - // Turn off TXFE if all bytes are written. - if (xfer->queued_len == xfer->total_len) - { - USB0.dtknqr4_fifoemptymsk &= ~(1 << n); - } - } - - // XFER Timeout - if (USB0.in_ep_reg[n].diepint & USB_D_TIMEOUT0_M) { - // Clear interrupt or enpoint will hang. - USB0.in_ep_reg[n].diepint = USB_D_TIMEOUT0_M; - // Maybe retry? - } - } - } -} - - -static void _dcd_int_handler(void* arg) -{ - (void) arg; - uint8_t const rhport = 0; - - const uint32_t int_status = USB0.gintsts; - //const uint32_t int_msk = USB0.gintmsk; - - if (int_status & USB_USBRST_M) { - // start of reset - ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); - USB0.gintsts = USB_USBRST_M; - // FIFOs will be reassigned when the endpoints are reopen - _allocated_fifos = 1; - bus_reset(); - } - - if (int_status & USB_RESETDET_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset while suspend"); - USB0.gintsts = USB_RESETDET_M; - bus_reset(); - } - - if (int_status & USB_ENUMDONE_M) { - // ENUMDNE detects speed of the link. For full-speed, we - // always expect the same value. This interrupt is considered - // the end of reset. - USB0.gintsts = USB_ENUMDONE_M; - enum_done_processing(); - dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); - } - - if(int_status & USB_USBSUSP_M) - { - USB0.gintsts = USB_USBSUSP_M; - dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); - } - - if(int_status & USB_WKUPINT_M) - { - USB0.gintsts = USB_WKUPINT_M; - dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); - } - - if (int_status & USB_OTGINT_M) - { - // OTG INT bit is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); - - uint32_t const otg_int = USB0.gotgint; - - if (otg_int & USB_SESENDDET_M) - { - dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); - } - - USB0.gotgint = otg_int; - } - -#if USE_SOF - if (int_status & USB_SOF_M) { - USB0.gintsts = USB_SOF_M; - dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); // do nothing actually - } -#endif - - if (int_status & USB_RXFLVI_M) { - // RXFLVL bit is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); - - // Mask out RXFLVL while reading data from FIFO - USB0.gintmsk &= ~USB_RXFLVIMSK_M; - read_rx_fifo(); - USB0.gintmsk |= USB_RXFLVIMSK_M; - } - - // OUT endpoint interrupt handling. - if (int_status & USB_OEPINT_M) { - // OEPINT is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); - handle_epout_ints(); - } - - // IN endpoint interrupt handling. - if (int_status & USB_IEPINT_M) { - // IEPINT bit read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); - handle_epin_ints(); - } - - // Without handling - USB0.gintsts |= USB_CURMOD_INT_M | - USB_MODEMIS_M | - USB_OTGINT_M | - USB_NPTXFEMP_M | - USB_GINNAKEFF_M | - USB_GOUTNAKEFF | - USB_ERLYSUSP_M | - USB_USBSUSP_M | - USB_ISOOUTDROP_M | - USB_EOPF_M | - USB_EPMIS_M | - USB_INCOMPISOIN_M | - USB_INCOMPIP_M | - USB_FETSUSP_M | - USB_PTXFEMP_M; -} - -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); -} - -void dcd_int_disable (uint8_t rhport) -{ - (void) rhport; - esp_intr_free(usb_ih); -} - -#endif // OPT_MCU_ESP32S2 - diff --git a/src/portable/espressif/esp32sx/dcd_esp32sx.c b/src/portable/espressif/esp32sx/dcd_esp32sx.c new file mode 100644 index 000000000..74842a291 --- /dev/null +++ b/src/portable/espressif/esp32sx/dcd_esp32sx.c @@ -0,0 +1,868 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Additions Copyright (c) 2020, Espressif Systems (Shanghai) Co. Ltd. + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" +#include "common/tusb_fifo.h" + +#if (((CFG_TUSB_MCU == OPT_MCU_ESP32S2) || (CFG_TUSB_MCU == OPT_MCU_ESP32S3)) && TUSB_OPT_DEVICE_ENABLED) + +// Espressif +#include "driver/periph_ctrl.h" +#include "freertos/xtensa_api.h" +#include "esp_intr_alloc.h" +#include "esp_log.h" +#include "driver/gpio.h" +#include "soc/dport_reg.h" +#include "soc/gpio_sig_map.h" +#include "soc/usb_periph.h" + +#include "device/dcd.h" + +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#define USE_SOF 0 + +// Max number of bi-directional endpoints including EP0 +// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0 +// We should probably prohibit enabling Endpoint IN > 4 (not done yet) +#define EP_MAX USB_OUT_EP_NUM + +// FIFO size in bytes +#define EP_FIFO_SIZE 1024 + +// Max number of IN EP FIFOs +#define EP_FIFO_NUM 5 + +typedef struct { + uint8_t *buffer; + // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API + uint16_t total_len; + uint16_t queued_len; + uint16_t max_size; + bool short_packet; +} xfer_ctl_t; + +static const char *TAG = "TUSB:DCD"; +static intr_handle_t usb_ih; + + +static uint32_t _setup_packet[2]; + +#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] +static xfer_ctl_t xfer_status[EP_MAX][2]; + +// Keep count of how many FIFOs are in use +static uint8_t _allocated_fifos = 1; //FIFO0 is always in use + +// Will either return an unused FIFO number, or 0 if all are used. +static uint8_t get_free_fifo(void) +{ + if (_allocated_fifos < EP_FIFO_NUM) return _allocated_fifos++; + return 0; +} + +// Setup the control endpoint 0. +static void bus_reset(void) +{ + for (int ep_num = 0; ep_num < USB_OUT_EP_NUM; ep_num++) { + USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK + } + + USB0.dcfg &= ~USB_DEVADDR_M; // reset address + + USB0.daintmsk |= USB_OUTEPMSK0_M | USB_INEPMSK0_M; + USB0.doepmsk |= USB_SETUPMSK_M | USB_XFERCOMPLMSK; + USB0.diepmsk |= USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; + + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO MAX | + // --------------- + // | ... | + // --------------- y + x + 16 + GRXFSIZ + // | IN FIFO 2 | + // --------------- x + 16 + GRXFSIZ + // | IN FIFO 1 | + // --------------- 16 + GRXFSIZ + // | IN FIFO 0 | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits): + // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN + // + // - All EP OUT shared a unique OUT FIFO which uses + // * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets). + // * 2 locations for OUT endpoint control words. + // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) + // * 1 location for global NAK (not required/used here). + // * It is recommended to allocate 2 times the largest packet size, therefore + // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 + USB0.grstctl |= 0x10 << USB_TXFNUM_S; // fifo 0x10, + USB0.grstctl |= USB_TXFFLSH_M; // Flush fifo + USB0.grxfsiz = 52; + + // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) + USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); + + // Ready to receive SETUP packet + USB0.out_ep_reg[0].doeptsiz |= USB_SUPCNT0_M; + + USB0.gintmsk |= USB_IEPINTMSK_M | USB_OEPINTMSK_M; +} + +static void enum_done_processing(void) +{ + ESP_EARLY_LOGV(TAG, "dcd_int_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); + // On current silicon on the Full Speed core, speed is fixed to Full Speed. + // However, keep for debugging and in case Low Speed is ever supported. + uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); + + // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL + if (enum_spd == 0x03) { // Full-Speed (PHY on 48 MHz) + USB0.in_ep_reg[0].diepctl &= ~USB_D_MPS0_V; // 64 bytes + USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall + xfer_status[0][TUSB_DIR_OUT].max_size = 64; + xfer_status[0][TUSB_DIR_IN].max_size = 64; + } else { + USB0.in_ep_reg[0].diepctl |= USB_D_MPS0_V; // 8 bytes + USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall + xfer_status[0][TUSB_DIR_OUT].max_size = 8; + xfer_status[0][TUSB_DIR_IN].max_size = 8; + } +} + + +/*------------------------------------------------------------------*/ +/* Controller API + *------------------------------------------------------------------*/ +void dcd_init(uint8_t rhport) +{ + ESP_LOGV(TAG, "DCD init - Start"); + + // A. Disconnect + ESP_LOGV(TAG, "DCD init - Soft DISCONNECT and Setting up"); + USB0.dctl |= USB_SFTDISCON_M; // Soft disconnect + + // B. Programming DCFG + /* If USB host misbehaves during status portion of control xfer + (non zero-length packet), send STALL back and discard. Full speed. */ + USB0.dcfg |= USB_NZSTSOUTHSHK_M | // NonZero .... STALL + (3 << 0); // dev speed: fullspeed 1.1 on 48 mhz // TODO no value in usb_reg.h (IDF-1476) + + USB0.gahbcfg |= USB_NPTXFEMPLVL_M | USB_GLBLLNTRMSK_M; // Global interruptions ON + USB0.gusbcfg |= USB_FORCEDEVMODE_M; // force devmode + USB0.gotgctl &= ~(USB_BVALIDOVVAL_M | USB_BVALIDOVEN_M | USB_VBVALIDOVVAL_M); //no overrides + + // C. Setting SNAKs, then connect + for (int n = 0; n < USB_OUT_EP_NUM; n++) { + USB0.out_ep_reg[n].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK + } + + // D. Interruption masking + USB0.gintmsk = 0; //mask all + USB0.gotgint = ~0U; //clear OTG ints + USB0.gintsts = ~0U; //clear pending ints + USB0.gintmsk = USB_OTGINTMSK_M | + USB_MODEMISMSK_M | + #if USE_SOF + USB_SOFMSK_M | + #endif + USB_RXFLVIMSK_M | + USB_ERLYSUSPMSK_M | + USB_USBSUSPMSK_M | + USB_USBRSTMSK_M | + USB_ENUMDONEMSK_M | + USB_RESETDETMSK_M | + USB_DISCONNINTMSK_M; // host most only + + dcd_connect(rhport); +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void)rhport; + ESP_LOGV(TAG, "DCD init - Set address : %u", dev_addr); + USB0.dcfg |= ((dev_addr & USB_DEVADDR_V) << USB_DEVADDR_S); + // Response with status after changing device address + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void)rhport; + + // TODO must manually clear this bit after 1-15 ms + // USB0.DCTL |= USB_RMTWKUPSIG_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 + *------------------------------------------------------------------*/ + +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) +{ + ESP_LOGV(TAG, "DCD endpoint opened"); + (void)rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); + + TU_ASSERT(desc_edpt->wMaxPacketSize.size <= 64); + TU_ASSERT(epnum < EP_MAX); + + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + xfer->max_size = desc_edpt->wMaxPacketSize.size; + + if (dir == TUSB_DIR_OUT) { + out_ep[epnum].doepctl |= USB_USBACTEP0_M | + desc_edpt->bmAttributes.xfer << USB_EPTYPE0_S | + desc_edpt->wMaxPacketSize.size << USB_MPS0_S; + USB0.daintmsk |= (1 << (16 + epnum)); + } else { + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO MAX | + // --------------- + // | ... | + // --------------- y + x + 16 + GRXFSIZ + // | IN FIFO 2 | + // --------------- x + 16 + GRXFSIZ + // | IN FIFO 1 | + // --------------- 16 + GRXFSIZ + // | IN FIFO 0 | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints + // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1) + // - Offset: GRXFSIZ + 16 + Size*(epnum-1) + // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". + + uint8_t fifo_num = get_free_fifo(); + TU_ASSERT(fifo_num != 0); + + in_ep[epnum].diepctl &= ~(USB_D_TXFNUM1_M | USB_D_EPTYPE1_M | USB_DI_SETD0PID1 | USB_D_MPS1_M); + in_ep[epnum].diepctl |= USB_D_USBACTEP1_M | + fifo_num << USB_D_TXFNUM1_S | + desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | + desc_edpt->wMaxPacketSize.size << 0; + + USB0.daintmsk |= (1 << (0 + epnum)); + + // Both TXFD and TXSA are in unit of 32-bit words. + // IN FIFO 0 was configured during enumeration, hence the "+ 16". + uint16_t const allocated_size = (USB0.grxfsiz & 0x0000ffff) + 16; + uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_FIFO_NUM-1); + uint32_t const fifo_offset = allocated_size + fifo_size*(fifo_num-1); + + // DIEPTXF starts at FIFO #1. + USB0.dieptxf[epnum - 1] = (fifo_size << USB_NPTXFDEP_S) | fifo_offset; + } + return true; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +{ + (void)rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = buffer; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->short_packet = false; + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint8_t short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if (short_packet_size > 0 || (total_bytes == 0)) { + num_packets++; + } + + ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", + epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), + num_packets, total_bytes); + + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them + // here. + if (dir == TUSB_DIR_IN) { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; + USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK + + // Enable fifo empty interrupt only if there are something to put in the fifo. + if(total_bytes != 0) { + USB0.dtknqr4_fifoemptymsk |= (1 << epnum); + } + } else { + // Each complete packet for OUT xfers triggers XFRC. + USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; + } + return true; +} + +#if 0 // TODO support dcd_edpt_xfer_fifo API +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void)rhport; + + // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 + TU_ASSERT(ff->item_size == 1); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->short_packet = false; + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint8_t short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if (short_packet_size > 0 || (total_bytes == 0)) { + num_packets++; + } + + ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", + epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), + num_packets, total_bytes); + + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them + // here. + if (dir == TUSB_DIR_IN) { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; + USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK + + // Enable fifo empty interrupt only if there are something to put in the fifo. + if(total_bytes != 0) { + USB0.dtknqr4_fifoemptymsk |= (1 << epnum); + } + } else { + // Each complete packet for OUT xfers triggers XFRC. + USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; + } + return true; +} +#endif + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if (dir == TUSB_DIR_IN) { + // Only disable currently enabled non-control endpoint + if ((epnum == 0) || !(in_ep[epnum].diepctl & USB_D_EPENA1_M)) { + in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M); + } else { + // Stop transmitting packets and NAK IN xfers. + in_ep[epnum].diepctl |= USB_DI_SNAK1_M; + while ((in_ep[epnum].diepint & USB_DI_SNAK1_M) == 0) ; + + // Disable the endpoint. Note that both SNAK and STALL are set here. + in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M | USB_D_EPDIS1_M); + while ((in_ep[epnum].diepint & USB_D_EPDISBLD0_M) == 0) ; + in_ep[epnum].diepint = USB_D_EPDISBLD0_M; + } + + // Flush the FIFO, and wait until we have confirmed it cleared. + uint8_t const fifo_num = ((in_ep[epnum].diepctl >> USB_D_TXFNUM1_S) & USB_D_TXFNUM1_V); + USB0.grstctl |= (fifo_num << USB_TXFNUM_S); + USB0.grstctl |= USB_TXFFLSH_M; + while ((USB0.grstctl & USB_TXFFLSH_M) != 0) ; + } else { + // Only disable currently enabled non-control endpoint + if ((epnum == 0) || !(out_ep[epnum].doepctl & USB_EPENA0_M)) { + out_ep[epnum].doepctl |= USB_STALL0_M; + } else { + // Asserting GONAK is required to STALL an OUT endpoint. + // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt + // anyway, and it can't be cleared by user code. If this while loop never + // finishes, we have bigger problems than just the stack. + USB0.dctl |= USB_SGOUTNAK_M; + while ((USB0.gintsts & USB_GOUTNAKEFF_M) == 0) ; + + // Ditto here- disable the endpoint. Note that only STALL and not SNAK + // is set here. + out_ep[epnum].doepctl |= (USB_STALL0_M | USB_EPDIS0_M); + while ((out_ep[epnum].doepint & USB_EPDISBLD0_M) == 0) ; + out_ep[epnum].doepint = USB_EPDISBLD0_M; + + // Allow other OUT endpoints to keep receiving. + USB0.dctl |= USB_CGOUTNAK_M; + } + } +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if (dir == TUSB_DIR_IN) { + in_ep[epnum].diepctl &= ~USB_D_STALL1_M; + + uint8_t eptype = (in_ep[epnum].diepctl & USB_D_EPTYPE1_M) >> USB_D_EPTYPE1_S; + // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt + // and bulk endpoints. + if (eptype == 2 || eptype == 3) { + in_ep[epnum].diepctl |= USB_DI_SETD0PID1_M; + } + } else { + out_ep[epnum].doepctl &= ~USB_STALL1_M; + + uint8_t eptype = (out_ep[epnum].doepctl & USB_EPTYPE1_M) >> USB_EPTYPE1_S; + // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt + // and bulk endpoints. + if (eptype == 2 || eptype == 3) { + out_ep[epnum].doepctl |= USB_DO_SETD0PID1_M; + } + } +} + +/*------------------------------------------------------------------*/ + +static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ uint16_t xfer_size) +{ + ESP_EARLY_LOGV(TAG, "USB - receive_packet"); + volatile uint32_t *rx_fifo = USB0.fifo[0]; + + // See above TODO + // uint16_t remaining = (out_ep->DOEPTSIZ & UsbDOEPTSIZ_XFRSIZ_Msk) >> UsbDOEPTSIZ_XFRSIZ_Pos; + // xfer->queued_len = xfer->total_len - remaining; + + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint16_t to_recv_size; + + if (remaining <= xfer->max_size) { + // Avoid buffer overflow. + to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; + } else { + // Room for full packet, choose recv_size based on what the microcontroller + // claims. + to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; + } + + // Common buffer read +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + // Ring buffer + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, to_recv_size); + } + else +#endif + { + uint8_t to_recv_rem = to_recv_size % 4; + uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; + + // Do not assume xfer buffer is aligned. + uint8_t *base = (xfer->buffer + xfer->queued_len); + + // This for loop always runs at least once- skip if less than 4 bytes + // to collect. + if (to_recv_size >= 4) { + for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { + uint32_t tmp = (*rx_fifo); + base[i] = tmp & 0x000000FF; + base[i + 1] = (tmp & 0x0000FF00) >> 8; + base[i + 2] = (tmp & 0x00FF0000) >> 16; + base[i + 3] = (tmp & 0xFF000000) >> 24; + } + } + + // Do not read invalid bytes from RX FIFO. + if (to_recv_rem != 0) { + uint32_t tmp = (*rx_fifo); + uint8_t *last_32b_bound = base + to_recv_size_aligned; + + last_32b_bound[0] = tmp & 0x000000FF; + if (to_recv_rem > 1) { + last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; + } + if (to_recv_rem > 2) { + last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; + } + } + } + + xfer->queued_len += xfer_size; + + // Per USB spec, a short OUT packet (including length 0) is always + // indicative of the end of a transfer (at least for ctl, bulk, int). + xfer->short_packet = (xfer_size < xfer->max_size); +} + +static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, uint8_t fifo_num) +{ + ESP_EARLY_LOGV(TAG, "USB - transmit_packet"); + volatile uint32_t *tx_fifo = USB0.fifo[fifo_num]; + + uint16_t remaining = (in_ep->dieptsiz & 0x7FFFFU) >> USB_D_XFERSIZE0_S; + xfer->queued_len = xfer->total_len - remaining; + + uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; + +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, to_xfer_size); + } + else +#endif + { + uint8_t to_xfer_rem = to_xfer_size % 4; + uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; + + // Buffer might not be aligned to 32b, so we need to force alignment + // by copying to a temp var. + uint8_t *base = (xfer->buffer + xfer->queued_len); + + // This for loop always runs at least once- skip if less than 4 bytes + // to send off. + if (to_xfer_size >= 4) { + for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { + uint32_t tmp = base[i] | (base[i + 1] << 8) | + (base[i + 2] << 16) | (base[i + 3] << 24); + (*tx_fifo) = tmp; + } + } + + // Do not read beyond end of buffer if not divisible by 4. + if (to_xfer_rem != 0) { + uint32_t tmp = 0; + uint8_t *last_32b_bound = base + to_xfer_size_aligned; + + tmp |= last_32b_bound[0]; + if (to_xfer_rem > 1) { + tmp |= (last_32b_bound[1] << 8); + } + if (to_xfer_rem > 2) { + tmp |= (last_32b_bound[2] << 16); + } + + (*tx_fifo) = tmp; + } + } +} + +static void read_rx_fifo(void) +{ + // Pop control word off FIFO (completed xfers will have 2 control words, + // we only pop one ctl word each interrupt). + uint32_t const ctl_word = USB0.grxstsp; + uint8_t const pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S; + uint8_t const epnum = (ctl_word & USB_CHNUM_M ) >> USB_CHNUM_S; + uint16_t const bcnt = (ctl_word & USB_BCNT_M ) >> USB_BCNT_S; + + switch (pktsts) { + case 0x01: // Global OUT NAK (Interrupt) + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Global OUT NAK"); + break; + + case 0x02: { // Out packet recvd + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet"); + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + receive_packet(xfer, bcnt); + } + break; + + case 0x03: // Out packet done (Interrupt) + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet done"); + break; + + case 0x04: // Step 2: Setup transaction completed (Interrupt) + // After this event, OEPINT interrupt will occur with SETUP bit set + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); + USB0.out_ep_reg[epnum].doeptsiz |= USB_SUPCNT0_M; + break; + + case 0x06: { // Step1: Setup data packet received + volatile uint32_t *rx_fifo = USB0.fifo[0]; + + // We can receive up to three setup packets in succession, but + // only the last one is valid. Therefore we just overwrite it + _setup_packet[0] = (*rx_fifo); + _setup_packet[1] = (*rx_fifo); + + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", _setup_packet[0], _setup_packet[1]); + } + break; + + default: // Invalid, do something here, like breakpoint? + TU_BREAKPOINT(); + break; + } +} + +static void handle_epout_ints(void) +{ + // GINTSTS will be cleared with DAINT == 0 + // DAINT for a given EP clears when DOEPINTx is cleared. + // DOEPINT will be cleared when DAINT's out bits are cleared. + for (int n = 0; n < USB_OUT_EP_NUM; n++) { + xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); + + if (USB0.daint & (1 << (16 + n))) { + // SETUP packet Setup Phase done. + if ((USB0.out_ep_reg[n].doepint & USB_SETUP0_M)) { + USB0.out_ep_reg[n].doepint = USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear + dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); + } + + // OUT XFER complete (single packet).q + if (USB0.out_ep_reg[n].doepint & USB_XFERCOMPL0_M) { + + ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP OUT - XFER complete (single packet)"); + USB0.out_ep_reg[n].doepint = USB_XFERCOMPL0_M; + + // Transfer complete if short packet or total len is transferred + if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { + xfer->short_packet = false; + dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); + } else { + // Schedule another packet to be received. + USB0.out_ep_reg[n].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[n].doepctl |= USB_EPENA0_M | USB_CNAK0_M; + } + } + } + } +} + +static void handle_epin_ints(void) +{ + // GINTSTS will be cleared with DAINT == 0 + // DAINT for a given EP clears when DIEPINTx is cleared. + // IEPINT will be cleared when DAINT's out bits are cleared. + for (uint32_t n = 0; n < USB_IN_EP_NUM; n++) { + xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN]; + + if (USB0.daint & (1 << (0 + n))) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP IN %u", n); + // IN XFER complete (entire xfer). + if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER complete!"); + USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M; + dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + } + + // XFER FIFO empty + if (USB0.in_ep_reg[n].diepint & USB_D_TXFEMP0_M) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER FIFO empty!"); + USB0.in_ep_reg[n].diepint = USB_D_TXFEMP0_M; + transmit_packet(xfer, &USB0.in_ep_reg[n], n); + + // Turn off TXFE if all bytes are written. + if (xfer->queued_len == xfer->total_len) + { + USB0.dtknqr4_fifoemptymsk &= ~(1 << n); + } + } + + // XFER Timeout + if (USB0.in_ep_reg[n].diepint & USB_D_TIMEOUT0_M) { + // Clear interrupt or enpoint will hang. + USB0.in_ep_reg[n].diepint = USB_D_TIMEOUT0_M; + // Maybe retry? + } + } + } +} + + +static void _dcd_int_handler(void* arg) +{ + (void) arg; + uint8_t const rhport = 0; + + const uint32_t int_status = USB0.gintsts; + //const uint32_t int_msk = USB0.gintmsk; + + if (int_status & USB_USBRST_M) { + // start of reset + ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); + USB0.gintsts = USB_USBRST_M; + // FIFOs will be reassigned when the endpoints are reopen + _allocated_fifos = 1; + bus_reset(); + } + + if (int_status & USB_RESETDET_M) { + ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset while suspend"); + USB0.gintsts = USB_RESETDET_M; + bus_reset(); + } + + if (int_status & USB_ENUMDONE_M) { + // ENUMDNE detects speed of the link. For full-speed, we + // always expect the same value. This interrupt is considered + // the end of reset. + USB0.gintsts = USB_ENUMDONE_M; + enum_done_processing(); + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); + } + + if(int_status & USB_USBSUSP_M) + { + USB0.gintsts = USB_USBSUSP_M; + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + } + + if(int_status & USB_WKUPINT_M) + { + USB0.gintsts = USB_WKUPINT_M; + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); + } + + if (int_status & USB_OTGINT_M) + { + // OTG INT bit is read-only + ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); + + uint32_t const otg_int = USB0.gotgint; + + if (otg_int & USB_SESENDDET_M) + { + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); + } + + USB0.gotgint = otg_int; + } + +#if USE_SOF + if (int_status & USB_SOF_M) { + USB0.gintsts = USB_SOF_M; + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); // do nothing actually + } +#endif + + if (int_status & USB_RXFLVI_M) { + // RXFLVL bit is read-only + ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); + + // Mask out RXFLVL while reading data from FIFO + USB0.gintmsk &= ~USB_RXFLVIMSK_M; + read_rx_fifo(); + USB0.gintmsk |= USB_RXFLVIMSK_M; + } + + // OUT endpoint interrupt handling. + if (int_status & USB_OEPINT_M) { + // OEPINT is read-only + ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); + handle_epout_ints(); + } + + // IN endpoint interrupt handling. + if (int_status & USB_IEPINT_M) { + // IEPINT bit read-only + ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); + handle_epin_ints(); + } + + // Without handling + USB0.gintsts |= USB_CURMOD_INT_M | + USB_MODEMIS_M | + USB_OTGINT_M | + USB_NPTXFEMP_M | + USB_GINNAKEFF_M | + USB_GOUTNAKEFF | + USB_ERLYSUSP_M | + USB_USBSUSP_M | + USB_ISOOUTDROP_M | + USB_EOPF_M | + USB_EPMIS_M | + USB_INCOMPISOIN_M | + USB_INCOMPIP_M | + USB_FETSUSP_M | + USB_PTXFEMP_M; +} + +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); +} + +void dcd_int_disable (uint8_t rhport) +{ + (void) rhport; + esp_intr_free(usb_ih); +} + +#endif // #if OPT_MCU_ESP32S2 || OPT_MCU_ESP32S3 + diff --git a/src/tusb_option.h b/src/tusb_option.h index 7585a9ff6..9fcc6c565 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -94,6 +94,7 @@ // Espressif #define OPT_MCU_ESP32S2 900 ///< Espressif ESP32-S2 +#define OPT_MCU_ESP32S3 901 ///< Espressif ESP32-S3 // Dialog #define OPT_MCU_DA1469X 1000 ///< Dialog Semiconductor DA1469x diff --git a/tools/build_esp32s2.py b/tools/build_esp32s2.py deleted file mode 100644 index 0ef05023c..000000000 --- a/tools/build_esp32s2.py +++ /dev/null @@ -1,99 +0,0 @@ -import os -import glob -import sys -import subprocess -import time - -SUCCEEDED = "\033[32msucceeded\033[0m" -FAILED = "\033[31mfailed\033[0m" -SKIPPED = "\033[33mskipped\033[0m" - -success_count = 0 -fail_count = 0 -skip_count = 0 -exit_status = 0 - -total_time = time.monotonic() - -build_format = '| {:23} | {:30} | {:18} | {:7} | {:6} | {:6} |' -build_separator = '-' * 100 - -def filter_with_input(mylist): - if len(sys.argv) > 1: - input_args = list(set(mylist).intersection(sys.argv)) - if len(input_args) > 0: - mylist[:] = input_args - -# Build all examples if not specified -all_examples = [] -for entry in os.scandir("examples/device"): - # Only includes example with CMakeLists.txt for esp32s, and skip board_test to speed up ci - if entry.is_dir() and os.path.exists(entry.path + "/sdkconfig.defaults") and entry.name != 'board_test': - all_examples.append(entry.name) -filter_with_input(all_examples) -all_examples.sort() - -# Build all boards if not specified -all_boards = [] -for entry in os.scandir("hw/bsp/esp32s2/boards"): - if entry.is_dir(): - all_boards.append(entry.name) -filter_with_input(all_boards) -all_boards.sort() - -def build_board(example, board): - global success_count, fail_count, skip_count, exit_status - start_time = time.monotonic() - flash_size = "-" - sram_size = "-" - - # Check if board is skipped - if skip_example(example, board): - success = SKIPPED - skip_count += 1 - print(build_format.format(example, board, success, '-', flash_size, sram_size)) - else: - subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - build_result = subprocess.run("make -j -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - - if build_result.returncode == 0: - success = SUCCEEDED - success_count += 1 - (flash_size, sram_size) = build_size(example, board) - else: - exit_status = build_result.returncode - success = FAILED - fail_count += 1 - - build_duration = time.monotonic() - start_time - print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size)) - - if build_result.returncode != 0: - print(build_result.stdout.decode("utf-8")) - -def build_size(example, board): - #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) - elf_file = 'examples/device/{}/_build/{}/*.elf'.format(example, board) - size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8") - size_list = size_output.split('\n')[1].split('\t') - flash_size = int(size_list[0]) - sram_size = int(size_list[1]) + int(size_list[2]) - return (flash_size, sram_size) - -def skip_example(example, board): - return 0 - -print(build_separator) -print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) -print(build_separator) - -for example in all_examples: - for board in all_boards: - build_board(example, board) - -total_time = time.monotonic() - total_time -print(build_separator) -print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) -print(build_separator) - -sys.exit(exit_status) diff --git a/tools/build_esp32sx.py b/tools/build_esp32sx.py new file mode 100644 index 000000000..82352c269 --- /dev/null +++ b/tools/build_esp32sx.py @@ -0,0 +1,99 @@ +import os +import glob +import sys +import subprocess +import time + +SUCCEEDED = "\033[32msucceeded\033[0m" +FAILED = "\033[31mfailed\033[0m" +SKIPPED = "\033[33mskipped\033[0m" + +success_count = 0 +fail_count = 0 +skip_count = 0 +exit_status = 0 + +total_time = time.monotonic() + +build_format = '| {:23} | {:30} | {:18} | {:7} | {:6} | {:6} |' +build_separator = '-' * 100 + +def filter_with_input(mylist): + if len(sys.argv) > 1: + input_args = list(set(mylist).intersection(sys.argv)) + if len(input_args) > 0: + mylist[:] = input_args + +# Build all examples if not specified +all_examples = [] +for entry in os.scandir("examples/device"): + # Only includes example with CMakeLists.txt for esp32s, and skip board_test to speed up ci + if entry.is_dir() and os.path.exists(entry.path + "/sdkconfig.defaults") and entry.name != 'board_test': + all_examples.append(entry.name) +filter_with_input(all_examples) +all_examples.sort() + +# Build all boards if not specified +all_boards = [] +for entry in os.scandir("hw/bsp/esp32sx/boards"): + if entry.is_dir(): + all_boards.append(entry.name) +filter_with_input(all_boards) +all_boards.sort() + +def build_board(example, board): + global success_count, fail_count, skip_count, exit_status + start_time = time.monotonic() + flash_size = "-" + sram_size = "-" + + # Check if board is skipped + if skip_example(example, board): + success = SKIPPED + skip_count += 1 + print(build_format.format(example, board, success, '-', flash_size, sram_size)) + else: + subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + build_result = subprocess.run("make -j -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + + if build_result.returncode == 0: + success = SUCCEEDED + success_count += 1 + (flash_size, sram_size) = build_size(example, board) + else: + exit_status = build_result.returncode + success = FAILED + fail_count += 1 + + build_duration = time.monotonic() - start_time + print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size)) + + if build_result.returncode != 0: + print(build_result.stdout.decode("utf-8")) + +def build_size(example, board): + #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) + elf_file = 'examples/device/{}/_build/{}/*.elf'.format(example, board) + size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8") + size_list = size_output.split('\n')[1].split('\t') + flash_size = int(size_list[0]) + sram_size = int(size_list[1]) + int(size_list[2]) + return (flash_size, sram_size) + +def skip_example(example, board): + return 0 + +print(build_separator) +print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) +print(build_separator) + +for example in all_examples: + for board in all_boards: + build_board(example, board) + +total_time = time.monotonic() - total_time +print(build_separator) +print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) +print(build_separator) + +sys.exit(exit_status) diff --git a/tools/build_family.py b/tools/build_family.py index 65d0e8fc2..35a61f97a 100644 --- a/tools/build_family.py +++ b/tools/build_family.py @@ -38,7 +38,7 @@ all_examples.sort() # If family are not specified in arguments, build all all_families = [] for entry in os.scandir("hw/bsp"): - if entry.is_dir() and os.path.isdir(entry.path + "/boards") and entry.name != "esp32s2": + if entry.is_dir() and os.path.isdir(entry.path + "/boards") and entry.name != "esp32sx": all_families.append(entry.name) filter_with_input(all_families) -- cgit v1.3.1 From 4408ffce88a46bb7f2b07b99a9df60b24e17700f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 20 Apr 2021 18:44:56 +0200 Subject: Fix pointer alt_setting to be cleared when driver gets initialized --- src/class/audio/audio_device.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 4057f5f64..d9d078817 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -265,17 +265,17 @@ typedef struct uint8_t ep_int_ctr; // Audio control interrupt EP. #endif - uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! - /*------------- From this point, data is not cleared by bus reset -------------*/ - // uint16_t desc_length; // Length of audio function descriptor // Buffer for control requests uint8_t * ctrl_buf; uint8_t ctrl_buf_sz; + // Current active alternate settings + uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! + // EP Transfer buffers and FIFOs #if CFG_TUD_AUDIO_ENABLE_EP_OUT #if !CFG_TUD_AUDIO_ENABLE_DECODING @@ -759,7 +759,10 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) uint8_t const *dummy2; // If a callback is used determine current alternate setting of - find index of audio streaming interface and index of interface - if (tud_audio_tx_done_pre_load_cb || tud_audio_tx_done_post_load_cb) TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); + + // Only send something if current alternate interface is not 0 as in this case nothing is to be sent due to UAC2 specifications + if (audio->alt_setting[idxItf] == 0) return false; // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). @@ -1424,7 +1427,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // 3. Open new EP uint8_t const itf = tu_u16_low(p_request->wIndex); - uint8_t const alt = tu_u16_low(p_request->wValue); + volatile uint8_t const alt = tu_u16_low(p_request->wValue); TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); @@ -1537,7 +1540,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Invoke callback - can be used to trigger data sampling if not already running if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - // Schedule first transmit - in case no sample data is available a ZLP is loaded + // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver])); } @@ -1840,7 +1843,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_IN // Data transmission of audio packet finished - if (_audiod_itf[idxDriver].ep_in == ep_addr) + if (_audiod_itf[idxDriver].ep_in == ep_addr && _audiod_itf[idxDriver].alt_setting != 0) { // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." -- cgit v1.3.1 From fef0d54559e957575a5f0adebb1af94b7a81dd4f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 20 Apr 2021 19:56:40 +0200 Subject: Refactor static function for better performance --- src/class/audio/audio_device.c | 272 +++++++++++++++++++++++------------------ 1 file changed, 150 insertions(+), 122 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index d9d078817..2504e9c83 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -347,7 +347,7 @@ typedef struct #define USE_LINEAR_BUFFER_TX 1 #endif -} audiod_interface_t; +} audiod_function_t; #ifndef USE_LINEAR_BUFFER_TX #define USE_LINEAR_BUFFER_TX 0 @@ -357,39 +357,41 @@ typedef struct #define USE_LINEAR_BUFFER_RX 0 #endif -#define ITF_MEM_RESET_SIZE offsetof(audiod_interface_t, ctrl_buf) +#define ITF_MEM_RESET_SIZE offsetof(audiod_function_t, ctrl_buf) //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION audiod_interface_t _audiod_itf[CFG_TUD_AUDIO]; +CFG_TUSB_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); +static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); #endif #if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received); +static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t* audio); +static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t* audio); #endif #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio); +static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio); #endif static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); -static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int); static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver); static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver); static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); +static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); #if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING -static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf); +static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf); #endif static inline uint8_t tu_desc_subtype(void const* desc) @@ -400,7 +402,7 @@ static inline uint8_t tu_desc_subtype(void const* desc) bool tud_audio_n_mounted(uint8_t itf) { TU_VERIFY(itf < CFG_TUD_AUDIO); - audiod_interface_t* audio = &_audiod_itf[itf]; + audiod_function_t* audio = &_audiod_fct[itf]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT if (audio->ep_out == 0) return false; @@ -429,20 +431,20 @@ bool tud_audio_n_mounted(uint8_t itf) uint16_t tud_audio_n_available(uint8_t itf) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - return tu_fifo_count(&_audiod_itf[itf].ep_out_ff); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + return tu_fifo_count(&_audiod_fct[itf].ep_out_ff); } uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - return tu_fifo_read_n(&_audiod_itf[itf].ep_out_ff, buffer, bufsize); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + return tu_fifo_read_n(&_audiod_fct[itf].ep_out_ff, buffer, bufsize); } bool tud_audio_n_clear_ep_out_ff(uint8_t itf) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - return tu_fifo_clear(&_audiod_itf[itf].ep_out_ff); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + return tu_fifo_clear(&_audiod_fct[itf].ep_out_ff); } #endif @@ -451,20 +453,20 @@ bool tud_audio_n_clear_ep_out_ff(uint8_t itf) // Delete all content in the support RX FIFOs bool tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); - return tu_fifo_clear(&_audiod_itf[itf].rx_supp_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_rx_supp_ff); + return tu_fifo_clear(&_audiod_fct[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); - return tu_fifo_count(&_audiod_itf[itf].rx_supp_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_rx_supp_ff); + return tu_fifo_count(&_audiod_fct[itf].rx_supp_ff[channelId]); } uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_rx_supp_ff); - return tu_fifo_read_n(&_audiod_itf[itf].rx_supp_ff[channelId], buffer, bufsize); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_rx_supp_ff); + return tu_fifo_read_n(&_audiod_fct[itf].rx_supp_ff[channelId], buffer, bufsize); } #endif @@ -473,16 +475,20 @@ uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffe #if CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) +static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) { - uint8_t idxDriver, idxItf; + uint8_t idxItf; uint8_t const *dummy2; + uint8_t idx_audio_fct = 0; - // Find index of audio streaming interface and index of interface - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, &idxDriver, &idxItf, &dummy2)); + if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) + { + idx_audio_fct = audiod_get_audio_fct_idx(audio); + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio, &idxItf, &dummy2)); + } // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) - if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting[idxItf])); + if (tud_audio_rx_done_pre_read_cb) TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); #if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT @@ -536,7 +542,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_interface_t* audio, uint16_ #endif // Call a weak callback here - a possibility for user to get informed decoding was completed - if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idxDriver, audio->ep_out, audio->alt_setting[idxItf])); + if (tud_audio_rx_done_post_read_cb) TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); return true; } @@ -618,7 +624,7 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const return src; } -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, uint16_t n_bytes_received) +static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) { (void) rhport; @@ -683,14 +689,14 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio, */ uint16_t tud_audio_n_write(uint8_t itf, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - return tu_fifo_write_n(&_audiod_itf[itf].ep_in_ff, data, len); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + return tu_fifo_write_n(&_audiod_fct[itf].ep_in_ff, data, len); } bool tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete all content in the EP IN FIFO { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - return tu_fifo_clear(&_audiod_itf[itf].ep_in_ff); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + return tu_fifo_clear(&_audiod_fct[itf].ep_in_ff); } #endif @@ -698,8 +704,8 @@ bool tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); - audiod_interface_t* audio = &_audiod_itf[itf]; + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + audiod_function_t* audio = &_audiod_fct[itf]; uint16_t n_bytes_copied = tu_fifo_count(&audio->tx_supp_ff[0]); @@ -713,14 +719,14 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force a bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_tx_supp_ff); - return tu_fifo_clear(&_audiod_itf[itf].tx_supp_ff[channelId]); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_tx_supp_ff); + return tu_fifo_clear(&_audiod_fct[itf].tx_supp_ff[channelId]); } uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL, channelId < _audiod_itf[itf].n_tx_supp_ff); - return tu_fifo_write_n(&_audiod_itf[itf].tx_supp_ff[channelId], data, len); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_tx_supp_ff); + return tu_fifo_write_n(&_audiod_fct[itf].tx_supp_ff[channelId], data, len); } #endif @@ -730,18 +736,18 @@ uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void // If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user uint16_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); // We write directly into the EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_int_ctr)); + TU_VERIFY(!usbd_edpt_busy(_audiod_fct[itf].rhport, _audiod_fct[itf].ep_int_ctr)); // Check length TU_VERIFY(len <= CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE); - memcpy(_audiod_itf[itf].ep_int_ctr_buf, buffer, len); + memcpy(_audiod_fct[itf].ep_int_ctr_buf, buffer, len); // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_int_ctr, _audiod_itf[itf].ep_int_ctr_buf, len)); + TU_VERIFY(usbd_edpt_xfer(_audiod_fct[itf].rhport, _audiod_fct[itf].ep_int_ctr, _audiod_fct[itf].ep_int_ctr_buf, len)); return true; } @@ -753,20 +759,20 @@ uint16_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint16_t // n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. #if CFG_TUD_AUDIO_ENABLE_EP_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) +static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) { - uint8_t idxDriver, idxItf; + uint8_t idxItf; uint8_t const *dummy2; - // If a callback is used determine current alternate setting of - find index of audio streaming interface and index of interface - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, &idxDriver, &idxItf, &dummy2)); + uint8_t idx_audio_fct = audiod_get_audio_fct_idx(audio); + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio, &idxItf, &dummy2)); // Only send something if current alternate interface is not 0 as in this case nothing is to be sent due to UAC2 specifications if (audio->alt_setting[idxItf] == 0) return false; // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idxDriver, audio->ep_in, audio->alt_setting[idxItf])); + if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); // Send everything in ISO EP FIFO uint16_t n_bytes_tx; @@ -826,7 +832,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_interface_t * audio) #endif // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idxDriver, audio->ep_in, audio->alt_setting[idxItf])); + if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); return true; } @@ -912,7 +918,7 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const return dst; } -static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* audio) +static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio) { // This function relies on the fact that the length of the support FIFOs was configured to be a multiple of the active sample size in bytes s.t. no sample is split within a wrap // This is ensured within set_interface, where the FIFOs are reconfigured according to this size @@ -981,7 +987,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_interface_t* aud // This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static inline bool audiod_fb_send(uint8_t rhport, audiod_interface_t *audio) +static inline bool audiod_fb_send(uint8_t rhport, audiod_function_t *audio) { return usbd_edpt_xfer(rhport, audio->ep_fb, (uint8_t *) &audio->fb_val, 4); } @@ -992,11 +998,11 @@ static inline bool audiod_fb_send(uint8_t rhport, audiod_interface_t *audio) //--------------------------------------------------------------------+ void audiod_init(void) { - tu_memclr(_audiod_itf, sizeof(_audiod_itf)); + tu_memclr(_audiod_fct, sizeof(_audiod_fct)); for(uint8_t i=0; i 1 case 1: - _audiod_itf[i].desc_length = CFG_TUD_AUDIO_FUNC_2_DESC_LEN; + _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_2_DESC_LEN; break; #endif #if CFG_TUD_AUDIO > 2 case 2: - _audiod_itf[i].desc_length = CFG_TUD_AUDIO_FUNC_3_DESC_LEN; + _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_3_DESC_LEN; break; #endif } @@ -1390,7 +1396,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin TU_ASSERT( i < CFG_TUD_AUDIO ); // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - uint16_t drv_len = _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor + uint16_t drv_len = _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor return drv_len; } @@ -1403,10 +1409,10 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * uint8_t idxDriver, idxItf; uint8_t const *dummy; - TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_itf[idxDriver].alt_setting[idxItf], 1)); + TU_VERIFY(audiod_get_AS_interface_index_global(itf, &idxDriver, &idxItf, &dummy)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[idxDriver].alt_setting[idxItf], 1)); - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_itf[idxDriver].alt_setting[idxItf]); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[idxDriver].alt_setting[idxItf]); return true; } @@ -1434,9 +1440,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Find index of audio streaming interface and index of interface uint8_t idxDriver, idxItf; uint8_t const *p_desc; - TU_VERIFY(audiod_get_AS_interface_index(itf, &idxDriver, &idxItf, &p_desc)); + TU_VERIFY(audiod_get_AS_interface_index_global(itf, &idxDriver, &idxItf, &p_desc)); - audiod_interface_t* audio = &_audiod_itf[idxDriver]; + audiod_function_t* audio = &_audiod_fct[idxDriver]; // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) #if CFG_TUD_AUDIO_ENABLE_EP_IN @@ -1542,7 +1548,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver])); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[idxDriver])); } #endif // CFG_TUD_AUDIO_ENABLE_EP_IN @@ -1635,7 +1641,7 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf); } else { @@ -1651,7 +1657,7 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf); } else { @@ -1672,7 +1678,7 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf); } else { @@ -1790,7 +1796,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const } // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf, _audiod_itf[idxDriver].ctrl_buf_sz)); + TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf, _audiod_fct[idxDriver].ctrl_buf_sz)); return true; } @@ -1826,7 +1832,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN // Data transmission of control interrupt finished - if (_audiod_itf[idxDriver].ep_int_ctr == ep_addr) + if (_audiod_fct[idxDriver].ep_int_ctr == ep_addr) { // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? @@ -1843,7 +1849,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_IN // Data transmission of audio packet finished - if (_audiod_itf[idxDriver].ep_in == ep_addr && _audiod_itf[idxDriver].alt_setting != 0) + if (_audiod_fct[idxDriver].ep_in == ep_addr && _audiod_fct[idxDriver].alt_setting != 0) { // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." @@ -1854,7 +1860,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // This is the only place where we can fill something into the EPs buffer! // Load new data - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_itf[idxDriver])); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[idxDriver])); // Transmission of ZLP is done by audiod_tx_done_cb() return true; @@ -1864,21 +1870,21 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_OUT // New audio packet received - if (_audiod_itf[idxDriver].ep_out == ep_addr) + if (_audiod_fct[idxDriver].ep_out == ep_addr) { - TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_itf[idxDriver], (uint16_t) xferred_bytes)); + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_fct[idxDriver], (uint16_t) xferred_bytes)); return true; } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Transmission of feedback EP finished - if (_audiod_itf[idxDriver].ep_fb == ep_addr) + if (_audiod_fct[idxDriver].ep_fb == ep_addr) { if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, &_audiod_itf[idxDriver]); + return audiod_fb_send(rhport, &_audiod_fct[idxDriver]); } #endif #endif @@ -1929,49 +1935,61 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req } // Crop length - if (len > _audiod_itf[idxDriver].ctrl_buf_sz) len = _audiod_itf[idxDriver].ctrl_buf_sz; + if (len > _audiod_fct[idxDriver].ctrl_buf_sz) len = _audiod_fct[idxDriver].ctrl_buf_sz; // Copy into buffer - memcpy((void *)_audiod_itf[idxDriver].ctrl_buf, data, (size_t)len); + memcpy((void *)_audiod_fct[idxDriver].ctrl_buf, data, (size_t)len); // Schedule transmit - return tud_control_xfer(rhport, p_request, (void*)_audiod_itf[idxDriver].ctrl_buf, len); + return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[idxDriver].ctrl_buf, len); +} + +// This helper function finds for a given audio function and AS interface number the index of the attached driver structure, the index of the interface in the audio function +// (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and +// finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. +static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int) +{ + if (audio->p_desc) + { + // Get pointer at end + uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; + + // Advance past AC descriptors + uint8_t const *p_desc = tu_desc_next(audio->p_desc); + p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; + + uint8_t tmp = 0; + while (p_desc < p_desc_end) + { + // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + { + *idxItf = tmp; + *pp_desc_int = p_desc; + return true; + } + + // Increase index, bytes read, and pointer + tmp++; + p_desc = tu_desc_next(p_desc); + } + } + return false; } // This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function // (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and // finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. -static bool audiod_get_AS_interface_index(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) +static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) { // Loop over audio driver interfaces uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) { - if (_audiod_itf[i].p_desc) + if (audiod_get_AS_interface_index(itf, &_audiod_fct[i], idxItf, pp_desc_int)) { - // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; - - // Advance past AC descriptors - uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - - uint8_t tmp = 0; - while (p_desc < p_desc_end) - { - // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) - { - *idxItf = tmp; - *idxDriver = i; - *pp_desc_int = p_desc; - return true; - } - - // Increase index, bytes read, and pointer - tmp++; - p_desc = tu_desc_next(p_desc); - } + *idxDriver = i; + return true; } } @@ -1985,10 +2003,10 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * for (i = 0; i < CFG_TUD_AUDIO; i++) { // Look for the correct driver by checking if the unique standard AC interface number fits - if (_audiod_itf[i].p_desc && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) + if (_audiod_fct[i].p_desc && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) { // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between - uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); // Points to CS AC descriptor + uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); // Points to CS AC descriptor uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor @@ -2011,15 +2029,15 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) { - if (_audiod_itf[i].p_desc) + if (_audiod_fct[i].p_desc) { // Get pointer at beginning and end - uint8_t const *p_desc = _audiod_itf[i].p_desc; - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc = _audiod_fct[i].p_desc; + uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; while (p_desc < p_desc_end) { - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_itf[i].p_desc)->bInterfaceNumber == itf) + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) { *idxDriver = i; return true; @@ -2036,13 +2054,13 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) { - if (_audiod_itf[i].p_desc) + if (_audiod_fct[i].p_desc) { // Get pointer at end - uint8_t const *p_desc_end = _audiod_itf[i].p_desc + _audiod_itf[i].desc_length; + uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length; // Advance past AC descriptors - EP we look for are streaming EPs - uint8_t const *p_desc = tu_desc_next(_audiod_itf[i].p_desc); + uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; while (p_desc < p_desc_end) @@ -2063,7 +2081,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) // p_desc points to the AS interface of alternate setting zero // itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter // Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for! -static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf) +static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf) { p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor of current alternate interface descriptor @@ -2151,12 +2169,12 @@ static void audiod_parse_for_AS_params(audiod_interface_t* audio, uint8_t const // Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_itf[itf].p_desc != NULL); + TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); // Format the feedback value - if (_audiod_itf[itf].rhport == 0) + if (_audiod_fct[itf].rhport == 0) { - uint8_t * fb = (uint8_t *) &_audiod_itf[itf].fb_val; + uint8_t * fb = (uint8_t *) &_audiod_fct[itf].fb_val; // For FS format is 10.14 *(fb++) = (feedback >> 2) & 0xFF; @@ -2168,17 +2186,27 @@ bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback) else { // For HS format is 16.16 as originally demanded - _audiod_itf[itf].fb_val = feedback; + _audiod_fct[itf].fb_val = feedback; } // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_itf[itf].rhport, _audiod_itf[itf].ep_fb)) + if (!usbd_edpt_busy(_audiod_fct[itf].rhport, _audiod_fct[itf].ep_fb)) { - return audiod_fb_send(_audiod_itf[itf].rhport, &_audiod_itf[itf]); + return audiod_fb_send(_audiod_fct[itf].rhport, &_audiod_fct[itf]); } return true; } #endif +// No security checks here - internal function only which should always succeed +uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio) +{ + for (uint8_t cnt=0; cnt < CFG_TUD_AUDIO; cnt++) + { + if (&_audiod_fct[cnt] == audio) return cnt; + } + return 0; +} + #endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO -- cgit v1.3.1 From c7c11b181c05136a1c077dc445f422c7e17edc02 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 20 Apr 2021 20:15:02 +0200 Subject: Clean up old depracted and misleading variable names --- src/class/audio/audio_device.c | 218 ++++++++++++++++++++--------------------- src/class/audio/audio_device.h | 66 ++++++------- 2 files changed, 142 insertions(+), 142 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 2504e9c83..4c6c79e30 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -383,15 +383,15 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *audio_fct_idx, uint8_t *idxItf, uint8_t const **pp_desc_int); static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int); -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver); -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver); -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver); +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *audio_fct_idx); +static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *audio_fct_idx); +static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *audio_fct_idx); static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); #if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING -static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf); +static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf); #endif static inline uint8_t tu_desc_subtype(void const* desc) @@ -399,10 +399,10 @@ static inline uint8_t tu_desc_subtype(void const* desc) return ((uint8_t const*) desc)[2]; } -bool tud_audio_n_mounted(uint8_t itf) +bool tud_audio_n_mounted(uint8_t audio_fct_idx) { - TU_VERIFY(itf < CFG_TUD_AUDIO); - audiod_function_t* audio = &_audiod_fct[itf]; + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO); + audiod_function_t* audio = &_audiod_fct[audio_fct_idx]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT if (audio->ep_out == 0) return false; @@ -429,44 +429,44 @@ bool tud_audio_n_mounted(uint8_t itf) #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -uint16_t tud_audio_n_available(uint8_t itf) +uint16_t tud_audio_n_available(uint8_t audio_fct_idx) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); - return tu_fifo_count(&_audiod_fct[itf].ep_out_ff); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + return tu_fifo_count(&_audiod_fct[audio_fct_idx].ep_out_ff); } -uint16_t tud_audio_n_read(uint8_t itf, void* buffer, uint16_t bufsize) +uint16_t tud_audio_n_read(uint8_t audio_fct_idx, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); - return tu_fifo_read_n(&_audiod_fct[itf].ep_out_ff, buffer, bufsize); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + return tu_fifo_read_n(&_audiod_fct[audio_fct_idx].ep_out_ff, buffer, bufsize); } -bool tud_audio_n_clear_ep_out_ff(uint8_t itf) +bool tud_audio_n_clear_ep_out_ff(uint8_t audio_fct_idx) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[itf].ep_out_ff); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + return tu_fifo_clear(&_audiod_fct[audio_fct_idx].ep_out_ff); } #endif #if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT // Delete all content in the support RX FIFOs -bool tud_audio_n_clear_rx_support_ff(uint8_t itf, uint8_t channelId) +bool tud_audio_n_clear_rx_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_rx_supp_ff); - return tu_fifo_clear(&_audiod_fct[itf].rx_supp_ff[channelId]); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_rx_supp_ff); + return tu_fifo_clear(&_audiod_fct[audio_fct_idx].rx_supp_ff[ff_idx]); } -uint16_t tud_audio_n_available_support_ff(uint8_t itf, uint8_t channelId) +uint16_t tud_audio_n_available_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_rx_supp_ff); - return tu_fifo_count(&_audiod_fct[itf].rx_supp_ff[channelId]); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_rx_supp_ff); + return tu_fifo_count(&_audiod_fct[audio_fct_idx].rx_supp_ff[ff_idx]); } -uint16_t tud_audio_n_read_support_ff(uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize) +uint16_t tud_audio_n_read_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx, void* buffer, uint16_t bufsize) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_rx_supp_ff); - return tu_fifo_read_n(&_audiod_fct[itf].rx_supp_ff[channelId], buffer, bufsize); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_rx_supp_ff); + return tu_fifo_read_n(&_audiod_fct[audio_fct_idx].rx_supp_ff[ff_idx], buffer, bufsize); } #endif @@ -682,30 +682,30 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. * - * \param[in] itf: Index of audio function interface + * \param[in] audio_fct_idx: Index of audio function interface * \param[in] data: Pointer to data array to be copied from * \param[in] len: # of array elements to copy * \return Number of bytes actually written */ -uint16_t tud_audio_n_write(uint8_t itf, const void * data, uint16_t len) +uint16_t tud_audio_n_write(uint8_t audio_fct_idx, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); - return tu_fifo_write_n(&_audiod_fct[itf].ep_in_ff, data, len); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + return tu_fifo_write_n(&_audiod_fct[audio_fct_idx].ep_in_ff, data, len); } -bool tud_audio_n_clear_ep_in_ff(uint8_t itf) // Delete all content in the EP IN FIFO +bool tud_audio_n_clear_ep_in_ff(uint8_t audio_fct_idx) // Delete all content in the EP IN FIFO { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[itf].ep_in_ff); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + return tu_fifo_clear(&_audiod_fct[audio_fct_idx].ep_in_ff); } #endif #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit +uint16_t tud_audio_n_flush_tx_support_ff(uint8_t audio_fct_idx) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); - audiod_function_t* audio = &_audiod_fct[itf]; + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + audiod_function_t* audio = &_audiod_fct[audio_fct_idx]; uint16_t n_bytes_copied = tu_fifo_count(&audio->tx_supp_ff[0]); @@ -717,16 +717,16 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t itf) // Force a return n_bytes_copied; } -bool tud_audio_n_clear_tx_support_ff(uint8_t itf, uint8_t channelId) +bool tud_audio_n_clear_tx_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_tx_supp_ff); - return tu_fifo_clear(&_audiod_fct[itf].tx_supp_ff[channelId]); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_tx_supp_ff); + return tu_fifo_clear(&_audiod_fct[audio_fct_idx].tx_supp_ff[ff_idx]); } -uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void * data, uint16_t len) +uint16_t tud_audio_n_write_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx, const void * data, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL, channelId < _audiod_fct[itf].n_tx_supp_ff); - return tu_fifo_write_n(&_audiod_fct[itf].tx_supp_ff[channelId], data, len); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_tx_supp_ff); + return tu_fifo_write_n(&_audiod_fct[audio_fct_idx].tx_supp_ff[ff_idx], data, len); } #endif @@ -734,20 +734,20 @@ uint16_t tud_audio_n_write_support_ff(uint8_t itf, uint8_t channelId, const void #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN // If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user -uint16_t tud_audio_int_ctr_n_write(uint8_t itf, uint8_t const* buffer, uint16_t len) +uint16_t tud_audio_int_ctr_n_write(uint8_t audio_fct_idx, uint8_t const* buffer, uint16_t len) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); // We write directly into the EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(_audiod_fct[itf].rhport, _audiod_fct[itf].ep_int_ctr)); + TU_VERIFY(!usbd_edpt_busy(_audiod_fct[audio_fct_idx].rhport, _audiod_fct[audio_fct_idx].ep_int_ctr)); // Check length TU_VERIFY(len <= CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE); - memcpy(_audiod_fct[itf].ep_int_ctr_buf, buffer, len); + memcpy(_audiod_fct[audio_fct_idx].ep_int_ctr_buf, buffer, len); // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(_audiod_fct[itf].rhport, _audiod_fct[itf].ep_int_ctr, _audiod_fct[itf].ep_int_ctr_buf, len)); + TU_VERIFY(usbd_edpt_xfer(_audiod_fct[audio_fct_idx].rhport, _audiod_fct[audio_fct_idx].ep_int_ctr, _audiod_fct[audio_fct_idx].ep_int_ctr_buf, len)); return true; } @@ -1406,13 +1406,13 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const itf = tu_u16_low(p_request->wIndex); // Find index of audio streaming interface - uint8_t idxDriver, idxItf; + uint8_t audio_fct_idx, idxItf; uint8_t const *dummy; - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &idxDriver, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[idxDriver].alt_setting[idxItf], 1)); + TU_VERIFY(audiod_get_AS_interface_index_global(itf, &audio_fct_idx, &idxItf, &dummy)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[audio_fct_idx].alt_setting[idxItf], 1)); - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[idxDriver].alt_setting[idxItf]); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[audio_fct_idx].alt_setting[idxItf]); return true; } @@ -1438,11 +1438,11 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); // Find index of audio streaming interface and index of interface - uint8_t idxDriver, idxItf; + uint8_t audio_fct_idx, idxItf; uint8_t const *p_desc; - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &idxDriver, &idxItf, &p_desc)); + TU_VERIFY(audiod_get_AS_interface_index_global(itf, &audio_fct_idx, &idxItf, &p_desc)); - audiod_function_t* audio = &_audiod_fct[idxDriver]; + audiod_function_t* audio = &_audiod_fct[audio_fct_idx]; // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) #if CFG_TUD_AUDIO_ENABLE_EP_IN @@ -1548,7 +1548,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[idxDriver])); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[audio_fct_idx])); } #endif // CFG_TUD_AUDIO_ENABLE_EP_IN @@ -1624,7 +1624,7 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const // Handle audio class specific set requests if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) { - uint8_t idxDriver; + uint8_t audio_fct_idx; switch (p_request->bmRequestType_bit.recipient) { @@ -1638,10 +1638,10 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const if (tud_audio_set_req_entity_cb) { // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &audio_fct_idx)); // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf); + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf); } else { @@ -1654,10 +1654,10 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const if (tud_audio_set_req_itf_cb) { // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + TU_VERIFY(audiod_verify_itf_exists(itf, &audio_fct_idx)); // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf); + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf); } else { @@ -1675,10 +1675,10 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const if (tud_audio_set_req_ep_cb) { // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + TU_VERIFY(audiod_verify_ep_exists(ep, &audio_fct_idx)); // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf); + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf); } else { @@ -1719,7 +1719,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) { uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t idxDriver; + uint8_t audio_fct_idx; // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) @@ -1732,7 +1732,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const if (entityID != 0) { // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &audio_fct_idx)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) @@ -1751,7 +1751,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const else { // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + TU_VERIFY(audiod_verify_itf_exists(itf, &audio_fct_idx)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) @@ -1774,7 +1774,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const uint8_t ep = TU_U16_LOW(p_request->wIndex); // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + TU_VERIFY(audiod_verify_ep_exists(ep, &audio_fct_idx)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) @@ -1796,7 +1796,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const } // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[idxDriver].ctrl_buf, _audiod_fct[idxDriver].ctrl_buf_sz)); + TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf, _audiod_fct[audio_fct_idx].ctrl_buf_sz)); return true; } @@ -1825,14 +1825,14 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 (void) xferred_bytes; // Search for interface belonging to given end point address and proceed as required - uint8_t idxDriver; - for (idxDriver = 0; idxDriver < CFG_TUD_AUDIO; idxDriver++) + uint8_t audio_fct_idx; + for (audio_fct_idx = 0; audio_fct_idx < CFG_TUD_AUDIO; audio_fct_idx++) { #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN // Data transmission of control interrupt finished - if (_audiod_fct[idxDriver].ep_int_ctr == ep_addr) + if (_audiod_fct[audio_fct_idx].ep_int_ctr == ep_addr) { // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? @@ -1849,7 +1849,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_IN // Data transmission of audio packet finished - if (_audiod_fct[idxDriver].ep_in == ep_addr && _audiod_fct[idxDriver].alt_setting != 0) + if (_audiod_fct[audio_fct_idx].ep_in == ep_addr && _audiod_fct[audio_fct_idx].alt_setting != 0) { // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." @@ -1860,7 +1860,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // This is the only place where we can fill something into the EPs buffer! // Load new data - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[idxDriver])); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[audio_fct_idx])); // Transmission of ZLP is done by audiod_tx_done_cb() return true; @@ -1870,21 +1870,21 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_OUT // New audio packet received - if (_audiod_fct[idxDriver].ep_out == ep_addr) + if (_audiod_fct[audio_fct_idx].ep_out == ep_addr) { - TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_fct[idxDriver], (uint16_t) xferred_bytes)); + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_fct[audio_fct_idx], (uint16_t) xferred_bytes)); return true; } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Transmission of feedback EP finished - if (_audiod_fct[idxDriver].ep_fb == ep_addr) + if (_audiod_fct[audio_fct_idx].ep_fb == ep_addr) { if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, &_audiod_fct[idxDriver]); + return audiod_fb_send(rhport, &_audiod_fct[audio_fct_idx]); } #endif #endif @@ -1899,7 +1899,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; // Get corresponding driver index - uint8_t idxDriver; + uint8_t audio_fct_idx; uint8_t itf = TU_U16_LOW(p_request->wIndex); // Conduct checks which depend on the recipient @@ -1913,12 +1913,12 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req if (entityID != 0) { // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &idxDriver)); + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &audio_fct_idx)); } else { // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &idxDriver)); + TU_VERIFY(audiod_verify_itf_exists(itf, &audio_fct_idx)); } break; @@ -1927,7 +1927,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req uint8_t ep = TU_U16_LOW(p_request->wIndex); // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &idxDriver)); + TU_VERIFY(audiod_verify_ep_exists(ep, &audio_fct_idx)); break; // Unknown/Unsupported recipient @@ -1935,13 +1935,13 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req } // Crop length - if (len > _audiod_fct[idxDriver].ctrl_buf_sz) len = _audiod_fct[idxDriver].ctrl_buf_sz; + if (len > _audiod_fct[audio_fct_idx].ctrl_buf_sz) len = _audiod_fct[audio_fct_idx].ctrl_buf_sz; // Copy into buffer - memcpy((void *)_audiod_fct[idxDriver].ctrl_buf, data, (size_t)len); + memcpy((void *)_audiod_fct[audio_fct_idx].ctrl_buf, data, (size_t)len); // Schedule transmit - return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[idxDriver].ctrl_buf, len); + return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[audio_fct_idx].ctrl_buf, len); } // This helper function finds for a given audio function and AS interface number the index of the attached driver structure, the index of the interface in the audio function @@ -1980,7 +1980,7 @@ static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio // This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function // (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and // finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *idxDriver, uint8_t *idxItf, uint8_t const **pp_desc_int) +static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *audio_fct_idx, uint8_t *idxItf, uint8_t const **pp_desc_int) { // Loop over audio driver interfaces uint8_t i; @@ -1988,7 +1988,7 @@ static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *idxDriver { if (audiod_get_AS_interface_index(itf, &_audiod_fct[i], idxItf, pp_desc_int)) { - *idxDriver = i; + *audio_fct_idx = i; return true; } } @@ -1997,7 +1997,7 @@ static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *idxDriver } // Verify an entity with the given ID exists and returns also the corresponding driver index -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *idxDriver) +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *audio_fct_idx) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -2014,7 +2014,7 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * { if (p_desc[3] == entityID) // Entity IDs are always at offset 3 { - *idxDriver = i; + *audio_fct_idx = i; return true; } p_desc = tu_desc_next(p_desc); @@ -2024,7 +2024,7 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * return false; } -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) +static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *audio_fct_idx) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -2039,7 +2039,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) { if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) { - *idxDriver = i; + *audio_fct_idx = i; return true; } p_desc = tu_desc_next(p_desc); @@ -2049,7 +2049,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *idxDriver) return false; } -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) +static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *audio_fct_idx) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -2067,7 +2067,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) { - *idxDriver = i; + *audio_fct_idx = i; return true; } p_desc = tu_desc_next(p_desc); @@ -2081,7 +2081,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver) // p_desc points to the AS interface of alternate setting zero // itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter // Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for! -static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const itf) +static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf) { p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor of current alternate interface descriptor @@ -2094,17 +2094,17 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) { #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf != audio->ep_in_as_intf_num && itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently + if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf != audio->ep_in_as_intf_num) break; + if (as_itf != audio->ep_in_as_intf_num) break; #endif #if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf != audio->ep_out_as_intf_num) break; + if (as_itf != audio->ep_out_as_intf_num) break; #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN - if (itf == audio->ep_in_as_intf_num) + if (as_itf == audio->ep_in_as_intf_num) { audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; audio->format_type_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; @@ -2116,7 +2116,7 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf == audio->ep_out_as_intf_num) + if (as_itf == audio->ep_out_as_intf_num) { audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; audio->format_type_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; @@ -2132,24 +2132,24 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) { #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf != audio->ep_in_as_intf_num && itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently + if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) break; // Abort loop, this interface has no EP, this driver does not support this currently #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf != audio->ep_in_as_intf_num) break; + if (as_itf != audio->ep_in_as_intf_num) break; #endif #if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf != audio->ep_out_as_intf_num) break; + if (as_itf != audio->ep_out_as_intf_num) break; #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN - if (itf == audio->ep_in_as_intf_num) + if (as_itf == audio->ep_in_as_intf_num) { audio->n_bytes_per_sampe_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; } #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (itf == audio->ep_out_as_intf_num) + if (as_itf == audio->ep_out_as_intf_num) { audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; } @@ -2167,14 +2167,14 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically -bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback) +bool tud_audio_n_fb_set(uint8_t audio_fct_idx, uint32_t feedback) { - TU_VERIFY(itf < CFG_TUD_AUDIO && _audiod_fct[itf].p_desc != NULL); + TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); // Format the feedback value - if (_audiod_fct[itf].rhport == 0) + if (_audiod_fct[audio_fct_idx].rhport == 0) { - uint8_t * fb = (uint8_t *) &_audiod_fct[itf].fb_val; + uint8_t * fb = (uint8_t *) &_audiod_fct[audio_fct_idx].fb_val; // For FS format is 10.14 *(fb++) = (feedback >> 2) & 0xFF; @@ -2186,13 +2186,13 @@ bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback) else { // For HS format is 16.16 as originally demanded - _audiod_fct[itf].fb_val = feedback; + _audiod_fct[audio_fct_idx].fb_val = feedback; } // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_fct[itf].rhport, _audiod_fct[itf].ep_fb)) + if (!usbd_edpt_busy(_audiod_fct[audio_fct_idx].rhport, _audiod_fct[audio_fct_idx].ep_fb)) { - return audiod_fb_send(_audiod_fct[itf].rhport, &_audiod_fct[itf]); + return audiod_fb_send(_audiod_fct[audio_fct_idx].rhport, &_audiod_fct[audio_fct_idx]); } return true; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index f91540b64..2dccc11bc 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -358,33 +358,33 @@ extern "C" { // Application API (Multiple Interfaces) // CFG_TUD_AUDIO > 1 //--------------------------------------------------------------------+ -bool tud_audio_n_mounted (uint8_t itf); +bool tud_audio_n_mounted (uint8_t audio_fct_idx); #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -uint16_t tud_audio_n_available (uint8_t itf); -uint16_t tud_audio_n_read (uint8_t itf, void* buffer, uint16_t bufsize); -bool tud_audio_n_clear_ep_out_ff (uint8_t itf); // Delete all content in the EP OUT FIFO +uint16_t tud_audio_n_available (uint8_t audio_fct_idx); +uint16_t tud_audio_n_read (uint8_t audio_fct_idx, void* buffer, uint16_t bufsize); +bool tud_audio_n_clear_ep_out_ff (uint8_t audio_fct_idx); // Delete all content in the EP OUT FIFO #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -bool tud_audio_n_clear_rx_support_ff (uint8_t itf, uint8_t channelId); // Delete all content in the support RX FIFOs -uint16_t tud_audio_n_available_support_ff (uint8_t itf, uint8_t channelId); -uint16_t tud_audio_n_read_support_ff (uint8_t itf, uint8_t channelId, void* buffer, uint16_t bufsize); +bool tud_audio_n_clear_rx_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx); // Delete all content in the support RX FIFOs +uint16_t tud_audio_n_available_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx); +uint16_t tud_audio_n_read_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx, void* buffer, uint16_t bufsize); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_write (uint8_t itf, const void * data, uint16_t len); -bool tud_audio_n_clear_ep_in_ff (uint8_t itf); // Delete all content in the EP IN FIFO +uint16_t tud_audio_n_write (uint8_t audio_fct_idx, const void * data, uint16_t len); +bool tud_audio_n_clear_ep_in_ff (uint8_t audio_fct_idx); // Delete all content in the EP IN FIFO #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_flush_tx_support_ff (uint8_t itf); // Force all content in the support TX FIFOs to be written into EP SW FIFO -bool tud_audio_n_clear_tx_support_ff (uint8_t itf, uint8_t channelId); -uint16_t tud_audio_n_write_support_ff (uint8_t itf, uint8_t channelId, const void * data, uint16_t len); +uint16_t tud_audio_n_flush_tx_support_ff (uint8_t audio_fct_idx); // Force all content in the support TX FIFOs to be written into EP SW FIFO +bool tud_audio_n_clear_tx_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx); +uint16_t tud_audio_n_write_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx, const void * data, uint16_t len); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -uint16_t tud_audio_int_ctr_n_write (uint8_t itf, uint8_t const* buffer, uint16_t len); +uint16_t tud_audio_int_ctr_n_write (uint8_t audio_fct_idx, uint8_t const* buffer, uint16_t len); #endif //--------------------------------------------------------------------+ @@ -402,9 +402,9 @@ static inline uint16_t tud_audio_read (void* buffer, uint1 #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -static inline bool tud_audio_clear_rx_support_ff (uint8_t channelId); -static inline uint16_t tud_audio_available_support_ff (uint8_t channelId); -static inline uint16_t tud_audio_read_support_ff (uint8_t channelId, void* buffer, uint16_t bufsize); +static inline bool tud_audio_clear_rx_support_ff (uint8_t ff_idx); +static inline uint16_t tud_audio_available_support_ff (uint8_t ff_idx); +static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, void* buffer, uint16_t bufsize); #endif // TX API @@ -416,8 +416,8 @@ static inline bool tud_audio_clear_ep_in_ff (void); #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_flush_tx_support_ff (void); -static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t channelId); -static inline uint16_t tud_audio_write_support_ff (uint8_t channelId, const void * data, uint16_t len); +static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t ff_idx); +static inline uint16_t tud_audio_write_support_ff (uint8_t ff_idx, const void * data, uint16_t len); #endif // INT CTR API @@ -439,13 +439,13 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_ENABLE_EP_IN -TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t audio_fct_idx, uint8_t ep_in, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t audio_fct_idx, uint8_t ep_in, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t itf, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t audio_fct_idx, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t audio_fct_idx, uint8_t ep_out, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -454,7 +454,7 @@ TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); // Value will be corrected for FS to 10.14 format automatically. // (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). // Feedback value will be sent at FB endpoint interval till it's changed. -bool tud_audio_n_fb_set(uint8_t itf, uint32_t feedback); +bool tud_audio_n_fb_set(uint8_t audio_fct_idx, uint32_t feedback); static inline bool tud_audio_fb_set(uint32_t feedback); #endif @@ -518,19 +518,19 @@ static inline bool tud_audio_clear_ep_out_ff(void) #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -static inline bool tud_audio_clear_rx_support_ff(uint8_t channelId) +static inline bool tud_audio_clear_rx_support_ff(uint8_t ff_idx) { - return tud_audio_n_clear_rx_support_ff(0, channelId); + return tud_audio_n_clear_rx_support_ff(0, ff_idx); } -static inline uint16_t tud_audio_available_support_ff(uint8_t channelId) +static inline uint16_t tud_audio_available_support_ff(uint8_t ff_idx) { - return tud_audio_n_available_support_ff(0, channelId); + return tud_audio_n_available_support_ff(0, ff_idx); } -static inline uint16_t tud_audio_read_support_ff(uint8_t channelId, void* buffer, uint16_t bufsize) +static inline uint16_t tud_audio_read_support_ff(uint8_t ff_idx, void* buffer, uint16_t bufsize) { - return tud_audio_n_read_support_ff(0, channelId, buffer, bufsize); + return tud_audio_n_read_support_ff(0, ff_idx, buffer, bufsize); } #endif @@ -558,14 +558,14 @@ static inline uint16_t tud_audio_flush_tx_support_ff(void) return tud_audio_n_flush_tx_support_ff(0); } -static inline uint16_t tud_audio_clear_tx_support_ff(uint8_t channelId) +static inline uint16_t tud_audio_clear_tx_support_ff(uint8_t ff_idx) { - return tud_audio_n_clear_tx_support_ff(0, channelId); + return tud_audio_n_clear_tx_support_ff(0, ff_idx); } -static inline uint16_t tud_audio_write_support_ff(uint8_t channelId, const void * data, uint16_t len) +static inline uint16_t tud_audio_write_support_ff(uint8_t ff_idx, const void * data, uint16_t len) { - return tud_audio_n_write_support_ff(0, channelId, data, len); + return tud_audio_n_write_support_ff(0, ff_idx, data, len); } #endif -- cgit v1.3.1 From 29bcc83d0f9bb132eee24a0585ed3565a3e2eaee Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 21 Apr 2021 17:01:38 +0200 Subject: Remove unnecessary volatile and short audio function index to func_id --- src/class/audio/audio_device.c | 196 ++++++++++++++++++++--------------------- src/class/audio/audio_device.h | 36 ++++---- 2 files changed, 116 insertions(+), 116 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 4c6c79e30..0a60d9ee5 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -383,11 +383,11 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * p_request); static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * p_request); -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *audio_fct_idx, uint8_t *idxItf, uint8_t const **pp_desc_int); +static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id, uint8_t *idxItf, uint8_t const **pp_desc_int); static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio, uint8_t *idxItf, uint8_t const **pp_desc_int); -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *audio_fct_idx); -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *audio_fct_idx); -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *audio_fct_idx); +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id); +static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id); +static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id); static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); #if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING @@ -399,10 +399,10 @@ static inline uint8_t tu_desc_subtype(void const* desc) return ((uint8_t const*) desc)[2]; } -bool tud_audio_n_mounted(uint8_t audio_fct_idx) +bool tud_audio_n_mounted(uint8_t func_id) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO); - audiod_function_t* audio = &_audiod_fct[audio_fct_idx]; + TU_VERIFY(func_id < CFG_TUD_AUDIO); + audiod_function_t* audio = &_audiod_fct[func_id]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT if (audio->ep_out == 0) return false; @@ -429,44 +429,44 @@ bool tud_audio_n_mounted(uint8_t audio_fct_idx) #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -uint16_t tud_audio_n_available(uint8_t audio_fct_idx) +uint16_t tud_audio_n_available(uint8_t func_id) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); - return tu_fifo_count(&_audiod_fct[audio_fct_idx].ep_out_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_count(&_audiod_fct[func_id].ep_out_ff); } -uint16_t tud_audio_n_read(uint8_t audio_fct_idx, void* buffer, uint16_t bufsize) +uint16_t tud_audio_n_read(uint8_t func_id, void* buffer, uint16_t bufsize) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); - return tu_fifo_read_n(&_audiod_fct[audio_fct_idx].ep_out_ff, buffer, bufsize); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_read_n(&_audiod_fct[func_id].ep_out_ff, buffer, bufsize); } -bool tud_audio_n_clear_ep_out_ff(uint8_t audio_fct_idx) +bool tud_audio_n_clear_ep_out_ff(uint8_t func_id) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[audio_fct_idx].ep_out_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_clear(&_audiod_fct[func_id].ep_out_ff); } #endif #if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT // Delete all content in the support RX FIFOs -bool tud_audio_n_clear_rx_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx) +bool tud_audio_n_clear_rx_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_rx_supp_ff); - return tu_fifo_clear(&_audiod_fct[audio_fct_idx].rx_supp_ff[ff_idx]); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + return tu_fifo_clear(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); } -uint16_t tud_audio_n_available_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx) +uint16_t tud_audio_n_available_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_rx_supp_ff); - return tu_fifo_count(&_audiod_fct[audio_fct_idx].rx_supp_ff[ff_idx]); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + return tu_fifo_count(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); } -uint16_t tud_audio_n_read_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx, void* buffer, uint16_t bufsize) +uint16_t tud_audio_n_read_support_ff(uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_rx_supp_ff); - return tu_fifo_read_n(&_audiod_fct[audio_fct_idx].rx_supp_ff[ff_idx], buffer, bufsize); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + return tu_fifo_read_n(&_audiod_fct[func_id].rx_supp_ff[ff_idx], buffer, bufsize); } #endif @@ -682,30 +682,30 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. * - * \param[in] audio_fct_idx: Index of audio function interface + * \param[in] func_id: Index of audio function interface * \param[in] data: Pointer to data array to be copied from * \param[in] len: # of array elements to copy * \return Number of bytes actually written */ -uint16_t tud_audio_n_write(uint8_t audio_fct_idx, const void * data, uint16_t len) +uint16_t tud_audio_n_write(uint8_t func_id, const void * data, uint16_t len) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); - return tu_fifo_write_n(&_audiod_fct[audio_fct_idx].ep_in_ff, data, len); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_write_n(&_audiod_fct[func_id].ep_in_ff, data, len); } -bool tud_audio_n_clear_ep_in_ff(uint8_t audio_fct_idx) // Delete all content in the EP IN FIFO +bool tud_audio_n_clear_ep_in_ff(uint8_t func_id) // Delete all content in the EP IN FIFO { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[audio_fct_idx].ep_in_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + return tu_fifo_clear(&_audiod_fct[func_id].ep_in_ff); } #endif #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -uint16_t tud_audio_n_flush_tx_support_ff(uint8_t audio_fct_idx) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit +uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); - audiod_function_t* audio = &_audiod_fct[audio_fct_idx]; + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + audiod_function_t* audio = &_audiod_fct[func_id]; uint16_t n_bytes_copied = tu_fifo_count(&audio->tx_supp_ff[0]); @@ -717,16 +717,16 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t audio_fct_idx) return n_bytes_copied; } -bool tud_audio_n_clear_tx_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx) +bool tud_audio_n_clear_tx_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_tx_supp_ff); - return tu_fifo_clear(&_audiod_fct[audio_fct_idx].tx_supp_ff[ff_idx]); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_tx_supp_ff); + return tu_fifo_clear(&_audiod_fct[func_id].tx_supp_ff[ff_idx]); } -uint16_t tud_audio_n_write_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx, const void * data, uint16_t len) +uint16_t tud_audio_n_write_support_ff(uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL, ff_idx < _audiod_fct[audio_fct_idx].n_tx_supp_ff); - return tu_fifo_write_n(&_audiod_fct[audio_fct_idx].tx_supp_ff[ff_idx], data, len); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_tx_supp_ff); + return tu_fifo_write_n(&_audiod_fct[func_id].tx_supp_ff[ff_idx], data, len); } #endif @@ -734,20 +734,20 @@ uint16_t tud_audio_n_write_support_ff(uint8_t audio_fct_idx, uint8_t ff_idx, con #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN // If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user -uint16_t tud_audio_int_ctr_n_write(uint8_t audio_fct_idx, uint8_t const* buffer, uint16_t len) +uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint16_t len) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); // We write directly into the EP's buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(_audiod_fct[audio_fct_idx].rhport, _audiod_fct[audio_fct_idx].ep_int_ctr)); + TU_VERIFY(!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr)); // Check length TU_VERIFY(len <= CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE); - memcpy(_audiod_fct[audio_fct_idx].ep_int_ctr_buf, buffer, len); + memcpy(_audiod_fct[func_id].ep_int_ctr_buf, buffer, len); // Schedule transmit - TU_VERIFY(usbd_edpt_xfer(_audiod_fct[audio_fct_idx].rhport, _audiod_fct[audio_fct_idx].ep_int_ctr, _audiod_fct[audio_fct_idx].ep_int_ctr_buf, len)); + TU_VERIFY(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr, _audiod_fct[func_id].ep_int_ctr_buf, len)); return true; } @@ -1406,13 +1406,13 @@ static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const itf = tu_u16_low(p_request->wIndex); // Find index of audio streaming interface - uint8_t audio_fct_idx, idxItf; + uint8_t func_id, idxItf; uint8_t const *dummy; - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &audio_fct_idx, &idxItf, &dummy)); - TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[audio_fct_idx].alt_setting[idxItf], 1)); + TU_VERIFY(audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &dummy)); + TU_VERIFY(tud_control_xfer(rhport, p_request, &_audiod_fct[func_id].alt_setting[idxItf], 1)); - TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[audio_fct_idx].alt_setting[idxItf]); + TU_LOG2(" Get itf: %u - current alt: %u\r\n", itf, _audiod_fct[func_id].alt_setting[idxItf]); return true; } @@ -1433,16 +1433,16 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // 3. Open new EP uint8_t const itf = tu_u16_low(p_request->wIndex); - volatile uint8_t const alt = tu_u16_low(p_request->wValue); + uint8_t const alt = tu_u16_low(p_request->wValue); TU_LOG2(" Set itf: %u - alt: %u\r\n", itf, alt); // Find index of audio streaming interface and index of interface - uint8_t audio_fct_idx, idxItf; + uint8_t func_id, idxItf; uint8_t const *p_desc; - TU_VERIFY(audiod_get_AS_interface_index_global(itf, &audio_fct_idx, &idxItf, &p_desc)); + TU_VERIFY(audiod_get_AS_interface_index_global(itf, &func_id, &idxItf, &p_desc)); - audiod_function_t* audio = &_audiod_fct[audio_fct_idx]; + audiod_function_t* audio = &_audiod_fct[func_id]; // Look if there is an EP to be closed - for this driver, there are only 3 possible EPs which may be closed (only AS related EPs can be closed, AC EP (if present) is always open) #if CFG_TUD_AUDIO_ENABLE_EP_IN @@ -1548,7 +1548,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[audio_fct_idx])); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id])); } #endif // CFG_TUD_AUDIO_ENABLE_EP_IN @@ -1624,7 +1624,7 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const // Handle audio class specific set requests if(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) { - uint8_t audio_fct_idx; + uint8_t func_id; switch (p_request->bmRequestType_bit.recipient) { @@ -1638,10 +1638,10 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const if (tud_audio_set_req_entity_cb) { // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &audio_fct_idx)); + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf); + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } else { @@ -1654,10 +1654,10 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const if (tud_audio_set_req_itf_cb) { // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &audio_fct_idx)); + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf); + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } else { @@ -1675,10 +1675,10 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const if (tud_audio_set_req_ep_cb) { // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &audio_fct_idx)); + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf); + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } else { @@ -1719,7 +1719,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) { uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t audio_fct_idx; + uint8_t func_id; // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) @@ -1732,7 +1732,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const if (entityID != 0) { // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &audio_fct_idx)); + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) @@ -1751,7 +1751,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const else { // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &audio_fct_idx)); + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) @@ -1774,7 +1774,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const uint8_t ep = TU_U16_LOW(p_request->wIndex); // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &audio_fct_idx)); + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) @@ -1796,7 +1796,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const } // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[audio_fct_idx].ctrl_buf, _audiod_fct[audio_fct_idx].ctrl_buf_sz)); + TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz)); return true; } @@ -1825,14 +1825,14 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 (void) xferred_bytes; // Search for interface belonging to given end point address and proceed as required - uint8_t audio_fct_idx; - for (audio_fct_idx = 0; audio_fct_idx < CFG_TUD_AUDIO; audio_fct_idx++) + uint8_t func_id; + for (func_id = 0; func_id < CFG_TUD_AUDIO; func_id++) { #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN // Data transmission of control interrupt finished - if (_audiod_fct[audio_fct_idx].ep_int_ctr == ep_addr) + if (_audiod_fct[func_id].ep_int_ctr == ep_addr) { // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) // In case there is nothing to send we have to return a NAK - this is taken care of by PHY ??? @@ -1849,7 +1849,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_IN // Data transmission of audio packet finished - if (_audiod_fct[audio_fct_idx].ep_in == ep_addr && _audiod_fct[audio_fct_idx].alt_setting != 0) + if (_audiod_fct[func_id].ep_in == ep_addr && _audiod_fct[func_id].alt_setting != 0) { // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." @@ -1860,7 +1860,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // This is the only place where we can fill something into the EPs buffer! // Load new data - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[audio_fct_idx])); + TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id])); // Transmission of ZLP is done by audiod_tx_done_cb() return true; @@ -1870,21 +1870,21 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_OUT // New audio packet received - if (_audiod_fct[audio_fct_idx].ep_out == ep_addr) + if (_audiod_fct[func_id].ep_out == ep_addr) { - TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_fct[audio_fct_idx], (uint16_t) xferred_bytes)); + TU_VERIFY(audiod_rx_done_cb(rhport, &_audiod_fct[func_id], (uint16_t) xferred_bytes)); return true; } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Transmission of feedback EP finished - if (_audiod_fct[audio_fct_idx].ep_fb == ep_addr) + if (_audiod_fct[func_id].ep_fb == ep_addr) { if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, &_audiod_fct[audio_fct_idx]); + return audiod_fb_send(rhport, &_audiod_fct[func_id]); } #endif #endif @@ -1899,7 +1899,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req if (p_request->bmRequestType_bit.direction == TUSB_DIR_OUT) return false; // Get corresponding driver index - uint8_t audio_fct_idx; + uint8_t func_id; uint8_t itf = TU_U16_LOW(p_request->wIndex); // Conduct checks which depend on the recipient @@ -1913,12 +1913,12 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req if (entityID != 0) { // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &audio_fct_idx)); + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); } else { // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &audio_fct_idx)); + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); } break; @@ -1927,7 +1927,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req uint8_t ep = TU_U16_LOW(p_request->wIndex); // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &audio_fct_idx)); + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); break; // Unknown/Unsupported recipient @@ -1935,13 +1935,13 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req } // Crop length - if (len > _audiod_fct[audio_fct_idx].ctrl_buf_sz) len = _audiod_fct[audio_fct_idx].ctrl_buf_sz; + if (len > _audiod_fct[func_id].ctrl_buf_sz) len = _audiod_fct[func_id].ctrl_buf_sz; // Copy into buffer - memcpy((void *)_audiod_fct[audio_fct_idx].ctrl_buf, data, (size_t)len); + memcpy((void *)_audiod_fct[func_id].ctrl_buf, data, (size_t)len); // Schedule transmit - return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[audio_fct_idx].ctrl_buf, len); + return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[func_id].ctrl_buf, len); } // This helper function finds for a given audio function and AS interface number the index of the attached driver structure, the index of the interface in the audio function @@ -1980,7 +1980,7 @@ static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio // This helper function finds for a given AS interface number the index of the attached driver structure, the index of the interface in the audio function // (e.g. the std. AS interface with interface number 15 is the first AS interface for the given audio function and thus gets index zero), and // finally a pointer to the std. AS interface, where the pointer always points to the first alternate setting i.e. alternate interface zero. -static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *audio_fct_idx, uint8_t *idxItf, uint8_t const **pp_desc_int) +static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *func_id, uint8_t *idxItf, uint8_t const **pp_desc_int) { // Loop over audio driver interfaces uint8_t i; @@ -1988,7 +1988,7 @@ static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *audio_fct { if (audiod_get_AS_interface_index(itf, &_audiod_fct[i], idxItf, pp_desc_int)) { - *audio_fct_idx = i; + *func_id = i; return true; } } @@ -1997,7 +1997,7 @@ static bool audiod_get_AS_interface_index_global(uint8_t itf, uint8_t *audio_fct } // Verify an entity with the given ID exists and returns also the corresponding driver index -static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *audio_fct_idx) +static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -2014,7 +2014,7 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * { if (p_desc[3] == entityID) // Entity IDs are always at offset 3 { - *audio_fct_idx = i; + *func_id = i; return true; } p_desc = tu_desc_next(p_desc); @@ -2024,7 +2024,7 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * return false; } -static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *audio_fct_idx) +static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -2039,7 +2039,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *audio_fct_idx) { if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) { - *audio_fct_idx = i; + *func_id = i; return true; } p_desc = tu_desc_next(p_desc); @@ -2049,7 +2049,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *audio_fct_idx) return false; } -static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *audio_fct_idx) +static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) @@ -2067,7 +2067,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *audio_fct_idx) { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) { - *audio_fct_idx = i; + *func_id = i; return true; } p_desc = tu_desc_next(p_desc); @@ -2167,14 +2167,14 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Input value feedback has to be in 16.16 format - the format will be converted according to speed settings automatically -bool tud_audio_n_fb_set(uint8_t audio_fct_idx, uint32_t feedback) +bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) { - TU_VERIFY(audio_fct_idx < CFG_TUD_AUDIO && _audiod_fct[audio_fct_idx].p_desc != NULL); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); // Format the feedback value - if (_audiod_fct[audio_fct_idx].rhport == 0) + if (_audiod_fct[func_id].rhport == 0) { - uint8_t * fb = (uint8_t *) &_audiod_fct[audio_fct_idx].fb_val; + uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; // For FS format is 10.14 *(fb++) = (feedback >> 2) & 0xFF; @@ -2186,13 +2186,13 @@ bool tud_audio_n_fb_set(uint8_t audio_fct_idx, uint32_t feedback) else { // For HS format is 16.16 as originally demanded - _audiod_fct[audio_fct_idx].fb_val = feedback; + _audiod_fct[func_id].fb_val = feedback; } // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_fct[audio_fct_idx].rhport, _audiod_fct[audio_fct_idx].ep_fb)) + if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) { - return audiod_fb_send(_audiod_fct[audio_fct_idx].rhport, &_audiod_fct[audio_fct_idx]); + return audiod_fb_send(_audiod_fct[func_id].rhport, &_audiod_fct[func_id]); } return true; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 2dccc11bc..c070e48c2 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -358,33 +358,33 @@ extern "C" { // Application API (Multiple Interfaces) // CFG_TUD_AUDIO > 1 //--------------------------------------------------------------------+ -bool tud_audio_n_mounted (uint8_t audio_fct_idx); +bool tud_audio_n_mounted (uint8_t func_id); #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING -uint16_t tud_audio_n_available (uint8_t audio_fct_idx); -uint16_t tud_audio_n_read (uint8_t audio_fct_idx, void* buffer, uint16_t bufsize); -bool tud_audio_n_clear_ep_out_ff (uint8_t audio_fct_idx); // Delete all content in the EP OUT FIFO +uint16_t tud_audio_n_available (uint8_t func_id); +uint16_t tud_audio_n_read (uint8_t func_id, void* buffer, uint16_t bufsize); +bool tud_audio_n_clear_ep_out_ff (uint8_t func_id); // Delete all content in the EP OUT FIFO #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -bool tud_audio_n_clear_rx_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx); // Delete all content in the support RX FIFOs -uint16_t tud_audio_n_available_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx); -uint16_t tud_audio_n_read_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx, void* buffer, uint16_t bufsize); +bool tud_audio_n_clear_rx_support_ff (uint8_t func_id, uint8_t ff_idx); // Delete all content in the support RX FIFOs +uint16_t tud_audio_n_available_support_ff (uint8_t func_id, uint8_t ff_idx); +uint16_t tud_audio_n_read_support_ff (uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_write (uint8_t audio_fct_idx, const void * data, uint16_t len); -bool tud_audio_n_clear_ep_in_ff (uint8_t audio_fct_idx); // Delete all content in the EP IN FIFO +uint16_t tud_audio_n_write (uint8_t func_id, const void * data, uint16_t len); +bool tud_audio_n_clear_ep_in_ff (uint8_t func_id); // Delete all content in the EP IN FIFO #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_flush_tx_support_ff (uint8_t audio_fct_idx); // Force all content in the support TX FIFOs to be written into EP SW FIFO -bool tud_audio_n_clear_tx_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx); -uint16_t tud_audio_n_write_support_ff (uint8_t audio_fct_idx, uint8_t ff_idx, const void * data, uint16_t len); +uint16_t tud_audio_n_flush_tx_support_ff (uint8_t func_id); // Force all content in the support TX FIFOs to be written into EP SW FIFO +bool tud_audio_n_clear_tx_support_ff (uint8_t func_id, uint8_t ff_idx); +uint16_t tud_audio_n_write_support_ff (uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN -uint16_t tud_audio_int_ctr_n_write (uint8_t audio_fct_idx, uint8_t const* buffer, uint16_t len); +uint16_t tud_audio_int_ctr_n_write (uint8_t func_id, uint8_t const* buffer, uint16_t len); #endif //--------------------------------------------------------------------+ @@ -439,13 +439,13 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_ENABLE_EP_IN -TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t audio_fct_idx, uint8_t ep_in, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t audio_fct_idx, uint8_t ep_in, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t audio_fct_idx, uint8_t ep_out, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t audio_fct_idx, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); +TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -454,7 +454,7 @@ TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport); // Value will be corrected for FS to 10.14 format automatically. // (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). // Feedback value will be sent at FB endpoint interval till it's changed. -bool tud_audio_n_fb_set(uint8_t audio_fct_idx, uint32_t feedback); +bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback); static inline bool tud_audio_fb_set(uint32_t feedback); #endif -- cgit v1.3.1 From 01661b3f281c4e044a370b33bf6617b8d2481407 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 14:56:52 -0400 Subject: Replace dfu_mode with dfu --- src/class/dfu/dfu.h | 24 +- src/class/dfu/dfu_device.c | 594 ++++++++++++++++++++++++++++++++++++++++ src/class/dfu/dfu_device.h | 131 +++++++++ src/class/dfu/dfu_mode_device.c | 594 ---------------------------------------- src/class/dfu/dfu_mode_device.h | 131 --------- src/tusb.h | 2 +- 6 files changed, 738 insertions(+), 738 deletions(-) create mode 100644 src/class/dfu/dfu_device.c create mode 100644 src/class/dfu/dfu_device.h delete mode 100644 src/class/dfu/dfu_mode_device.c delete mode 100644 src/class/dfu/dfu_mode_device.h (limited to 'src') diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h index 2040e415c..af08a29f7 100644 --- a/src/class/dfu/dfu.h +++ b/src/class/dfu/dfu.h @@ -73,7 +73,7 @@ typedef enum { DFU_MANIFEST_WAIT_RESET = 8, DFU_UPLOAD_IDLE = 9, DFU_ERROR = 10, -} dfu_mode_state_t; +} dfu_state_t; // DFU Status typedef enum { @@ -93,7 +93,7 @@ typedef enum { DFU_STATUS_ERRPOR = 0x0D, DFU_STATUS_ERRUNKNOWN = 0x0E, DFU_STATUS_ERRSTALLEDPKT = 0x0F, -} dfu_mode_device_status_t; +} dfu_device_status_t; #define DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK (1 << 0) #define DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK (1 << 1) @@ -134,7 +134,7 @@ static tu_lookup_table_t const _dfu_request_table = .items = _dfu_request_lookup }; -static tu_lookup_entry_t const _dfu_mode_state_lookup[] = +static tu_lookup_entry_t const _dfu_state_lookup[] = { { .key = APP_IDLE , .data = "APP_IDLE" }, { .key = APP_DETACH , .data = "APP_DETACH" }, @@ -149,13 +149,13 @@ static tu_lookup_entry_t const _dfu_mode_state_lookup[] = { .key = DFU_ERROR , .data = "DFU_ERROR" }, }; -static tu_lookup_table_t const _dfu_mode_state_table = +static tu_lookup_table_t const _dfu_state_table = { - .count = TU_ARRAY_SIZE(_dfu_mode_state_lookup), - .items = _dfu_mode_state_lookup + .count = TU_ARRAY_SIZE(_dfu_state_lookup), + .items = _dfu_state_lookup }; -static tu_lookup_entry_t const _dfu_mode_status_lookup[] = +static tu_lookup_entry_t const _dfu_status_lookup[] = { { .key = DFU_STATUS_OK , .data = "OK" }, { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, @@ -175,10 +175,10 @@ static tu_lookup_entry_t const _dfu_mode_status_lookup[] = { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, }; -static tu_lookup_table_t const _dfu_mode_status_table = +static tu_lookup_table_t const _dfu_status_table = { - .count = TU_ARRAY_SIZE(_dfu_mode_status_lookup), - .items = _dfu_mode_status_lookup + .count = TU_ARRAY_SIZE(_dfu_status_lookup), + .items = _dfu_status_lookup }; #endif @@ -186,8 +186,8 @@ static tu_lookup_table_t const _dfu_mode_status_table = #define dfu_debug_print_context() \ { \ TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ - tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state), \ - tu_lookup_find(&_dfu_mode_status_table, _dfu_state_ctx.status) ); \ + tu_lookup_find(&_dfu_state_table, _dfu_state_ctx.state), \ + tu_lookup_find(&_dfu_status_table, _dfu_state_ctx.status) ); \ } diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c new file mode 100644 index 000000000..98213d320 --- /dev/null +++ b/src/class/dfu/dfu_device.c @@ -0,0 +1,594 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) + +#include "dfu_device.h" +#include "device/usbd_pvt.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +typedef struct TU_ATTR_PACKED +{ + dfu_device_status_t status; + dfu_state_t state; + uint8_t attrs; + bool blk_transfer_in_proc; + + uint8_t itf_num; + uint16_t last_block_num; + uint16_t last_transfer_len; + CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; +} dfu_state_ctx_t; + +// Only a single dfu state is allowed +CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx; + + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); +static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); +static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); + + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void dfu_moded_init(void) +{ + _dfu_state_ctx.state = APP_DETACH; // After init, reset will occur. We want to be in APP_DETACH to move to DFU_IDLE + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.attrs = 0; + _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; + + dfu_debug_print_context(); +} + +void dfu_moded_reset(uint8_t rhport) +{ + if (_dfu_state_ctx.state == APP_DETACH) + { + _dfu_state_ctx.state = DFU_IDLE; + } else { + if ( tud_dfu_usb_reset_cb ) + { + tud_dfu_usb_reset_cb(rhport, &_dfu_state_ctx.state); + } else { + switch (_dfu_state_ctx.state) + { + case DFU_IDLE: + case DFU_DNLOAD_SYNC: + case DFU_DNBUSY: + case DFU_DNLOAD_IDLE: + case DFU_MANIFEST_SYNC: + case DFU_MANIFEST: + case DFU_MANIFEST_WAIT_RESET: + case DFU_UPLOAD_IDLE: + { + _dfu_state_ctx.state = (tud_dfu_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; + } + break; + + case DFU_ERROR: + default: + { + _dfu_state_ctx.state = APP_IDLE; + } + break; + } + } + } + + if(_dfu_state_ctx.state == APP_IDLE) + { + tud_dfu_reboot_to_rt_cb(); + } + + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; + dfu_debug_print_context(); +} + +uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) +{ + (void) rhport; + (void) max_len; + + // Ensure this is DFU Mode + TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && + (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); + + uint8_t const * p_desc = tu_desc_next( itf_desc ); + uint16_t drv_len = sizeof(tusb_desc_interface_t); + + if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) + { + tusb_desc_dfu_functional_t *dfu_desc = (tusb_desc_dfu_functional_t *)p_desc; + _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + return drv_len; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) + { + dfu_req_dnload_reply(rhport, request); + return true; + } + + // nothing to do with any other DATA or ACK stage + if ( stage != CONTROL_STAGE_SETUP ) return true; + + TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + + // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request + if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && + TUSB_REQ_SET_INTERFACE == request->bRequest ) + { + tud_control_status(rhport, request); + return true; + } + + // Handle class request only from here + TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); + + switch (request->bRequest) + { + case DFU_REQUEST_DETACH: + case DFU_REQUEST_DNLOAD: + case DFU_REQUEST_UPLOAD: + case DFU_REQUEST_GETSTATUS: + case DFU_REQUEST_CLRSTATUS: + case DFU_REQUEST_GETSTATE: + case DFU_REQUEST_ABORT: + { + return dfu_state_machine(rhport, request); + } + break; + + default: + { + TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); + return ( tud_dfu_req_nonstandard_cb ) ? tud_dfu_req_nonstandard_cb(rhport, stage, request) : false; + } + break; + } + + return true; +} + +static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) +{ + TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, wLength); + tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, retval); + return retval; +} + +static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + dfu_status_req_payload_t resp; + + resp.bStatus = _dfu_state_ctx.status; + if ( tud_dfu_get_poll_timeout_cb ) + { + tud_dfu_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); + } else { + memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); + } + resp.bState = _dfu_state_ctx.state; + resp.iString = ( tud_dfu_get_status_desc_table_index_cb ) ? tud_dfu_get_status_desc_table_index_cb() : 0; + + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); +} + +static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); +} + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) +{ + _dfu_state_ctx.last_block_num = request->wValue; + _dfu_state_ctx.last_transfer_len = request->wLength; + // TODO: add "zero" copy mode so the buffer we read into can be provided by the user + // if they wish, there still will be the internal control buffer copy to this buffer + // but this mode would provide zero copy from the class driver to the application + + // setup for data phase + tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); +} + +static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) +{ + uint8_t bwPollTimeout[3] = {0,0,0}; + + if ( tud_dfu_get_poll_timeout_cb ) + { + tud_dfu_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); + } + + tud_dfu_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); + + // TODO: I want the real xferred len, not what is expected. May need to change usbd.c to do this. + tud_dfu_req_dnload_data_cb(_dfu_state_ctx.last_block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, _dfu_state_ctx.last_transfer_len); + _dfu_state_ctx.blk_transfer_in_proc = false; + + _dfu_state_ctx.last_block_num = 0; + _dfu_state_ctx.last_transfer_len = 0; +} + +void tud_dfu_poll_timeout_done() +{ + if (_dfu_state_ctx.state == DFU_DNBUSY) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + } else if (_dfu_state_ctx.state == DFU_MANIFEST) + { + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) + ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; + } +} + +static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) +{ + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_state_ctx.state)); + + switch (_dfu_state_ctx.state) + { + case DFU_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + dfu_req_dnload_setup(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_UPLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + { + _dfu_state_ctx.state = DFU_UPLOAD_IDLE; + dfu_req_upload(rhport, request, request->wValue, request->wLength); + } else { + _dfu_state_ctx.state = DFU_ERROR; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + ; // do nothing, but don't stall so continue on + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ( _dfu_state_ctx.blk_transfer_in_proc ) + { + _dfu_state_ctx.state = DFU_DNBUSY; + dfu_req_getstatus_reply(rhport, request); + } else { + _dfu_state_ctx.state = DFU_DNLOAD_IDLE; + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNBUSY: + { + switch (request->bRequest) + { + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_DNLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_DNLOAD: + { + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (request->wLength > 0) ) + { + _dfu_state_ctx.state = DFU_DNLOAD_SYNC; + _dfu_state_ctx.blk_transfer_in_proc = true; + dfu_req_dnload_setup(rhport, request); + } else { + if ( tud_dfu_device_data_done_check_cb() ) + { + _dfu_state_ctx.state = DFU_MANIFEST_SYNC; + tud_control_status(rhport, request); + } else { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall + } + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if ( tud_dfu_abort_cb ) + { + tud_dfu_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_SYNC: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) + { + _dfu_state_ctx.state = DFU_MANIFEST; + dfu_req_getstatus_reply(rhport, request); + } else { + if ( tud_dfu_firmware_valid_check_cb() ) + { + _dfu_state_ctx.state = DFU_IDLE; + } + dfu_req_getstatus_reply(rhport, request); + } + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + _dfu_state_ctx.state = DFU_ERROR; + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST: + { + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_MANIFEST_WAIT_RESET: + { + // technically we should never even get here, but we will handle it just in case + TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); + switch (request->bRequest) + { + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_UPLOAD_IDLE: + { + switch (request->bRequest) + { + case DFU_REQUEST_UPLOAD: + { + if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) + { + _dfu_state_ctx.state = DFU_IDLE; + } + } + break; + + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + case DFU_REQUEST_ABORT: + { + if (tud_dfu_abort_cb) + { + tud_dfu_abort_cb(); + } + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + case DFU_ERROR: + { + switch (request->bRequest) + { + case DFU_REQUEST_GETSTATUS: + { + dfu_req_getstatus_reply(rhport, request); + } + break; + + case DFU_REQUEST_CLRSTATUS: + { + _dfu_state_ctx.state = DFU_IDLE; + } + break; + + case DFU_REQUEST_GETSTATE: + { + dfu_req_getstate_reply(rhport, request); + } + break; + + default: + { + return false; // stall on all other requests + } + break; + } + } + break; + + default: + _dfu_state_ctx.state = DFU_ERROR; + TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); + return false; // Unexpected state, stall and change to error + } + + return true; +} + + +#endif diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h new file mode 100644 index 000000000..3bc1f4ae4 --- /dev/null +++ b/src/class/dfu/dfu_device.h @@ -0,0 +1,131 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 XMOS LIMITED + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_DFU_DEVICE_H_ +#define _TUSB_DFU_DEVICE_H_ + +#include "common/tusb_common.h" +#include "device/usbd.h" +#include "dfu.h" + +#ifdef __cplusplus + extern "C" { +#endif + + +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ +// Invoked when a reset is received to check if firmware is valid +bool tud_dfu_firmware_valid_check_cb(void); + +// Invoked when the device must reboot to dfu runtime mode +void tud_dfu_reboot_to_rt_cb(void); + +// Invoked during initialization of the dfu driver to set attributes +// Return byte set with bitmasks: +// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK +// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK +// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK +// DFU_FUNC_ATTR_WILL_DETACH_BITMASK +// Note: This should match the USB descriptor +uint8_t tud_dfu_init_attrs_cb(void); + +// Invoked during a DFU_GETSTATUS request to get for the string index +// to the status description string table. +TU_ATTR_WEAK uint8_t tud_dfu_get_status_desc_table_index_cb(void); + +// Invoked during a USB reset +// Lets the app perform custom behavior on a USB reset. +// If not defined, the default behavior remains the DFU specification of +// Checking the firmware valid and changing to the error state or rebooting to runtime +// Note: If used, the application must perform the reset logic for all states. +// Changing the state to APP_IDLE will result in tud_dfu_reboot_to_rt_cb being called +TU_ATTR_WEAK void tud_dfu_usb_reset_cb(uint8_t rhport, dfu_state_t *state); + +// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use +// before the subsequent DFU_GETSTATUS requests. +// The purpose of this value is to allow the device to tell the host +// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks +// to allow the device to have time to erase, write memory, etc. +// ms_timeout is a pointer to array of length 3. +// Refer to the USB DFU class specification for more details +TU_ATTR_WEAK void tud_dfu_get_poll_timeout_cb(uint8_t *ms_timeout); + +// Invoked when a DFU_DNLOAD request is received +// This should start a timer for ms_timeout ms +// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called +// NOTE: This callback should return immediately, and not implement the delay +// internally, as this will hold up the class stack from receiving any packets +// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states +void tud_dfu_start_poll_timeout_cb(uint8_t *ms_timeout); + +// Must be called when the poll_timeout has elapsed +void tud_dfu_poll_timeout_done(void); + +// Invoked when a DFU_DNLOAD request is received +// This callback takes the wBlockNum chunk of length length and provides it +// to the application at the data pointer. This data is only valid for this +// call, so the app must use it not or copy it. +void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); + +// Invoked during the last DFU_DNLOAD request, signifying that the host believes +// it is done transmitting data. +// Return true if the application agrees there is no more data +// Return false if the device disagrees, which will stall the pipe, and the Host +// should initiate a recovery procedure +bool tud_dfu_device_data_done_check_cb(void); + +// Invoked when the Host has terminated a download or upload transfer +TU_ATTR_WEAK void tud_dfu_abort_cb(void); + +// Invoked when a DFU_UPLOAD request is received +// This callback must populate data with up to length bytes +// Return the number of bytes to write +uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); + +// Invoked when a nonstandard request is received +// Use may be vendor specific. +// Return false to stall +TU_ATTR_WEAK bool tud_dfu_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + +// Invoked during a DFU_GETSTATUS request to get for the string index +// to the status description string table. +TU_ATTR_WEAK uint8_t tud_dfu_get_status_desc_table_index_cb(void); +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void dfu_moded_init(void); +void dfu_moded_reset(uint8_t rhport); +uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DFU_MODE_DEVICE_H_ */ diff --git a/src/class/dfu/dfu_mode_device.c b/src/class/dfu/dfu_mode_device.c deleted file mode 100644 index 5f8c714c0..000000000 --- a/src/class/dfu/dfu_mode_device.c +++ /dev/null @@ -1,594 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * 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. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) - -#include "dfu_mode_device.h" -#include "device/usbd_pvt.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED -{ - dfu_mode_device_status_t status; - dfu_mode_state_t state; - uint8_t attrs; - bool blk_transfer_in_proc; - - uint8_t itf_num; - uint16_t last_block_num; - uint16_t last_transfer_len; - CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; -} dfu_mode_state_ctx_t; - -// Only a single dfu state is allowed -CFG_TUSB_MEM_SECTION static dfu_mode_state_ctx_t _dfu_state_ctx; - - -static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); -static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); -static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); -static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); -static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const * request); - - -//--------------------------------------------------------------------+ -// USBD Driver API -//--------------------------------------------------------------------+ -void dfu_moded_init(void) -{ - _dfu_state_ctx.state = APP_DETACH; // After init, reset will occur. We want to be in APP_DETACH to move to DFU_IDLE - _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = 0; - _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; - - dfu_debug_print_context(); -} - -void dfu_moded_reset(uint8_t rhport) -{ - if (_dfu_state_ctx.state == APP_DETACH) - { - _dfu_state_ctx.state = DFU_IDLE; - } else { - if ( tud_dfu_mode_usb_reset_cb ) - { - tud_dfu_mode_usb_reset_cb(rhport, &_dfu_state_ctx.state); - } else { - switch (_dfu_state_ctx.state) - { - case DFU_IDLE: - case DFU_DNLOAD_SYNC: - case DFU_DNBUSY: - case DFU_DNLOAD_IDLE: - case DFU_MANIFEST_SYNC: - case DFU_MANIFEST: - case DFU_MANIFEST_WAIT_RESET: - case DFU_UPLOAD_IDLE: - { - _dfu_state_ctx.state = (tud_dfu_mode_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; - } - break; - - case DFU_ERROR: - default: - { - _dfu_state_ctx.state = APP_IDLE; - } - break; - } - } - } - - if(_dfu_state_ctx.state == APP_IDLE) - { - tud_dfu_mode_reboot_to_rt_cb(); - } - - _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; - dfu_debug_print_context(); -} - -uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void) rhport; - (void) max_len; - - // Ensure this is DFU Mode - TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && - (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); - - uint8_t const * p_desc = tu_desc_next( itf_desc ); - uint16_t drv_len = sizeof(tusb_desc_interface_t); - - if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) - { - tusb_desc_dfu_functional_t *dfu_desc = (tusb_desc_dfu_functional_t *)p_desc; - _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; - - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - - return drv_len; -} - -// Invoked when a control transfer occurred on an interface of this class -// Driver response accordingly to the request and the transfer stage (setup/data/ack) -// return false to stall control endpoint (e.g unsupported request) -bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) - { - dfu_mode_req_dnload_reply(rhport, request); - return true; - } - - // nothing to do with any other DATA or ACK stage - if ( stage != CONTROL_STAGE_SETUP ) return true; - - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - - // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request - if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_SET_INTERFACE == request->bRequest ) - { - tud_control_status(rhport, request); - return true; - } - - // Handle class request only from here - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - switch (request->bRequest) - { - case DFU_REQUEST_DETACH: - case DFU_REQUEST_DNLOAD: - case DFU_REQUEST_UPLOAD: - case DFU_REQUEST_GETSTATUS: - case DFU_REQUEST_CLRSTATUS: - case DFU_REQUEST_GETSTATE: - case DFU_REQUEST_ABORT: - { - return dfu_mode_state_machine(rhport, request); - } - break; - - default: - { - TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); - return ( tud_dfu_mode_req_nonstandard_cb ) ? tud_dfu_mode_req_nonstandard_cb(rhport, stage, request) : false; - } - break; - } - - return true; -} - -static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) -{ - TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); - uint16_t retval = tud_dfu_mode_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, wLength); - tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, retval); - return retval; -} - -static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - dfu_status_req_payload_t resp; - - resp.bStatus = _dfu_state_ctx.status; - if ( tud_dfu_mode_get_poll_timeout_cb ) - { - tud_dfu_mode_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); - } else { - memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); - } - resp.bState = _dfu_state_ctx.state; - resp.iString = ( tud_dfu_mode_get_status_desc_table_index_cb ) ? tud_dfu_mode_get_status_desc_table_index_cb() : 0; - - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); -} - -static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); -} - -static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) -{ - _dfu_state_ctx.last_block_num = request->wValue; - _dfu_state_ctx.last_transfer_len = request->wLength; - // TODO: add "zero" copy mode so the buffer we read into can be provided by the user - // if they wish, there still will be the internal control buffer copy to this buffer - // but this mode would provide zero copy from the class driver to the application - - // setup for data phase - tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); -} - -static void dfu_mode_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - uint8_t bwPollTimeout[3] = {0,0,0}; - - if ( tud_dfu_mode_get_poll_timeout_cb ) - { - tud_dfu_mode_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); - } - - tud_dfu_mode_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); - - // TODO: I want the real xferred len, not what is expected. May need to change usbd.c to do this. - tud_dfu_mode_req_dnload_data_cb(_dfu_state_ctx.last_block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, _dfu_state_ctx.last_transfer_len); - _dfu_state_ctx.blk_transfer_in_proc = false; - - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; -} - -void tud_dfu_mode_poll_timeout_done() -{ - if (_dfu_state_ctx.state == DFU_DNBUSY) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - } else if (_dfu_state_ctx.state == DFU_MANIFEST) - { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) - ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; - } -} - -static bool dfu_mode_state_machine(uint8_t rhport, tusb_control_request_t const * request) -{ - TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); - TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_mode_state_table, _dfu_state_ctx.state)); - - switch (_dfu_state_ctx.state) - { - case DFU_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DNLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (request->wLength > 0) ) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - _dfu_state_ctx.blk_transfer_in_proc = true; - dfu_req_dnload_setup(rhport, request); - } else { - _dfu_state_ctx.state = DFU_ERROR; - } - } - break; - - case DFU_REQUEST_UPLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) - { - _dfu_state_ctx.state = DFU_UPLOAD_IDLE; - dfu_req_upload(rhport, request, request->wValue, request->wLength); - } else { - _dfu_state_ctx.state = DFU_ERROR; - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - ; // do nothing, but don't stall so continue on - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_DNLOAD_SYNC: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - if ( _dfu_state_ctx.blk_transfer_in_proc ) - { - _dfu_state_ctx.state = DFU_DNBUSY; - dfu_req_getstatus_reply(rhport, request); - } else { - _dfu_state_ctx.state = DFU_DNLOAD_IDLE; - dfu_req_getstatus_reply(rhport, request); - } - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_DNBUSY: - { - switch (request->bRequest) - { - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_DNLOAD_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DNLOAD: - { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (request->wLength > 0) ) - { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - _dfu_state_ctx.blk_transfer_in_proc = true; - dfu_req_dnload_setup(rhport, request); - } else { - if ( tud_dfu_mode_device_data_done_check_cb() ) - { - _dfu_state_ctx.state = DFU_MANIFEST_SYNC; - tud_control_status(rhport, request); - } else { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall - } - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - if ( tud_dfu_mode_abort_cb ) - { - tud_dfu_mode_abort_cb(); - } - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_MANIFEST_SYNC: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) - { - _dfu_state_ctx.state = DFU_MANIFEST; - dfu_req_getstatus_reply(rhport, request); - } else { - if ( tud_dfu_mode_firmware_valid_check_cb() ) - { - _dfu_state_ctx.state = DFU_IDLE; - } - dfu_req_getstatus_reply(rhport, request); - } - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - _dfu_state_ctx.state = DFU_ERROR; - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_MANIFEST: - { - switch (request->bRequest) - { - default: - { - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_MANIFEST_WAIT_RESET: - { - // technically we should never even get here, but we will handle it just in case - TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); - switch (request->bRequest) - { - default: - { - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_UPLOAD_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_UPLOAD: - { - if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) - { - _dfu_state_ctx.state = DFU_IDLE; - } - } - break; - - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - case DFU_REQUEST_ABORT: - { - if (tud_dfu_mode_abort_cb) - { - tud_dfu_mode_abort_cb(); - } - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - default: - { - return false; // stall on all other requests - } - break; - } - } - break; - - case DFU_ERROR: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - dfu_req_getstatus_reply(rhport, request); - } - break; - - case DFU_REQUEST_CLRSTATUS: - { - _dfu_state_ctx.state = DFU_IDLE; - } - break; - - case DFU_REQUEST_GETSTATE: - { - dfu_req_getstate_reply(rhport, request); - } - break; - - default: - { - return false; // stall on all other requests - } - break; - } - } - break; - - default: - _dfu_state_ctx.state = DFU_ERROR; - TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); - return false; // Unexpected state, stall and change to error - } - - return true; -} - - -#endif diff --git a/src/class/dfu/dfu_mode_device.h b/src/class/dfu/dfu_mode_device.h deleted file mode 100644 index c25910b23..000000000 --- a/src/class/dfu/dfu_mode_device.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 XMOS LIMITED - * - * 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. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef _TUSB_DFU_MODE_DEVICE_H_ -#define _TUSB_DFU_MODE_DEVICE_H_ - -#include "common/tusb_common.h" -#include "device/usbd.h" -#include "dfu.h" - -#ifdef __cplusplus - extern "C" { -#endif - - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ -// Invoked when a reset is received to check if firmware is valid -bool tud_dfu_mode_firmware_valid_check_cb(void); - -// Invoked when the device must reboot to dfu runtime mode -void tud_dfu_mode_reboot_to_rt_cb(void); - -// Invoked during initialization of the dfu driver to set attributes -// Return byte set with bitmasks: -// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK -// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK -// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK -// DFU_FUNC_ATTR_WILL_DETACH_BITMASK -// Note: This should match the USB descriptor -uint8_t tud_dfu_mode_init_attrs_cb(void); - -// Invoked during a DFU_GETSTATUS request to get for the string index -// to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(void); - -// Invoked during a USB reset -// Lets the app perform custom behavior on a USB reset. -// If not defined, the default behavior remains the DFU specification of -// Checking the firmware valid and changing to the error state or rebooting to runtime -// Note: If used, the application must perform the reset logic for all states. -// Changing the state to APP_IDLE will result in tud_dfu_mode_reboot_to_rt_cb being called -TU_ATTR_WEAK void tud_dfu_mode_usb_reset_cb(uint8_t rhport, dfu_mode_state_t *state); - -// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use -// before the subsequent DFU_GETSTATUS requests. -// The purpose of this value is to allow the device to tell the host -// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks -// to allow the device to have time to erase, write memory, etc. -// ms_timeout is a pointer to array of length 3. -// Refer to the USB DFU class specification for more details -TU_ATTR_WEAK void tud_dfu_mode_get_poll_timeout_cb(uint8_t *ms_timeout); - -// Invoked when a DFU_DNLOAD request is received -// This should start a timer for ms_timeout ms -// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called -// NOTE: This callback should return immediately, and not implement the delay -// internally, as this will hold up the class stack from receiving any packets -// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states -void tud_dfu_mode_start_poll_timeout_cb(uint8_t *ms_timeout); - -// Must be called when the poll_timeout has elapsed -void tud_dfu_mode_poll_timeout_done(void); - -// Invoked when a DFU_DNLOAD request is received -// This callback takes the wBlockNum chunk of length length and provides it -// to the application at the data pointer. This data is only valid for this -// call, so the app must use it not or copy it. -void tud_dfu_mode_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); - -// Invoked during the last DFU_DNLOAD request, signifying that the host believes -// it is done transmitting data. -// Return true if the application agrees there is no more data -// Return false if the device disagrees, which will stall the pipe, and the Host -// should initiate a recovery procedure -bool tud_dfu_mode_device_data_done_check_cb(void); - -// Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_mode_abort_cb(void); - -// Invoked when a DFU_UPLOAD request is received -// This callback must populate data with up to length bytes -// Return the number of bytes to write -uint16_t tud_dfu_mode_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); - -// Invoked when a nonstandard request is received -// Use may be vendor specific. -// Return false to stall -TU_ATTR_WEAK bool tud_dfu_mode_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - -// Invoked during a DFU_GETSTATUS request to get for the string index -// to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_mode_get_status_desc_table_index_cb(void); -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -void dfu_moded_init(void); -void dfu_moded_reset(uint8_t rhport); -uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DFU_MODE_DEVICE_H_ */ diff --git a/src/tusb.h b/src/tusb.h index c9558515c..56504550c 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -97,7 +97,7 @@ #endif #if CFG_TUD_DFU_MODE - #include "class/dfu/dfu_mode_device.h" + #include "class/dfu/dfu_device.h" #endif #if CFG_TUD_NET -- cgit v1.3.1 From 88dea7a0a8f7cb1bc21eaa45a3abb9a912b030d6 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 15:02:50 -0400 Subject: Move debug from .h to .c --- src/class/dfu/dfu.h | 80 ------------------------------------------- src/class/dfu/dfu_device.c | 77 +++++++++++++++++++++++++++++++++++++++++ src/class/dfu/dfu_rt_device.c | 9 +++-- 3 files changed, 84 insertions(+), 82 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h index af08a29f7..18de3bf99 100644 --- a/src/class/dfu/dfu.h +++ b/src/class/dfu/dfu.h @@ -111,86 +111,6 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(dfu_status_req_payload_t) == 6, "size is not correct"); - -//--------------------------------------------------------------------+ -// Debug -//--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 - -static tu_lookup_entry_t const _dfu_request_lookup[] = -{ - { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, - { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, - { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, - { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, - { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, - { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, - { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, -}; - -static tu_lookup_table_t const _dfu_request_table = -{ - .count = TU_ARRAY_SIZE(_dfu_request_lookup), - .items = _dfu_request_lookup -}; - -static tu_lookup_entry_t const _dfu_state_lookup[] = -{ - { .key = APP_IDLE , .data = "APP_IDLE" }, - { .key = APP_DETACH , .data = "APP_DETACH" }, - { .key = DFU_IDLE , .data = "DFU_IDLE" }, - { .key = DFU_DNLOAD_SYNC , .data = "DFU_DNLOAD_SYNC" }, - { .key = DFU_DNBUSY , .data = "DFU_DNBUSY" }, - { .key = DFU_DNLOAD_IDLE , .data = "DFU_DNLOAD_IDLE" }, - { .key = DFU_MANIFEST_SYNC , .data = "DFU_MANIFEST_SYNC" }, - { .key = DFU_MANIFEST , .data = "DFU_MANIFEST" }, - { .key = DFU_MANIFEST_WAIT_RESET , .data = "DFU_MANIFEST_WAIT_RESET" }, - { .key = DFU_UPLOAD_IDLE , .data = "DFU_UPLOAD_IDLE" }, - { .key = DFU_ERROR , .data = "DFU_ERROR" }, -}; - -static tu_lookup_table_t const _dfu_state_table = -{ - .count = TU_ARRAY_SIZE(_dfu_state_lookup), - .items = _dfu_state_lookup -}; - -static tu_lookup_entry_t const _dfu_status_lookup[] = -{ - { .key = DFU_STATUS_OK , .data = "OK" }, - { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, - { .key = DFU_STATUS_ERRFILE , .data = "errFILE" }, - { .key = DFU_STATUS_ERRWRITE , .data = "errWRITE" }, - { .key = DFU_STATUS_ERRERASE , .data = "errERASE" }, - { .key = DFU_STATUS_ERRCHECK_ERASED , .data = "errCHECK_ERASED" }, - { .key = DFU_STATUS_ERRPROG , .data = "errPROG" }, - { .key = DFU_STATUS_ERRVERIFY , .data = "errVERIFY" }, - { .key = DFU_STATUS_ERRADDRESS , .data = "errADDRESS" }, - { .key = DFU_STATUS_ERRNOTDONE , .data = "errNOTDONE" }, - { .key = DFU_STATUS_ERRFIRMWARE , .data = "errFIRMWARE" }, - { .key = DFU_STATUS_ERRVENDOR , .data = "errVENDOR" }, - { .key = DFU_STATUS_ERRUSBR , .data = "errUSBR" }, - { .key = DFU_STATUS_ERRPOR , .data = "errPOR" }, - { .key = DFU_STATUS_ERRUNKNOWN , .data = "errUNKNOWN" }, - { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, -}; - -static tu_lookup_table_t const _dfu_status_table = -{ - .count = TU_ARRAY_SIZE(_dfu_status_lookup), - .items = _dfu_status_lookup -}; - -#endif - -#define dfu_debug_print_context() \ -{ \ - TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ - tu_lookup_find(&_dfu_state_table, _dfu_state_ctx.state), \ - tu_lookup_find(&_dfu_status_table, _dfu_state_ctx.status) ); \ -} - - #ifdef __cplusplus } #endif diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 98213d320..f3763adc7 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -61,6 +61,83 @@ static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * re static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 2 + +static tu_lookup_entry_t const _dfu_request_lookup[] = +{ + { .key = DFU_REQUEST_DETACH , .data = "DETACH" }, + { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" }, + { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" }, + { .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" }, + { .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" }, + { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" }, + { .key = DFU_REQUEST_ABORT , .data = "ABORT" }, +}; + +static tu_lookup_table_t const _dfu_request_table = +{ + .count = TU_ARRAY_SIZE(_dfu_request_lookup), + .items = _dfu_request_lookup +}; + +static tu_lookup_entry_t const _dfu_state_lookup[] = +{ + { .key = APP_IDLE , .data = "APP_IDLE" }, + { .key = APP_DETACH , .data = "APP_DETACH" }, + { .key = DFU_IDLE , .data = "DFU_IDLE" }, + { .key = DFU_DNLOAD_SYNC , .data = "DFU_DNLOAD_SYNC" }, + { .key = DFU_DNBUSY , .data = "DFU_DNBUSY" }, + { .key = DFU_DNLOAD_IDLE , .data = "DFU_DNLOAD_IDLE" }, + { .key = DFU_MANIFEST_SYNC , .data = "DFU_MANIFEST_SYNC" }, + { .key = DFU_MANIFEST , .data = "DFU_MANIFEST" }, + { .key = DFU_MANIFEST_WAIT_RESET , .data = "DFU_MANIFEST_WAIT_RESET" }, + { .key = DFU_UPLOAD_IDLE , .data = "DFU_UPLOAD_IDLE" }, + { .key = DFU_ERROR , .data = "DFU_ERROR" }, +}; + +static tu_lookup_table_t const _dfu_state_table = +{ + .count = TU_ARRAY_SIZE(_dfu_state_lookup), + .items = _dfu_state_lookup +}; + +static tu_lookup_entry_t const _dfu_status_lookup[] = +{ + { .key = DFU_STATUS_OK , .data = "OK" }, + { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" }, + { .key = DFU_STATUS_ERRFILE , .data = "errFILE" }, + { .key = DFU_STATUS_ERRWRITE , .data = "errWRITE" }, + { .key = DFU_STATUS_ERRERASE , .data = "errERASE" }, + { .key = DFU_STATUS_ERRCHECK_ERASED , .data = "errCHECK_ERASED" }, + { .key = DFU_STATUS_ERRPROG , .data = "errPROG" }, + { .key = DFU_STATUS_ERRVERIFY , .data = "errVERIFY" }, + { .key = DFU_STATUS_ERRADDRESS , .data = "errADDRESS" }, + { .key = DFU_STATUS_ERRNOTDONE , .data = "errNOTDONE" }, + { .key = DFU_STATUS_ERRFIRMWARE , .data = "errFIRMWARE" }, + { .key = DFU_STATUS_ERRVENDOR , .data = "errVENDOR" }, + { .key = DFU_STATUS_ERRUSBR , .data = "errUSBR" }, + { .key = DFU_STATUS_ERRPOR , .data = "errPOR" }, + { .key = DFU_STATUS_ERRUNKNOWN , .data = "errUNKNOWN" }, + { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" }, +}; + +static tu_lookup_table_t const _dfu_status_table = +{ + .count = TU_ARRAY_SIZE(_dfu_status_lookup), + .items = _dfu_status_lookup +}; + +#endif + +#define dfu_debug_print_context() \ +{ \ + TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \ + tu_lookup_find(&_dfu_state_table, _dfu_state_ctx.state), \ + tu_lookup_find(&_dfu_status_table, _dfu_state_ctx.status) ); \ +} //--------------------------------------------------------------------+ // USBD Driver API diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 9da2e1e4f..faeae9b68 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -93,11 +93,11 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request // Handle class request only from here TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - TU_LOG2(" DFU RT Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); switch (request->bRequest) { case DFU_REQUEST_DETACH: { + TU_LOG2(" DFU RT Request: DETACH\r\n"); tud_control_status(rhport, request); tud_dfu_runtime_reboot_to_dfu_cb(); } @@ -105,6 +105,7 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request case DFU_REQUEST_GETSTATUS: { + TU_LOG2(" DFU RT Request: GETSTATUS\r\n"); dfu_status_req_payload_t resp; // Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0 memset(&resp, 0x00, sizeof(dfu_status_req_payload_t)); @@ -112,7 +113,11 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request } break; - default: return false; // stall unsupported request + default: + { + TU_LOG2(" DFU RT Unexpected Request: %d\r\n", request->bRequest); + return false; // stall unsupported request + } } return true; -- cgit v1.3.1 From 0936a76dc905a104f03cd1135fc22a8652ee8c7f Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 15:59:49 -0400 Subject: Remove nonstd behaviour --- src/class/dfu/dfu_device.c | 2 +- src/class/dfu/dfu_device.h | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index f3763adc7..85e884d0d 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -269,7 +269,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque default: { TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); - return ( tud_dfu_req_nonstandard_cb ) ? tud_dfu_req_nonstandard_cb(rhport, stage, request) : false; + return false; // stall unsupported request } break; } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 3bc1f4ae4..28a241b3a 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -107,11 +107,6 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(void); // Return the number of bytes to write uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); -// Invoked when a nonstandard request is received -// Use may be vendor specific. -// Return false to stall -TU_ATTR_WEAK bool tud_dfu_req_nonstandard_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - // Invoked during a DFU_GETSTATUS request to get for the string index // to the status description string table. TU_ATTR_WEAK uint8_t tud_dfu_get_status_desc_table_index_cb(void); -- cgit v1.3.1 From 18e9d253e986670f77a0f15f687eec258011605f Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 16:04:09 -0400 Subject: Remove usb reset callback --- src/class/dfu/dfu_device.c | 39 +++++++++++++++++---------------------- src/class/dfu/dfu_device.h | 8 -------- 2 files changed, 17 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 85e884d0d..085c2b455 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -160,32 +160,27 @@ void dfu_moded_reset(uint8_t rhport) { _dfu_state_ctx.state = DFU_IDLE; } else { - if ( tud_dfu_usb_reset_cb ) + switch (_dfu_state_ctx.state) { - tud_dfu_usb_reset_cb(rhport, &_dfu_state_ctx.state); - } else { - switch (_dfu_state_ctx.state) + case DFU_IDLE: + case DFU_DNLOAD_SYNC: + case DFU_DNBUSY: + case DFU_DNLOAD_IDLE: + case DFU_MANIFEST_SYNC: + case DFU_MANIFEST: + case DFU_MANIFEST_WAIT_RESET: + case DFU_UPLOAD_IDLE: { - case DFU_IDLE: - case DFU_DNLOAD_SYNC: - case DFU_DNBUSY: - case DFU_DNLOAD_IDLE: - case DFU_MANIFEST_SYNC: - case DFU_MANIFEST: - case DFU_MANIFEST_WAIT_RESET: - case DFU_UPLOAD_IDLE: - { - _dfu_state_ctx.state = (tud_dfu_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; - } - break; + _dfu_state_ctx.state = (tud_dfu_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; + } + break; - case DFU_ERROR: - default: - { - _dfu_state_ctx.state = APP_IDLE; - } - break; + case DFU_ERROR: + default: + { + _dfu_state_ctx.state = APP_IDLE; } + break; } } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 28a241b3a..e92935fd7 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -58,14 +58,6 @@ uint8_t tud_dfu_init_attrs_cb(void); // to the status description string table. TU_ATTR_WEAK uint8_t tud_dfu_get_status_desc_table_index_cb(void); -// Invoked during a USB reset -// Lets the app perform custom behavior on a USB reset. -// If not defined, the default behavior remains the DFU specification of -// Checking the firmware valid and changing to the error state or rebooting to runtime -// Note: If used, the application must perform the reset logic for all states. -// Changing the state to APP_IDLE will result in tud_dfu_reboot_to_rt_cb being called -TU_ATTR_WEAK void tud_dfu_usb_reset_cb(uint8_t rhport, dfu_state_t *state); - // Invoked during a DFU_GETSTATUS request to set the timeout in ms to use // before the subsequent DFU_GETSTATUS requests. // The purpose of this value is to allow the device to tell the host -- cgit v1.3.1 From 289af581bb796f730324ac663b3f20d57d03e487 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 16:06:06 -0400 Subject: Remove uunused code --- src/class/dfu/dfu_device.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index e92935fd7..322cc6496 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -45,15 +45,6 @@ bool tud_dfu_firmware_valid_check_cb(void); // Invoked when the device must reboot to dfu runtime mode void tud_dfu_reboot_to_rt_cb(void); -// Invoked during initialization of the dfu driver to set attributes -// Return byte set with bitmasks: -// DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK -// DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK -// DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK -// DFU_FUNC_ATTR_WILL_DETACH_BITMASK -// Note: This should match the USB descriptor -uint8_t tud_dfu_init_attrs_cb(void); - // Invoked during a DFU_GETSTATUS request to get for the string index // to the status description string table. TU_ATTR_WEAK uint8_t tud_dfu_get_status_desc_table_index_cb(void); -- cgit v1.3.1 From e54d9d10af40f4d83410f1e9cd94c47138c7fe7f Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 16:39:43 -0400 Subject: Add const --- src/class/dfu/dfu_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 085c2b455..ed7d381f0 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -158,7 +158,7 @@ void dfu_moded_reset(uint8_t rhport) { if (_dfu_state_ctx.state == APP_DETACH) { - _dfu_state_ctx.state = DFU_IDLE; + _dfu_state_ctx.state = DFU_IDLE; } else { switch (_dfu_state_ctx.state) { @@ -210,7 +210,7 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) { - tusb_desc_dfu_functional_t *dfu_desc = (tusb_desc_dfu_functional_t *)p_desc; + tusb_desc_dfu_functional_t const *dfu_desc = (tusb_desc_dfu_functional_t const *)p_desc; _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; drv_len += tu_desc_len(p_desc); -- cgit v1.3.1 From 45e401e69df87353f528d0e3ce313d5af5a4f90c Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 16:42:54 -0400 Subject: Remove unused alt_setting --- src/device/usbd.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index f9700811f..3d71b5e35 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -546,10 +546,10 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb #define TUD_DFU_MODE_DESC_LEN (9 + 9) // DFU runtime descriptor -// Interface number, string index, alternate setting, attributes, detach timeout, transfer size -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _stridx, _alt_setting, _attr, _timeout, _xfer_size) \ +// Interface number, string index, attributes, detach timeout, transfer size +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \ /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt_setting, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -- cgit v1.3.1 From cc440ade81a72df3a605e0abc427a284b8bbc424 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 16:47:05 -0400 Subject: Remove custom status description table --- src/class/dfu/dfu_device.c | 2 +- src/class/dfu/dfu_device.h | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index ed7d381f0..f0a90073b 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -292,7 +292,7 @@ static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); } resp.bState = _dfu_state_ctx.state; - resp.iString = ( tud_dfu_get_status_desc_table_index_cb ) ? tud_dfu_get_status_desc_table_index_cb() : 0; + resp.iString = 0; tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 322cc6496..d19115555 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -90,9 +90,6 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(void); // Return the number of bytes to write uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); -// Invoked during a DFU_GETSTATUS request to get for the string index -// to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_get_status_desc_table_index_cb(void); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -- cgit v1.3.1 From 8c80ddeb542007efd547eced028d9bb3e933d434 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 17:00:57 -0400 Subject: Fix statte check on DATA stage --- src/class/dfu/dfu_device.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index f0a90073b..59369a78f 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -58,7 +58,7 @@ CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx; static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); -static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); +static void dfu_req_dnload_reply(void); static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); //--------------------------------------------------------------------+ @@ -225,9 +225,9 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, // return false to stall control endpoint (e.g unsupported request) bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - if ( (stage == CONTROL_STAGE_DATA) && (request->bRequest == DFU_DNLOAD_SYNC) ) + if ( (stage == CONTROL_STAGE_DATA) && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC) ) { - dfu_req_dnload_reply(rhport, request); + dfu_req_dnload_reply(); return true; } @@ -314,7 +314,7 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); } -static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) +static void dfu_req_dnload_reply(void) { uint8_t bwPollTimeout[3] = {0,0,0}; @@ -333,7 +333,7 @@ static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * _dfu_state_ctx.last_transfer_len = 0; } -void tud_dfu_poll_timeout_done() +void tud_dfu_poll_timeout_done(void) { if (_dfu_state_ctx.state == DFU_DNBUSY) { -- cgit v1.3.1 From b8e5885c2b97725e30ff57e6adc8cb7696711f28 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 22 Apr 2021 17:45:33 -0400 Subject: Removes polltimeout behaviour and restructures Moves dfu_req_dnload_reply to ACK stage of a DNREQUEST. Removes unneeded variables due to other simplifications. --- src/class/dfu/dfu_device.c | 78 ++++++++++++++++++---------------------------- src/class/dfu/dfu_device.h | 28 +++-------------- 2 files changed, 34 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 59369a78f..25588aabc 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -44,10 +44,6 @@ typedef struct TU_ATTR_PACKED dfu_state_t state; uint8_t attrs; bool blk_transfer_in_proc; - - uint8_t itf_num; - uint16_t last_block_num; - uint16_t last_transfer_len; CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; } dfu_state_ctx_t; @@ -58,7 +54,7 @@ CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx; static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); -static void dfu_req_dnload_reply(void); +static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); //--------------------------------------------------------------------+ @@ -148,8 +144,6 @@ void dfu_moded_init(void) _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; dfu_debug_print_context(); } @@ -191,8 +185,6 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; dfu_debug_print_context(); } @@ -225,23 +217,20 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, // return false to stall control endpoint (e.g unsupported request) bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - if ( (stage == CONTROL_STAGE_DATA) && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC) ) - { - dfu_req_dnload_reply(); - return true; - } - - // nothing to do with any other DATA or ACK stage - if ( stage != CONTROL_STAGE_SETUP ) return true; + // nothing to do with DATA stage + if ( stage == CONTROL_STAGE_DATA ) return true; TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request - if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_SET_INTERFACE == request->bRequest ) + if(stage == CONTROL_STAGE_SETUP) { - tud_control_status(rhport, request); - return true; + // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request + if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && + TUSB_REQ_SET_INTERFACE == request->bRequest ) + { + tud_control_status(rhport, request); + return true; + } } // Handle class request only from here @@ -249,15 +238,27 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque switch (request->bRequest) { - case DFU_REQUEST_DETACH: case DFU_REQUEST_DNLOAD: + { + if ( (stage == CONTROL_STAGE_ACK) + && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC)) + { + dfu_req_dnload_reply(rhport, request); + return true; + } + } // fallthrough + case DFU_REQUEST_DETACH: case DFU_REQUEST_UPLOAD: case DFU_REQUEST_GETSTATUS: case DFU_REQUEST_CLRSTATUS: case DFU_REQUEST_GETSTATE: case DFU_REQUEST_ABORT: { - return dfu_state_machine(rhport, request); + if(stage == CONTROL_STAGE_SETUP) + { + return dfu_state_machine(rhport, request); + } } break; @@ -285,12 +286,7 @@ static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const dfu_status_req_payload_t resp; resp.bStatus = _dfu_state_ctx.status; - if ( tud_dfu_get_poll_timeout_cb ) - { - tud_dfu_get_poll_timeout_cb((uint8_t *)&resp.bwPollTimeout); - } else { - memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); - } + memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3); resp.bState = _dfu_state_ctx.state; resp.iString = 0; @@ -304,8 +300,6 @@ static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) { - _dfu_state_ctx.last_block_num = request->wValue; - _dfu_state_ctx.last_transfer_len = request->wLength; // TODO: add "zero" copy mode so the buffer we read into can be provided by the user // if they wish, there still will be the internal control buffer copy to this buffer // but this mode would provide zero copy from the class driver to the application @@ -314,26 +308,14 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); } -static void dfu_req_dnload_reply(void) +static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { - uint8_t bwPollTimeout[3] = {0,0,0}; - - if ( tud_dfu_get_poll_timeout_cb ) - { - tud_dfu_get_poll_timeout_cb((uint8_t *)&bwPollTimeout); - } - - tud_dfu_start_poll_timeout_cb((uint8_t *)&bwPollTimeout); - - // TODO: I want the real xferred len, not what is expected. May need to change usbd.c to do this. - tud_dfu_req_dnload_data_cb(_dfu_state_ctx.last_block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, _dfu_state_ctx.last_transfer_len); + (void) rhport; + tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)&_dfu_state_ctx.transfer_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; - - _dfu_state_ctx.last_block_num = 0; - _dfu_state_ctx.last_transfer_len = 0; } -void tud_dfu_poll_timeout_done(void) +void tud_dfu_dnload_complete(void) { if (_dfu_state_ctx.state == DFU_DNBUSY) { diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index d19115555..0c567ff45 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -45,36 +45,16 @@ bool tud_dfu_firmware_valid_check_cb(void); // Invoked when the device must reboot to dfu runtime mode void tud_dfu_reboot_to_rt_cb(void); -// Invoked during a DFU_GETSTATUS request to get for the string index -// to the status description string table. -TU_ATTR_WEAK uint8_t tud_dfu_get_status_desc_table_index_cb(void); - -// Invoked during a DFU_GETSTATUS request to set the timeout in ms to use -// before the subsequent DFU_GETSTATUS requests. -// The purpose of this value is to allow the device to tell the host -// how long to wait between the DFU_DNLOAD and DFU_GETSTATUS checks -// to allow the device to have time to erase, write memory, etc. -// ms_timeout is a pointer to array of length 3. -// Refer to the USB DFU class specification for more details -TU_ATTR_WEAK void tud_dfu_get_poll_timeout_cb(uint8_t *ms_timeout); - -// Invoked when a DFU_DNLOAD request is received -// This should start a timer for ms_timeout ms -// When the timer has elapsed, tud_dfu_runtime_poll_timeout_done must be called -// NOTE: This callback should return immediately, and not implement the delay -// internally, as this will hold up the class stack from receiving any packets -// during the DFU_DNLOAD_SYNC and DFU_DNBUSY states -void tud_dfu_start_poll_timeout_cb(uint8_t *ms_timeout); - -// Must be called when the poll_timeout has elapsed -void tud_dfu_poll_timeout_done(void); - // Invoked when a DFU_DNLOAD request is received // This callback takes the wBlockNum chunk of length length and provides it // to the application at the data pointer. This data is only valid for this // call, so the app must use it not or copy it. void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); +// Must be called when the application is done using the last block of data +// provided by tud_dfu_req_dnload_data_cb +void tud_dfu_dnload_complete(void); + // Invoked during the last DFU_DNLOAD request, signifying that the host believes // it is done transmitting data. // Return true if the application agrees there is no more data -- cgit v1.3.1 From 03f974c9b92bf9e0fc6e74ab4d15ad77a4a8b339 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 23 Apr 2021 10:27:48 +0200 Subject: Implement functions to allow for DMA usage in audio driver. - Add tud_audio_n_get_ep_out_ff(), tud_audio_n_get_ep_in_ff(), tud_audio_n_get_rx_support_ff(), and tud_audio_n_get_tx_support_ff() - Change get_linear_read/write_info() to return linear and wrapped part at once - Adjusted affected code in audio_device.c and tested with audio_4_channel. --- src/class/audio/audio_device.c | 77 ++++++++++++++++----------- src/class/audio/audio_device.h | 29 ++++++++++ src/common/tusb_fifo.c | 35 +++++++----- src/common/tusb_fifo.h | 6 ++- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 4 +- 5 files changed, 103 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 0a60d9ee5..f96878b5b 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -447,27 +447,39 @@ bool tud_audio_n_clear_ep_out_ff(uint8_t func_id) return tu_fifo_clear(&_audiod_fct[func_id].ep_out_ff); } +tu_fifo_t* tud_audio_n_get_ep_out_ff(uint8_t func_id) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_out_ff; + return NULL; +} + #endif #if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT // Delete all content in the support RX FIFOs bool tud_audio_n_clear_rx_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); return tu_fifo_clear(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); } uint16_t tud_audio_n_available_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); return tu_fifo_count(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); } uint16_t tud_audio_n_read_support_ff(uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_rx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); return tu_fifo_read_n(&_audiod_fct[func_id].rx_supp_ff[ff_idx], buffer, bufsize); } + +tu_fifo_t* tud_audio_n_get_rx_support_ff(uint8_t func_id, uint8_t ff_idx) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff) return &_audiod_fct[func_id].rx_supp_ff[ff_idx]; + return NULL; +} #endif // This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO (or support FIFOs + decoding of received stream into audio channels). @@ -635,32 +647,26 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u uint8_t cnt_ff; // Decode - void * dst; + void * dst, * dst_wrap; uint8_t * src; uint8_t * dst_end; - uint16_t len; + uint16_t len, len_wrap; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nBytesPerFFToRead); - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); + len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, nBytesPerFFToRead, &dst, &len_wrap, &dst_wrap); dst_end = dst + len; - src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); // Handle wrapped part of FIFO - if (len < nBytesPerFFToRead) + if (len_wrap != 0) { - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, &dst, nBytesPerFFToRead - len); - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len); - - dst_end = dst + len; - - audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); + dst_end = dst_wrap + len_wrap; + audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst_wrap, dst_end, src, n_ff_used); } + tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len + len_wrap); } // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it @@ -699,9 +705,16 @@ bool tud_audio_n_clear_ep_in_ff(uint8_t func_id) // Del return tu_fifo_clear(&_audiod_fct[func_id].ep_in_ff); } +tu_fifo_t* tud_audio_n_get_ep_in_ff(uint8_t func_id) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL) return &_audiod_fct[func_id].ep_in_ff; + return NULL; +} + #endif #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN + uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id) // Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit { TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); @@ -719,15 +732,22 @@ uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id) // For bool tud_audio_n_clear_tx_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_tx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); return tu_fifo_clear(&_audiod_fct[func_id].tx_supp_ff[ff_idx]); } uint16_t tud_audio_n_write_support_ff(uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL, ff_idx < _audiod_fct[func_id].n_tx_supp_ff); + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); return tu_fifo_write_n(&_audiod_fct[func_id].tx_supp_ff[ff_idx], data, len); } + +tu_fifo_t* tud_audio_n_get_tx_support_ff(uint8_t func_id, uint8_t ff_idx) +{ + if(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff) return &_audiod_fct[func_id].tx_supp_ff[ff_idx]; + return NULL; +} + #endif @@ -751,6 +771,7 @@ uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint1 return true; } + #endif @@ -952,32 +973,28 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy; // Encode - void * src; + void * src, * src_wrap; uint8_t * dst; uint8_t * src_end; - uint16_t len; + uint16_t len, len_wrap; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nBytesPerFFToSend); - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); + len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, nBytesPerFFToSend, &src, &len_wrap, &src_wrap); src_end = src + len; - dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); // Handle wrapped part of FIFO - if (len < nBytesPerFFToSend) + if (len_wrap != 0) { - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, &src, nBytesPerFFToSend - len); - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len); - - src_end = src + len; - - audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); + src_end = src_wrap + len_wrap; + audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src_wrap, src_end, dst, n_ff_used); } + + tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len + len_wrap); } return nBytesPerFFToSend * n_ff_used; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index c070e48c2..66cc29739 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -33,6 +33,7 @@ #include "device/usbd.h" #include "audio.h" +#include "tusb_fifo.h" //--------------------------------------------------------------------+ // Class Driver Configuration @@ -364,23 +365,27 @@ bool tud_audio_n_mounted (uint8_t func_id); uint16_t tud_audio_n_available (uint8_t func_id); uint16_t tud_audio_n_read (uint8_t func_id, void* buffer, uint16_t bufsize); bool tud_audio_n_clear_ep_out_ff (uint8_t func_id); // Delete all content in the EP OUT FIFO +tu_fifo_t* tud_audio_n_get_ep_out_ff (uint8_t func_id); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING bool tud_audio_n_clear_rx_support_ff (uint8_t func_id, uint8_t ff_idx); // Delete all content in the support RX FIFOs uint16_t tud_audio_n_available_support_ff (uint8_t func_id, uint8_t ff_idx); uint16_t tud_audio_n_read_support_ff (uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize); +tu_fifo_t* tud_audio_n_get_rx_support_ff (uint8_t func_id, uint8_t ff_idx); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING uint16_t tud_audio_n_write (uint8_t func_id, const void * data, uint16_t len); bool tud_audio_n_clear_ep_in_ff (uint8_t func_id); // Delete all content in the EP IN FIFO +tu_fifo_t* tud_audio_n_get_ep_in_ff (uint8_t func_id); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING uint16_t tud_audio_n_flush_tx_support_ff (uint8_t func_id); // Force all content in the support TX FIFOs to be written into EP SW FIFO bool tud_audio_n_clear_tx_support_ff (uint8_t func_id, uint8_t ff_idx); uint16_t tud_audio_n_write_support_ff (uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len); +tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_idx); #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN @@ -399,12 +404,14 @@ static inline bool tud_audio_mounted (void); static inline uint16_t tud_audio_available (void); static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); +static inline tu_fifo_t* tud_audio_get_ep_out_ff (void); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING static inline bool tud_audio_clear_rx_support_ff (uint8_t ff_idx); static inline uint16_t tud_audio_available_support_ff (uint8_t ff_idx); static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, void* buffer, uint16_t bufsize); +static inline tu_fifo_t* tud_audio_get_rx_support_ff (uint8_t ff_idx); #endif // TX API @@ -412,12 +419,14 @@ static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, voi #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_write (const void * data, uint16_t len); static inline bool tud_audio_clear_ep_in_ff (void); +static inline tu_fifo_t* tud_audio_get_ep_in_ff (void); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING static inline uint16_t tud_audio_flush_tx_support_ff (void); static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t ff_idx); static inline uint16_t tud_audio_write_support_ff (uint8_t ff_idx, const void * data, uint16_t len); +static inline tu_fifo_t* tud_audio_get_tx_support_ff (uint8_t ff_idx); #endif // INT CTR API @@ -514,6 +523,11 @@ static inline bool tud_audio_clear_ep_out_ff(void) return tud_audio_n_clear_ep_out_ff(0); } +static inline tu_fifo_t* tud_audio_get_ep_out_ff(void) +{ + return tud_audio_n_get_ep_out_ff(0); +} + #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING @@ -533,6 +547,11 @@ static inline uint16_t tud_audio_read_support_ff(uint8_t ff_idx, void* buffer, u return tud_audio_n_read_support_ff(0, ff_idx, buffer, bufsize); } +static inline tu_fifo_t* tud_audio_get_rx_support_ff(uint8_t ff_idx) +{ + return tud_audio_n_get_rx_support_ff(0, ff_idx); +} + #endif // TX API @@ -549,6 +568,11 @@ static inline bool tud_audio_clear_ep_in_ff(void) return tud_audio_n_clear_ep_in_ff(0); } +static inline tu_fifo_t* tud_audio_get_ep_in_ff(void) +{ + return tud_audio_n_get_ep_in_ff(0); +} + #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING @@ -568,6 +592,11 @@ static inline uint16_t tud_audio_write_support_ff(uint8_t ff_idx, const void * d return tud_audio_n_write_support_ff(0, ff_idx, data, len); } +static inline tu_fifo_t* tud_audio_get_tx_support_ff(uint8_t ff_idx) +{ + return tud_audio_n_get_tx_support_ff(0, ff_idx); +} + #endif #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 098d54801..3bca8397b 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -905,7 +905,7 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n) +uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap) { // Operate on temporary values in case they change in between uint16_t w = f->wr_idx, r = f->rd_idx; @@ -933,23 +933,26 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, w = get_relative_pointer(f, w, 0); r = get_relative_pointer(f, r, offset); + // Copy pointer to buffer to start reading from + *ptr_lin = &f->buffer[r]; + *ptr_wrap = f->buffer; + // Check if there is a wrap around necessary uint16_t len; if (w > r) { + // Non wrapping case len = w - r; + len = tu_min16(n, len); // Limit to required length + *len_wrap = 0; } else { len = f->depth - r; // Also the case if FIFO was full + len = tu_min16(n, len); + *len_wrap = n-len; // n was already limited to what is available } - // Limit to required length - len = tu_min16(n, len); - - // Copy pointer to buffer to start reading from - *ptr = &f->buffer[r]; - return len; } @@ -976,7 +979,7 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, void **ptr, Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n) +uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap) { uint16_t w = f->wr_idx, r = f->rd_idx; uint16_t free = _tu_fifo_remaining(f, w, r); @@ -1004,22 +1007,26 @@ uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, void **ptr // Get relative pointers w = get_relative_pointer(f, w, offset); r = get_relative_pointer(f, r, 0); + + // Copy pointer to buffer to start writing to + *ptr_lin = &f->buffer[w]; + *ptr_wrap = f->buffer; // Always start of buffer + uint16_t len; if (w < r) { + // Non wrapping case len = r-w; + len = tu_min16(n, len); // Limit to required length + *len_wrap = 0; } else { len = f->depth - w; + len = tu_min16(n, len); // Limit to required length + *len_wrap = n-len; // Remaining length - n already was limited to free or FIFO depth } - // Limit to required length - len = tu_min16(n, len); - - // Copy pointer to buffer to start reading from - *ptr = &f->buffer[w]; - return len; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index b2d0b5be9..28998ad24 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -134,8 +134,10 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // This functions deliver a pointer to start reading/writing from/to and a valid linear length along which no wrap occurs. // In case not all of your data is available within one read/write, update the read/write pointer by // tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation -uint16_t tu_fifo_get_linear_read_info (tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n); -uint16_t tu_fifo_get_linear_write_info (tu_fifo_t *f, uint16_t offset, void **ptr, uint16_t n); +// TODO - update comments + +uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap); +uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap); static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index b8b0fc104..dd0d76c1f 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -993,7 +993,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part void * src; - uint16_t len = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes); // We want to read from the FIFO + uint16_t len = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes); // We want to read from the FIFO - THIS FUNCTION CHANGED!!! TU_VERIFY(len && dcd_write_packet_memory(dst, src, len)); // and write it into the PMA tu_fifo_advance_read_pointer(ff, len); @@ -1075,7 +1075,7 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part void * dst; - uint16_t len = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes); + uint16_t len = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes); // THIS FUNCTION CHANGED!!!! TU_VERIFY(len && dcd_read_packet_memory(dst, src, len)); tu_fifo_advance_write_pointer(ff, len); -- cgit v1.3.1 From 4dd1f1f3b50592d71fefcd8fb149322fad5a8493 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 23 Apr 2021 10:32:22 +0200 Subject: Fix include path in audio_device.h --- src/class/audio/audio_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 66cc29739..c5f8967e4 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -33,7 +33,7 @@ #include "device/usbd.h" #include "audio.h" -#include "tusb_fifo.h" +#include "common/tusb_fifo.h" //--------------------------------------------------------------------+ // Class Driver Configuration -- cgit v1.3.1 From a98d0217a05129b36d2eef76f36b986c31f84e92 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 23 Apr 2021 10:47:22 +0200 Subject: Init len_wrap = 0 to fix compiler complains. --- src/class/audio/audio_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index f96878b5b..4fdb58333 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -650,7 +650,7 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u void * dst, * dst_wrap; uint8_t * src; uint8_t * dst_end; - uint16_t len, len_wrap; + uint16_t len, len_wrap = 0; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { @@ -976,7 +976,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi void * src, * src_wrap; uint8_t * dst; uint8_t * src_end; - uint16_t len, len_wrap; + uint16_t len, len_wrap = 0; // Give len_wrap a value such that compiler does not complain - although it gets initialized in any case... for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { -- cgit v1.3.1 From 7072f0155e994005d8a0ccf5658f765df8a443b8 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 23 Apr 2021 11:48:54 +0200 Subject: Change tu_fifo_get_linear_write/read_info() to return a struct Compilers always complain that variables set by function via pointer might be uninitialized so to avoid that return values are now delivered via struct. --- src/class/audio/audio_device.c | 36 +++++++++++++++--------------- src/common/tusb_fifo.c | 50 +++++++++++++++++++----------------------- src/common/tusb_fifo.h | 12 ++++++++-- 3 files changed, 51 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 4fdb58333..25bf9e2d9 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -647,26 +647,26 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u uint8_t cnt_ff; // Decode - void * dst, * dst_wrap; uint8_t * src; uint8_t * dst_end; - uint16_t len, len_wrap = 0; + + tu_fifo_linear_wr_info info; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - len = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, nBytesPerFFToRead, &dst, &len_wrap, &dst_wrap); + info = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, nBytesPerFFToRead); - dst_end = dst + len; - src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst, dst_end, src, n_ff_used); + dst_end = info.ptr_lin + info.len_lin; + src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); // Handle wrapped part of FIFO - if (len_wrap != 0) + if (info.len_wrap != 0) { - dst_end = dst_wrap + len_wrap; - audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, dst_wrap, dst_end, src, n_ff_used); + dst_end = info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_wrap, dst_end, src, n_ff_used); } - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], len + len_wrap); + tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it @@ -973,28 +973,28 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy; // Encode - void * src, * src_wrap; uint8_t * dst; uint8_t * src_end; - uint16_t len, len_wrap = 0; // Give len_wrap a value such that compiler does not complain - although it gets initialized in any case... + + tu_fifo_linear_wr_info info; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - len = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, nBytesPerFFToSend, &src, &len_wrap, &src_wrap); + info = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, nBytesPerFFToSend); - src_end = src + len; - dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src, src_end, dst, n_ff_used); + src_end = info.ptr_lin + info.len_lin; + dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); // Handle wrapped part of FIFO - if (len_wrap != 0) + if (info.len_wrap != 0) { - src_end = src_wrap + len_wrap; - audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, src_wrap, src_end, dst, n_ff_used); + src_end = info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used); } - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], len + len_wrap); + tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } return nBytesPerFFToSend * n_ff_used; diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 3bca8397b..75dae0906 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -905,7 +905,7 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap) +tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n) { // Operate on temporary values in case they change in between uint16_t w = f->wr_idx, r = f->rd_idx; @@ -922,8 +922,10 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, cnt = f->depth; } + tu_fifo_linear_wr_info info = {0,0,NULL,NULL}; + // Skip beginning of buffer - if (cnt == 0 || offset >= cnt) return 0; + if (cnt == 0 || offset >= cnt) return info; // Check if we can read something at and after offset - if too less is available we read what remains cnt -= offset; @@ -934,26 +936,22 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, r = get_relative_pointer(f, r, offset); // Copy pointer to buffer to start reading from - *ptr_lin = &f->buffer[r]; - *ptr_wrap = f->buffer; + info.ptr_lin = &f->buffer[r]; + info.ptr_wrap = f->buffer; // Check if there is a wrap around necessary - uint16_t len; - if (w > r) { // Non wrapping case - len = w - r; - len = tu_min16(n, len); // Limit to required length - *len_wrap = 0; + info.len_lin = tu_min16(n, w - r); // Limit to required length + info.len_wrap = 0; } else { - len = f->depth - r; // Also the case if FIFO was full - len = tu_min16(n, len); - *len_wrap = n-len; // n was already limited to what is available + info.len_lin = tu_min16(n, f->depth - r); // Also the case if FIFO was full + info.len_wrap = n-info.len_lin; // n was already limited to what is available } - return len; + return info; } /******************************************************************************/ @@ -979,11 +977,13 @@ uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap) +tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n) { uint16_t w = f->wr_idx, r = f->rd_idx; uint16_t free = _tu_fifo_remaining(f, w, r); + tu_fifo_linear_wr_info info = {0,0,NULL,NULL}; + if (!f->overwritable) { // Not overwritable limit up to full @@ -992,7 +992,7 @@ uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n else if (n >= f->depth) { // If overwrite is allowed it must be less than or equal to 2 x buffer length, otherwise the overflow can not be resolved by the read functions - TU_VERIFY(n <= 2*f->depth); + if(n > 2*f->depth) return info; n = f->depth; // We start writing at the read pointer's position since we fill the complete @@ -1002,31 +1002,27 @@ uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n } // Check if there is room to write to - if (free == 0 || offset >= free) return 0; + if (free == 0 || offset >= free) return info; // Get relative pointers w = get_relative_pointer(f, w, offset); r = get_relative_pointer(f, r, 0); // Copy pointer to buffer to start writing to - *ptr_lin = &f->buffer[w]; - *ptr_wrap = f->buffer; // Always start of buffer - - uint16_t len; + info.ptr_lin = &f->buffer[w]; + info.ptr_wrap = f->buffer; // Always start of buffer if (w < r) { // Non wrapping case - len = r-w; - len = tu_min16(n, len); // Limit to required length - *len_wrap = 0; + info.len_lin = tu_min16(n, r-w); // Limit to required length + info.len_wrap = 0; } else { - len = f->depth - w; - len = tu_min16(n, len); // Limit to required length - *len_wrap = n-len; // Remaining length - n already was limited to free or FIFO depth + info.len_lin = tu_min16(n, f->depth - w); // Limit to required length + info.len_wrap = n-info.len_lin; // Remaining length - n already was limited to free or FIFO depth } - return len; + return info; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 28998ad24..c23f25723 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -80,6 +80,14 @@ typedef struct } tu_fifo_t; +typedef struct +{ + uint16_t len_lin ; ///< linear length in item size + uint16_t len_wrap ; ///< wrapped length in item size + void * ptr_lin ; ///< linear part start pointer + void * ptr_wrap ; ///< wrapped part start pointer +} tu_fifo_linear_wr_info; + #define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ { \ .buffer = _buffer, \ @@ -136,8 +144,8 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation // TODO - update comments -uint16_t tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap); -uint16_t tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n, void **ptr_lin, uint16_t *len_wrap, void **ptr_wrap); +tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n); +tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n); static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { -- cgit v1.3.1 From 8642c2045c140d117e03ae8585805b473e6ca351 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 24 Apr 2021 10:44:14 +0700 Subject: update dcd ip3511 for better multiple rhport support --- hw/bsp/lpc55/boards/double_m33_express/board.h | 3 + hw/bsp/lpc55/boards/lpcxpresso55s28/board.h | 3 + hw/bsp/lpc55/boards/lpcxpresso55s69/board.h | 3 + src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 129 ++++++++++++++++--------- 4 files changed, 95 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/hw/bsp/lpc55/boards/double_m33_express/board.h b/hw/bsp/lpc55/boards/double_m33_express/board.h index e73d700ba..6e43b8fc5 100644 --- a/hw/bsp/lpc55/boards/double_m33_express/board.h +++ b/hw/bsp/lpc55/boards/double_m33_express/board.h @@ -53,6 +53,9 @@ #define UART_RX_PINMUX 0U, 29U, IOCON_PIO_DIG_FUNC1_EN #define UART_TX_PINMUX 0U, 30U, IOCON_PIO_DIG_FUNC1_EN +// XTAL +//#define XTAL0_CLK_HZ 16000000U + #ifdef __cplusplus } #endif diff --git a/hw/bsp/lpc55/boards/lpcxpresso55s28/board.h b/hw/bsp/lpc55/boards/lpcxpresso55s28/board.h index cbf42c630..10f74ec3f 100644 --- a/hw/bsp/lpc55/boards/lpcxpresso55s28/board.h +++ b/hw/bsp/lpc55/boards/lpcxpresso55s28/board.h @@ -46,6 +46,9 @@ #define UART_RX_PINMUX 0, 29, IOCON_PIO_DIG_FUNC1_EN #define UART_TX_PINMUX 0, 30, IOCON_PIO_DIG_FUNC1_EN +// XTAL +#define XTAL0_CLK_HZ 16000000U + #ifdef __cplusplus } #endif diff --git a/hw/bsp/lpc55/boards/lpcxpresso55s69/board.h b/hw/bsp/lpc55/boards/lpcxpresso55s69/board.h index cbf42c630..10f74ec3f 100644 --- a/hw/bsp/lpc55/boards/lpcxpresso55s69/board.h +++ b/hw/bsp/lpc55/boards/lpcxpresso55s69/board.h @@ -46,6 +46,9 @@ #define UART_RX_PINMUX 0, 29, IOCON_PIO_DIG_FUNC1_EN #define UART_TX_PINMUX 0, 30, IOCON_PIO_DIG_FUNC1_EN +// XTAL +#define XTAL0_CLK_HZ 16000000U + #ifdef __cplusplus } #endif diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index e4d92458c..7dd44918c 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -33,11 +33,7 @@ * - LPC51U68 * - LPC54114 * - LPC55s69 - * - * For similar controller of other families, this file may require some minimal changes to work with. - * Previous MCUs such as LPC17xx, LPC40xx, LPC18xx, LPC43xx have their own driver implementation. */ - #if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_LPC11UXX || \ CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ CFG_TUSB_MCU == OPT_MCU_LPC15XX || \ @@ -45,30 +41,72 @@ CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ CFG_TUSB_MCU == OPT_MCU_LPC55XX) +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ + #if CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13XX || CFG_TUSB_MCU == OPT_MCU_LPC15XX - // LPC 11Uxx, 13xx, 15xx use lpcopen + // LPCOpen #include "chip.h" - #define DCD_REGS LPC_USB - -#elif CFG_TUSB_MCU == OPT_MCU_LPC51UXX || CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \ - CFG_TUSB_MCU == OPT_MCU_LPC55XX // TODO 55xx has dual usb controllers +#else + // SDK #include "fsl_device_registers.h" - #define DCD_REGS USB0 - + #define INCLUDE_FSL_DEVICE_REGISTERS #endif #include "device/dcd.h" -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ + +typedef struct { + __IO uint32_t DEVCMDSTAT; // Device Command/Status register, offset: 0x0 + __I uint32_t INFO; // Info register, offset: 0x4 + __IO uint32_t EPLISTSTART; // EP Command/Status List start address, offset: 0x8 + __IO uint32_t DATABUFSTART; // Data buffer start address, offset: 0xC + __IO uint32_t LPM; // Link Power Management register, offset: 0x10 + __IO uint32_t EPSKIP; // Endpoint skip, offset: 0x14 + __IO uint32_t EPINUSE; // Endpoint Buffer in use, offset: 0x18 + __IO uint32_t EPBUFCFG; // Endpoint Buffer Configuration register, offset: 0x1C + __IO uint32_t INTSTAT; // interrupt status register, offset: 0x20 + __IO uint32_t INTEN; // interrupt enable register, offset: 0x24 + __IO uint32_t INTSETSTAT; // set interrupt status register, offset: 0x28 + uint8_t RESERVED_0[8]; + __I uint32_t EPTOGGLE; // Endpoint toggle register, offset: 0x34 +} dcd_registers_t; + +typedef struct +{ + dcd_registers_t* regs; // registers + const IRQn_Type irqnum; // IRQ number + const uint8_t ep_count; // Max bi-directional Endpoints +}dcd_controller_t; // Number of endpoints // - 11 13 15 51 54 has 5x2 endpoints -// - 18/43 usb0 & 55s usb1 (HS) has 6x2 endpoints -// - 18/43 usb1 & 55s usb0 (FS) has 4x2 endpoints +// - 55 usb0 (FS) has 5x2 endpoints, usb1 (HS) has 6x2 endpoints #define EP_COUNT 10 + +#ifdef INCLUDE_FSL_DEVICE_REGISTERS + static const dcd_controller_t _dcd_controller[] = + { + { .regs = (dcd_registers_t*) USB0_BASE , .irqnum = USB0_IRQn, .ep_count = FSL_FEATURE_USB_EP_NUM }, + #if FSL_FEATURE_SOC_USBHSD_COUNT + { .regs = (dcd_registers_t*) USBHSD_BASE, .irqnum = USB1_IRQn, .ep_count = FSL_FEATURE_USBHSD_EP_NUM } + #endif + }; + +#else + static const dcd_controller_t _dcd_controller[] = + { + { .regs = (dcd_registers_t*) LPC_USB0_BASE, .irqnum = USB0_IRQn, .ep_count = 5 }, + }; + +#endif + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + // only SRAM1 & USB RAM can be used for transfer. // Used to set DATABUFSTART which is 22-bit aligned // 2000 0000 to 203F FFFF @@ -164,14 +202,14 @@ static inline uint8_t ep_addr2id(uint8_t endpoint_addr) //--------------------------------------------------------------------+ void dcd_init(uint8_t rhport) { - (void) rhport; + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; - DCD_REGS->EPLISTSTART = (uint32_t) _dcd.ep; - DCD_REGS->DATABUFSTART = SRAM_REGION; // 22-bit alignment + dcd_reg->EPLISTSTART = (uint32_t) _dcd.ep; + dcd_reg->DATABUFSTART = SRAM_REGION; // 22-bit alignment - DCD_REGS->INTSTAT = DCD_REGS->INTSTAT; // clear all pending interrupt - DCD_REGS->INTEN = INT_DEVICE_STATUS_MASK; - DCD_REGS->DEVCMDSTAT |= CMDSTAT_DEVICE_ENABLE_MASK | CMDSTAT_DEVICE_CONNECT_MASK | + dcd_reg->INTSTAT = dcd_reg->INTSTAT; // clear all pending interrupt + dcd_reg->INTEN = INT_DEVICE_STATUS_MASK; + dcd_reg->DEVCMDSTAT |= CMDSTAT_DEVICE_ENABLE_MASK | CMDSTAT_DEVICE_CONNECT_MASK | CMDSTAT_RESET_CHANGE_MASK | CMDSTAT_CONNECT_CHANGE_MASK | CMDSTAT_SUSPEND_CHANGE_MASK; NVIC_ClearPendingIRQ(USB0_IRQn); @@ -191,11 +229,13 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; + // Response with status first before changing device address dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); - DCD_REGS->DEVCMDSTAT &= ~CMDSTAT_DEVICE_ADDR_MASK; - DCD_REGS->DEVCMDSTAT |= dev_addr; + dcd_reg->DEVCMDSTAT &= ~CMDSTAT_DEVICE_ADDR_MASK; + dcd_reg->DEVCMDSTAT |= dev_addr; } void dcd_remote_wakeup(uint8_t rhport) @@ -205,14 +245,14 @@ void dcd_remote_wakeup(uint8_t rhport) void dcd_connect(uint8_t rhport) { - (void) rhport; - DCD_REGS->DEVCMDSTAT |= CMDSTAT_DEVICE_CONNECT_MASK; + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; + dcd_reg->DEVCMDSTAT |= CMDSTAT_DEVICE_CONNECT_MASK; } void dcd_disconnect(uint8_t rhport) { - (void) rhport; - DCD_REGS->DEVCMDSTAT &= ~CMDSTAT_DEVICE_CONNECT_MASK; + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; + dcd_reg->DEVCMDSTAT &= ~CMDSTAT_DEVICE_CONNECT_MASK; } //--------------------------------------------------------------------+ @@ -255,7 +295,8 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) _dcd.ep[ep_id][0].is_iso = (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS); // Enable EP interrupt - DCD_REGS->INTEN |= TU_BIT(ep_id); + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; + dcd_reg->INTEN |= TU_BIT(ep_id); return true; } @@ -288,7 +329,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to //--------------------------------------------------------------------+ // IRQ //--------------------------------------------------------------------+ -static void bus_reset(void) +static void bus_reset(uint8_t rhport) { tu_memclr(&_dcd, sizeof(dcd_data_t)); @@ -300,13 +341,15 @@ static void bus_reset(void) _dcd.ep[0][1].buffer_offset = get_buf_offset(_dcd.setup_packet); - DCD_REGS->EPINUSE = 0; - DCD_REGS->EPBUFCFG = 0; - DCD_REGS->EPSKIP = 0xFFFFFFFF; + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; + + dcd_reg->EPINUSE = 0; + dcd_reg->EPBUFCFG = 0; + dcd_reg->EPSKIP = 0xFFFFFFFF; - DCD_REGS->INTSTAT = DCD_REGS->INTSTAT; // clear all pending interrupt - DCD_REGS->DEVCMDSTAT |= CMDSTAT_SETUP_RECEIVED_MASK; // clear setup received interrupt - DCD_REGS->INTEN = INT_DEVICE_STATUS_MASK | TU_BIT(0) | TU_BIT(1); // enable device status & control endpoints + dcd_reg->INTSTAT = dcd_reg->INTSTAT; // clear all pending interrupt + dcd_reg->DEVCMDSTAT |= CMDSTAT_SETUP_RECEIVED_MASK; // clear setup received interrupt + dcd_reg->INTEN = INT_DEVICE_STATUS_MASK | TU_BIT(0) | TU_BIT(1); // enable device status & control endpoints } static void process_xfer_isr(uint32_t int_status) @@ -341,22 +384,22 @@ static void process_xfer_isr(uint32_t int_status) void dcd_int_handler(uint8_t rhport) { - (void) rhport; // TODO support multiple USB on supported mcu such as LPC55s69 + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; - uint32_t const cmd_stat = DCD_REGS->DEVCMDSTAT; + uint32_t const cmd_stat = dcd_reg->DEVCMDSTAT; - uint32_t int_status = DCD_REGS->INTSTAT & DCD_REGS->INTEN; - DCD_REGS->INTSTAT = int_status; // Acknowledge handled interrupt + uint32_t int_status = dcd_reg->INTSTAT & dcd_reg->INTEN; + dcd_reg->INTSTAT = int_status; // Acknowledge handled interrupt if (int_status == 0) return; //------------- Device Status -------------// if ( int_status & INT_DEVICE_STATUS_MASK ) { - DCD_REGS->DEVCMDSTAT |= CMDSTAT_RESET_CHANGE_MASK | CMDSTAT_CONNECT_CHANGE_MASK | CMDSTAT_SUSPEND_CHANGE_MASK; + dcd_reg->DEVCMDSTAT |= CMDSTAT_RESET_CHANGE_MASK | CMDSTAT_CONNECT_CHANGE_MASK | CMDSTAT_SUSPEND_CHANGE_MASK; if ( cmd_stat & CMDSTAT_RESET_CHANGE_MASK) // bus reset { - bus_reset(); + bus_reset(rhport); dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); } @@ -396,7 +439,7 @@ void dcd_int_handler(uint8_t rhport) _dcd.ep[0][0].active = _dcd.ep[1][0].active = 0; _dcd.ep[0][0].stall = _dcd.ep[1][0].stall = 0; - DCD_REGS->DEVCMDSTAT |= CMDSTAT_SETUP_RECEIVED_MASK; + dcd_reg->DEVCMDSTAT |= CMDSTAT_SETUP_RECEIVED_MASK; dcd_event_setup_received(0, _dcd.setup_packet, true); -- cgit v1.3.1 From 8bed369c7fc238d0653b25d32af5f33ec00a9c98 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 24 Apr 2021 11:30:14 +0700 Subject: lpc55 better multiport support --- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 127 ++++++++++++++------------- 1 file changed, 66 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 7dd44918c..f22387984 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -56,6 +56,19 @@ #include "device/dcd.h" +// only SRAM1 & USB RAM can be used for transfer. +// Used to set DATABUFSTART which is 22-bit aligned +// 2000 0000 to 203F FFFF +#define SRAM_REGION 0x20000000 + +// Absolute max of endpoints pairs for all port +// - 11 13 15 51 54 has 5x2 endpoints +// - 55 usb0 (FS) has 5x2 endpoints, usb1 (HS) has 6x2 endpoints +#define MAX_EP_PAIRS 6 + +//--------------------------------------------------------------------+ +// IP3511 Registers +//--------------------------------------------------------------------+ typedef struct { __IO uint32_t DEVCMDSTAT; // Device Command/Status register, offset: 0x0 @@ -73,45 +86,6 @@ typedef struct { __I uint32_t EPTOGGLE; // Endpoint toggle register, offset: 0x34 } dcd_registers_t; -typedef struct -{ - dcd_registers_t* regs; // registers - const IRQn_Type irqnum; // IRQ number - const uint8_t ep_count; // Max bi-directional Endpoints -}dcd_controller_t; - -// Number of endpoints -// - 11 13 15 51 54 has 5x2 endpoints -// - 55 usb0 (FS) has 5x2 endpoints, usb1 (HS) has 6x2 endpoints -#define EP_COUNT 10 - - -#ifdef INCLUDE_FSL_DEVICE_REGISTERS - static const dcd_controller_t _dcd_controller[] = - { - { .regs = (dcd_registers_t*) USB0_BASE , .irqnum = USB0_IRQn, .ep_count = FSL_FEATURE_USB_EP_NUM }, - #if FSL_FEATURE_SOC_USBHSD_COUNT - { .regs = (dcd_registers_t*) USBHSD_BASE, .irqnum = USB1_IRQn, .ep_count = FSL_FEATURE_USBHSD_EP_NUM } - #endif - }; - -#else - static const dcd_controller_t _dcd_controller[] = - { - { .regs = (dcd_registers_t*) LPC_USB0_BASE, .irqnum = USB0_IRQn, .ep_count = 5 }, - }; - -#endif - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -// only SRAM1 & USB RAM can be used for transfer. -// Used to set DATABUFSTART which is 22-bit aligned -// 2000 0000 to 203F FFFF -#define SRAM_REGION 0x20000000 - /* Although device controller are the same. Somehow only LPC134x can execute * DMA with 1023 bytes for Bulk/Control. Others (11u, 51u, 54xxx) can only work * with max 64 bytes @@ -141,6 +115,10 @@ enum { CMDSTAT_VBUS_DEBOUNCED_MASK = TU_BIT(28), }; +//--------------------------------------------------------------------+ +// Endpoint Command/Status List +//--------------------------------------------------------------------+ + typedef struct TU_ATTR_PACKED { // Bits 21:6 (aligned 64) used in conjunction with bit 31:22 of DATABUFSTART @@ -171,19 +149,46 @@ typedef struct { // 256 byte aligned, 2 for double buffer (not used) // Each cmd_sts can only transfer up to DMA_NBYTES_MAX bytes each - ep_cmd_sts_t ep[EP_COUNT][2]; - - xfer_dma_t dma[EP_COUNT]; + ep_cmd_sts_t ep[2*MAX_EP_PAIRS][2]; + xfer_dma_t dma[2*MAX_EP_PAIRS]; TU_ATTR_ALIGNED(64) uint8_t setup_packet[8]; }dcd_data_t; +// EP list must be 256-byte aligned +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(256) static dcd_data_t _dcd; + //--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION +// Multiple Controllers //--------------------------------------------------------------------+ -// EP list must be 256-byte aligned -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(256) static dcd_data_t _dcd; +typedef struct +{ + dcd_registers_t* regs; // registers + const IRQn_Type irqnum; // IRQ number + const uint8_t ep_pairs; // Max bi-directional Endpoints +}dcd_controller_t; + +#ifdef INCLUDE_FSL_DEVICE_REGISTERS + static const dcd_controller_t _dcd_controller[] = + { + { .regs = (dcd_registers_t*) USB0_BASE , .irqnum = USB0_IRQn, .ep_pairs = FSL_FEATURE_USB_EP_NUM }, + #if FSL_FEATURE_SOC_USBHSD_COUNT + { .regs = (dcd_registers_t*) USBHSD_BASE, .irqnum = USB1_IRQn, .ep_pairs = FSL_FEATURE_USBHSD_EP_NUM } + #endif + }; + +#else + static const dcd_controller_t _dcd_controller[] = + { + { .regs = (dcd_registers_t*) LPC_USB0_BASE, .irqnum = USB0_IRQn, .ep_pairs = 5 }, + }; + +#endif + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ static inline uint16_t get_buf_offset(void const * buffer) { @@ -212,19 +217,17 @@ void dcd_init(uint8_t rhport) dcd_reg->DEVCMDSTAT |= CMDSTAT_DEVICE_ENABLE_MASK | CMDSTAT_DEVICE_CONNECT_MASK | CMDSTAT_RESET_CHANGE_MASK | CMDSTAT_CONNECT_CHANGE_MASK | CMDSTAT_SUSPEND_CHANGE_MASK; - NVIC_ClearPendingIRQ(USB0_IRQn); + NVIC_ClearPendingIRQ(_dcd_controller[rhport].irqnum); } void dcd_int_enable(uint8_t rhport) { - (void) rhport; - NVIC_EnableIRQ(USB0_IRQn); + NVIC_EnableIRQ(_dcd_controller[rhport].irqnum); } void dcd_int_disable(uint8_t rhport) { - (void) rhport; - NVIC_DisableIRQ(USB0_IRQn); + NVIC_DisableIRQ(_dcd_controller[rhport].irqnum); } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) @@ -334,7 +337,7 @@ static void bus_reset(uint8_t rhport) tu_memclr(&_dcd, sizeof(dcd_data_t)); // disable all non-control endpoints on bus reset - for(uint8_t ep_id = 2; ep_id < EP_COUNT; ep_id++) + for(uint8_t ep_id = 2; ep_id < 2*MAX_EP_PAIRS; ep_id++) { _dcd.ep[ep_id][0].disable = _dcd.ep[ep_id][1].disable = 1; } @@ -352,9 +355,11 @@ static void bus_reset(uint8_t rhport) dcd_reg->INTEN = INT_DEVICE_STATUS_MASK | TU_BIT(0) | TU_BIT(1); // enable device status & control endpoints } -static void process_xfer_isr(uint32_t int_status) +static void process_xfer_isr(uint8_t rhport, uint32_t int_status) { - for(uint8_t ep_id = 0; ep_id < EP_COUNT; ep_id++ ) + uint8_t const max_ep = 2*_dcd_controller[rhport].ep_pairs; + + for(uint8_t ep_id = 0; ep_id < max_ep; ep_id++ ) { if ( tu_bit_test(int_status, ep_id) ) { @@ -373,10 +378,10 @@ static void process_xfer_isr(uint32_t int_status) { xfer_dma->total_bytes = xfer_dma->xferred_bytes; - uint8_t const ep_addr = (ep_id / 2) | ((ep_id & 0x01) ? TUSB_DIR_IN_MASK : 0); + uint8_t const ep_addr = tu_edpt_addr(ep_id / 2, ep_id & 0x01); // TODO no way determine if the transfer is failed or not - dcd_event_xfer_complete(0, ep_addr, xfer_dma->xferred_bytes, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, ep_addr, xfer_dma->xferred_bytes, XFER_RESULT_SUCCESS, true); } } } @@ -400,7 +405,7 @@ void dcd_int_handler(uint8_t rhport) if ( cmd_stat & CMDSTAT_RESET_CHANGE_MASK) // bus reset { bus_reset(rhport); - dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); } if (cmd_stat & CMDSTAT_CONNECT_CHANGE_MASK) @@ -409,7 +414,7 @@ void dcd_int_handler(uint8_t rhport) if (cmd_stat & CMDSTAT_DEVICE_ADDR_MASK) { // debouncing as this can be set when device is powering - dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true); + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); } } @@ -421,13 +426,13 @@ void dcd_int_handler(uint8_t rhport) // Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration. if (cmd_stat & CMDSTAT_DEVICE_ADDR_MASK) { - dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); } } } // else // { // resume signal -// dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); +// dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); // } // } } @@ -441,7 +446,7 @@ void dcd_int_handler(uint8_t rhport) dcd_reg->DEVCMDSTAT |= CMDSTAT_SETUP_RECEIVED_MASK; - dcd_event_setup_received(0, _dcd.setup_packet, true); + dcd_event_setup_received(rhport, _dcd.setup_packet, true); // keep waiting for next setup _dcd.ep[0][1].buffer_offset = get_buf_offset(_dcd.setup_packet); @@ -451,7 +456,7 @@ void dcd_int_handler(uint8_t rhport) } // Endpoint transfer complete interrupt - process_xfer_isr(int_status); + process_xfer_isr(rhport, int_status); } #endif -- cgit v1.3.1 From 7089df2088a8f9ad977f5deecd34a6ba3d8399b3 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 24 Apr 2021 12:19:13 +0700 Subject: lpc55 correct bus_reset with highspeed on support controller correct hsphy init for family --- hw/bsp/lpc55/family.c | 74 +++++++++++++++------- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 46 ++++++++++---- .../nxp/transdimension/dcd_transdimension.c | 1 + 3 files changed, 84 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/hw/bsp/lpc55/family.c b/hw/bsp/lpc55/family.c index c11c74e4d..ba16a93ab 100644 --- a/hw/bsp/lpc55/family.c +++ b/hw/bsp/lpc55/family.c @@ -164,43 +164,71 @@ void board_init(void) /* PORT0 PIN22 configured as USB0_VBUS */ IOCON_PinMuxSet(IOCON, 0U, 22U, IOCON_PIO_DIG_FUNC7_EN); - // USB Controller - POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); /*Turn on USB0 Phy */ - POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /*< Turn on USB1 Phy */ +#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE + // Port0 is Full Speed + + /* Turn on USB0 Phy */ + POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); /* reset the IP to make sure it's in reset state. */ RESET_PeripheralReset(kUSB0D_RST_SHIFT_RSTn); RESET_PeripheralReset(kUSB0HSL_RST_SHIFT_RSTn); RESET_PeripheralReset(kUSB0HMR_RST_SHIFT_RSTn); - RESET_PeripheralReset(kUSB1H_RST_SHIFT_RSTn); - RESET_PeripheralReset(kUSB1D_RST_SHIFT_RSTn); - RESET_PeripheralReset(kUSB1_RST_SHIFT_RSTn); - RESET_PeripheralReset(kUSB1RAM_RST_SHIFT_RSTn); -#if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE - CLOCK_EnableClock(kCLOCK_Usbh1); - /* Put PHY powerdown under software control */ - USBHSH->PORTMODE = USBHSH_PORTMODE_SW_PDCOM_MASK; - /* According to reference mannual, device mode setting has to be set by access usb host register */ - USBHSH->PORTMODE |= USBHSH_PORTMODE_DEV_ENABLE_MASK; - /* enable usb1 host clock */ - CLOCK_DisableClock(kCLOCK_Usbh1); -#endif - -#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE // Enable USB Clock Adjustments to trim the FRO for the full speed controller ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_USBCLKADJ_MASK; CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false); CLOCK_AttachClk(kFRO_HF_to_USB0_CLK); - /* enable usb0 host clock */ - CLOCK_EnableClock(kCLOCK_Usbhsl0); + /*According to reference mannual, device mode setting has to be set by access usb host register */ + CLOCK_EnableClock(kCLOCK_Usbhsl0); // enable usb0 host clock USBFSH->PORTMODE |= USBFSH_PORTMODE_DEV_ENABLE_MASK; - /* disable usb0 host clock */ - CLOCK_DisableClock(kCLOCK_Usbhsl0); - CLOCK_EnableUsbfs0DeviceClock(kCLOCK_UsbfsSrcFro, CLOCK_GetFreq(kCLOCK_FroHf)); /* enable USB Device clock */ + CLOCK_DisableClock(kCLOCK_Usbhsl0); // disable usb0 host clock + + /* enable USB Device clock */ + CLOCK_EnableUsbfs0DeviceClock(kCLOCK_UsbfsSrcFro, CLOCK_GetFreq(kCLOCK_FroHf)); #endif +#if CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE + // Port1 is High Speed + + /* Turn on USB1 Phy */ + POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); + + /* reset the IP to make sure it's in reset state. */ + RESET_PeripheralReset(kUSB1H_RST_SHIFT_RSTn); + RESET_PeripheralReset(kUSB1D_RST_SHIFT_RSTn); + RESET_PeripheralReset(kUSB1_RST_SHIFT_RSTn); + RESET_PeripheralReset(kUSB1RAM_RST_SHIFT_RSTn); + + /* According to reference mannual, device mode setting has to be set by access usb host register */ + CLOCK_EnableClock(kCLOCK_Usbh1); // enable usb0 host clock + + USBHSH->PORTMODE = USBHSH_PORTMODE_SW_PDCOM_MASK; // Put PHY powerdown under software control + USBHSH->PORTMODE |= USBHSH_PORTMODE_DEV_ENABLE_MASK; + + CLOCK_DisableClock(kCLOCK_Usbh1); // disable usb0 host clock + + /* enable USB Device clock */ + CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_UsbPhySrcExt, XTAL0_CLK_HZ); + CLOCK_EnableUsbhs0DeviceClock(kCLOCK_UsbSrcUnused, 0U); + //USB_EhciPhyInit(CONTROLLER_ID, BOARD_XTAL0_CLK_HZ, NULL); + + // Enable PHY support for Low speed device + LS via FS Hub + USBPHY->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK | USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; + + // Enable all power for normal operation + USBPHY->PWD = 0; + + USBPHY->CTRL_SET = USBPHY_CTRL_SET_ENAUTOCLR_CLKGATE_MASK; + USBPHY->CTRL_SET = USBPHY_CTRL_SET_ENAUTOCLR_PHY_PWD_MASK; + + // TX Timing +// uint32_t phytx = USBPHY->TX; +// phytx &= ~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK); +// phytx |= USBPHY_TX_D_CAL(0x0C) | USBPHY_TX_TXCAL45DP(0x06) | USBPHY_TX_TXCAL45DM(0x06); +// USBPHY->TX = phytx; +#endif } //--------------------------------------------------------------------+ diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index f22387984..090d9e602 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -61,11 +61,6 @@ // 2000 0000 to 203F FFFF #define SRAM_REGION 0x20000000 -// Absolute max of endpoints pairs for all port -// - 11 13 15 51 54 has 5x2 endpoints -// - 55 usb0 (FS) has 5x2 endpoints, usb1 (HS) has 6x2 endpoints -#define MAX_EP_PAIRS 6 - //--------------------------------------------------------------------+ // IP3511 Registers //--------------------------------------------------------------------+ @@ -107,14 +102,19 @@ 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 soft-connect 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), + // 23-22 is link speed (only available for HighSpeed port) CMDSTAT_CONNECT_CHANGE_MASK = TU_BIT(24), CMDSTAT_SUSPEND_CHANGE_MASK = TU_BIT(25), CMDSTAT_RESET_CHANGE_MASK = TU_BIT(26), CMDSTAT_VBUS_DEBOUNCED_MASK = TU_BIT(28), }; +enum { + CMDSTAT_SPEED_SHIFT = 22 +}; + //--------------------------------------------------------------------+ // Endpoint Command/Status List //--------------------------------------------------------------------+ @@ -143,6 +143,11 @@ typedef struct uint16_t nbytes; }xfer_dma_t; +// Absolute max of endpoints pairs for all port +// - 11 13 15 51 54 has 5x2 endpoints +// - 55 usb0 (FS) has 5x2 endpoints, usb1 (HS) has 6x2 endpoints +#define MAX_EP_PAIRS 6 + // NOTE data will be transferred as soon as dcd get request by dcd_pipe(_queue)_xfer using double buffering. // current_td is used to keep track of number of remaining & xferred bytes of the current request. typedef struct @@ -150,8 +155,8 @@ typedef struct // 256 byte aligned, 2 for double buffer (not used) // Each cmd_sts can only transfer up to DMA_NBYTES_MAX bytes each ep_cmd_sts_t ep[2*MAX_EP_PAIRS][2]; - xfer_dma_t dma[2*MAX_EP_PAIRS]; + TU_ATTR_ALIGNED(64) uint8_t setup_packet[8]; }dcd_data_t; @@ -164,24 +169,25 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(256) static dcd_data_t _dcd; typedef struct { - dcd_registers_t* regs; // registers - const IRQn_Type irqnum; // IRQ number - const uint8_t ep_pairs; // Max bi-directional Endpoints + dcd_registers_t* regs; // registers + const tusb_speed_t max_speed; // max link speed + const IRQn_Type irqnum; // IRQ number + const uint8_t ep_pairs; // Max bi-directional Endpoints }dcd_controller_t; #ifdef INCLUDE_FSL_DEVICE_REGISTERS static const dcd_controller_t _dcd_controller[] = { - { .regs = (dcd_registers_t*) USB0_BASE , .irqnum = USB0_IRQn, .ep_pairs = FSL_FEATURE_USB_EP_NUM }, + { .regs = (dcd_registers_t*) USB0_BASE , .max_speed = TUSB_SPEED_FULL, .irqnum = USB0_IRQn, .ep_pairs = FSL_FEATURE_USB_EP_NUM }, #if FSL_FEATURE_SOC_USBHSD_COUNT - { .regs = (dcd_registers_t*) USBHSD_BASE, .irqnum = USB1_IRQn, .ep_pairs = FSL_FEATURE_USBHSD_EP_NUM } + { .regs = (dcd_registers_t*) USBHSD_BASE, .max_speed = TUSB_SPEED_HIGH, .irqnum = USB1_IRQn, .ep_pairs = FSL_FEATURE_USBHSD_EP_NUM } #endif }; #else static const dcd_controller_t _dcd_controller[] = { - { .regs = (dcd_registers_t*) LPC_USB0_BASE, .irqnum = USB0_IRQn, .ep_pairs = 5 }, + { .regs = (dcd_registers_t*) LPC_USB0_BASE, .max_speed = TUSB_SPEED_FULL, .irqnum = USB0_IRQn, .ep_pairs = 5 }, }; #endif @@ -405,7 +411,19 @@ void dcd_int_handler(uint8_t rhport) if ( cmd_stat & CMDSTAT_RESET_CHANGE_MASK) // bus reset { bus_reset(rhport); - dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); + + tusb_speed_t speed = TUSB_SPEED_FULL; + + if (_dcd_controller[rhport].max_speed == TUSB_SPEED_HIGH) + { + // 0 : reserved, 1 : full, 2 : high, 3: super + if ( 2 == ((cmd_stat >> CMDSTAT_SPEED_SHIFT) & 0x3UL) ) + { + speed= TUSB_SPEED_HIGH; + } + } + + dcd_event_bus_reset(rhport, speed, true); } if (cmd_stat & CMDSTAT_CONNECT_CHANGE_MASK) diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index afc7184a0..eeab3f487 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -34,6 +34,7 @@ //--------------------------------------------------------------------+ #if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX #include "fsl_device_registers.h" + #define INCLUDE_FSL_DEVICE_REGISTERS #else // LPCOpen for 18xx & 43xx #include "chip.h" -- cgit v1.3.1 From b15d126d594630e8ad75780f54a9218ccb5ad7b9 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 24 Apr 2021 13:36:05 +0700 Subject: lpc55 improve multiple controller support port1 highspeed requires USB_RAM --- hw/bsp/lpc55/family.mk | 6 ++++-- src/device/usbd.c | 4 +++- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 17 +++++++---------- 3 files changed, 14 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/hw/bsp/lpc55/family.mk b/hw/bsp/lpc55/family.mk index c8874f571..46923cc4f 100644 --- a/hw/bsp/lpc55/family.mk +++ b/hw/bsp/lpc55/family.mk @@ -14,13 +14,15 @@ CFLAGS += \ -mfloat-abi=hard \ -mfpu=fpv5-sp-d16 \ -DCFG_TUSB_MCU=OPT_MCU_LPC55XX \ - -DCFG_TUSB_MEM_SECTION='__attribute__((section(".data")))' \ -DCFG_TUSB_MEM_ALIGN='__attribute__((aligned(64)))' \ -DBOARD_DEVICE_RHPORT_NUM=$(PORT) ifeq ($(PORT), 1) - CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED $(info "PORT1 High Speed") + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + + # LPC55 Highspeed Port1 can only write to USB_SRAM region + CFLAGS += -DCFG_TUSB_MEM_SECTION='__attribute__((section("m_usb_global")))' else $(info "PORT0 Full Speed") endif diff --git a/src/device/usbd.c b/src/device/usbd.c index 8a3d8ec2f..2853b619b 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -302,6 +302,8 @@ static char const* const _tusb_std_request_str[] = "Synch Frame" }; +static char const* const _tusb_speed_str[] = { "Full", "Low", "High" }; + // for usbd_control to print the name of control complete driver void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) { @@ -464,7 +466,7 @@ void tud_task (void) switch ( event.event_id ) { case DCD_EVENT_BUS_RESET: - TU_LOG2("\r\n"); + TU_LOG2(": %s Speed\r\n", _tusb_speed_str[event.bus_reset.speed]); usbd_reset(event.rhport); _usbd_dev.speed = event.bus_reset.speed; break; diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 090d9e602..d7efd8066 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -56,11 +56,6 @@ #include "device/dcd.h" -// only SRAM1 & USB RAM can be used for transfer. -// Used to set DATABUFSTART which is 22-bit aligned -// 2000 0000 to 203F FFFF -#define SRAM_REGION 0x20000000 - //--------------------------------------------------------------------+ // IP3511 Registers //--------------------------------------------------------------------+ @@ -161,6 +156,9 @@ typedef struct }dcd_data_t; // EP list must be 256-byte aligned +// Some MCU controller may require this variable to be placed in specific SRAM region. +// For example: LPC55s69 port1 Highspeed must be USB_RAM (0x40100000) +// Use CFG_TUSB_MEM_SECTION to place it accordingly. CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(256) static dcd_data_t _dcd; //--------------------------------------------------------------------+ @@ -179,7 +177,7 @@ typedef struct static const dcd_controller_t _dcd_controller[] = { { .regs = (dcd_registers_t*) USB0_BASE , .max_speed = TUSB_SPEED_FULL, .irqnum = USB0_IRQn, .ep_pairs = FSL_FEATURE_USB_EP_NUM }, - #if FSL_FEATURE_SOC_USBHSD_COUNT + #if defined(FSL_FEATURE_SOC_USBHSD_COUNT) && FSL_FEATURE_SOC_USBHSD_COUNT { .regs = (dcd_registers_t*) USBHSD_BASE, .max_speed = TUSB_SPEED_HIGH, .irqnum = USB1_IRQn, .ep_pairs = FSL_FEATURE_USBHSD_EP_NUM } #endif }; @@ -203,9 +201,9 @@ static inline uint16_t get_buf_offset(void const * buffer) return ( (addr >> 6) & 0xFFFFUL ) ; } -static inline uint8_t ep_addr2id(uint8_t endpoint_addr) +static inline uint8_t ep_addr2id(uint8_t ep_addr) { - return 2*(endpoint_addr & 0x0F) + ((endpoint_addr & TUSB_DIR_IN_MASK) ? 1 : 0); + return 2*(ep_addr & 0x0F) + ((ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0); } //--------------------------------------------------------------------+ @@ -216,8 +214,7 @@ void dcd_init(uint8_t rhport) dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; dcd_reg->EPLISTSTART = (uint32_t) _dcd.ep; - dcd_reg->DATABUFSTART = SRAM_REGION; // 22-bit alignment - + dcd_reg->DATABUFSTART = tu_align((uint32_t) &_dcd, 22); // 22-bit alignment dcd_reg->INTSTAT = dcd_reg->INTSTAT; // clear all pending interrupt dcd_reg->INTEN = INT_DEVICE_STATUS_MASK; dcd_reg->DEVCMDSTAT |= CMDSTAT_DEVICE_ENABLE_MASK | CMDSTAT_DEVICE_CONNECT_MASK | -- cgit v1.3.1 From f14daf208135802f45d9f1c4276f3655e12dd123 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 24 Apr 2021 15:04:58 +0700 Subject: fix unaligned access with port1 hs --- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index d7efd8066..2be14084b 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -136,6 +136,9 @@ typedef struct uint16_t xferred_bytes; uint16_t nbytes; + + // prevent unaligned access on Highspeed port on USB_SRAM + uint16_t TU_RESERVED; }xfer_dma_t; // Absolute max of endpoints pairs for all port @@ -324,7 +327,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to uint8_t const ep_id = ep_addr2id(ep_addr); - tu_varclr(&_dcd.dma[ep_id]); + tu_memclr(&_dcd.dma[ep_id], sizeof(xfer_dma_t)); _dcd.dma[ep_id].total_bytes = total_bytes; prepare_ep_xfer(ep_id, get_buf_offset(buffer), total_bytes); -- cgit v1.3.1 From 8ebdf2b0979c39e7a709939ad38b5916838f1318 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 26 Apr 2021 14:43:58 +0700 Subject: ip3511 correct buffer offset, nbytes layout for highspeed port1 able to get passed enumeration and up to READ10 --- hw/bsp/lpc55/family.c | 2 +- src/common/tusb_common.h | 2 +- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 105 +++++++++++++++++++++------ 3 files changed, 84 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/hw/bsp/lpc55/family.c b/hw/bsp/lpc55/family.c index ba16a93ab..890c2f5c5 100644 --- a/hw/bsp/lpc55/family.c +++ b/hw/bsp/lpc55/family.c @@ -212,7 +212,7 @@ void board_init(void) /* enable USB Device clock */ CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_UsbPhySrcExt, XTAL0_CLK_HZ); CLOCK_EnableUsbhs0DeviceClock(kCLOCK_UsbSrcUnused, 0U); - //USB_EhciPhyInit(CONTROLLER_ID, BOARD_XTAL0_CLK_HZ, NULL); + CLOCK_EnableClock(kCLOCK_UsbRam1); // Enable PHY support for Low speed device + LS via FS Hub USBPHY->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK | USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 147856d45..705ff867c 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -115,8 +115,8 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align(uint32_t value, uint32_t a return value & ((uint32_t) ~(alignment-1)); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align16 (uint32_t value) { return (value & 0xFFFFFFF0UL); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align4k (uint32_t value) { return (value & 0xFFFFF000UL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); } diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 2be14084b..f3762257a 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -114,22 +114,39 @@ enum { // Endpoint Command/Status List //--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED +// Endpoint Command/Status +typedef union TU_ATTR_PACKED { - // Bits 21:6 (aligned 64) used in conjunction with bit 31:22 of DATABUFSTART - volatile uint16_t buffer_offset; - - volatile uint16_t nbytes : 10 ; - uint16_t is_iso : 1 ; - uint16_t toggle_mode : 1 ; - uint16_t toggle_reset : 1 ; - uint16_t stall : 1 ; - uint16_t disable : 1 ; - volatile uint16_t active : 1 ; + // Full and High speed has different bit layout for buffer_offset and nbytes + + // Buffer (aligned 64) = DATABUFSTART [31:22] | buffer_offset [21:6] + volatile struct { + uint32_t offset : 16; + uint32_t nbytes : 10; + uint32_t TU_RESERVED : 6; + } buffer_fs; + + // Buffer (aligned 64) = USB_RAM [31:17] | buffer_offset [16:6] + volatile struct { + uint32_t offset : 11 ; + uint32_t nbytes : 15 ; + uint32_t TU_RESERVED : 6 ; + } buffer_hs; + + volatile struct { + uint32_t TU_RESERVED : 26; + uint32_t is_iso : 1 ; + uint32_t toggle_mode : 1 ; + uint32_t toggle_reset : 1 ; + uint32_t stall : 1 ; + uint32_t disable : 1 ; + uint32_t active : 1 ; + }; }ep_cmd_sts_t; TU_VERIFY_STATIC( sizeof(ep_cmd_sts_t) == 4, "size is not correct" ); +// Software transfer management typedef struct { uint16_t total_bytes; @@ -217,8 +234,8 @@ void dcd_init(uint8_t rhport) dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; dcd_reg->EPLISTSTART = (uint32_t) _dcd.ep; - dcd_reg->DATABUFSTART = tu_align((uint32_t) &_dcd, 22); // 22-bit alignment - dcd_reg->INTSTAT = dcd_reg->INTSTAT; // clear all pending interrupt + dcd_reg->DATABUFSTART = tu_align((uint32_t) &_dcd, TU_BIT(22)); // 22-bit alignment + dcd_reg->INTSTAT |= dcd_reg->INTSTAT; // clear all pending interrupt dcd_reg->INTEN = INT_DEVICE_STATUS_MASK; dcd_reg->DEVCMDSTAT |= CMDSTAT_DEVICE_ENABLE_MASK | CMDSTAT_DEVICE_CONNECT_MASK | CMDSTAT_RESET_CHANGE_MASK | CMDSTAT_CONNECT_CHANGE_MASK | CMDSTAT_SUSPEND_CHANGE_MASK; @@ -310,15 +327,34 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } -static void prepare_ep_xfer(uint8_t ep_id, uint16_t buf_offset, uint16_t total_bytes) +static void prepare_setup_packet(uint8_t rhport) +{ + if (_dcd_controller[rhport].max_speed == TUSB_SPEED_FULL ) + { + _dcd.ep[0][1].buffer_fs.offset = get_buf_offset(_dcd.setup_packet);; + }else + { + _dcd.ep[0][1].buffer_hs.offset = get_buf_offset(_dcd.setup_packet);; + } +} + +static void prepare_ep_xfer(uint8_t rhport, uint8_t ep_id, uint16_t buf_offset, uint16_t total_bytes) { uint16_t const nbytes = tu_min16(total_bytes, DMA_NBYTES_MAX); _dcd.dma[ep_id].nbytes = nbytes; - _dcd.ep[ep_id][0].buffer_offset = buf_offset; - _dcd.ep[ep_id][0].nbytes = nbytes; - _dcd.ep[ep_id][0].active = 1; + if (_dcd_controller[rhport].max_speed == TUSB_SPEED_FULL ) + { + _dcd.ep[ep_id][0].buffer_fs.offset = buf_offset; + _dcd.ep[ep_id][0].buffer_fs.nbytes = nbytes; + }else + { + _dcd.ep[ep_id][0].buffer_hs.offset = buf_offset; + _dcd.ep[ep_id][0].buffer_hs.nbytes = nbytes; + } + + _dcd.ep[ep_id][0].active = 1; } bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) @@ -330,7 +366,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to tu_memclr(&_dcd.dma[ep_id], sizeof(xfer_dma_t)); _dcd.dma[ep_id].total_bytes = total_bytes; - prepare_ep_xfer(ep_id, get_buf_offset(buffer), total_bytes); + prepare_ep_xfer(rhport, ep_id, get_buf_offset(buffer), total_bytes); return true; } @@ -348,7 +384,7 @@ static void bus_reset(uint8_t rhport) _dcd.ep[ep_id][0].disable = _dcd.ep[ep_id][1].disable = 1; } - _dcd.ep[0][1].buffer_offset = get_buf_offset(_dcd.setup_packet); + prepare_setup_packet(rhport); dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; @@ -372,16 +408,36 @@ static void process_xfer_isr(uint8_t rhport, uint32_t int_status) ep_cmd_sts_t * ep_cs = &_dcd.ep[ep_id][0]; xfer_dma_t* xfer_dma = &_dcd.dma[ep_id]; - xfer_dma->xferred_bytes += xfer_dma->nbytes - ep_cs->nbytes; + if ( ep_id == 0 || ep_id == 1) + { + // For control endpoint, we need to manually clear Active bit + ep_cs->active = 0; + } + + uint16_t buf_offset; + uint16_t buf_nbytes; + + if (_dcd_controller[rhport].max_speed == TUSB_SPEED_FULL) + { + buf_offset = ep_cs->buffer_fs.offset; + buf_nbytes = ep_cs->buffer_fs.nbytes; + }else + { + buf_offset = ep_cs->buffer_hs.offset; + buf_nbytes = ep_cs->buffer_hs.nbytes; + } + + xfer_dma->xferred_bytes += xfer_dma->nbytes - buf_nbytes; - if ( (ep_cs->nbytes == 0) && (xfer_dma->total_bytes > xfer_dma->xferred_bytes) ) + if ( (buf_nbytes == 0) && (xfer_dma->total_bytes > xfer_dma->xferred_bytes) ) { // There is more data to transfer // buff_offset has been already increased by hw to correct value for next transfer - prepare_ep_xfer(ep_id, ep_cs->buffer_offset, xfer_dma->total_bytes - xfer_dma->xferred_bytes); + prepare_ep_xfer(rhport, ep_id, buf_offset, xfer_dma->total_bytes - xfer_dma->xferred_bytes); } else { + // for detecting ZLP xfer_dma->total_bytes = xfer_dma->xferred_bytes; uint8_t const ep_addr = tu_edpt_addr(ep_id / 2, ep_id & 0x01); @@ -402,12 +458,15 @@ void dcd_int_handler(uint8_t rhport) uint32_t int_status = dcd_reg->INTSTAT & dcd_reg->INTEN; dcd_reg->INTSTAT = int_status; // Acknowledge handled interrupt + TU_LOG2_HEX(int_status); + if (int_status == 0) return; //------------- Device Status -------------// if ( int_status & INT_DEVICE_STATUS_MASK ) { dcd_reg->DEVCMDSTAT |= CMDSTAT_RESET_CHANGE_MASK | CMDSTAT_CONNECT_CHANGE_MASK | CMDSTAT_SUSPEND_CHANGE_MASK; + if ( cmd_stat & CMDSTAT_RESET_CHANGE_MASK) // bus reset { bus_reset(rhport); @@ -467,7 +526,7 @@ void dcd_int_handler(uint8_t rhport) dcd_event_setup_received(rhport, _dcd.setup_packet, true); // keep waiting for next setup - _dcd.ep[0][1].buffer_offset = get_buf_offset(_dcd.setup_packet); + prepare_setup_packet(rhport); // clear bit0 int_status = tu_bit_clear(int_status, 0); -- cgit v1.3.1 From a8e109cb3d2af7a54cc5694e1507f21127d36028 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 26 Apr 2021 17:14:20 +0700 Subject: clean up --- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index f3762257a..4a009bc07 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -194,19 +194,21 @@ typedef struct }dcd_controller_t; #ifdef INCLUDE_FSL_DEVICE_REGISTERS - static const dcd_controller_t _dcd_controller[] = - { - { .regs = (dcd_registers_t*) USB0_BASE , .max_speed = TUSB_SPEED_FULL, .irqnum = USB0_IRQn, .ep_pairs = FSL_FEATURE_USB_EP_NUM }, - #if defined(FSL_FEATURE_SOC_USBHSD_COUNT) && FSL_FEATURE_SOC_USBHSD_COUNT - { .regs = (dcd_registers_t*) USBHSD_BASE, .max_speed = TUSB_SPEED_HIGH, .irqnum = USB1_IRQn, .ep_pairs = FSL_FEATURE_USBHSD_EP_NUM } - #endif - }; + +static const dcd_controller_t _dcd_controller[] = +{ + { .regs = (dcd_registers_t*) USB0_BASE , .max_speed = TUSB_SPEED_FULL, .irqnum = USB0_IRQn, .ep_pairs = FSL_FEATURE_USB_EP_NUM }, + #if defined(FSL_FEATURE_SOC_USBHSD_COUNT) && FSL_FEATURE_SOC_USBHSD_COUNT + { .regs = (dcd_registers_t*) USBHSD_BASE, .max_speed = TUSB_SPEED_HIGH, .irqnum = USB1_IRQn, .ep_pairs = FSL_FEATURE_USBHSD_EP_NUM } + #endif +}; #else - static const dcd_controller_t _dcd_controller[] = - { - { .regs = (dcd_registers_t*) LPC_USB0_BASE, .max_speed = TUSB_SPEED_FULL, .irqnum = USB0_IRQn, .ep_pairs = 5 }, - }; + +static const dcd_controller_t _dcd_controller[] = +{ + { .regs = (dcd_registers_t*) LPC_USB0_BASE, .max_speed = TUSB_SPEED_FULL, .irqnum = USB0_IRQn, .ep_pairs = 5 }, +}; #endif @@ -458,8 +460,6 @@ void dcd_int_handler(uint8_t rhport) uint32_t int_status = dcd_reg->INTSTAT & dcd_reg->INTEN; dcd_reg->INTSTAT = int_status; // Acknowledge handled interrupt - TU_LOG2_HEX(int_status); - if (int_status == 0) return; //------------- Device Status -------------// -- cgit v1.3.1 From c26875e70d120f564f4e68c1dc79d9e7e3642b70 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 26 Apr 2021 17:42:49 +0700 Subject: add TUP_MCU_STRICT_ALIGN macro that manually pick bytes for lpc55 port1 that is m4 but cannot unaligned acces on usb ram --- src/class/msc/msc_device.c | 19 ++++---------- src/common/tusb_common.h | 63 ++++++++++++++++++++++++++++++++++++++-------- src/tusb_option.h | 11 ++++++++ 3 files changed, 69 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 194f4d3cb..539941935 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -77,28 +77,19 @@ static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc); static inline uint32_t rdwr10_get_lba(uint8_t const command[]) { - // read10 & write10 has the same format - scsi_write10_t* p_rdwr10 = (scsi_write10_t*) command; + // use offsetof to avoid pointer to the odd/unaligned address + uint32_t const lba = tu_unaligned_read32(command + offsetof(scsi_write10_t, lba)); - // copy first to prevent mis-aligned access - uint32_t lba; - // use offsetof to avoid pointer to the odd/misaligned address - memcpy(&lba, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, lba), 4); - - // lba is in Big Endian format + // lba is in Big Endian return tu_ntohl(lba); } static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) { - // read10 & write10 has the same format - scsi_write10_t* p_rdwr10 = (scsi_write10_t*) command; - - // copy first to prevent mis-aligned access - uint16_t block_count; // use offsetof to avoid pointer to the odd/misaligned address - memcpy(&block_count, (uint8_t*) p_rdwr10 + offsetof(scsi_write10_t, block_count), 2); + uint16_t const block_count = tu_unaligned_read16(command + offsetof(scsi_write10_t, block_count)); + // block count is in Big Endian return tu_ntohs(block_count); } diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 705ff867c..2cc12c6be 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -47,13 +47,13 @@ #define U16_TO_U8S_BE(u16) TU_U16_HIGH(u16), TU_U16_LOW(u16) #define U16_TO_U8S_LE(u16) TU_U16_LOW(u16), TU_U16_HIGH(u16) -#define U32_B1_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 24) & 0x000000ff)) // MSB -#define U32_B2_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 16) & 0x000000ff)) -#define U32_B3_U8(u32) ((uint8_t) ((((uint32_t) u32) >> 8) & 0x000000ff)) -#define U32_B4_U8(u32) ((uint8_t) (((uint32_t) u32) & 0x000000ff)) // LSB +#define TU_U32_BYTE3(u32) ((uint8_t) ((((uint32_t) u32) >> 24) & 0x000000ff)) // MSB +#define TU_U32_BYTE2(u32) ((uint8_t) ((((uint32_t) u32) >> 16) & 0x000000ff)) +#define TU_U32_BYTE1(u32) ((uint8_t) ((((uint32_t) u32) >> 8) & 0x000000ff)) +#define TU_U32_BYTE0(u32) ((uint8_t) (((uint32_t) u32) & 0x000000ff)) // LSB -#define U32_TO_U8S_BE(u32) U32_B1_U8(u32), U32_B2_U8(u32), U32_B3_U8(u32), U32_B4_U8(u32) -#define U32_TO_U8S_LE(u32) U32_B4_U8(u32), U32_B3_U8(u32), U32_B2_U8(u32), U32_B1_U8(u32) +#define U32_TO_U8S_BE(u32) TU_U32_BYTE3(u32), TU_U32_BYTE2(u32), TU_U32_BYTE1(u32), TU_U32_BYTE0(u32) +#define U32_TO_U8S_LE(u32) TU_U32_BYTE0(u32), TU_U32_BYTE1(u32), TU_U32_BYTE2(u32), TU_U32_BYTE3(u32) #define TU_BIT(n) (1U << (n)) @@ -81,9 +81,9 @@ #define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) //------------- Bytes -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) { - return ( ((uint32_t) b1) << 24) | ( ((uint32_t) b2) << 16) | ( ((uint32_t) b3) << 8) | b4; + return ( ((uint32_t) b3) << 24) | ( ((uint32_t) b2) << 16) | ( ((uint32_t) b1) << 8) | b0; } TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) @@ -91,8 +91,13 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) return (uint16_t) ((((uint16_t) high) << 8) | low); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t u16) { return (uint8_t) (((uint16_t) (u16 >> 8)) & 0x00ff); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t u16) { return (uint8_t) (u16 & 0x00ff); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte3(uint32_t u32) { return TU_U32_BYTE3(u32); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte2(uint32_t u32) { return TU_U32_BYTE2(u32); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte1(uint32_t u32) { return TU_U32_BYTE1(u32); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte0(uint32_t u32) { return TU_U32_BYTE0(u32); } + +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t u16) { return TU_U16_HIGH(u16); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t u16) { return TU_U16_LOW(u16); } //------------- Bits -------------// TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_set (uint32_t value, uint8_t pos) { return value | TU_BIT(pos); } @@ -141,6 +146,8 @@ static inline uint8_t tu_log2(uint32_t value) //------------- Unaligned Access -------------// #if TUP_ARCH_STRICT_ALIGN +// Rely on compiler to generate correct code for unaligned access + typedef struct { uint16_t val; } TU_ATTR_PACKED tu_unaligned_uint16_t; typedef struct { uint32_t val; } TU_ATTR_PACKED tu_unaligned_uint32_t; @@ -168,8 +175,44 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_ ua16->val = value; } +#elif TUP_MCU_STRICT_ALIGN + +// MCU such as LPC_IP3511 Highspeed cannot access unaligned memory on USB_RAM although it is ARM M4. +// We have to manually pick up bytes since tu_unaligned_uint32_t will still generate unaligned code +// NOTE: volatile cast to memory to prevent compiler to optimize and generate unaligned code +// TODO Big Endian may need minor changes +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem) +{ + volatile uint8_t const* buf8 = (uint8_t const*) mem; + return tu_u32(buf8[3], buf8[2], buf8[1], buf8[0]); +} + +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value) +{ + volatile uint8_t* buf8 = (uint8_t*) mem; + buf8[0] = tu_u32_byte0(value); + buf8[1] = tu_u32_byte1(value); + buf8[2] = tu_u32_byte2(value); + buf8[3] = tu_u32_byte3(value); +} + +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem) +{ + volatile uint8_t const* buf8 = (uint8_t const*) mem; + return tu_u16(buf8[1], buf8[0]); +} + +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value) +{ + volatile uint8_t* buf8 = (uint8_t*) mem; + buf8[0] = tu_u16_low(value); + buf8[1] = tu_u16_high(value); +} + + #else +// MCU that could access unaligned memory natively TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32 (const void* mem ) { return *((uint32_t*) mem); } TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16 (const void* mem ) { return *((uint16_t*) mem); } diff --git a/src/tusb_option.h b/src/tusb_option.h index 9fcc6c565..b59c7cb22 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -283,6 +283,7 @@ // TUP_ARCH_STRICT_ALIGN if arch cannot access unaligned memory + // ARMv7+ (M3-M7, M23-M33) can access unaligned memory #if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) #define TUP_ARCH_STRICT_ALIGN 0 @@ -290,6 +291,16 @@ #define TUP_ARCH_STRICT_ALIGN 1 #endif +// TUP_MCU_STRICT_ALIGN will overwrite TUP_ARCH_STRICT_ALIGN. +// In case TUP_MCU_STRICT_ALIGN = 1 and TUP_ARCH_STRICT_ALIGN =0, we will not reply on compiler +// to generate unaligned access code. +// LPC_IP3511 Highspeed cannot access unaligned memory on USB_RAM +#if TUD_OPT_HIGH_SPEED && (CFG_TUSB_MCU == OPT_MCU_LPC54XXX || CFG_TUSB_MCU == OPT_MCU_LPC55XX) + #define TUP_MCU_STRICT_ALIGN 1 +#else + #define TUP_MCU_STRICT_ALIGN 0 +#endif + //------------------------------------------------------------------ // Configuration Validation //------------------------------------------------------------------ -- cgit v1.3.1 From ba90a8cb793449d6562d209326ef40e00e3db983 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 26 Apr 2021 20:22:40 +0700 Subject: use correct NBYTES_MAX for full and high speed --- hw/bsp/lpc55/boards/lpcxpresso55s69/board.mk | 1 + src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 25 +++++++++++-------------- 2 files changed, 12 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/hw/bsp/lpc55/boards/lpcxpresso55s69/board.mk b/hw/bsp/lpc55/boards/lpcxpresso55s69/board.mk index 88a065d4c..8adf62df8 100644 --- a/hw/bsp/lpc55/boards/lpcxpresso55s69/board.mk +++ b/hw/bsp/lpc55/boards/lpcxpresso55s69/board.mk @@ -2,6 +2,7 @@ MCU_VARIANT = LPC55S69 MCU_CORE = LPC55S69_cm33_core0 CFLAGS += -DCPU_LPC55S69JBD100_cm33_core0 +PORT ?= 1 JLINK_DEVICE = LPC55S69 PYOCD_TARGET = LPC55S69 diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 4a009bc07..4392d1882 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -76,16 +76,10 @@ typedef struct { __I uint32_t EPTOGGLE; // Endpoint toggle register, offset: 0x34 } dcd_registers_t; -/* Although device controller are the same. Somehow only LPC134x can execute - * DMA with 1023 bytes for Bulk/Control. Others (11u, 51u, 54xxx) can only work - * with max 64 bytes - */ +// Max nbytes for each control/bulk/interrupt transfer enum { - #if CFG_TUSB_MCU == OPT_MCU_LPC13XX - DMA_NBYTES_MAX = 1023 - #else - DMA_NBYTES_MAX = 64 - #endif + NBYTES_CBI_FULLSPEED_MAX = 64, + NBYTES_CBI_HIGHSPEED_MAX = 32767 // can be up to all 15-bit, but only tested with 4096 }; enum { @@ -342,20 +336,23 @@ static void prepare_setup_packet(uint8_t rhport) static void prepare_ep_xfer(uint8_t rhport, uint8_t ep_id, uint16_t buf_offset, uint16_t total_bytes) { - uint16_t const nbytes = tu_min16(total_bytes, DMA_NBYTES_MAX); - - _dcd.dma[ep_id].nbytes = nbytes; + uint16_t nbytes; if (_dcd_controller[rhport].max_speed == TUSB_SPEED_FULL ) { + // TODO ISO FullSpeed can have up to 1023 bytes + nbytes = tu_min16(total_bytes, NBYTES_CBI_FULLSPEED_MAX); _dcd.ep[ep_id][0].buffer_fs.offset = buf_offset; - _dcd.ep[ep_id][0].buffer_fs.nbytes = nbytes; + _dcd.ep[ep_id][0].buffer_fs.nbytes = nbytes; }else { + nbytes = tu_min16(total_bytes, NBYTES_CBI_HIGHSPEED_MAX); _dcd.ep[ep_id][0].buffer_hs.offset = buf_offset; - _dcd.ep[ep_id][0].buffer_hs.nbytes = nbytes; + _dcd.ep[ep_id][0].buffer_hs.nbytes = nbytes; } + _dcd.dma[ep_id].nbytes = nbytes; + _dcd.ep[ep_id][0].active = 1; } -- cgit v1.3.1 From c9177246d25b8bd6972a947da4f6d5a39f86f7c6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 28 Apr 2021 12:31:24 +0700 Subject: temporarily fix include recusrive loop --- src/class/audio/audio_device.c | 4 ++-- src/class/audio/audio_device.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 25bf9e2d9..8615b2468 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -55,9 +55,9 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ -#include "audio_device.h" -#include "class/audio/audio.h" #include "device/usbd_pvt.h" +#include "audio_device.h" +//#include "common/tusb_fifo.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index c5f8967e4..b8e6ef9c0 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -33,7 +33,6 @@ #include "device/usbd.h" #include "audio.h" -#include "common/tusb_fifo.h" //--------------------------------------------------------------------+ // Class Driver Configuration -- cgit v1.3.1 From f830800d00520ed2a91d9095e77738f4558324b2 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Thu, 29 Apr 2021 16:04:18 -0400 Subject: Fix typo and clean up reset --- src/class/dfu/dfu_device.c | 44 ++++++-------------------------------------- src/class/dfu/dfu_device.h | 3 --- 2 files changed, 6 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 25588aabc..da9f189aa 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -140,7 +140,7 @@ static tu_lookup_table_t const _dfu_status_table = //--------------------------------------------------------------------+ void dfu_moded_init(void) { - _dfu_state_ctx.state = APP_DETACH; // After init, reset will occur. We want to be in APP_DETACH to move to DFU_IDLE + _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; @@ -150,39 +150,7 @@ void dfu_moded_init(void) void dfu_moded_reset(uint8_t rhport) { - if (_dfu_state_ctx.state == APP_DETACH) - { - _dfu_state_ctx.state = DFU_IDLE; - } else { - switch (_dfu_state_ctx.state) - { - case DFU_IDLE: - case DFU_DNLOAD_SYNC: - case DFU_DNBUSY: - case DFU_DNLOAD_IDLE: - case DFU_MANIFEST_SYNC: - case DFU_MANIFEST: - case DFU_MANIFEST_WAIT_RESET: - case DFU_UPLOAD_IDLE: - { - _dfu_state_ctx.state = (tud_dfu_firmware_valid_check_cb()) ? APP_IDLE : DFU_ERROR; - } - break; - - case DFU_ERROR: - default: - { - _dfu_state_ctx.state = APP_IDLE; - } - break; - } - } - - if(_dfu_state_ctx.state == APP_IDLE) - { - tud_dfu_reboot_to_rt_cb(); - } - + _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.blk_transfer_in_proc = false; dfu_debug_print_context(); @@ -276,8 +244,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) { TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); - uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)&_dfu_state_ctx.transfer_buf, wLength); - tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, retval); + uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; } @@ -305,13 +273,13 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * // but this mode would provide zero copy from the class driver to the application // setup for data phase - tud_control_xfer(rhport, request, &_dfu_state_ctx.transfer_buf, request->wLength); + tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, request->wLength); } static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { (void) rhport; - tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)&_dfu_state_ctx.transfer_buf, request->wLength); + tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 0c567ff45..aa8ee23d4 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -42,9 +42,6 @@ // Invoked when a reset is received to check if firmware is valid bool tud_dfu_firmware_valid_check_cb(void); -// Invoked when the device must reboot to dfu runtime mode -void tud_dfu_reboot_to_rt_cb(void); - // Invoked when a DFU_DNLOAD request is received // This callback takes the wBlockNum chunk of length length and provides it // to the application at the data pointer. This data is only valid for this -- cgit v1.3.1 From 8f72c97f7b0fa14badbc36497fba2c6d21cb59d0 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 12:59:12 +0200 Subject: Change read infos to pointer type --- src/class/audio/audio_device.c | 50 +++++++++++++----------- src/common/tusb_fifo.c | 88 +++++++++++++++++++++--------------------- src/common/tusb_fifo.h | 6 +-- 3 files changed, 76 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8615b2468..f19f8f6fe 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -650,23 +650,26 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u uint8_t * src; uint8_t * dst_end; - tu_fifo_linear_wr_info info; + tu_fifo_buffer_info_t info; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; - info = tu_fifo_get_linear_write_info(&audio->rx_supp_ff[cnt_ff], 0, nBytesPerFFToRead); + tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info, nBytesPerFFToRead); - dst_end = info.ptr_lin + info.len_lin; - src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); - - // Handle wrapped part of FIFO - if (info.len_wrap != 0) + if (info.len_lin != 0) { - dst_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_wrap, dst_end, src, n_ff_used); + src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; + dst_end = info.ptr_lin + info.len_lin; + src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); + + // Handle wrapped part of FIFO + if (info.len_wrap != 0) + { + dst_end = info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_wrap, dst_end, src, n_ff_used); + } + tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it @@ -976,25 +979,28 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi uint8_t * dst; uint8_t * src_end; - tu_fifo_linear_wr_info info; + tu_fifo_buffer_info_t info; for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - info = tu_fifo_get_linear_read_info(&audio->tx_supp_ff[cnt_ff], 0, nBytesPerFFToSend); - - src_end = info.ptr_lin + info.len_lin; - dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); + tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info, nBytesPerFFToSend); - // Handle wrapped part of FIFO - if (info.len_wrap != 0) + if (info.ptr_lin != 0) { - src_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used); - } + src_end = info.ptr_lin + info.len_lin; + dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); + // Handle wrapped part of FIFO + if (info.len_wrap != 0) + { + src_end = info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used); + } + + tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); + } } return nBytesPerFFToSend * n_ff_used; diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 75dae0906..1c4084882 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -883,7 +883,7 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) /******************************************************************************/ /*! - @brief Get linear read info + @brief Get read info Returns the length and pointer from which bytes can be read in a linear manner. This is of major interest for DMA transmissions. If returned length is zero the @@ -895,24 +895,18 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) wrapped part! @param[in] f Pointer to FIFO - @param[in] offset - Number of ITEMS to ignore before start writing - @param[out] **ptr - Pointer to start writing to - @param[in] n - Number of ITEMS to read from buffer - @return len - Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid + @param[out] *info + Pointer to struct which holds the desired infos */ /******************************************************************************/ -tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n) +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n) { // Operate on temporary values in case they change in between uint16_t w = f->wr_idx, r = f->rd_idx; uint16_t cnt = _tu_fifo_count(f, w, r); - // Check overflow and correct if required + // Check overflow and correct if required - may happen in case a DMA wrote too fast if (cnt > f->depth) { _ff_lock(f->mutex_rd); @@ -922,36 +916,40 @@ tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offse cnt = f->depth; } - tu_fifo_linear_wr_info info = {0,0,NULL,NULL}; - // Skip beginning of buffer - if (cnt == 0 || offset >= cnt) return info; + if (cnt == 0) + { + info->len_lin = 0; + info->len_wrap = 0; + info->ptr_lin = NULL; + info->ptr_wrap = NULL; + return; + } - // Check if we can read something at and after offset - if too less is available we read what remains - cnt -= offset; if (cnt < n) n = cnt; // Get relative pointers - w = get_relative_pointer(f, w, 0); - r = get_relative_pointer(f, r, offset); + w = get_relative_pointer(f, w,0); + r = get_relative_pointer(f, r,0); // Copy pointer to buffer to start reading from - info.ptr_lin = &f->buffer[r]; - info.ptr_wrap = f->buffer; + info->ptr_lin = &f->buffer[r]; // Check if there is a wrap around necessary if (w > r) { // Non wrapping case - info.len_lin = tu_min16(n, w - r); // Limit to required length - info.len_wrap = 0; + info->len_lin = tu_min16(n, w - r); // Limit to required length + info->len_wrap = 0; + info->ptr_wrap = NULL; } else { - info.len_lin = tu_min16(n, f->depth - r); // Also the case if FIFO was full - info.len_wrap = n-info.len_lin; // n was already limited to what is available + info->len_lin = tu_min16(n, f->depth - r); // Also the case if FIFO was full + info->len_wrap = n-info->len_lin; + info->ptr_wrap = f->buffer; } - return info; + return; } /******************************************************************************/ @@ -967,22 +965,18 @@ tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offse time to get a pointer to the wrapped part! @param[in] f Pointer to FIFO - @param[in] offset - Number of ITEMS to ignore before start writing - @param[out] **ptr - Pointer to start writing to + @param[out] *info + Pointer to struct which holds the desired infos @param[in] n Number of ITEMS to write into buffer - @return len - Length of linear part IN ITEMS, if zero corresponding pointer ptr is invalid */ /******************************************************************************/ -tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n) +void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n) { uint16_t w = f->wr_idx, r = f->rd_idx; uint16_t free = _tu_fifo_remaining(f, w, r); - tu_fifo_linear_wr_info info = {0,0,NULL,NULL}; + // We need n here because we must enforce the read and write pointers to be not more separated than 2*depth! if (!f->overwritable) { @@ -1002,27 +996,35 @@ tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offs } // Check if there is room to write to - if (free == 0 || offset >= free) return info; + if (free == 0) + { + info->len_lin = 0; + info->len_wrap = 0; + info->ptr_lin = NULL; + info->ptr_wrap = NULL; + return; + } // Get relative pointers - w = get_relative_pointer(f, w, offset); - r = get_relative_pointer(f, r, 0); + w = get_relative_pointer(f, w,0); + r = get_relative_pointer(f, r,0); // Copy pointer to buffer to start writing to - info.ptr_lin = &f->buffer[w]; - info.ptr_wrap = f->buffer; // Always start of buffer + info->ptr_lin = &f->buffer[w]; if (w < r) { // Non wrapping case - info.len_lin = tu_min16(n, r-w); // Limit to required length - info.len_wrap = 0; + info->len_lin = tu_min16(n, r-w); // Limit to required length + info->len_wrap = 0; + info->ptr_wrap = NULL; } else { - info.len_lin = tu_min16(n, f->depth - w); // Limit to required length - info.len_wrap = n-info.len_lin; // Remaining length - n already was limited to free or FIFO depth + info->len_lin = tu_min16(n, f->depth - w); // Limit to required length + info->len_wrap = n-info->len_lin; // Remaining length - n already was limited to free or FIFO depth + info->ptr_wrap = f->buffer; // Always start of buffer } - return info; + return; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index c23f25723..797a5e728 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -86,7 +86,7 @@ typedef struct uint16_t len_wrap ; ///< wrapped length in item size void * ptr_lin ; ///< linear part start pointer void * ptr_wrap ; ///< wrapped part start pointer -} tu_fifo_linear_wr_info; +} tu_fifo_buffer_info_t; #define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ { \ @@ -144,8 +144,8 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation // TODO - update comments -tu_fifo_linear_wr_info tu_fifo_get_linear_read_info(tu_fifo_t *f, uint16_t offset, uint16_t n); -tu_fifo_linear_wr_info tu_fifo_get_linear_write_info(tu_fifo_t *f, uint16_t offset, uint16_t n); +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); +void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { -- cgit v1.3.1 From 5f268608d7c15551adddaf20f4b96c0ac1df4633 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 13:39:55 +0200 Subject: Remove offset feature from fifo.c --- src/common/tusb_fifo.c | 67 ++++++++++++++++++++++---------------------------- src/common/tusb_fifo.h | 6 ++--- 2 files changed, 33 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 1c4084882..323bb6270 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -348,9 +348,9 @@ static uint16_t backward_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) } // get relative from absolute pointer -static uint16_t get_relative_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) +static uint16_t get_relative_pointer(tu_fifo_t* f, uint16_t p) { - return _ff_mod(advance_pointer(f, p, offset), f->depth); + return _ff_mod(p, f->depth); } // Works on local copies of w and r - return only the difference and as such can be used to determine an overflow @@ -396,7 +396,7 @@ static inline void _tu_fifo_correct_read_pointer(tu_fifo_t* f, uint16_t wAbs) // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -static bool _tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t wAbs, uint16_t rAbs) +static bool _tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint16_t rAbs) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); @@ -408,9 +408,9 @@ static bool _tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer, uin } // Skip beginning of buffer - if (cnt == 0 || offset >= cnt) return false; + if (cnt == 0) return false; - uint16_t rRel = get_relative_pointer(f, rAbs, offset); + uint16_t rRel = get_relative_pointer(f, rAbs); // Peek data _ff_pull(f, p_buffer, rRel); @@ -420,7 +420,7 @@ static bool _tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer, uin // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs, tu_fifo_copy_mode_t copy_mode) +static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs, tu_fifo_copy_mode_t copy_mode) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); @@ -433,13 +433,12 @@ static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffe } // Skip beginning of buffer - if (cnt == 0 || offset >= cnt) return 0; + if (cnt == 0) return 0; // Check if we can read something at and after offset - if too less is available we read what remains - cnt -= offset; if (cnt < n) n = cnt; - uint16_t rRel = get_relative_pointer(f, rAbs, offset); + uint16_t rRel = get_relative_pointer(f, rAbs); // Peek data _ff_pull_n(f, p_buffer, n, rRel, copy_mode); @@ -479,7 +478,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu w = r; } - uint16_t wRel = get_relative_pointer(f, w, 0); + uint16_t wRel = get_relative_pointer(f, w); // Write data _ff_push_n(f, buf8, n, wRel, copy_mode); @@ -497,7 +496,7 @@ static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo _ff_lock(f->mutex_rd); // Peek the data - n = _tu_fifo_peek_at_n(f, 0, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + n = _tu_fifo_peek_at_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable // Advance read pointer f->rd_idx = advance_pointer(f, f->rd_idx, n); @@ -635,7 +634,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) _ff_lock(f->mutex_rd); // Peek the data - bool ret = _tu_fifo_peek_at(f, 0, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + bool ret = _tu_fifo_peek_at(f, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable // Advance pointer f->rd_idx = advance_pointer(f, f->rd_idx, ret); @@ -685,10 +684,10 @@ uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint1 @returns TRUE if the queue is not empty */ /******************************************************************************/ -bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) +bool tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer) { _ff_lock(f->mutex_rd); - bool ret = _tu_fifo_peek_at(f, offset, p_buffer, f->wr_idx, f->rd_idx); + bool ret = _tu_fifo_peek_at(f, p_buffer, f->wr_idx, f->rd_idx); _ff_unlock(f->mutex_rd); return ret; } @@ -700,8 +699,6 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) @param[in] f Pointer to the FIFO buffer to manipulate - @param[in] offset - Position to read from in the FIFO buffer with respect to read pointer @param[in] p_buffer Pointer to the place holder for data read from the buffer @param[in] n @@ -710,10 +707,10 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t offset, void * p_buffer) @returns Number of bytes written to p_buffer */ /******************************************************************************/ -uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, uint16_t offset, void * p_buffer, uint16_t n) +uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, void * p_buffer, uint16_t n) { _ff_lock(f->mutex_rd); - bool ret = _tu_fifo_peek_at_n(f, offset, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); + bool ret = _tu_fifo_peek_at_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); _ff_unlock(f->mutex_rd); return ret; } @@ -742,7 +739,7 @@ bool tu_fifo_write(tu_fifo_t* f, const void * data) if ( _tu_fifo_full(f, w, f->rd_idx) && !f->overwritable ) return false; - uint16_t wRel = get_relative_pointer(f, w, 0); + uint16_t wRel = get_relative_pointer(f, w); // Write data _ff_push(f, data, wRel); @@ -929,8 +926,8 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n if (cnt < n) n = cnt; // Get relative pointers - w = get_relative_pointer(f, w,0); - r = get_relative_pointer(f, r,0); + w = get_relative_pointer(f, w); + r = get_relative_pointer(f, r); // Copy pointer to buffer to start reading from info->ptr_lin = &f->buffer[r]; @@ -976,8 +973,17 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t uint16_t w = f->wr_idx, r = f->rd_idx; uint16_t free = _tu_fifo_remaining(f, w, r); - // We need n here because we must enforce the read and write pointers to be not more separated than 2*depth! + if (free == 0 || n > 2*f->depth) // If overwrite is allowed it must be less than or equal to 2 x buffer length, otherwise the overflow can not be resolved by the read functions + { + info->len_lin = 0; + info->len_wrap = 0; + info->ptr_lin = NULL; + info->ptr_wrap = NULL; + return; + } + + // We need n here because we must enforce the read and write pointers to be not more separated than 2*depth! if (!f->overwritable) { // Not overwritable limit up to full @@ -985,9 +991,6 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t } else if (n >= f->depth) { - // If overwrite is allowed it must be less than or equal to 2 x buffer length, otherwise the overflow can not be resolved by the read functions - if(n > 2*f->depth) return info; - n = f->depth; // We start writing at the read pointer's position since we fill the complete // buffer and we do not want to modify the read pointer within a write function! @@ -995,19 +998,9 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t w = r; } - // Check if there is room to write to - if (free == 0) - { - info->len_lin = 0; - info->len_wrap = 0; - info->ptr_lin = NULL; - info->ptr_wrap = NULL; - return; - } - // Get relative pointers - w = get_relative_pointer(f, w,0); - r = get_relative_pointer(f, r,0); + w = get_relative_pointer(f, w); + r = get_relative_pointer(f, r); // Copy pointer to buffer to start writing to info->ptr_lin = &f->buffer[w]; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 797a5e728..fffe87bce 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -123,8 +123,8 @@ bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); uint16_t tu_fifo_read_n_const_addr_full_words (tu_fifo_t* f, void * buffer, uint16_t n); -bool tu_fifo_peek_at (tu_fifo_t* f, uint16_t pos, void * p_buffer); -uint16_t tu_fifo_peek_at_n (tu_fifo_t* f, uint16_t pos, void * p_buffer, uint16_t n); +bool tu_fifo_peek_at (tu_fifo_t* f, void * p_buffer); +uint16_t tu_fifo_peek_at_n (tu_fifo_t* f, void * p_buffer, uint16_t n); uint16_t tu_fifo_count (tu_fifo_t* f); bool tu_fifo_empty (tu_fifo_t* f); @@ -149,7 +149,7 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { - return tu_fifo_peek_at(f, 0, p_buffer); + return tu_fifo_peek_at(f, p_buffer); } static inline uint16_t tu_fifo_depth(tu_fifo_t* f) -- cgit v1.3.1 From de933c45bc627f930e1951ee606aa76784af47cf Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 14:56:14 +0200 Subject: Remove all remainings with peek_at --- src/class/cdc/cdc_device.c | 4 ++-- src/class/cdc/cdc_device.h | 2 +- src/class/vendor/vendor_device.c | 4 ++-- src/class/vendor/vendor_device.h | 2 +- src/common/tusb_fifo.c | 16 ++++++++-------- src/common/tusb_fifo.h | 9 ++------- test/test/test_fifo.c | 3 --- 7 files changed, 16 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 0a7691916..f5853fddb 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -146,9 +146,9 @@ uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) return num_read; } -bool tud_cdc_n_peek(uint8_t itf, int pos, uint8_t* chr) +bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) { - return tu_fifo_peek_at(&_cdcd_itf[itf].rx_ff, pos, chr); + return tu_fifo_peek(&_cdcd_itf[itf].rx_ff, chr); } void tud_cdc_n_read_flush (uint8_t itf) diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 0885922c6..2566798c5 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -83,7 +83,7 @@ int32_t tud_cdc_n_read_char (uint8_t itf); void tud_cdc_n_read_flush (uint8_t itf); // Get a byte from FIFO at the specified position without removing it -bool tud_cdc_n_peek (uint8_t itf, int pos, uint8_t* u8); +bool tud_cdc_n_peek (uint8_t itf, uint8_t* u8); // Write bytes to TX FIFO, data may remain in the FIFO for a while uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 9b0a3c25f..ef1f5d2fe 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -72,9 +72,9 @@ uint32_t tud_vendor_n_available (uint8_t itf) return tu_fifo_count(&_vendord_itf[itf].rx_ff); } -bool tud_vendor_n_peek(uint8_t itf, int pos, uint8_t* u8) +bool tud_vendor_n_peek(uint8_t itf, uint8_t* u8) { - return tu_fifo_peek_at(&_vendord_itf[itf].rx_ff, pos, u8); + return tu_fifo_peek(&_vendord_itf[itf].rx_ff, u8); } //--------------------------------------------------------------------+ diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index a4235bfce..ffa2e3b70 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -45,7 +45,7 @@ bool tud_vendor_n_mounted (uint8_t itf); uint32_t tud_vendor_n_available (uint8_t itf); uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize); -bool tud_vendor_n_peek (uint8_t itf, int pos, uint8_t* u8); +bool tud_vendor_n_peek (uint8_t itf, uint8_t* u8); uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); uint32_t tud_vendor_n_write_available (uint8_t itf); diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 323bb6270..92e6bd02c 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -396,7 +396,7 @@ static inline void _tu_fifo_correct_read_pointer(tu_fifo_t* f, uint16_t wAbs) // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -static bool _tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint16_t rAbs) +static bool _tu_fifo_peek(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint16_t rAbs) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); @@ -420,7 +420,7 @@ static bool _tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer, uint16_t wAbs, uint1 // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -static uint16_t _tu_fifo_peek_at_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs, tu_fifo_copy_mode_t copy_mode) +static uint16_t _tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t wAbs, uint16_t rAbs, tu_fifo_copy_mode_t copy_mode) { uint16_t cnt = _tu_fifo_count(f, wAbs, rAbs); @@ -496,7 +496,7 @@ static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo _ff_lock(f->mutex_rd); // Peek the data - n = _tu_fifo_peek_at_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + n = _tu_fifo_peek_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable // Advance read pointer f->rd_idx = advance_pointer(f, f->rd_idx, n); @@ -634,7 +634,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) _ff_lock(f->mutex_rd); // Peek the data - bool ret = _tu_fifo_peek_at(f, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + bool ret = _tu_fifo_peek(f, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable // Advance pointer f->rd_idx = advance_pointer(f, f->rd_idx, ret); @@ -684,10 +684,10 @@ uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint1 @returns TRUE if the queue is not empty */ /******************************************************************************/ -bool tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer) +bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { _ff_lock(f->mutex_rd); - bool ret = _tu_fifo_peek_at(f, p_buffer, f->wr_idx, f->rd_idx); + bool ret = _tu_fifo_peek(f, p_buffer, f->wr_idx, f->rd_idx); _ff_unlock(f->mutex_rd); return ret; } @@ -707,10 +707,10 @@ bool tu_fifo_peek_at(tu_fifo_t* f, void * p_buffer) @returns Number of bytes written to p_buffer */ /******************************************************************************/ -uint16_t tu_fifo_peek_at_n(tu_fifo_t* f, void * p_buffer, uint16_t n) +uint16_t tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n) { _ff_lock(f->mutex_rd); - bool ret = _tu_fifo_peek_at_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); + bool ret = _tu_fifo_peek_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); _ff_unlock(f->mutex_rd); return ret; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index fffe87bce..36f0d9302 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -123,8 +123,8 @@ bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t n); uint16_t tu_fifo_read_n_const_addr_full_words (tu_fifo_t* f, void * buffer, uint16_t n); -bool tu_fifo_peek_at (tu_fifo_t* f, void * p_buffer); -uint16_t tu_fifo_peek_at_n (tu_fifo_t* f, void * p_buffer, uint16_t n); +bool tu_fifo_peek (tu_fifo_t* f, void * p_buffer); +uint16_t tu_fifo_peek_n (tu_fifo_t* f, void * p_buffer, uint16_t n); uint16_t tu_fifo_count (tu_fifo_t* f); bool tu_fifo_empty (tu_fifo_t* f); @@ -147,11 +147,6 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); -static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) -{ - return tu_fifo_peek_at(f, p_buffer); -} - static inline uint16_t tu_fifo_depth(tu_fifo_t* f) { return f->depth; diff --git a/test/test/test_fifo.c b/test/test/test_fifo.c index b6c22f569..5ea8de512 100644 --- a/test/test/test_fifo.c +++ b/test/test/test_fifo.c @@ -150,9 +150,6 @@ void test_peek(void) tu_fifo_peek(&ff, &temp); TEST_ASSERT_EQUAL(10, temp); - - tu_fifo_peek_at(&ff, 1, &temp); - TEST_ASSERT_EQUAL(20, temp); } void test_empty(void) -- cgit v1.3.1 From 14e2c004cd9db7d386beb2b91804f8e4dfea55f1 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 15:08:14 +0200 Subject: Remove variable n in tu_fifo_get_read_info() --- src/class/audio/audio_device.c | 10 ++++++++-- src/common/tusb_fifo.c | 10 ++++------ src/common/tusb_fifo.h | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index f19f8f6fe..fc5402834 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -985,13 +985,19 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi { dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; - tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info, nBytesPerFFToSend); + tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info); - if (info.ptr_lin != 0) + // Limit up to desired length + info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); + + if (info.len_lin != 0) { src_end = info.ptr_lin + info.len_lin; dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); + // Limit up to desired length + info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap); + // Handle wrapped part of FIFO if (info.len_wrap != 0) { diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 92e6bd02c..306b68653 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -896,7 +896,7 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) Pointer to struct which holds the desired infos */ /******************************************************************************/ -void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n) +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) { // Operate on temporary values in case they change in between uint16_t w = f->wr_idx, r = f->rd_idx; @@ -923,8 +923,6 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n return; } - if (cnt < n) n = cnt; - // Get relative pointers w = get_relative_pointer(f, w); r = get_relative_pointer(f, r); @@ -935,14 +933,14 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n // Check if there is a wrap around necessary if (w > r) { // Non wrapping case - info->len_lin = tu_min16(n, w - r); // Limit to required length + info->len_lin = cnt; info->len_wrap = 0; info->ptr_wrap = NULL; } else { - info->len_lin = tu_min16(n, f->depth - r); // Also the case if FIFO was full - info->len_wrap = n-info->len_lin; + info->len_lin = f->depth - r; // Also the case if FIFO was full + info->len_wrap = cnt - info->len_lin; info->ptr_wrap = f->buffer; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 36f0d9302..c6bcdaec5 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -144,7 +144,7 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation // TODO - update comments -void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); static inline uint16_t tu_fifo_depth(tu_fifo_t* f) -- cgit v1.3.1 From 5f88def9c9fd7e17b8765fda7dceea051a1faa85 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 15:14:27 +0200 Subject: Comment cleanup --- src/common/tusb_fifo.c | 14 +++++--------- src/common/tusb_fifo.h | 3 --- 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 306b68653..c80bb1497 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -884,12 +884,9 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) Returns the length and pointer from which bytes can be read in a linear manner. This is of major interest for DMA transmissions. If returned length is zero the - corresponding pointer is invalid. The returned length is limited to the number - of ITEMS n which the user wants to write into the buffer. - The write pointer does NOT get advanced, use tu_fifo_advance_read_pointer() to - do so! If the length returned is less than n i.e. lenoverwritable) { diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index c6bcdaec5..7bc6b60b9 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -140,9 +140,6 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies to handle a possible wrapping part // This functions deliver a pointer to start reading/writing from/to and a valid linear length along which no wrap occurs. -// In case not all of your data is available within one read/write, update the read/write pointer by -// tu_fifo_advance_read_pointer()/tu_fifo_advance_write_pointer and conduct a second read/write operation -// TODO - update comments void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); -- cgit v1.3.1 From 54f332fae095c1bc15d631fd3b5ef79f8a707578 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 15:42:27 +0200 Subject: Fix cdc peeks() --- src/class/cdc/cdc_device.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 2566798c5..614bbf5dc 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -117,7 +117,7 @@ static inline uint32_t tud_cdc_available (void); static inline int32_t tud_cdc_read_char (void); static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize); static inline void tud_cdc_read_flush (void); -static inline bool tud_cdc_peek (int pos, uint8_t* u8); +static inline bool tud_cdc_peek (uint8_t* u8); static inline uint32_t tud_cdc_write_char (char ch); static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize); @@ -207,9 +207,9 @@ static inline void tud_cdc_read_flush (void) tud_cdc_n_read_flush(0); } -static inline bool tud_cdc_peek (int pos, uint8_t* u8) +static inline bool tud_cdc_peek (uint8_t* u8) { - return tud_cdc_n_peek(0, pos, u8); + return tud_cdc_n_peek(u8); } static inline uint32_t tud_cdc_write_char (char ch) -- cgit v1.3.1 From 6acfa14fec1805b6f875f4bdbe00360065e72731 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 17:23:34 +0200 Subject: Fix bug in cdc_peek --- src/class/cdc/cdc_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 614bbf5dc..986585c5b 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -209,7 +209,7 @@ static inline void tud_cdc_read_flush (void) static inline bool tud_cdc_peek (uint8_t* u8) { - return tud_cdc_n_peek(u8); + return tud_cdc_n_peek(0, u8); } static inline uint32_t tud_cdc_write_char (char ch) -- cgit v1.3.1 From 5add664874f4855491e28c3a869105eb25c5f4d7 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 30 Apr 2021 17:37:14 +0200 Subject: Remove n from tu_fifo_get_write_info() and fix bug in vendor class --- src/class/audio/audio_device.c | 8 ++++---- src/class/vendor/vendor_device.h | 6 +++--- src/common/tusb_fifo.c | 33 ++++++++------------------------- src/common/tusb_fifo.h | 2 +- 4 files changed, 16 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index fc5402834..76ebc8aba 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -654,15 +654,17 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info, nBytesPerFFToRead); + tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info); if (info.len_lin != 0) { + info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin); src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; dst_end = info.ptr_lin + info.len_lin; src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); // Handle wrapped part of FIFO + info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap); if (info.len_wrap != 0) { dst_end = info.ptr_wrap + info.len_wrap; @@ -987,11 +989,9 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info); - // Limit up to desired length - info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); - if (info.len_lin != 0) { + info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length src_end = info.ptr_lin + info.len_lin; dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index ffa2e3b70..2c3d79a3d 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -59,7 +59,7 @@ uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str); static inline bool tud_vendor_mounted (void); static inline uint32_t tud_vendor_available (void); static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize); -static inline bool tud_vendor_peek (int pos, uint8_t* u8); +static inline bool tud_vendor_peek (uint8_t* u8); static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize); static inline uint32_t tud_vendor_write_str (char const* str); static inline uint32_t tud_vendor_write_available (void); @@ -95,9 +95,9 @@ static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize) return tud_vendor_n_read(0, buffer, bufsize); } -static inline bool tud_vendor_peek (int pos, uint8_t* u8) +static inline bool tud_vendor_peek (uint8_t* u8) { - return tud_vendor_n_peek(0, pos, u8); + return tud_vendor_n_peek(0, u8); } static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize) diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index c80bb1497..a386273f0 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -950,11 +950,9 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) Returns the length and pointer to which bytes can be written into FIFO in a linear manner. This is of major interest for DMA transmissions not using circular mode. If a returned length is zero the - corresponding pointer is invalid. The returned length is limited to the number of BYTES n which the user - wants to write into the buffer. - The write pointer does NOT get advanced, use tu_fifo_advance_write_pointer() to do so! If the length - returned is less than n i.e. lenwr_idx, r = f->rd_idx; uint16_t free = _tu_fifo_remaining(f, w, r); - if (free == 0 || n > 2*f->depth) // If overwrite is allowed it must be less than or equal to 2 x buffer length, otherwise the overflow can not be resolved by the read functions + if (free == 0) { info->len_lin = 0; info->len_wrap = 0; @@ -977,21 +975,6 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t return; } - // We need n here because we must enforce the read and write pointers to be not more separated than 2*depth! - if (!f->overwritable) - { - // Not overwritable limit up to full - n = tu_min16(n, free); - } - else if (n >= f->depth) - { - n = f->depth; - // We start writing at the read pointer's position since we fill the complete - // buffer and we do not want to modify the read pointer within a write function! - // This would end up in a race condition with read functions! - w = r; - } - // Get relative pointers w = get_relative_pointer(f, w); r = get_relative_pointer(f, r); @@ -1002,14 +985,14 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t if (w < r) { // Non wrapping case - info->len_lin = tu_min16(n, r-w); // Limit to required length + info->len_lin = r-w; // Limit to required length info->len_wrap = 0; info->ptr_wrap = NULL; } else { - info->len_lin = tu_min16(n, f->depth - w); // Limit to required length - info->len_wrap = n-info->len_lin; // Remaining length - n already was limited to free or FIFO depth + info->len_lin = f->depth - w; + info->len_wrap = free - info->len_lin; // Remaining length - n already was limited to free or FIFO depth info->ptr_wrap = f->buffer; // Always start of buffer } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 7bc6b60b9..f8cc282d3 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -142,7 +142,7 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // This functions deliver a pointer to start reading/writing from/to and a valid linear length along which no wrap occurs. void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); -void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info, uint16_t n); +void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); static inline uint16_t tu_fifo_depth(tu_fifo_t* f) { -- cgit v1.3.1 From 18c35bb89e74c3b3455ca7e7cd52a9a3cb1f2d4e Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 2 May 2021 15:01:28 +0700 Subject: some text fomarting, update unit test to test get buffer info for fifo --- src/common/tusb_fifo.c | 42 ++++++------ src/common/tusb_fifo.h | 45 ++++++------- test/test/test_fifo.c | 176 +++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 193 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index a386273f0..81e11eb01 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -57,7 +57,8 @@ static inline void _ff_unlock(tu_fifo_mutex_t mutex) #endif /** \enum tu_fifo_copy_mode_t - * \brief Write modes intended to allow special read and write functions to be able to copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others + * \brief Write modes intended to allow special read and write functions to be able to + * copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others */ typedef enum { @@ -77,7 +78,10 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si f->item_size = item_size; f->overwritable = overwritable; - f->max_pointer_idx = 2*depth - 1; // Limit index space to 2*depth - this allows for a fast "modulo" calculation but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable only if overflow happens once (important for unsupervised DMA applications) + // Limit index space to 2*depth - this allows for a fast "modulo" calculation + // but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable + // only if overflow happens once (important for unsupervised DMA applications) + f->max_pointer_idx = 2*depth - 1; f->non_used_index_space = UINT16_MAX - f->max_pointer_idx; f->rd_idx = f->wr_idx = 0; @@ -319,7 +323,8 @@ static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t rel, tu static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) { // We limit the index space of p such that a correct wrap around happens - // Check for a wrap around or if we are in unused index space - This has to be checked first!! We are exploiting the wrap around to the correct index + // Check for a wrap around or if we are in unused index space - This has to be checked first!! + // We are exploiting the wrap around to the correct index if ((p > p + offset) || (p + offset > f->max_pointer_idx)) { p = (p + offset) + f->non_used_index_space; @@ -335,7 +340,8 @@ static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) static uint16_t backward_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) { // We limit the index space of p such that a correct wrap around happens - // Check for a wrap around or if we are in unused index space - This has to be checked first!! We are exploiting the wrap around to the correct index + // Check for a wrap around or if we are in unused index space - This has to be checked first!! + // We are exploiting the wrap around to the correct index if ((p < p - offset) || (p - offset > f->max_pointer_idx)) { p = (p - offset) - f->non_used_index_space; @@ -496,7 +502,8 @@ static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo _ff_lock(f->mutex_rd); // Peek the data - n = _tu_fifo_peek_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + // f->rd_idx might get modified in case of an overflow so we can not use a local variable + n = _tu_fifo_peek_n(f, buffer, n, f->wr_idx, f->rd_idx, copy_mode); // Advance read pointer f->rd_idx = advance_pointer(f, f->rd_idx, n); @@ -634,7 +641,8 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) _ff_lock(f->mutex_rd); // Peek the data - bool ret = _tu_fifo_peek(f, buffer, f->wr_idx, f->rd_idx); // f->rd_idx might get modified in case of an overflow so we can not use a local variable + // f->rd_idx might get modified in case of an overflow so we can not use a local variable + bool ret = _tu_fifo_peek(f, buffer, f->wr_idx, f->rd_idx); // Advance pointer f->rd_idx = advance_pointer(f, f->rd_idx, ret); @@ -910,12 +918,12 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) cnt = f->depth; } - // Skip beginning of buffer + // Check if fifo is empty if (cnt == 0) { - info->len_lin = 0; + info->len_lin = 0; info->len_wrap = 0; - info->ptr_lin = NULL; + info->ptr_lin = NULL; info->ptr_wrap = NULL; return; } @@ -930,18 +938,16 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) // Check if there is a wrap around necessary if (w > r) { // Non wrapping case - info->len_lin = cnt; + info->len_lin = cnt; info->len_wrap = 0; info->ptr_wrap = NULL; } else { - info->len_lin = f->depth - r; // Also the case if FIFO was full + info->len_lin = f->depth - r; // Also the case if FIFO was full info->len_wrap = cnt - info->len_lin; info->ptr_wrap = f->buffer; } - - return; } /******************************************************************************/ @@ -957,8 +963,6 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) Pointer to FIFO @param[out] *info Pointer to struct which holds the desired infos - @param[in] n - Number of ITEMS to write into buffer */ /******************************************************************************/ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) @@ -985,16 +989,14 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) if (w < r) { // Non wrapping case - info->len_lin = r-w; // Limit to required length + info->len_lin = r-w; info->len_wrap = 0; info->ptr_wrap = NULL; } else { info->len_lin = f->depth - w; - info->len_wrap = free - info->len_lin; // Remaining length - n already was limited to free or FIFO depth - info->ptr_wrap = f->buffer; // Always start of buffer + info->len_wrap = free - info->len_lin; // Remaining length - n already was limited to free or FIFO depth + info->ptr_wrap = f->buffer; // Always start of buffer } - - return; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index f8cc282d3..8d73911f0 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -25,10 +25,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup Group_Common - * \defgroup group_fifo fifo - * @{ */ - #ifndef _TUSB_FIFO_H_ #define _TUSB_FIFO_H_ @@ -62,16 +58,16 @@ extern "C" { */ typedef struct { - uint8_t* buffer ; ///< buffer pointer - uint16_t depth ; ///< max items - uint16_t item_size ; ///< size of each item - bool overwritable ; + uint8_t* buffer ; ///< buffer pointer + uint16_t depth ; ///< max items + uint16_t item_size ; ///< size of each item + bool overwritable ; - uint16_t non_used_index_space ; ///< required for non-power-of-two buffer length - uint16_t max_pointer_idx ; ///< maximum absolute pointer index + uint16_t non_used_index_space ; ///< required for non-power-of-two buffer length + uint16_t max_pointer_idx ; ///< maximum absolute pointer index - volatile uint16_t wr_idx ; ///< write pointer - volatile uint16_t rd_idx ; ///< read pointer + volatile uint16_t wr_idx ; ///< write pointer + volatile uint16_t rd_idx ; ///< read pointer #if CFG_FIFO_MUTEX tu_fifo_mutex_t mutex_wr; @@ -82,10 +78,10 @@ typedef struct typedef struct { - uint16_t len_lin ; ///< linear length in item size - uint16_t len_wrap ; ///< wrapped length in item size - void * ptr_lin ; ///< linear part start pointer - void * ptr_wrap ; ///< wrapped part start pointer + uint16_t len_lin ; ///< linear length in item size + uint16_t len_wrap ; ///< wrapped length in item size + void * ptr_lin ; ///< linear part start pointer + void * ptr_wrap ; ///< wrapped part start pointer } tu_fifo_buffer_info_t; #define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ @@ -133,21 +129,22 @@ uint16_t tu_fifo_remaining (tu_fifo_t* f); bool tu_fifo_overflowed (tu_fifo_t* f); void tu_fifo_correct_read_pointer (tu_fifo_t* f); +static inline uint16_t tu_fifo_depth(tu_fifo_t* f) +{ + return f->depth; +} + // Pointer modifications intended to be used in combinations with DMAs. // USE WITH CARE - NO SAFTY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED! void tu_fifo_advance_write_pointer (tu_fifo_t *f, uint16_t n); void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); -// If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies to handle a possible wrapping part -// This functions deliver a pointer to start reading/writing from/to and a valid linear length along which no wrap occurs. - -void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); +// If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies +// to handle a possible wrapping part. These functions deliver a pointer to start +// reading/writing from/to and a valid linear length along which no wrap occurs. +void tu_fifo_get_read_info (tu_fifo_t *f, tu_fifo_buffer_info_t *info); void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); -static inline uint16_t tu_fifo_depth(tu_fifo_t* f) -{ - return f->depth; -} #ifdef __cplusplus } diff --git a/test/test/test_fifo.c b/test/test/test_fifo.c index 5ea8de512..f9bfc5f03 100644 --- a/test/test/test_fifo.c +++ b/test/test/test_fifo.c @@ -24,15 +24,19 @@ * This file is part of the TinyUSB stack. */ +#include #include "unity.h" #include "tusb_fifo.h" #define FIFO_SIZE 10 -TU_FIFO_DEF(ff, FIFO_SIZE, uint8_t, false); +TU_FIFO_DEF(tu_ff, FIFO_SIZE, uint8_t, false); +tu_fifo_t* ff = &tu_ff; +tu_fifo_buffer_info_t info; void setUp(void) { - tu_fifo_clear(&ff); + tu_fifo_clear(ff); + memset(&info, 0, sizeof(tu_fifo_buffer_info_t)); } void tearDown(void) @@ -44,12 +48,12 @@ void tearDown(void) //--------------------------------------------------------------------+ void test_normal(void) { - for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(&ff, &i); + for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &i); for(uint8_t i=0; i < FIFO_SIZE; i++) { uint8_t c; - tu_fifo_read(&ff, &c); + tu_fifo_read(ff, &c); TEST_ASSERT_EQUAL(i, c); } } @@ -86,30 +90,30 @@ void test_read_n(void) uint8_t data[20]; for(int i=0; i 4 - rd_count = tu_fifo_read_n(&ff, rd, 5); + rd_count = tu_fifo_read_n(ff, rd, 5); TEST_ASSERT_EQUAL( 5, rd_count ); TEST_ASSERT_EQUAL_MEMORY( data, rd, rd_count ); // 0 -> 4 // case 2: Read index + count > depth // write 10, 11, 12 - tu_fifo_write(&ff, data+10); - tu_fifo_write(&ff, data+11); - tu_fifo_write(&ff, data+12); + tu_fifo_write(ff, data+10); + tu_fifo_write(ff, data+11); + tu_fifo_write(ff, data+12); - rd_count = tu_fifo_read_n(&ff, rd, 7); + rd_count = tu_fifo_read_n(ff, rd, 7); TEST_ASSERT_EQUAL( 7, rd_count ); TEST_ASSERT_EQUAL_MEMORY( data+5, rd, rd_count ); // 5 -> 11 // Should only read until empty - TEST_ASSERT_EQUAL( 1, tu_fifo_read_n(&ff, rd, 100) ); + TEST_ASSERT_EQUAL( 1, tu_fifo_read_n(ff, rd, 100) ); } void test_write_n(void) @@ -119,52 +123,172 @@ void test_write_n(void) for(int i=0; i 4 // case 2: wr + count > depth - tu_fifo_write_n(&ff, data+8, 6); // wr = 3, count = 9 + tu_fifo_write_n(ff, data+8, 6); // wr = 3, count = 9 - for(rd_count=0; rd_count<7; rd_count++) tu_fifo_read(&ff, rd+rd_count); // wr = 3, count = 2 + for(rd_count=0; rd_count<7; rd_count++) tu_fifo_read(ff, rd+rd_count); // wr = 3, count = 2 TEST_ASSERT_EQUAL_MEMORY( data+5, rd, rd_count); // 5 -> 11 - TEST_ASSERT_EQUAL(2, tu_fifo_count(&ff)); + TEST_ASSERT_EQUAL(2, tu_fifo_count(ff)); } void test_peek(void) { uint8_t temp; - temp = 10; tu_fifo_write(&ff, &temp); - temp = 20; tu_fifo_write(&ff, &temp); - temp = 30; tu_fifo_write(&ff, &temp); + temp = 10; tu_fifo_write(ff, &temp); + temp = 20; tu_fifo_write(ff, &temp); + temp = 30; tu_fifo_write(ff, &temp); temp = 0; - tu_fifo_peek(&ff, &temp); + tu_fifo_peek(ff, &temp); TEST_ASSERT_EQUAL(10, temp); + + tu_fifo_read(ff, &temp); + tu_fifo_read(ff, &temp); + + tu_fifo_peek(ff, &temp); + TEST_ASSERT_EQUAL(30, temp); +} + +void test_get_read_info_when_no_wrap() +{ + uint8_t ch = 1; + + // write 6 items + for(uint8_t i=0; i < 6; i++) tu_fifo_write(ff, &ch); + + // read 2 items + tu_fifo_read(ff, &ch); + tu_fifo_read(ff, &ch); + + tu_fifo_get_read_info(ff, &info); + + TEST_ASSERT_EQUAL(4, info.len_lin); + TEST_ASSERT_EQUAL(0, info.len_wrap); + + TEST_ASSERT_EQUAL_PTR(ff->buffer+2, info.ptr_lin); + TEST_ASSERT_NULL(info.ptr_wrap); +} + +void test_get_read_info_when_wrapped() +{ + uint8_t ch = 1; + + // make fifo full + for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &ch); + + // read 6 items + for(uint8_t i=0; i < 6; i++) tu_fifo_read(ff, &ch); + + // write 2 items + tu_fifo_write(ff, &ch); + tu_fifo_write(ff, &ch); + + tu_fifo_get_read_info(ff, &info); + + TEST_ASSERT_EQUAL(FIFO_SIZE-6, info.len_lin); + TEST_ASSERT_EQUAL(2, info.len_wrap); + + TEST_ASSERT_EQUAL_PTR(ff->buffer+6, info.ptr_lin); + TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap); +} + +void test_get_write_info_when_no_wrap() +{ + uint8_t ch = 1; + + // write 2 items + tu_fifo_write(ff, &ch); + tu_fifo_write(ff, &ch); + + tu_fifo_get_write_info(ff, &info); + + TEST_ASSERT_EQUAL(FIFO_SIZE-2, info.len_lin); + TEST_ASSERT_EQUAL(0, info.len_wrap); + + TEST_ASSERT_EQUAL_PTR(ff->buffer+2, info .ptr_lin); + // application should check len instead of ptr. + // TEST_ASSERT_NULL(info.ptr_wrap); +} + +void test_get_write_info_when_wrapped() +{ + uint8_t ch = 1; + + // write 6 items + for(uint8_t i=0; i < 6; i++) tu_fifo_write(ff, &ch); + + // read 2 items + tu_fifo_read(ff, &ch); + tu_fifo_read(ff, &ch); + + tu_fifo_get_write_info(ff, &info); + + TEST_ASSERT_EQUAL(FIFO_SIZE-6, info.len_lin); + TEST_ASSERT_EQUAL(2, info.len_wrap); + + TEST_ASSERT_EQUAL_PTR(ff->buffer+6, info .ptr_lin); + TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_wrap); } void test_empty(void) { uint8_t temp; - TEST_ASSERT_TRUE(tu_fifo_empty(&ff)); - tu_fifo_write(&ff, &temp); - TEST_ASSERT_FALSE(tu_fifo_empty(&ff)); + TEST_ASSERT_TRUE(tu_fifo_empty(ff)); + + // read info + tu_fifo_get_read_info(ff, &info); + + TEST_ASSERT_EQUAL(0, info.len_lin); + TEST_ASSERT_EQUAL(0, info.len_wrap); + + TEST_ASSERT_NULL(info.ptr_lin); + TEST_ASSERT_NULL(info.ptr_wrap); + + // write info + tu_fifo_get_write_info(ff, &info); + + TEST_ASSERT_EQUAL(FIFO_SIZE, info.len_lin); + TEST_ASSERT_EQUAL(0, info.len_wrap); + + TEST_ASSERT_EQUAL_PTR(ff->buffer, info .ptr_lin); + // application should check len instead of ptr. + // TEST_ASSERT_NULL(info.ptr_wrap); + + // write 1 then re-check empty + tu_fifo_write(ff, &temp); + TEST_ASSERT_FALSE(tu_fifo_empty(ff)); } void test_full(void) { - TEST_ASSERT_FALSE(tu_fifo_full(&ff)); + TEST_ASSERT_FALSE(tu_fifo_full(ff)); + + for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(ff, &i); + + TEST_ASSERT_TRUE(tu_fifo_full(ff)); + + // read info + tu_fifo_get_read_info(ff, &info); + + TEST_ASSERT_EQUAL(FIFO_SIZE, info.len_lin); + TEST_ASSERT_EQUAL(0, info.len_wrap); - for(uint8_t i=0; i < FIFO_SIZE; i++) tu_fifo_write(&ff, &i); + TEST_ASSERT_EQUAL_PTR(ff->buffer, info.ptr_lin); + // skip this, application must check len instead of buffer + // TEST_ASSERT_NULL(info.ptr_wrap); - TEST_ASSERT_TRUE(tu_fifo_full(&ff)); + // write info } -- cgit v1.3.1 From dab1ed6b327a41976a2d4968d80747ac35fde113 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Wed, 5 May 2021 17:42:38 -0400 Subject: Add example to be tested Update API description. --- examples/device/dfu/CMakeLists.txt | 41 +++++++ examples/device/dfu/Makefile | 12 ++ examples/device/dfu/src/main.c | 188 ++++++++++++++++++++++++++++++ examples/device/dfu/src/tusb_config.h | 90 ++++++++++++++ examples/device/dfu/src/usb_descriptors.c | 167 ++++++++++++++++++++++++++ src/class/dfu/dfu_device.h | 3 +- 6 files changed, 500 insertions(+), 1 deletion(-) create mode 100644 examples/device/dfu/CMakeLists.txt create mode 100644 examples/device/dfu/Makefile create mode 100644 examples/device/dfu/src/main.c create mode 100644 examples/device/dfu/src/tusb_config.h create mode 100644 examples/device/dfu/src/usb_descriptors.c (limited to 'src') diff --git a/examples/device/dfu/CMakeLists.txt b/examples/device/dfu/CMakeLists.txt new file mode 100644 index 000000000..f4bf75c26 --- /dev/null +++ b/examples/device/dfu/CMakeLists.txt @@ -0,0 +1,41 @@ +# use directory name for project id +get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME) +set(PROJECT ${BOARD}-${PROJECT}) + +# TOP is absolute path to root directory of TinyUSB git repo +set(TOP "../../..") +get_filename_component(TOP "${TOP}" REALPATH) + +# Check for -DFAMILY= +if(FAMILY STREQUAL "rp2040") + cmake_minimum_required(VERSION 3.12) + set(PICO_SDK_PATH ${TOP}/hw/mcu/raspberrypi/pico-sdk) + include(${PICO_SDK_PATH}/pico_sdk_init.cmake) + project(${PROJECT}) + pico_sdk_init() + add_executable(${PROJECT}) + + include(${TOP}/hw/bsp/${FAMILY}/family.cmake) + + # Example source + target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c + ) + + # Example include + target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + + # Example defines + target_compile_definitions(${PROJECT} PUBLIC + CFG_TUSB_OS=OPT_OS_PICO + ) + + target_link_libraries(${PROJECT} pico_stdlib pico_fix_rp2040_usb_device_enumeration) + pico_add_extra_outputs(${PROJECT}) + +else() + message(FATAL_ERROR "Invalid FAMILY specified") +endif() diff --git a/examples/device/dfu/Makefile b/examples/device/dfu/Makefile new file mode 100644 index 000000000..69b633fea --- /dev/null +++ b/examples/device/dfu/Makefile @@ -0,0 +1,12 @@ +include ../../../tools/top.mk +include ../../make.mk + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +include ../../rules.mk diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c new file mode 100644 index 000000000..3849de44d --- /dev/null +++ b/examples/device/dfu/src/main.c @@ -0,0 +1,188 @@ +/* + * 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. + * + */ + + /* + * After device is enumerated in dfu mode run the following commands + * + * To transfer firmware from host to device: + * + * $ dfu-util -D [filename] + * + * To transfer firmware from device to host: + * + * $ dfu-util -U [filename] + * + */ + +#include +#include +#include + +#include "bsp/board.h" +#include "tusb.h" + + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ +#ifndef DFU_VERBOSE +#define DFU_VERBOSE 0 +#endif + +/* Blink pattern + * - 1000 ms : device should reboot + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_DFU_MODE = 100, + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +void led_blinking_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + tusb_init(); + + while (1) + { + tud_task(); // tinyusb device task + led_blinking_task(); + } + + return 0; +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + blink_interval_ms = BLINK_NOT_MOUNTED; +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) +{ + (void) remote_wakeup_en; + blink_interval_ms = BLINK_SUSPENDED; +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked on DFU_DETACH request to reboot to the bootloader +void tud_dfu_runtime_reboot_to_dfu_cb(void) +{ + blink_interval_ms = BLINK_DFU_MODE; +} + +//--------------------------------------------------------------------+ +// Class callbacks +//--------------------------------------------------------------------+ +bool tud_dfu_firmware_valid_check_cb(void) +{ + TU_LOG2(" Firmware check\r\n"); + return true; +} + +void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length) +{ + TU_LOG2(" Received BlockNum %u of length %u\r\n", wBlockNum, length); + +#if DFU_VERBOSE + for(uint16_t i=0; i 31 ) { + chr_count = 31; + } + + // Convert ASCII string into UTF-16 + for(uint8_t i=0; i Date: Fri, 7 May 2021 16:49:48 -0400 Subject: Update hcd_rp2040.c Remove reference to the deprecated "num" and "in" members of struct hw_endpoint which still exist in an assert statement and break DEBUG builds. --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 224f6ef21..40d208679 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -487,7 +487,6 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet // EP0 out _hw_endpoint_init(ep, dev_addr, 0x00, ep->wMaxPacketSize, 0, 0); assert(ep->configured); - assert(ep->num == 0 && !ep->in); ep->total_len = 8; ep->transfer_size = 8; ep->active = true; -- cgit v1.3.1 From 5d69b2ac4ddd7dd1cf54b0bad5fd74f6bbbaf2f5 Mon Sep 17 00:00:00 2001 From: ogatatsu Date: Mon, 10 May 2021 17:19:44 +0900 Subject: fix hid report descriptor --- src/class/hid/hid_device.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 0c59d5d20..ce713559e 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -184,9 +184,9 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 /* 6-byte Keycodes */ \ HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\ HID_USAGE_MIN ( 0 ) ,\ - HID_USAGE_MAX ( 255 ) ,\ + HID_USAGE_MAX_N ( 255, 2 ) ,\ HID_LOGICAL_MIN ( 0 ) ,\ - HID_LOGICAL_MAX ( 255 ) ,\ + HID_LOGICAL_MAX_N( 255, 2 ) ,\ HID_REPORT_COUNT ( 6 ) ,\ HID_REPORT_SIZE ( 8 ) ,\ HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ @@ -272,7 +272,7 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 * 0x00 - do nothing * 0x01 - Power Off * 0x02 - Standby - * 0x04 - Wake Host + * 0x03 - Wake Host */ #define TUD_HID_REPORT_DESC_SYSTEM_CONTROL(...) \ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ @@ -285,8 +285,8 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 HID_LOGICAL_MAX ( 3 ) ,\ HID_REPORT_COUNT ( 1 ) ,\ HID_REPORT_SIZE ( 2 ) ,\ - HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_SLEEP ) ,\ HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_SLEEP ) ,\ HID_USAGE ( HID_USAGE_DESKTOP_SYSTEM_WAKE_UP ) ,\ HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\ /* 6 bit padding */ \ -- cgit v1.3.1 From 13de8f5d98eceae8771af78e6acb126f8da19854 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 10 May 2021 19:15:46 +0700 Subject: minor clean up --- src/common/tusb_types.h | 2 ++ src/portable/espressif/esp32sx/dcd_esp32sx.c | 2 +- src/portable/microchip/samg/dcd_samg.c | 2 +- src/portable/nuvoton/nuc120/dcd_nuc120.c | 2 +- src/portable/nuvoton/nuc121/dcd_nuc121.c | 2 +- src/portable/nuvoton/nuc505/dcd_nuc505.c | 2 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/synopsys/dcd_synopsys.c | 2 +- src/portable/template/dcd_template.c | 2 +- src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 2 +- 10 files changed, 11 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ba3fe2c41..922d3daff 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -309,6 +309,8 @@ typedef struct TU_ATTR_PACKED uint8_t bMaxPower ; ///< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. Expressed in 2 mA units (i.e., 50 = 100 mA). } tusb_desc_configuration_t; +TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct"); + /// USB Interface Descriptor typedef struct TU_ATTR_PACKED { diff --git a/src/portable/espressif/esp32sx/dcd_esp32sx.c b/src/portable/espressif/esp32sx/dcd_esp32sx.c index 74842a291..502273a9b 100644 --- a/src/portable/espressif/esp32sx/dcd_esp32sx.c +++ b/src/portable/espressif/esp32sx/dcd_esp32sx.c @@ -27,7 +27,6 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if (((CFG_TUSB_MCU == OPT_MCU_ESP32S2) || (CFG_TUSB_MCU == OPT_MCU_ESP32S3)) && TUSB_OPT_DEVICE_ENABLED) @@ -41,6 +40,7 @@ #include "soc/gpio_sig_map.h" #include "soc/usb_periph.h" +#include "common/tusb_fifo.h" #include "device/dcd.h" // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 62fab8d17..9b6a1f9a5 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -25,11 +25,11 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if CFG_TUSB_MCU == OPT_MCU_SAMG #include "sam.h" +#include "common/tusb_fifo.h" #include "device/dcd.h" // TODO should support (SAM3S || SAM4S || SAM4E || SAMG55) diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 5dc3bca21..7aeb49f2a 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -34,10 +34,10 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC120) +#include "common/tusb_fifo.h" #include "device/dcd.h" #include "NUC100Series.h" diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index d50e82846..e76d7118c 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -34,10 +34,10 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && ( (CFG_TUSB_MCU == OPT_MCU_NUC121) || (CFG_TUSB_MCU == OPT_MCU_NUC126) ) +#include "common/tusb_fifo.h" #include "device/dcd.h" #include "NuMicro.h" diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index b7bbb020b..46081d4d0 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -34,10 +34,10 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC505) +#include "common/tusb_fifo.h" #include "device/dcd.h" #include "NUC505Series.h" diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index dd0d76c1f..0b7605a73 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -102,7 +102,6 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if defined(STM32F102x6) || defined(STM32F102xB) || \ defined(STM32F103x6) || defined(STM32F103xB) || \ @@ -121,6 +120,7 @@ // Some definitions are copied to our private include file. #undef USE_HAL_DRIVER +#include "common/tusb_fifo.h" #include "device/dcd.h" #include "portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h" diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 0fe7c2a3c..76f5c6050 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -28,7 +28,6 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) // We disable SOF for now until needed later on @@ -98,6 +97,7 @@ #endif +#include "common/tusb_fifo.h" #include "device/dcd.h" //--------------------------------------------------------------------+ diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index d8c8753d3..92a9f3144 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -25,10 +25,10 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if CFG_TUSB_MCU == OPT_MCU_NONE +#include "common/tusb_fifo.h" #include "device/dcd.h" //--------------------------------------------------------------------+ diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 48e9dd592..e13ee697e 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -26,11 +26,11 @@ */ #include "tusb_option.h" -#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MSP430x5xx ) #include "msp430.h" +#include "common/tusb_fifo.h" #include "device/dcd.h" /*------------------------------------------------------------------*/ -- cgit v1.3.1 From 74ca1894de12429e1a16d75242889dcd520eea68 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 10 May 2021 15:58:04 +0200 Subject: audio_device: Fix build error ep_in_as_intf_num was incorrectly used to access out interface which is defined for 'in' interface. Code related to 'out' endpoint should use ep_out_as_intf_num instead. --- src/class/audio/audio_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 76ebc8aba..72533013c 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -496,7 +496,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) { idx_audio_fct = audiod_get_audio_fct_idx(audio); - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio, &idxItf, &dummy2)); + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio, &idxItf, &dummy2)); } // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) -- cgit v1.3.1 From 72f52020864bb8980fa6c5adc7bf31d1c233d133 Mon Sep 17 00:00:00 2001 From: corvus-ossifragus <77814520+corvus-ossifragus@users.noreply.github.com> Date: Mon, 10 May 2021 10:09:09 -0400 Subject: Update trace statements that referenced deprecated structure elements. --- .gitignore | 1 + src/portable/raspberrypi/rp2040/hcd_rp2040.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/.gitignore b/.gitignore index f7adff4c9..f180d4079 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ cov-int # cppcheck build directories *-build-dir /_bin/ +examples/host/cdc_msc_hid/setup.bat diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 40d208679..5201d1d4c 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -306,8 +306,8 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep->wMaxPacketSize = wMaxPacketSize; ep->transfer_type = transfer_type; - pico_trace("hw_endpoint_init dev %d ep %d %s xfer %d\n", ep->dev_addr, ep->num, ep_dir_string[ep->in], ep->transfer_type); - pico_trace("dev %d ep %d %s setup buffer @ 0x%p\n", ep->dev_addr, ep->num, ep_dir_string[ep->in], ep->hw_data_buf); + pico_trace("hw_endpoint_init dev %d ep %d %s xfer %d\n", ep->dev_addr, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)], ep->transfer_type); + pico_trace("dev %d ep %d %s setup buffer @ 0x%p\n", ep->dev_addr, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)], ep->hw_data_buf); uint dpram_offset = hw_data_offset(ep->hw_data_buf); // Bits 0-5 should be 0 assert(!(dpram_offset & 0b111111)); -- cgit v1.3.1 From e2f795067acede0b93de8f7f27edb6aaa76eda57 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 11 May 2021 08:53:33 +0200 Subject: Allow build for NRF5340 MCU Errata code referred to NRF_USBD_BASE. This definition is not present in NRF5340 but both NRF52 and NRF53 do have NRF_USBD which maps to NRF_USBD_BASE for NRF52 and to NRF_USBD_S_BASE for NRF5340. This just make build possible for NRF5340. --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 6b8095a00..3bb9bd37a 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -924,8 +924,8 @@ void tusb_hal_nrf_power_event (uint32_t event) if ( nrfx_usbd_errata_166() ) { - *((volatile uint32_t *) (NRF_USBD_BASE + 0x800)) = 0x7E3; - *((volatile uint32_t *) (NRF_USBD_BASE + 0x804)) = 0x40; + *((volatile uint32_t *) ((uint8_t *) (NRF_USBD) + 0x800)) = 0x7E3; + *((volatile uint32_t *) ((uint8_t *) (NRF_USBD) + 0x804)) = 0x40; __ISB(); __DSB(); } -- cgit v1.3.1 From 9233269a2c97c9ca980276a288b1b225cb4d3825 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 May 2021 18:38:23 +0700 Subject: only apply errata walkaround for nrf52 --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 3bb9bd37a..977ec6cdb 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -833,9 +833,8 @@ void tusb_hal_nrf_power_event (uint32_t event) NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk; __ISB(); __DSB(); // for sync - /* Enable the peripheral */ +#ifdef NRF52_SERIES // ERRATA 171, 187, 166 - if ( nrfx_usbd_errata_187() ) { // CRITICAL_REGION_ENTER(); @@ -867,7 +866,9 @@ void tusb_hal_nrf_power_event (uint32_t event) } // CRITICAL_REGION_EXIT(); } +#endif + /* Enable the peripheral */ NRF_USBD->ENABLE = 1; __ISB(); __DSB(); // for sync @@ -889,6 +890,7 @@ void tusb_hal_nrf_power_event (uint32_t event) NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk; __ISB(); __DSB(); // for sync +#ifdef NRF52_SERIES if ( nrfx_usbd_errata_171() ) { // CRITICAL_REGION_ENTER(); @@ -924,11 +926,12 @@ void tusb_hal_nrf_power_event (uint32_t event) if ( nrfx_usbd_errata_166() ) { - *((volatile uint32_t *) ((uint8_t *) (NRF_USBD) + 0x800)) = 0x7E3; - *((volatile uint32_t *) ((uint8_t *) (NRF_USBD) + 0x804)) = 0x40; + *((volatile uint32_t *) (NRF_USBD_BASE + 0x800)) = 0x7E3; + *((volatile uint32_t *) (NRF_USBD_BASE + 0x804)) = 0x40; __ISB(); __DSB(); } +#endif // ISO buffer Lower half for IN, upper half for OUT NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN; -- cgit v1.3.1 From e163f85ee024ff366253478cfd20e3fc35e96819 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 18 May 2021 12:32:20 +0700 Subject: clean up, rename some HID device symbol/API - add tud_hid_n_interface_protocol() - rename tud_hid_n_boot_mode() to tud_hid_n_get_protocol() - rename tud_hid_boot_mode_cb() to tud_hid_set_protocol_cb() - add HID_PROTOCOL_BOOT/REPORT to avoid magic number 0,1 - rename HID_PROTOCOL_NONE/KEYBOARD/MOUSE to HID_ITF_PROTOCOL_ to avoid confusion --- .../device/hid_composite/src/usb_descriptors.c | 2 +- .../hid_composite_freertos/src/usb_descriptors.c | 2 +- .../device/hid_generic_inout/src/usb_descriptors.c | 2 +- .../hid_multiple_interface/src/usb_descriptors.c | 4 +- src/class/hid/hid.h | 29 +++++++---- src/class/hid/hid_device.c | 58 ++++++++++++---------- src/class/hid/hid_device.h | 55 ++++++++++++-------- src/class/hid/hid_host.c | 4 +- 8 files changed, 92 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index ccc1306bd..1aff5e68e 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -108,7 +108,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5) + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_composite_freertos/src/usb_descriptors.c b/examples/device/hid_composite_freertos/src/usb_descriptors.c index ccc1306bd..1aff5e68e 100644 --- a/examples/device/hid_composite_freertos/src/usb_descriptors.c +++ b/examples/device/hid_composite_freertos/src/usb_descriptors.c @@ -108,7 +108,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5) + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index db4ddd76e..5a2f5ffdc 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -104,7 +104,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval - TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) + TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/hid_multiple_interface/src/usb_descriptors.c b/examples/device/hid_multiple_interface/src/usb_descriptors.c index a28e57a2b..9eef21504 100644 --- a/examples/device/hid_multiple_interface/src/usb_descriptors.c +++ b/examples/device/hid_multiple_interface/src/usb_descriptors.c @@ -119,8 +119,8 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_HID1, 4, HID_PROTOCOL_NONE, sizeof(desc_hid_report1), EPNUM_HID1, CFG_TUD_HID_EP_BUFSIZE, 10), - TUD_HID_DESCRIPTOR(ITF_NUM_HID2, 5, HID_PROTOCOL_NONE, sizeof(desc_hid_report2), EPNUM_HID2, CFG_TUD_HID_EP_BUFSIZE, 10) + TUD_HID_DESCRIPTOR(ITF_NUM_HID1, 4, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report1), EPNUM_HID1, CFG_TUD_HID_EP_BUFSIZE, 10), + TUD_HID_DESCRIPTOR(ITF_NUM_HID2, 5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report2), EPNUM_HID2, CFG_TUD_HID_EP_BUFSIZE, 10) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 351a4d600..6014e54a6 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -62,15 +62,15 @@ typedef enum { HID_SUBCLASS_NONE = 0, ///< No Subclass HID_SUBCLASS_BOOT = 1 ///< Boot Interface Subclass -}hid_subclass_type_t; +}hid_subclass_enum_t; -/// HID Protocol +/// HID Interface Protocol typedef enum { - HID_PROTOCOL_NONE = 0, ///< None - HID_PROTOCOL_KEYBOARD = 1, ///< Keyboard - HID_PROTOCOL_MOUSE = 2 ///< Mouse -}hid_protocol_type_t; + HID_ITF_PROTOCOL_NONE = 0, ///< None + HID_ITF_PROTOCOL_KEYBOARD = 1, ///< Keyboard + HID_ITF_PROTOCOL_MOUSE = 2 ///< Mouse +}hid_interface_protocol_enum_t; /// HID Descriptor Type typedef enum @@ -78,7 +78,7 @@ typedef enum HID_DESC_TYPE_HID = 0x21, ///< HID Descriptor HID_DESC_TYPE_REPORT = 0x22, ///< Report Descriptor HID_DESC_TYPE_PHYSICAL = 0x23 ///< Physical Descriptor -}hid_descriptor_type_t; +}hid_descriptor_enum_t; /// HID Request Report Type typedef enum @@ -87,7 +87,7 @@ typedef enum HID_REPORT_TYPE_INPUT, ///< Input HID_REPORT_TYPE_OUTPUT, ///< Output HID_REPORT_TYPE_FEATURE ///< Feature -}hid_report_type_t; +}hid_report_enum_t; /// HID Class Specific Control Request typedef enum @@ -98,9 +98,9 @@ typedef enum HID_REQ_CONTROL_SET_REPORT = 0x09, ///< Set Report HID_REQ_CONTROL_SET_IDLE = 0x0a, ///< Set Idle HID_REQ_CONTROL_SET_PROTOCOL = 0x0b ///< Set Protocol -}hid_request_type_t; +}hid_request_enum_t; -/// HID Country Code +/// HID Local Code typedef enum { HID_LOCAL_NotSupported = 0 , ///< NotSupported @@ -139,7 +139,14 @@ typedef enum HID_LOCAL_US , ///< US HID_LOCAL_Yugoslavia , ///< Yugoslavia HID_LOCAL_Turkish_F ///< Turkish-F -} hid_country_code_t; +} hid_local_enum_t; + +// HID protocol value used by GetProtocol / SetProtocol +enum +{ + HID_PROTOCOL_BOOT = 0, + HID_PROTOCOL_REPORT = 1 +}; /** @} */ diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 18d35bc20..62d63e30a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -43,7 +43,8 @@ typedef struct uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; // optional Out endpoint - uint8_t boot_protocol; // Boot mouse or keyboard + uint8_t itf_protocol; // Boot mouse or keyboard + bool boot_mode; // default = false (Report) uint8_t idle_rate; // up to application to handle idle rate uint16_t report_desc_len; @@ -51,6 +52,8 @@ typedef struct CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE]; CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE]; + // TODO save hid descriptor since host can specifically request this after enumeration + // Note: HID descriptor may be not available from application after enumeration tusb_hid_descriptor_hid_t const * hid_descriptor; } hidd_interface_t; @@ -70,16 +73,16 @@ static inline uint8_t get_index_by_itfnum(uint8_t itf_num) //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ -bool tud_hid_n_ready(uint8_t itf) +bool tud_hid_n_ready(uint8_t instance) { - uint8_t const ep_in = _hidd_itf[itf].ep_in; + uint8_t const ep_in = _hidd_itf[instance].ep_in; return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } -bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len) +bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len) { uint8_t const rhport = 0; - hidd_interface_t * p_hid = &_hidd_itf[itf]; + hidd_interface_t * p_hid = &_hidd_itf[instance]; // claim endpoint TU_VERIFY( usbd_edpt_claim(rhport, p_hid->ep_in) ); @@ -102,12 +105,17 @@ bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_ return usbd_edpt_xfer(TUD_OPT_RHPORT, p_hid->ep_in, p_hid->epin_buf, len); } -bool tud_hid_n_boot_mode(uint8_t itf) +uint8_t tud_hid_n_interface_protocol(uint8_t instance) +{ + return _hidd_itf[instance].itf_protocol; +} + +bool tud_hid_n_get_protocol(uint8_t instance) { - return _hidd_itf[itf].boot_mode; + return _hidd_itf[instance].boot_mode; } -bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) +bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) { hid_keyboard_report_t report; @@ -121,10 +129,10 @@ bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, tu_memclr(report.keycode, 6); } - return tud_hid_n_report(itf, report_id, &report, sizeof(report)); + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); } -bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, +bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) { hid_mouse_report_t report = @@ -136,10 +144,10 @@ bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, .pan = horizontal }; - return tud_hid_n_report(itf, report_id, &report, sizeof(report)); + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); } -bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, +bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) { hid_gamepad_report_t report = @@ -154,7 +162,7 @@ bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, .buttons = buttons, }; - return tud_hid_n_report(itf, report_id, &report, sizeof(report)); + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); } //--------------------------------------------------------------------+ @@ -203,7 +211,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 p_desc = tu_desc_next(p_desc); TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0); - if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->boot_protocol = desc_itf->bInterfaceProtocol; + if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->itf_protocol = desc_itf->bInterfaceProtocol; p_hid->boot_mode = false; // default mode is REPORT p_hid->itf_num = desc_itf->bInterfaceNumber; @@ -318,8 +326,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t case HID_REQ_CONTROL_GET_PROTOCOL: if ( stage == CONTROL_STAGE_SETUP ) { - // 0 is Boot, 1 is Report protocol - uint8_t protocol = (uint8_t)(1-p_hid->boot_mode); + uint8_t protocol = (p_hid->boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT); tud_control_xfer(rhport, request, &protocol, 1); } break; @@ -327,15 +334,14 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t case HID_REQ_CONTROL_SET_PROTOCOL: if ( stage == CONTROL_STAGE_SETUP ) { - // 0 is Boot, 1 is Report protocol - p_hid->boot_mode = 1 - request->wValue; + p_hid->boot_mode = (request->wValue == HID_PROTOCOL_BOOT); tud_control_status(rhport, request); } else if ( stage == CONTROL_STAGE_ACK ) { - if (tud_hid_boot_mode_cb) + if (tud_hid_set_protocol_cb) { - tud_hid_boot_mode_cb(hid_itf, p_hid->boot_mode); + tud_hid_set_protocol_cb(hid_itf, p_hid->boot_mode); } } break; @@ -354,29 +360,29 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ { (void) result; - uint8_t itf = 0; + uint8_t instance = 0; hidd_interface_t * p_hid = _hidd_itf; // Identify which interface to use - for (itf = 0; itf < CFG_TUD_HID; itf++) + for (instance = 0; instance < CFG_TUD_HID; instance++) { - p_hid = &_hidd_itf[itf]; + p_hid = &_hidd_itf[instance]; if ( (ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in) ) break; } - TU_ASSERT(itf < CFG_TUD_HID); + TU_ASSERT(instance < CFG_TUD_HID); // Sent report successfully if (ep_addr == p_hid->ep_in) { if (tud_hid_report_complete_cb) { - tud_hid_report_complete_cb(itf, p_hid->epin_buf, (uint8_t) xferred_bytes); + tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint8_t) xferred_bytes); } } // Received report else if (ep_addr == p_hid->ep_out) { - tud_hid_set_report_cb(itf, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); + tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, xferred_bytes); TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 0c59d5d20..cc34f19ac 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -55,34 +55,39 @@ //--------------------------------------------------------------------+ // Check if the interface is ready to use -bool tud_hid_n_ready(uint8_t itf); +bool tud_hid_n_ready(uint8_t instance); -// Check if current mode is Boot (true) or Report (false) -bool tud_hid_n_boot_mode(uint8_t itf); +// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible value +uint8_t tud_hid_n_interface_protocol(uint8_t instance); + +// Check if active protocol is Boot (true) or Report (false) +bool tud_hid_n_get_protocol(uint8_t instance); // Send report to host -bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len); +bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len); // KEYBOARD: convenient helper to send keyboard report if application // use template layout report as defined by hid_keyboard_report_t -bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); +bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); // MOUSE: convenient helper to send mouse report if application // use template layout report as defined by hid_mouse_report_t -bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); // Gamepad: convenient helper to send mouse report if application // use template layout report TUD_HID_REPORT_DESC_GAMEPAD -bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); +bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ -static inline bool tud_hid_ready(void); -static inline bool tud_hid_boot_mode(void); -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); -static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); -static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +static inline bool tud_hid_ready(void); +static inline uint8_t tud_hid_interface_protocol(void); +static inline bool tud_hid_get_protocol(void); +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); +static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); +static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); +static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); //--------------------------------------------------------------------+ // Callbacks (Weak is optional) @@ -90,29 +95,29 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 // Invoked when received GET HID REPORT DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf); +uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance); // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); +uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); +void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); // Invoked when received SET_PROTOCOL request ( mode switch Boot <-> Report ) -TU_ATTR_WEAK void tud_hid_boot_mode_cb(uint8_t itf, uint8_t boot_mode); +TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, bool boot_mode); // Invoked when received SET_IDLE request. return false will stall the request // - Idle Rate = 0 : only send report if there is changes, i.e skip duplication // - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). -TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t itf, uint8_t idle_rate); +TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate); // Invoked when sent REPORT successfully to host // Application can use this to send the next report // Note: For composite reports, report[0] is report ID -TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len); +TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint8_t len); //--------------------------------------------------------------------+ @@ -123,9 +128,14 @@ static inline bool tud_hid_ready(void) return tud_hid_n_ready(0); } -static inline bool tud_hid_boot_mode(void) +static inline uint8_t tud_hid_interface_protocol(void) +{ + return tud_hid_n_interface_protocol(0); +} + +static inline bool tud_hid_get_protocol(void) { - return tud_hid_n_boot_mode(0); + return tud_hid_n_get_protocol(0); } static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) @@ -143,6 +153,11 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); } +static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) +{ + return tud_hid_n_gamepad_report(0, x, y, z, rz, rx, ry, hat, buttons); +} + /* --------------------------------------------------------------------+ * HID Report Descriptor Template * diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 64d1b8e5d..28440b1b4 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -178,7 +178,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c if ( HID_SUBCLASS_BOOT == p_interface_desc->bInterfaceSubClass ) { #if CFG_TUH_HID_KEYBOARD - if ( HID_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol) + if ( HID_ITF_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol) { TU_ASSERT( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) ); TU_LOG2_HEX(keyboardh_data[dev_addr-1].ep_in); @@ -186,7 +186,7 @@ bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c #endif #if CFG_TUH_HID_MOUSE - if ( HID_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol) + if ( HID_ITF_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol) { TU_ASSERT ( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) ); TU_LOG2_HEX(mouseh_data[dev_addr-1].ep_in); -- cgit v1.3.1 From 7e9e682e09c2629a9575343e4efaf43d328bde33 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 18 May 2021 12:38:11 +0700 Subject: update to use HID spec protocol value for get/set_protocol() --- src/class/hid/hid.h | 4 ++-- src/class/hid/hid_device.c | 6 +++--- src/class/hid/hid_device.h | 11 ++++++----- 3 files changed, 11 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 6014e54a6..5c30f7585 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -142,11 +142,11 @@ typedef enum } hid_local_enum_t; // HID protocol value used by GetProtocol / SetProtocol -enum +typedef enum { HID_PROTOCOL_BOOT = 0, HID_PROTOCOL_REPORT = 1 -}; +} hid_protocol_mode_enum_t; /** @} */ diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 62d63e30a..4d33c85d3 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -112,7 +112,7 @@ uint8_t tud_hid_n_interface_protocol(uint8_t instance) bool tud_hid_n_get_protocol(uint8_t instance) { - return _hidd_itf[instance].boot_mode; + return _hidd_itf[instance].boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; } bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) @@ -334,14 +334,14 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t case HID_REQ_CONTROL_SET_PROTOCOL: if ( stage == CONTROL_STAGE_SETUP ) { - p_hid->boot_mode = (request->wValue == HID_PROTOCOL_BOOT); tud_control_status(rhport, request); } else if ( stage == CONTROL_STAGE_ACK ) { + p_hid->boot_mode = (request->wValue == HID_PROTOCOL_BOOT); if (tud_hid_set_protocol_cb) { - tud_hid_set_protocol_cb(hid_itf, p_hid->boot_mode); + tud_hid_set_protocol_cb(hid_itf, (uint8_t) request->wValue); } } break; diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index cc34f19ac..2cc4a9546 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -60,8 +60,8 @@ bool tud_hid_n_ready(uint8_t instance); // Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible value uint8_t tud_hid_n_interface_protocol(uint8_t instance); -// Check if active protocol is Boot (true) or Report (false) -bool tud_hid_n_get_protocol(uint8_t instance); +// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +uint8_t tud_hid_n_get_protocol(uint8_t instance); // Send report to host bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint8_t len); @@ -83,7 +83,7 @@ bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int //--------------------------------------------------------------------+ static inline bool tud_hid_ready(void); static inline uint8_t tud_hid_interface_protocol(void); -static inline bool tud_hid_get_protocol(void); +static inline uint8_t tud_hid_get_protocol(void); static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); @@ -106,8 +106,9 @@ uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_t // received data on OUT endpoint ( Report ID = 0, Type = 0 ) void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); -// Invoked when received SET_PROTOCOL request ( mode switch Boot <-> Report ) -TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, bool boot_mode); +// Invoked when received SET_PROTOCOL request +// protocol is either HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol); // Invoked when received SET_IDLE request. return false will stall the request // - Idle Rate = 0 : only send report if there is changes, i.e skip duplication -- cgit v1.3.1 From a26752a93e56b2fb2d683e5a9f9934b432531d9b Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 18 May 2021 12:45:59 +0700 Subject: fix build error --- src/class/hid/hid.h | 2 +- src/class/hid/hid_device.c | 2 +- src/class/hid/hid_device.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 5c30f7585..c63b6f00b 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -87,7 +87,7 @@ typedef enum HID_REPORT_TYPE_INPUT, ///< Input HID_REPORT_TYPE_OUTPUT, ///< Output HID_REPORT_TYPE_FEATURE ///< Feature -}hid_report_enum_t; +}hid_report_type_t; /// HID Class Specific Control Request typedef enum diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 4d33c85d3..ab9ef3ad8 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -110,7 +110,7 @@ uint8_t tud_hid_n_interface_protocol(uint8_t instance) return _hidd_itf[instance].itf_protocol; } -bool tud_hid_n_get_protocol(uint8_t instance) +uint8_t tud_hid_n_get_protocol(uint8_t instance) { return _hidd_itf[instance].boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 2cc4a9546..b3701c7e0 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -134,7 +134,7 @@ static inline uint8_t tud_hid_interface_protocol(void) return tud_hid_n_interface_protocol(0); } -static inline bool tud_hid_get_protocol(void) +static inline uint8_t tud_hid_get_protocol(void) { return tud_hid_n_get_protocol(0); } @@ -156,7 +156,7 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) { - return tud_hid_n_gamepad_report(0, x, y, z, rz, rx, ry, hat, buttons); + return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); } /* --------------------------------------------------------------------+ -- cgit v1.3.1 From 1dd2cd43dda857de3f4272074c595e663ef09b22 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Feb 2021 13:10:47 +0700 Subject: add hcd_ehci.h as interface for ehci port --- src/host/usbh.c | 2 +- src/portable/ehci/ehci.c | 5 +- src/portable/ehci/hcd_ehci.h | 53 ++++++++++++++++++++++ .../nxp/transdimension/hcd_transdimension.c | 4 +- 4 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 src/portable/ehci/hcd_ehci.h (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index a4ee4cb5c..3761f279c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -656,7 +656,7 @@ static bool enum_new_device(hcd_event_t* event) //------------- connected/disconnected directly with roothub -------------// if (dev0->hub_addr == 0) { - // wait until device is stable + // wait until device is stable TODO non blocking osal_task_delay(RESET_DELAY); // device unplugged while delaying diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index e2327fdc0..484e49600 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -37,6 +37,7 @@ #include "host/hcd.h" #include "host/usbh_hcd.h" +#include "hcd_ehci.h" #include "ehci.h" //--------------------------------------------------------------------+ @@ -49,10 +50,6 @@ // Periodic frame list must be 4K alignment CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data; -// EHCI portable -uint32_t hcd_ehci_register_addr(uint8_t rhport); -bool hcd_ehci_init (uint8_t rhport); // TODO move later - //--------------------------------------------------------------------+ // PROTOTYPE //--------------------------------------------------------------------+ diff --git a/src/portable/ehci/hcd_ehci.h b/src/portable/ehci/hcd_ehci.h new file mode 100644 index 000000000..480d11eda --- /dev/null +++ b/src/portable/ehci/hcd_ehci.h @@ -0,0 +1,53 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_HCD_EHCI_H_ +#define _TUSB_HCD_EHCI_H_ + +#ifdef __cplusplus + extern "C" { +#endif + + +//--------------------------------------------------------------------+ +// API Implemented by HCD +//--------------------------------------------------------------------+ + +// Get operational address i.e EHCI Command register +uint32_t hcd_ehci_register_addr(uint8_t rhport); + +//--------------------------------------------------------------------+ +// API Implemented by EHCI +//--------------------------------------------------------------------+ + +// Initialize EHCI driver +extern bool hcd_ehci_init (uint8_t rhport); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/portable/nxp/transdimension/hcd_transdimension.c b/src/portable/nxp/transdimension/hcd_transdimension.c index e6b7afe8f..db447ef23 100644 --- a/src/portable/nxp/transdimension/hcd_transdimension.c +++ b/src/portable/nxp/transdimension/hcd_transdimension.c @@ -43,6 +43,7 @@ #include "common/tusb_common.h" #include "common_transdimension.h" +#include "portable/ehci/hcd_ehci.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF @@ -75,9 +76,6 @@ typedef struct }; #endif -// TODO better prototype later -extern bool hcd_ehci_init (uint8_t rhport); // from ehci.c - //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ -- cgit v1.3.1 From 98f5082191e2135ca783a24a39f95ee82639b9fc Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Feb 2021 13:19:32 +0700 Subject: rename var to be consistent --- src/class/hid/hid_host.c | 36 +++++++++++++++++++----------------- src/class/hid/hid_host.h | 2 +- src/class/msc/msc_host.c | 12 +++++------- src/class/msc/msc_host.h | 2 +- src/host/usbh.c | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 64d1b8e5d..9e41f9f45 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -47,12 +47,12 @@ typedef struct { //--------------------------------------------------------------------+ // HID Interface common functions //--------------------------------------------------------------------+ -static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *p_endpoint_desc, hidh_interface_t *p_hid) +static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *desc_ep, hidh_interface_t *p_hid) { - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, p_endpoint_desc) ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); - p_hid->ep_in = p_endpoint_desc->bEndpointAddress; - p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor + p_hid->ep_in = desc_ep->bEndpointAddress; + p_hid->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor p_hid->itf_num = interface_number; p_hid->valid = true; @@ -161,34 +161,36 @@ void hidh_init(void) CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256]; #endif -bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) +bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) { - uint8_t const *p_desc = (uint8_t const *) p_interface_desc; + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + + uint8_t const *p_desc = (uint8_t const *) desc_itf; //------------- HID descriptor -------------// - p_desc += p_desc[DESC_OFFSET_LEN]; - tusb_hid_descriptor_hid_t const *p_desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == p_desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA); + p_desc = tu_desc_next(p_desc); + tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA); //------------- Endpoint Descriptor -------------// - p_desc += p_desc[DESC_OFFSET_LEN]; - tusb_desc_endpoint_t const * p_endpoint_desc = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint_desc->bDescriptorType, TUSB_ERROR_INVALID_PARA); + p_desc = tu_desc_next(p_desc); + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, TUSB_ERROR_INVALID_PARA); - if ( HID_SUBCLASS_BOOT == p_interface_desc->bInterfaceSubClass ) + if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { #if CFG_TUH_HID_KEYBOARD - if ( HID_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol) + if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { - TU_ASSERT( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) ); + TU_ASSERT( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, &keyboardh_data[dev_addr-1]) ); TU_LOG2_HEX(keyboardh_data[dev_addr-1].ep_in); } else #endif #if CFG_TUH_HID_MOUSE - if ( HID_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol) + if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) { - TU_ASSERT ( hidh_interface_open(rhport, dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) ); + TU_ASSERT ( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, &mouseh_data[dev_addr-1]) ); TU_LOG2_HEX(mouseh_data[dev_addr-1].ep_in); } else #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 5c77398f8..174601594 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -196,7 +196,7 @@ void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); // Internal Class Driver API //--------------------------------------------------------------------+ void hidh_init(void); -bool hidh_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); +bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length); bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num); bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hidh_close(uint8_t dev_addr); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 34dbec2e3..3e8573df0 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -357,15 +357,13 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) +bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) { - TU_VERIFY (MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && - MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol); + TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && + MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); msch_interface_t* p_msc = get_itf(dev_addr); - - //------------- Open Data Pipe -------------// - tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); for(uint32_t i=0; i<2; i++) { @@ -383,7 +381,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc); } - p_msc->itf_num = itf_desc->bInterfaceNumber; + p_msc->itf_num = desc_itf->bInterfaceNumber; (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); return true; diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 8116e729f..d99f1204a 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -116,7 +116,7 @@ void tuh_msc_unmount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ void msch_init(void); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); +bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length); bool msch_set_config(uint8_t dev_addr, uint8_t itf_num); bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void msch_close(uint8_t dev_addr); diff --git a/src/host/usbh.c b/src/host/usbh.c index 3761f279c..86da97bb8 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -79,7 +79,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = DRIVER_NAME("HID") .class_code = TUSB_CLASS_HID, .init = hidh_init, - .open = hidh_open_subtask, + .open = hidh_open, .set_config = hidh_set_config, .xfer_cb = hidh_xfer_cb, .close = hidh_close -- cgit v1.3.1 From f1148ca5ac8f56774af4b58175d0d61442f86544 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Feb 2021 13:54:18 +0700 Subject: reworking hid host --- src/class/hid/hid_host.c | 43 +++++++++++++++++++++++++++++++++++-------- src/class/hid/hid_host.h | 8 ++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 9e41f9f45..7ae50e4d7 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -35,13 +35,40 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +/* "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard + "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse + "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control + "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control + "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad + "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen + "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad + "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF + */ typedef struct { - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - bool valid; + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; - uint16_t report_size; + bool valid; + uint16_t report_size; // TODO remove later + + uint8_t boot_protocol; // None, Keyboard, Mouse + bool boot_mode; // Boot or Report protocol + uint8_t report_count; // Number of reports + + struct { + uint8_t in_len; // length of IN report + uint8_t out_len; // length of OUT report + uint8_t usage_page; + uint8_t usage; + }reports[CFG_TUH_HID_MAX_REPORT]; + + // Parsed Report ID for convenient API + uint8_t report_id_keyboard; + uint8_t reprot_id_mouse; + uint8_t report_id_gamepad; + uint8_t report_id_consumer; + uint8_t report_id_vendor; }hidh_interface_t; //--------------------------------------------------------------------+ @@ -51,9 +78,9 @@ static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t { TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); + p_hid->itf_num = interface_number; p_hid->ep_in = desc_ep->bEndpointAddress; p_hid->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor - p_hid->itf_num = interface_number; p_hid->valid = true; return true; @@ -170,12 +197,12 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de //------------- HID descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA); + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, TUSB_ERROR_INVALID_PARA); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 174601594..d43158186 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -38,6 +38,14 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUH_HID_MAX_REPORT +#define CFG_TUH_HID_MAX_REPORT 8 +#endif + //--------------------------------------------------------------------+ // KEYBOARD Application API //--------------------------------------------------------------------+ -- cgit v1.3.1 From 68fa17e17ca900ec2800c55c9345a2a0fed3fca9 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Feb 2021 14:07:33 +0700 Subject: more API rename --- examples/host/cdc_msc_hid/src/main.c | 4 ++-- src/class/hid/hid_device.h | 4 ++-- src/class/hid/hid_host.c | 8 ++++---- src/class/hid/hid_host.h | 14 ++++++++++++-- 4 files changed, 20 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index c6ab54682..84e88e509 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -257,7 +257,7 @@ void hid_task(void) uint8_t const addr = 1; #if CFG_TUH_HID_KEYBOARD - if ( tuh_hid_keyboard_is_mounted(addr) ) + if ( tuh_hid_keyboard_mounted(addr) ) { if ( !tuh_hid_keyboard_is_busy(addr) ) { @@ -268,7 +268,7 @@ void hid_task(void) #endif #if CFG_TUH_HID_MOUSE - if ( tuh_hid_mouse_is_mounted(addr) ) + if ( tuh_hid_mouse_mounted(addr) ) { if ( !tuh_hid_mouse_is_busy(addr) ) { diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 0c59d5d20..7520d3453 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -50,7 +50,7 @@ #endif //--------------------------------------------------------------------+ -// Application API (Multiple Ports) +// Application API (Multiple Instances) // CFG_TUD_HID > 1 //--------------------------------------------------------------------+ @@ -76,7 +76,7 @@ bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); //--------------------------------------------------------------------+ -// Application API (Single Port) +// Application API (Single Instance) //--------------------------------------------------------------------+ static inline bool tud_hid_ready(void); static inline bool tud_hid_boot_mode(void); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 7ae50e4d7..aa6188a24 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -113,7 +113,7 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int static hidh_interface_t keyboardh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- KEYBOARD PUBLIC API (parameter validation required) -------------// -bool tuh_hid_keyboard_is_mounted(uint8_t dev_addr) +bool tuh_hid_keyboard_mounted(uint8_t dev_addr) { return tuh_device_is_configured(dev_addr) && (keyboardh_data[dev_addr-1].ep_in != 0); } @@ -125,7 +125,7 @@ tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* p_report) bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) { - return tuh_hid_keyboard_is_mounted(dev_addr) && hcd_edpt_busy(dev_addr, keyboardh_data[dev_addr-1].ep_in); + return tuh_hid_keyboard_mounted(dev_addr) && hcd_edpt_busy(dev_addr, keyboardh_data[dev_addr-1].ep_in); } #endif @@ -138,14 +138,14 @@ bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- Public API -------------// -bool tuh_hid_mouse_is_mounted(uint8_t dev_addr) +bool tuh_hid_mouse_mounted(uint8_t dev_addr) { return tuh_device_is_configured(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); } bool tuh_hid_mouse_is_busy(uint8_t dev_addr) { - return tuh_hid_mouse_is_mounted(dev_addr) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); + return tuh_hid_mouse_mounted(dev_addr) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); } tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index d43158186..f777fe45d 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -46,6 +46,16 @@ #define CFG_TUH_HID_MAX_REPORT 8 #endif +//--------------------------------------------------------------------+ +// Application API (Multiple Instances) +// CFG_TUH_HID > 1 +//--------------------------------------------------------------------+ + + +//--------------------------------------------------------------------+ +// Application API (Single Instance) +//--------------------------------------------------------------------+ + //--------------------------------------------------------------------+ // KEYBOARD Application API //--------------------------------------------------------------------+ @@ -63,7 +73,7 @@ extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; // TODO used weak attr if * \retval true if device supports Keyboard interface * \retval false if device does not support Keyboard interface or is not mounted */ -bool tuh_hid_keyboard_is_mounted(uint8_t dev_addr); +bool tuh_hid_keyboard_mounted(uint8_t dev_addr); /** \brief Check if the interface is currently busy or not * \param[in] dev_addr device address @@ -128,7 +138,7 @@ void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr); * \retval true if device supports Mouse interface * \retval false if device does not support Mouse interface or is not mounted */ -bool tuh_hid_mouse_is_mounted(uint8_t dev_addr); +bool tuh_hid_mouse_mounted(uint8_t dev_addr); /** \brief Check if the interface is currently busy or not * \param[in] dev_addr device address -- cgit v1.3.1 From 2666e1efec20d78f8f74c23cdbb7977737b8d956 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 2 May 2021 01:46:22 +0700 Subject: add tuh_inited() and tud_inited() --- src/device/usbd.c | 19 ++++++++++++++++--- src/device/usbd.h | 3 +++ src/host/usbh.c | 14 ++++++++++++++ src/host/usbh.h | 3 +++ 4 files changed, 36 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 2853b619b..fe18b21b3 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -44,6 +44,10 @@ //--------------------------------------------------------------------+ // Device Data //--------------------------------------------------------------------+ + +// Invalid driver ID in itf2drv[] ep2drv[][] mapping +enum { DRVID_INVALID = 0xFFu }; + typedef struct { struct TU_ATTR_PACKED @@ -76,9 +80,6 @@ typedef struct static usbd_device_t _usbd_dev; -// Invalid driver ID in itf2drv[] ep2drv[][] mapping -enum { DRVID_INVALID = 0xFFu }; - //--------------------------------------------------------------------+ // Class Driver //--------------------------------------------------------------------+ @@ -241,6 +242,8 @@ static inline usbd_class_driver_t const * get_driver(uint8_t drvid) // DCD Event //--------------------------------------------------------------------+ +static bool _initialized = false; + // Event queue // OPT_MODE_DEVICE is used by OS NONE for mutex (disable usb isr) OSAL_QUEUE_DEF(OPT_MODE_DEVICE, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); @@ -368,8 +371,16 @@ bool tud_connect(void) //--------------------------------------------------------------------+ // USBD Task //--------------------------------------------------------------------+ +bool tud_inited(void) +{ + return _initialized; +} + bool tud_init (void) { + // skip if already initialized + if (_initialized) return _initialized; + TU_LOG2("USBD init\r\n"); tu_varclr(&_usbd_dev); @@ -402,6 +413,8 @@ bool tud_init (void) dcd_init(TUD_OPT_RHPORT); dcd_int_enable(TUD_OPT_RHPORT); + _initialized = true; + return true; } diff --git a/src/device/usbd.h b/src/device/usbd.h index 7c50a6db0..10fbe0bf1 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -43,6 +43,9 @@ extern "C" { // Init device stack bool tud_init (void); +// Check if device stack is already initialized +bool tud_inited(void); + // Task function should be called in main/rtos loop void tud_task (void); diff --git a/src/host/usbh.c b/src/host/usbh.c index 86da97bb8..411945fdb 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -121,6 +121,8 @@ enum { CONFIG_NUM = 1 }; // default to use configuration 1 // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ +static bool _initialized = false; + // including zero-address CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; @@ -170,8 +172,19 @@ void osal_task_delay(uint32_t msec) //--------------------------------------------------------------------+ // CLASS-USBD API (don't require to verify parameters) //--------------------------------------------------------------------+ + +bool tuh_inited(void) +{ + return _initialized; +} + bool tuh_init(void) { + // skip if already initialized + if (_initialized) return _initialized; + + TU_LOG2("USBH init\r\n"); + tu_memclr(_usbh_devices, sizeof(usbh_device_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); //------------- Enumeration & Reporter Task init -------------// @@ -202,6 +215,7 @@ bool tuh_init(void) TU_ASSERT(hcd_init(TUH_OPT_RHPORT)); hcd_int_enable(TUH_OPT_RHPORT); + _initialized = true; return true; } diff --git a/src/host/usbh.h b/src/host/usbh.h index a05010b36..732a4b66e 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -78,6 +78,9 @@ typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request // Init host stack bool tuh_init(void); +// Check if host stack is already initialized +bool tuh_inited(void); + // Task function should be called in main/rtos loop void tuh_task(void); -- cgit v1.3.1 From 3a7f8b3ac3988eeb653ada6e3efdd7acb68fbe0f Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 May 2021 17:32:52 +0700 Subject: separte tusb_init/inited() to tud/tuh init/inited add rhport to tud_init() --- src/device/usbd.c | 14 +++++++------- src/device/usbd.h | 2 +- src/host/usbh.c | 14 +++++++------- src/host/usbh.h | 2 +- src/tusb.c | 27 +++++++++++++++------------ 5 files changed, 31 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index fe18b21b3..280235911 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -242,7 +242,7 @@ static inline usbd_class_driver_t const * get_driver(uint8_t drvid) // DCD Event //--------------------------------------------------------------------+ -static bool _initialized = false; +static bool _usbd_initialized = false; // Event queue // OPT_MODE_DEVICE is used by OS NONE for mutex (disable usb isr) @@ -373,13 +373,13 @@ bool tud_connect(void) //--------------------------------------------------------------------+ bool tud_inited(void) { - return _initialized; + return _usbd_initialized; } -bool tud_init (void) +bool tud_init (uint8_t rhport) { // skip if already initialized - if (_initialized) return _initialized; + if (_usbd_initialized) return _usbd_initialized; TU_LOG2("USBD init\r\n"); @@ -410,10 +410,10 @@ bool tud_init (void) } // Init device controller driver - dcd_init(TUD_OPT_RHPORT); - dcd_int_enable(TUD_OPT_RHPORT); + dcd_init(rhport); + dcd_int_enable(rhport); - _initialized = true; + _usbd_initialized = true; return true; } diff --git a/src/device/usbd.h b/src/device/usbd.h index 10fbe0bf1..c0bec9566 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -41,7 +41,7 @@ extern "C" { //--------------------------------------------------------------------+ // Init device stack -bool tud_init (void); +bool tud_init (uint8_t rhport); // Check if device stack is already initialized bool tud_inited(void); diff --git a/src/host/usbh.c b/src/host/usbh.c index 411945fdb..5132d7e93 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -121,7 +121,7 @@ enum { CONFIG_NUM = 1 }; // default to use configuration 1 // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -static bool _initialized = false; +static bool _usbh_initialized = false; // including zero-address CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; @@ -175,13 +175,13 @@ void osal_task_delay(uint32_t msec) bool tuh_inited(void) { - return _initialized; + return _usbh_initialized; } -bool tuh_init(void) +bool tuh_init(uint8_t rhport) { // skip if already initialized - if (_initialized) return _initialized; + if (_usbh_initialized) return _usbh_initialized; TU_LOG2("USBH init\r\n"); @@ -212,10 +212,10 @@ bool tuh_init(void) usbh_class_drivers[drv_id].init(); } - TU_ASSERT(hcd_init(TUH_OPT_RHPORT)); - hcd_int_enable(TUH_OPT_RHPORT); + TU_ASSERT(hcd_init(rhport)); + hcd_int_enable(rhport); - _initialized = true; + _usbh_initialized = true; return true; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 732a4b66e..809ffd40b 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -76,7 +76,7 @@ typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request //--------------------------------------------------------------------+ // Init host stack -bool tuh_init(void); +bool tuh_init(uint8_t rhport); // Check if host stack is already initialized bool tuh_inited(void); diff --git a/src/tusb.c b/src/tusb.c index 31452e897..0350fa1de 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -30,8 +30,6 @@ #include "tusb.h" -static bool _initialized = false; - // TODO clean up #if TUSB_OPT_DEVICE_ENABLED #include "device/usbd_pvt.h" @@ -39,25 +37,30 @@ static bool _initialized = false; bool tusb_init(void) { - // skip if already initialized - if (_initialized) return true; - -#if TUSB_OPT_HOST_ENABLED - TU_ASSERT( tuh_init() ); // init host stack -#endif - #if TUSB_OPT_DEVICE_ENABLED - TU_ASSERT ( tud_init() ); // init device stack + TU_ASSERT ( tud_init(TUD_OPT_RHPORT) ); // init device stack #endif - _initialized = true; +#if TUSB_OPT_HOST_ENABLED + TU_ASSERT( tuh_init(TUH_OPT_RHPORT) ); // init host stack +#endif return true; } bool tusb_inited(void) { - return _initialized; + bool ret = false; + +#if TUSB_OPT_DEVICE_ENABLED + ret = ret || tud_inited(); +#endif + +#if TUSB_OPT_HOST_ENABLED + ret = ret || tuh_inited(); +#endif + + return ret; } /*------------------------------------------------------------------*/ -- cgit v1.3.1 From 13613eafb70acd028572305b3e0b9064f905b835 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 May 2021 18:11:46 +0700 Subject: correct ehci control endpoint address report on xfer complete improve host log --- src/host/usbh.c | 9 ++++++--- src/host/usbh_control.c | 1 + src/portable/ehci/ehci.c | 15 ++++++++------- 3 files changed, 15 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index 5132d7e93..88e5c02a7 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -626,10 +626,11 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request static bool enum_request_set_addr(void) { // Set Address - TU_LOG2("Set Address \r\n"); uint8_t const new_addr = get_new_address(); TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices + TU_LOG2("Set Address = %d\r\n", new_addr); + usbh_device_t* dev0 = &_usbh_devices[0]; usbh_device_t* new_dev = &_usbh_devices[new_addr]; @@ -783,6 +784,7 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c TU_ASSERT ( usbh_pipe_control_open(new_addr, new_dev->ep0_packet_size) ); // Get full device descriptor + TU_LOG2("Get Device Descriptor\r\n"); tusb_control_request_t const new_request = { .bmRequestType_bit = @@ -849,7 +851,8 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r TU_ASSERT(total_len <= CFG_TUSB_HOST_ENUM_BUFFER_SIZE); - //Get full configuration descriptor + // Get full configuration descriptor + TU_LOG2("Get Configuration Descriptor\r\n"); tusb_control_request_t const new_request = { .bmRequestType_bit = @@ -879,7 +882,7 @@ static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request // Driver open aren't allowed to make any usb transfer yet parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); - TU_LOG2("Set Configuration Descriptor\r\n"); + TU_LOG2("Set Configuration = %d\r\n", CONFIG_NUM); tusb_control_request_t const new_request = { .bmRequestType_bit = diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index de55bd5e1..2b9f47793 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -80,6 +80,7 @@ bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) { + TU_LOG2("\r\n"); if (_ctrl_xfer.complete_cb) _ctrl_xfer.complete_cb(dev_addr, &_ctrl_xfer.request, result); } diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 484e49600..eab1f8928 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -513,18 +513,19 @@ static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) // free all TDs from the head td to the first active TD while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active) { - // TD need to be freed and removed from qhd, before invoking callback - bool is_ioc = (p_qhd->p_qtd_list_head->int_on_complete != 0); - p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; + ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_qtd_list_head; + bool const is_ioc = (qtd->int_on_complete != 0); + uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, qtd->pid == EHCI_PID_IN ? 1 : 0); - p_qhd->p_qtd_list_head->used = 0; // free QTD + p_qhd->total_xferred_bytes += qtd->expected_bytes - qtd->total_bytes; + + // TD need to be freed and removed from qhd, before invoking callback + qtd->used = 0; // free QTD qtd_remove_1st_from_qhd(p_qhd); if (is_ioc) { - // end of request - // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), p_qhd->total_xferred_bytes, XFER_RESULT_SUCCESS, true); + hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, p_qhd->total_xferred_bytes, XFER_RESULT_SUCCESS, true); p_qhd->total_xferred_bytes = 0; } } -- cgit v1.3.1 From e83bdcdfdc521fef2dd182a5f83cd1c1be673865 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 15:29:17 +0700 Subject: reworking hid host --- examples/host/cdc_msc_hid/src/main.c | 2 +- examples/host/cdc_msc_hid/src/tusb_config.h | 4 + src/class/hid/hid_host.c | 159 ++++++++++++++++------------ src/class/hid/hid_host.h | 14 ++- src/host/usbh.c | 1 + 5 files changed, 108 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 652a372e9..b3fd1f2af 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -154,7 +154,7 @@ static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) prev_report = *p_new_report; } -void tuh_hid_keyboard_mounted_cb(uint8_t dev_addr) +void tuh_hid_mounted_cb(uint8_t dev_addr) { // application set-up printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index fabc7765c..82155f1ca 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -73,9 +73,13 @@ #define CFG_TUH_HUB 1 #define CFG_TUH_CDC 1 + +#define CFG_TUH_HID 2 + #define CFG_TUH_HID_KEYBOARD 1 #define CFG_TUH_HID_MOUSE 1 #define CFG_TUSB_HOST_HID_GENERIC 0 // (not yet supported) + #define CFG_TUH_MSC 1 #define CFG_TUH_VENDOR 0 diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index aa6188a24..dae20b305 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -44,11 +44,14 @@ "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF */ -typedef struct { +typedef struct +{ uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; + uint16_t report_desc_len; + bool valid; uint16_t report_size; // TODO remove later @@ -61,16 +64,38 @@ typedef struct { uint8_t out_len; // length of OUT report uint8_t usage_page; uint8_t usage; - }reports[CFG_TUH_HID_MAX_REPORT]; + }reports[CFG_TUH_HID_REPORT_MAX]; // Parsed Report ID for convenient API - uint8_t report_id_keyboard; - uint8_t reprot_id_mouse; - uint8_t report_id_gamepad; - uint8_t report_id_consumer; - uint8_t report_id_vendor; + uint8_t rid_keyboard; + uint8_t rid_mouse; + uint8_t rid_gamepad; + uint8_t rid_consumer; }hidh_interface_t; +typedef struct +{ + uint8_t inst_count; + hidh_interface_t instance[CFG_TUH_HID]; +} hidh_device_t; + +static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; + +#if 0 +CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256]; +#endif + +TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) +{ + return &_hidh_dev[dev_addr-1]; +} + +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t inst) +{ + return &_hidh_dev[dev_addr-1].instance[inst]; +} + + //--------------------------------------------------------------------+ // HID Interface common functions //--------------------------------------------------------------------+ @@ -108,27 +133,32 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int //--------------------------------------------------------------------+ // KEYBOARD //--------------------------------------------------------------------+ -#if CFG_TUH_HID_KEYBOARD -static hidh_interface_t keyboardh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 - -//------------- KEYBOARD PUBLIC API (parameter validation required) -------------// -bool tuh_hid_keyboard_mounted(uint8_t dev_addr) +bool tuh_hid_keyboard_mounted(uint8_t dev_addr) { - return tuh_device_is_configured(dev_addr) && (keyboardh_data[dev_addr-1].ep_in != 0); + uint8_t itf = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + + // TODO check rid_keyboard + return tuh_device_is_configured(dev_addr) && (hid_itf->ep_in != 0); } -tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* p_report) +tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* buffer) { - return hidh_interface_get_report(dev_addr, p_report, &keyboardh_data[dev_addr-1]); + uint8_t itf = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + + return hidh_interface_get_report(dev_addr, buffer, hid_itf); } bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) { - return tuh_hid_keyboard_mounted(dev_addr) && hcd_edpt_busy(dev_addr, keyboardh_data[dev_addr-1].ep_in); + uint8_t itf = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + + return tuh_hid_keyboard_mounted(dev_addr) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); } -#endif //--------------------------------------------------------------------+ // MOUSE @@ -158,36 +188,20 @@ tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) //--------------------------------------------------------------------+ // GENERIC //--------------------------------------------------------------------+ -#if CFG_TUSB_HOST_HID_GENERIC -//STATIC_ struct { -// hidh_interface_info_t -//} generic_data[CFG_TUSB_HOST_DEVICE_MAX]; - -#endif //--------------------------------------------------------------------+ // CLASS-USBH API (don't require to verify parameters) //--------------------------------------------------------------------+ void hidh_init(void) { -#if CFG_TUH_HID_KEYBOARD - tu_memclr(&keyboardh_data, sizeof(hidh_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); -#endif + tu_memclr(_hidh_dev, sizeof(_hidh_dev)); #if CFG_TUH_HID_MOUSE tu_memclr(&mouseh_data, sizeof(hidh_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); #endif - -#if CFG_TUSB_HOST_HID_GENERIC - hidh_generic_init(); -#endif } -#if 0 -CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256]; -#endif - bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) { TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); @@ -199,6 +213,18 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); + // not enough interface, try to increase CFG_TUH_HID + // TODO multiple devices + hidh_device_t* hid_dev = get_dev(dev_addr); + TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID); + + hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); + hid_dev->inst_count++; + + hid_itf->itf_num = desc_itf->bInterfaceNumber; + hid_itf->boot_mode = false; // default is report mode + hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); + //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; @@ -206,11 +232,20 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { + hid_itf->boot_protocol = desc_itf->bInterfaceProtocol; + #if CFG_TUH_HID_KEYBOARD if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { - TU_ASSERT( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, &keyboardh_data[dev_addr-1]) ); - TU_LOG2_HEX(keyboardh_data[dev_addr-1].ep_in); + TU_ASSERT( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, hid_itf) ); + TU_LOG2_HEX(hid_itf->ep_in); + + hid_itf->report_count = 1; + + hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; + hid_itf->reports[0].usage = HID_USAGE_DESKTOP_KEYBOARD; + hid_itf->reports[0].in_len = 8; + hid_itf->reports[0].out_len = 1; } else #endif @@ -226,13 +261,9 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de // Not supported protocol return false; } - }else - { - // Not supported subclass - return false; } - *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_desc_endpoint_t); + *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); return true; } @@ -276,12 +307,13 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) usbh_driver_set_config_complete(dev_addr, itf_num); -#if CFG_TUH_HID_KEYBOARD - if (( keyboardh_data[dev_addr-1].itf_num == itf_num) && keyboardh_data[dev_addr-1].valid) - { - tuh_hid_keyboard_mounted_cb(dev_addr); +// uint8_t itf = 0; +// hidh_interface_t* hid_itf = &_hidh_itf[itf]; + + + if (itf_num == 0 ) { + if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr); } -#endif #if CFG_TUH_HID_MOUSE if (( mouseh_data[dev_addr-1].ep_in == itf_num ) && mouseh_data[dev_addr-1].valid) @@ -297,12 +329,15 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 { (void) xferred_bytes; // TODO may need to use this para later +// uint8_t itf = 0; +// hidh_interface_t* hid_itf = &_hidh_itf[itf]; + #if CFG_TUH_HID_KEYBOARD - if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) - { - tuh_hid_keyboard_isr(dev_addr, event); - return true; - } +// if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) +// { +// tuh_hid_keyboard_isr(dev_addr, event); +// return true; +// } #endif #if CFG_TUH_HID_MOUSE @@ -311,10 +346,6 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 tuh_hid_mouse_isr(dev_addr, event); return true; } -#endif - -#if CFG_TUSB_HOST_HID_GENERIC - #endif return true; @@ -322,13 +353,11 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 void hidh_close(uint8_t dev_addr) { -#if CFG_TUH_HID_KEYBOARD - if ( keyboardh_data[dev_addr-1].ep_in != 0 ) - { - hidh_interface_close(&keyboardh_data[dev_addr-1]); - tuh_hid_keyboard_unmounted_cb(dev_addr); - } -#endif + uint8_t itf = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + + if (tuh_hid_unmounted_cb) tuh_hid_unmounted_cb(dev_addr); + hidh_interface_close(hid_itf); #if CFG_TUH_HID_MOUSE if( mouseh_data[dev_addr-1].ep_in != 0 ) @@ -337,12 +366,6 @@ void hidh_close(uint8_t dev_addr) tuh_hid_mouse_unmounted_cb( dev_addr ); } #endif - -#if CFG_TUSB_HOST_HID_GENERIC - hidh_generic_close(dev_addr); -#endif } - - #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index f777fe45d..10ecc457f 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -42,8 +42,8 @@ // Class Driver Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUH_HID_MAX_REPORT -#define CFG_TUH_HID_MAX_REPORT 8 +#ifndef CFG_TUH_HID_REPORT_MAX +#define CFG_TUH_HID_REPORT_MAX 4 #endif //--------------------------------------------------------------------+ @@ -56,6 +56,12 @@ // Application API (Single Instance) //--------------------------------------------------------------------+ +// tuh_hid_instance_count() +//bool tuh_hid_get_report(uint8_t dev_addr, uint8_t report_id, void * p_report, uint8_t len); + +TU_ATTR_WEAK void tuh_hid_mounted_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr); + //--------------------------------------------------------------------+ // KEYBOARD Application API //--------------------------------------------------------------------+ @@ -66,7 +72,9 @@ * The interface API includes status checking function, data transferring function and callback functions * @{ */ -extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; // TODO used weak attr if build failed without KEYBOARD enabled +// TODO used weak attr if build failed without KEYBOARD enabled +// TODO remove +extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; /** \brief Check if device supports Keyboard interface or not * \param[in] dev_addr device address diff --git a/src/host/usbh.c b/src/host/usbh.c index 88e5c02a7..f7cad4640 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -915,6 +915,7 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co // Start the Set Configuration process for interfaces (itf = 0xff) // Since driver can perform control transfer within its set_config, this is done asynchronously. // The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete() + // TODO use separated API instead of usig 0xff usbh_driver_set_config_complete(dev_addr, 0xff); return true; -- cgit v1.3.1 From e0dbb489aed9d9e7f081c379400dcb74600ede6a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 19:27:05 +0700 Subject: rename CFG_TUSB_HOST_ENUM_BUFFER_SIZE to CFG_TUH_ENUMERATION_BUFSZIE add usbh_get_enum_buf --- examples/host/cdc_msc_hid/src/tusb_config.h | 13 +++++++++++++ src/host/usbh.c | 9 +++++++-- src/host/usbh.h | 2 ++ src/host/usbh_control.c | 2 +- src/tusb_option.h | 4 ++-- 5 files changed, 25 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 82155f1ca..e1e02e31e 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -71,6 +71,9 @@ // CONFIGURATION //-------------------------------------------------------------------- +// Size of buffer to hold descriptors and other data used for enumeration +#define CFG_TUH_ENUMERATION_BUFSZIE 256 + #define CFG_TUH_HUB 1 #define CFG_TUH_CDC 1 @@ -85,6 +88,16 @@ #define CFG_TUSB_HOST_DEVICE_MAX (CFG_TUH_HUB ? 5 : 1) // normal hub has 4 ports +//------------- HID -------------// + +// Max number of reports per interface +// E.g composite HID with keyboard + mouse + gamepad will have 3 reports +#define CFG_TUH_HID_REPORT_MAX 4 + +// Max buffer +#define CFG_TUH_HID_REPORT_DESCRIPTOR_BUFSIZE 256 + + #ifdef __cplusplus } #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index f7cad4640..fe0b2b987 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -131,7 +131,7 @@ CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; OSAL_QUEUE_DEF(OPT_MODE_HOST, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); static osal_queue_t _usbh_q; -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _usbh_ctrl_buf[CFG_TUSB_HOST_ENUM_BUFFER_SIZE]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSZIE]; //------------- Helper Function Prototypes -------------// static bool enum_new_device(hcd_event_t* event); @@ -144,6 +144,11 @@ uint8_t usbh_get_rhport(uint8_t dev_addr) return _usbh_devices[dev_addr].rhport; } +uint8_t* usbh_get_enum_buf(void) +{ + return _usbh_ctrl_buf; +} + //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) //--------------------------------------------------------------------+ @@ -849,7 +854,7 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r // Use offsetof to avoid pointer to the odd/misaligned address memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); - TU_ASSERT(total_len <= CFG_TUSB_HOST_ENUM_BUFFER_SIZE); + TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSZIE); // Get full configuration descriptor TU_LOG2("Get Configuration Descriptor\r\n"); diff --git a/src/host/usbh.h b/src/host/usbh.h index 809ffd40b..5e7abe868 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -124,6 +124,8 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); uint8_t usbh_get_rhport(uint8_t dev_addr); +uint8_t* usbh_get_enum_buf(void); + #ifdef __cplusplus } #endif diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 2b9f47793..974d10662 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -50,7 +50,7 @@ typedef struct static usbh_control_xfer_t _ctrl_xfer; //CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN -//static uint8_t _tuh_ctrl_buf[CFG_TUSB_HOST_ENUM_BUFFER_SIZE]; +//static uint8_t _tuh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSZIE]; //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION diff --git a/src/tusb_option.h b/src/tusb_option.h index b59c7cb22..53d3d9d20 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -269,8 +269,8 @@ //------------- HID CLASS -------------// #define HOST_CLASS_HID ( CFG_TUH_HID_KEYBOARD + CFG_TUH_HID_MOUSE + CFG_TUSB_HOST_HID_GENERIC ) - #ifndef CFG_TUSB_HOST_ENUM_BUFFER_SIZE - #define CFG_TUSB_HOST_ENUM_BUFFER_SIZE 256 + #ifndef CFG_TUH_ENUMERATION_BUFSZIE + #define CFG_TUH_ENUMERATION_BUFSZIE 256 #endif //------------- CLASS -------------// -- cgit v1.3.1 From 510beef9f8f78689424ee8f62d3883b89fe794fa Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 19:27:34 +0700 Subject: make tuh_msc_mount_cb() tuh_msc_unmount_cb() as weak callback --- src/class/msc/msc_host.c | 9 ++++++--- src/class/msc/msc_host.h | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 3e8573df0..4869c8c03 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -287,7 +287,7 @@ bool tuh_msc_reset(uint8_t dev_addr) #endif //--------------------------------------------------------------------+ -// CLASS-USBH API (don't require to verify parameters) +// CLASS-USBH API //--------------------------------------------------------------------+ void msch_init(void) { @@ -298,7 +298,9 @@ void msch_close(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); tu_memclr(p_msc, sizeof(msch_interface_t)); - tuh_msc_unmount_cb(dev_addr); // invoke Application Callback + + // invoke Application Callback + if (tuh_msc_unmount_cb) tuh_msc_unmount_cb(dev_addr); } bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) @@ -471,8 +473,9 @@ static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw // Mark enumeration is complete p_msc->mounted = true; - tuh_msc_mount_cb(dev_addr); + if (tuh_msc_mount_cb) tuh_msc_mount_cb(dev_addr); + // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, p_msc->itf_num); return true; diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index d99f1204a..7ebc9b5a8 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -106,10 +106,10 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r //------------- Application Callback -------------// // Invoked when a device with MassStorage interface is mounted -void tuh_msc_mount_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_msc_mount_cb(uint8_t dev_addr); // Invoked when a device with MassStorage interface is unmounted -void tuh_msc_unmount_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_msc_unmount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API -- cgit v1.3.1 From be165a67134d08f7c32386de041f1a2665e696be Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 19:36:52 +0700 Subject: reworking host hid API --- examples/host/cdc_msc_hid/src/main.c | 17 +-- src/class/hid/hid_host.c | 274 ++++++++++++++++++++--------------- src/class/hid/hid_host.h | 62 ++++---- 3 files changed, 192 insertions(+), 161 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index b3fd1f2af..5543e9efb 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -162,19 +162,12 @@ void tuh_hid_mounted_cb(uint8_t dev_addr) tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); } -void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr) +void tuh_hid_unmounted_cb(uint8_t dev_addr) { // application tear-down printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); } -// invoked ISR context -void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event) -{ - (void) dev_addr; - (void) event; -} - #endif #if CFG_TUH_HID_MOUSE @@ -242,12 +235,6 @@ void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr) printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); } -// invoked ISR context -void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event) -{ - (void) dev_addr; - (void) event; -} #endif @@ -257,7 +244,7 @@ void hid_task(void) uint8_t const addr = 1; #if CFG_TUH_HID_KEYBOARD - if ( tuh_hid_keyboard_mounted(addr) ) + if ( tuh_n_hid_n_keyboard_mounted(addr, 0) ) { if ( !tuh_hid_keyboard_is_busy(addr) ) { diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index dae20b305..a5aa33c2c 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -50,6 +50,7 @@ typedef struct uint8_t ep_in; uint8_t ep_out; + uint8_t report_desc_type; uint16_t report_desc_len; bool valid; @@ -75,42 +76,51 @@ typedef struct typedef struct { - uint8_t inst_count; - hidh_interface_t instance[CFG_TUH_HID]; + uint8_t itf_count; + hidh_interface_t interface[CFG_TUH_HID]; } hidh_device_t; static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; -#if 0 -CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256]; -#endif +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t _report_desc_buf[256]; +// Get Device by address TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) { return &_hidh_dev[dev_addr-1]; } -TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t inst) +// Get Interface by instance number +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) { - return &_hidh_dev[dev_addr-1].instance[inst]; + return &_hidh_dev[dev_addr-1].interface[instance]; } +// Get Interface by interface number +static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) +{ + for(uint8_t inst=0; institf_num == itf) && (hid->ep_in != 0) ) return hid; + } + + return NULL; +} //--------------------------------------------------------------------+ -// HID Interface common functions +// Application API //--------------------------------------------------------------------+ -static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *desc_ep, hidh_interface_t *p_hid) +uint8_t tuh_n_hid_instance_count(uint8_t daddr) { - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); - - p_hid->itf_num = interface_number; - p_hid->ep_in = desc_ep->bEndpointAddress; - p_hid->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor - p_hid->valid = true; - - return true; + return get_dev(daddr)->itf_count; } +//--------------------------------------------------------------------+ +// HID Interface common functions +//--------------------------------------------------------------------+ + static inline void hidh_interface_close(hidh_interface_t *p_hid) { tu_memclr(p_hid, sizeof(hidh_interface_t)); @@ -123,7 +133,7 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int // TODO change to use is configured function TU_ASSERT(TUSB_DEVICE_STATE_CONFIGURED == tuh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); TU_VERIFY(report, TUSB_ERROR_INVALID_PARA); - TU_ASSERT(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); + TU_VERIFY(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size) ) ; @@ -134,10 +144,9 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int // KEYBOARD //--------------------------------------------------------------------+ -bool tuh_hid_keyboard_mounted(uint8_t dev_addr) +bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) { - uint8_t itf = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); // TODO check rid_keyboard return tuh_device_is_configured(dev_addr) && (hid_itf->ep_in != 0); @@ -153,13 +162,12 @@ tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* buffer) bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) { - uint8_t itf = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + uint8_t instance = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return tuh_hid_keyboard_mounted(dev_addr) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); + return tuh_n_hid_n_keyboard_mounted(dev_addr, instance) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); } - //--------------------------------------------------------------------+ // MOUSE //--------------------------------------------------------------------+ @@ -191,17 +199,63 @@ tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) //--------------------------------------------------------------------+ -// CLASS-USBH API (don't require to verify parameters) +// USBH API //--------------------------------------------------------------------+ void hidh_init(void) { tu_memclr(_hidh_dev, sizeof(_hidh_dev)); +} + +bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +{ + (void) xferred_bytes; // TODO may need to use this para later + +// uint8_t itf = 0; +// hidh_interface_t* hid_itf = &_hidh_itf[itf]; + +#if CFG_TUH_HID_KEYBOARD +// if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) +// { +// tuh_hid_keyboard_isr(dev_addr, event); +// return true; +// } +#endif #if CFG_TUH_HID_MOUSE - tu_memclr(&mouseh_data, sizeof(hidh_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); +// if ( ep_addr == mouseh_data[dev_addr-1].ep_in ) +// { +// tuh_hid_mouse_isr(dev_addr, event); +// return true; +// } #endif + + return true; } +void hidh_close(uint8_t dev_addr) +{ + uint8_t itf = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + + if (tuh_hid_unmounted_cb) tuh_hid_unmounted_cb(dev_addr); + hidh_interface_close(hid_itf); + +#if CFG_TUH_HID_MOUSE + if( mouseh_data[dev_addr-1].ep_in != 0 ) + { + hidh_interface_close(&mouseh_data[dev_addr-1]); + tuh_hid_mouse_unmounted_cb( dev_addr ); + } +#endif +} + +//--------------------------------------------------------------------+ +// Enumeration +//--------------------------------------------------------------------+ + +static bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); + bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) { TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); @@ -216,50 +270,59 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de // not enough interface, try to increase CFG_TUH_HID // TODO multiple devices hidh_device_t* hid_dev = get_dev(dev_addr); - TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID); - - hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); - hid_dev->inst_count++; - - hid_itf->itf_num = desc_itf->bInterfaceNumber; - hid_itf->boot_mode = false; // default is report mode - hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); + TU_ASSERT(hid_dev->itf_count < CFG_TUH_HID); //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); + // TODO also open endpoint OUT + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); + + hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->itf_count); + hid_dev->itf_count++; + + hid_itf->itf_num = desc_itf->bInterfaceNumber; + hid_itf->ep_in = desc_ep->bEndpointAddress; + hid_itf->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor + hid_itf->valid = true; + + TU_LOG2_HEX(hid_itf->ep_in); + + // Assume bNumDescriptors = 1 + hid_itf->report_desc_type = desc_hid->bReportType; + hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); + + hid_itf->boot_mode = false; // default is report mode if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { hid_itf->boot_protocol = desc_itf->bInterfaceProtocol; - #if CFG_TUH_HID_KEYBOARD if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { - TU_ASSERT( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, hid_itf) ); - TU_LOG2_HEX(hid_itf->ep_in); - + // TODO boot protocol may still have more report in report mode hid_itf->report_count = 1; hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; hid_itf->reports[0].usage = HID_USAGE_DESKTOP_KEYBOARD; hid_itf->reports[0].in_len = 8; hid_itf->reports[0].out_len = 1; - } else - #endif - - #if CFG_TUH_HID_MOUSE - if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) + } + else if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) { - TU_ASSERT ( hidh_interface_open(rhport, dev_addr, desc_itf->bInterfaceNumber, desc_ep, &mouseh_data[dev_addr-1]) ); - TU_LOG2_HEX(mouseh_data[dev_addr-1].ep_in); - } else - #endif + // TODO boot protocol may still have more report in report mode + hid_itf->report_count = 1; + hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; + hid_itf->reports[0].usage = HID_USAGE_DESKTOP_MOUSE; + hid_itf->reports[0].in_len = 8; + hid_itf->reports[0].out_len = 1; + } + else { - // Not supported protocol - return false; + // Unknown protocol + TU_ASSERT(false); } } @@ -270,23 +333,11 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) { -#if 0 - //------------- Get Report Descriptor TODO HID parser -------------// - if ( p_desc_hid->bNumDescriptors ) - { - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_INTERFACE), - TUSB_REQ_GET_DESCRIPTOR, (p_desc_hid->bReportType << 8), 0, - p_desc_hid->wReportLength, report_descriptor ), - error - ); - (void) error; // if error in getting report descriptor --> treating like there is none - } -#endif + // Idle rate = 0 mean only report when there is changes + uint16_t const idle_rate = 0; -#if 0 - // SET IDLE = 0 request - // Device can stall if not support this request + // SET IDLE request, device can stall if not support this request + TU_LOG2("Set Idle \r\n"); tusb_control_request_t const request = { .bmRequestType_bit = @@ -296,76 +347,65 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) .direction = TUSB_DIR_OUT }, .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = 0, // idle_rate = 0 - .wIndex = p_interface_desc->bInterfaceNumber, + .wValue = idle_rate, + .wIndex = itf_num, .wLength = 0 }; - // stall is a valid response for SET_IDLE, therefore we could ignore result of this request - tuh_control_xfer(dev_addr, &request, NULL, NULL); -#endif - - usbh_driver_set_config_complete(dev_addr, itf_num); - -// uint8_t itf = 0; -// hidh_interface_t* hid_itf = &_hidh_itf[itf]; - - - if (itf_num == 0 ) { - if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr); - } - -#if CFG_TUH_HID_MOUSE - if (( mouseh_data[dev_addr-1].ep_in == itf_num ) && mouseh_data[dev_addr-1].valid) - { - tuh_hid_mouse_mounted_cb(dev_addr); - } -#endif + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, config_set_idle_complete) ); return true; } -bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) +bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - (void) xferred_bytes; // TODO may need to use this para later + // Stall is a valid response for SET_IDLE, therefore we could ignore its result + (void) result; -// uint8_t itf = 0; -// hidh_interface_t* hid_itf = &_hidh_itf[itf]; + uint8_t const itf_num = (uint8_t) request->wIndex; -#if CFG_TUH_HID_KEYBOARD -// if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) -// { -// tuh_hid_keyboard_isr(dev_addr, event); -// return true; -// } -#endif + hidh_interface_t* hid_itf = get_interface(dev_addr, itf_num); -#if CFG_TUH_HID_MOUSE - if ( ep_addr == mouseh_data[dev_addr-1].ep_in ) + // Get Report Descriptor + // using usbh enumeration buffer since report descriptor can be very long + TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSZIE ); + + TU_LOG2("HID Get Report Descriptor\r\n"); + tusb_control_request_t const new_request = { - tuh_hid_mouse_isr(dev_addr, event); - return true; - } -#endif + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_u16(hid_itf->report_desc_type, 0), + .wIndex = itf_num, + .wLength = hid_itf->report_desc_len + }; + TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete)); return true; } -void hidh_close(uint8_t dev_addr) +bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - uint8_t itf = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + TU_ASSERT(XFER_RESULT_SUCCESS == result); + uint8_t const itf_num = (uint8_t) request->wIndex; + hidh_interface_t* hid_itf = get_interface(dev_addr, itf_num); - if (tuh_hid_unmounted_cb) tuh_hid_unmounted_cb(dev_addr); - hidh_interface_close(hid_itf); + if (tuh_hid_descriptor_report_cb) tuh_hid_descriptor_report_cb(dev_addr, hid_itf->itf_num, usbh_get_enum_buf(), request->wLength); -#if CFG_TUH_HID_MOUSE - if( mouseh_data[dev_addr-1].ep_in != 0 ) - { - hidh_interface_close(&mouseh_data[dev_addr-1]); - tuh_hid_mouse_unmounted_cb( dev_addr ); - } -#endif + // TODO Report descriptor parser + + // enumeration is complete + if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr); + + // notify usbh that driver enumeration is complete + usbh_driver_set_config_complete(dev_addr, itf_num); + + return true; } #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 10ecc457f..98c652338 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -46,22 +46,51 @@ #define CFG_TUH_HID_REPORT_MAX 4 #endif +#ifndef CFG_TUH_HID_REPORT_DESCRIPTOR_BUFSIZE +#define CFG_TUH_HID_REPORT_DESCRIPTOR_BUFSIZE 256 +#endif + //--------------------------------------------------------------------+ -// Application API (Multiple Instances) -// CFG_TUH_HID > 1 +// Application API (Multiple devices) +// Note: +// - tud_n : is multiple devices API +// - class_n : is multiple instances API //--------------------------------------------------------------------+ +// Get the number of HID instances +uint8_t tuh_n_hid_instance_count(uint8_t daddr); + +// Check if HID instance support keyboard +bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); + + //--------------------------------------------------------------------+ -// Application API (Single Instance) +// Application API (Single device) //--------------------------------------------------------------------+ -// tuh_hid_instance_count() +// Get the number of HID instances +TU_ATTR_ALWAYS_INLINE static inline +uint8_t tuh_hid_instance_count(void) +{ + return tuh_n_hid_instance_count(1); +} + //bool tuh_hid_get_report(uint8_t dev_addr, uint8_t report_id, void * p_report, uint8_t len); +//--------------------------------------------------------------------+ +// Callbacks (Weak is optional) +//--------------------------------------------------------------------+ + +// Invoked when report descriptor is received +// Note: enumeration is still not complete yet +TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t daddr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); + TU_ATTR_WEAK void tuh_hid_mounted_cb(uint8_t dev_addr); TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr); + + //--------------------------------------------------------------------+ // KEYBOARD Application API //--------------------------------------------------------------------+ @@ -193,31 +222,6 @@ void tuh_hid_mouse_mounted_cb(uint8_t dev_addr); */ void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr); -/** @} */ // Mouse_Host -/** @} */ // ClassDriver_HID_Mouse - -//--------------------------------------------------------------------+ -// GENERIC Application API -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Generic Generic (not supported yet) - * @{ */ - -/** \defgroup Generic_Host Host - * The interface API includes status checking function, data transferring function and callback functions - * @{ */ - -bool tuh_hid_generic_is_mounted(uint8_t dev_addr); -tusb_error_t tuh_hid_generic_get_report(uint8_t dev_addr, void* p_report, bool int_on_complete); -tusb_error_t tuh_hid_generic_set_report(uint8_t dev_addr, void* p_report, bool int_on_complete); -tusb_interface_status_t tuh_hid_generic_get_status(uint8_t dev_addr); -tusb_interface_status_t tuh_hid_generic_set_status(uint8_t dev_addr); - -//------------- Application Callback -------------// -void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); - -/** @} */ // Generic_Host -/** @} */ // ClassDriver_HID_Generic - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -- cgit v1.3.1 From a5cd81a2266541c14dfeb2617b2a826296aab688 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 20:04:19 +0700 Subject: correct hid host mount/unmount callback rename HOST_CLASS_HID to CFG_TUH_HID --- examples/host/cdc_msc_hid/src/main.c | 4 +-- src/class/hid/hid_host.c | 64 ++++++++++++++++++++---------------- src/class/hid/hid_host.h | 6 ++-- src/host/usbh.c | 2 +- src/tusb.h | 2 +- src/tusb_option.h | 3 -- 6 files changed, 42 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 5543e9efb..ccc50bbf2 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -154,7 +154,7 @@ static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) prev_report = *p_new_report; } -void tuh_hid_mounted_cb(uint8_t dev_addr) +void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) { // application set-up printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); @@ -162,7 +162,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr) tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); } -void tuh_hid_unmounted_cb(uint8_t dev_addr) +void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) { // application tear-down printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index a5aa33c2c..6e8ec47c8 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_HOST_ENABLED && HOST_CLASS_HID) +#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HID) #include "common/tusb_common.h" #include "hid_host.h" @@ -76,8 +76,8 @@ typedef struct typedef struct { - uint8_t itf_count; - hidh_interface_t interface[CFG_TUH_HID]; + uint8_t inst_count; + hidh_interface_t instances[CFG_TUH_HID]; } hidh_device_t; static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; @@ -93,15 +93,28 @@ TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) // Get Interface by instance number TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) { - return &_hidh_dev[dev_addr-1].interface[instance]; + return &_hidh_dev[dev_addr-1].instances[instance]; +} + +// Get instance ID by interface number +static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return inst; + } + + return 0xff; } // Get Interface by interface number static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) { - for(uint8_t inst=0; institf_num == itf) && (hid->ep_in != 0) ) return hid; } @@ -114,18 +127,13 @@ static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) //--------------------------------------------------------------------+ uint8_t tuh_n_hid_instance_count(uint8_t daddr) { - return get_dev(daddr)->itf_count; + return get_dev(daddr)->inst_count; } //--------------------------------------------------------------------+ // HID Interface common functions //--------------------------------------------------------------------+ -static inline void hidh_interface_close(hidh_interface_t *p_hid) -{ - tu_memclr(p_hid, sizeof(hidh_interface_t)); -} - // called from public API need to validate parameters tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_t *p_hid) { @@ -234,19 +242,13 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 void hidh_close(uint8_t dev_addr) { - uint8_t itf = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, itf); - - if (tuh_hid_unmounted_cb) tuh_hid_unmounted_cb(dev_addr); - hidh_interface_close(hid_itf); - -#if CFG_TUH_HID_MOUSE - if( mouseh_data[dev_addr-1].ep_in != 0 ) + hidh_device_t* hid_dev = get_dev(dev_addr); + if (tuh_hid_unmounted_cb) { - hidh_interface_close(&mouseh_data[dev_addr-1]); - tuh_hid_mouse_unmounted_cb( dev_addr ); + for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++) tuh_hid_unmounted_cb(dev_addr, inst); } -#endif + + tu_memclr(hid_dev, sizeof(hidh_device_t)); } //--------------------------------------------------------------------+ @@ -270,7 +272,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de // not enough interface, try to increase CFG_TUH_HID // TODO multiple devices hidh_device_t* hid_dev = get_dev(dev_addr); - TU_ASSERT(hid_dev->itf_count < CFG_TUH_HID); + TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID); //------------- Endpoint Descriptor -------------// p_desc = tu_desc_next(p_desc); @@ -280,8 +282,8 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de // TODO also open endpoint OUT TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); - hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->itf_count); - hid_dev->itf_count++; + hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); + hid_dev->inst_count++; hid_itf->itf_num = desc_itf->bInterfaceNumber; hid_itf->ep_in = desc_ep->bEndpointAddress; @@ -393,14 +395,18 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co { TU_ASSERT(XFER_RESULT_SUCCESS == result); uint8_t const itf_num = (uint8_t) request->wIndex; - hidh_interface_t* hid_itf = get_interface(dev_addr, itf_num); + uint8_t const inst = get_instance_id(dev_addr, itf_num); + //hidh_interface_t* hid_itf = get_instance(dev_addr, inst); - if (tuh_hid_descriptor_report_cb) tuh_hid_descriptor_report_cb(dev_addr, hid_itf->itf_num, usbh_get_enum_buf(), request->wLength); + if (tuh_hid_descriptor_report_cb) + { + tuh_hid_descriptor_report_cb(dev_addr, inst, usbh_get_enum_buf(), request->wLength); + } // TODO Report descriptor parser // enumeration is complete - if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr); + if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, inst); // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, itf_num); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 98c652338..c45ca9bd4 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -60,7 +60,7 @@ // Get the number of HID instances uint8_t tuh_n_hid_instance_count(uint8_t daddr); -// Check if HID instance support keyboard +// Check if HID instance has keyboard bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); @@ -86,8 +86,8 @@ uint8_t tuh_hid_instance_count(void) // Note: enumeration is still not complete yet TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t daddr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); -TU_ATTR_WEAK void tuh_hid_mounted_cb(uint8_t dev_addr); -TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_hid_mounted_cb (uint8_t dev_addr, uint8_t instance); +TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); diff --git a/src/host/usbh.c b/src/host/usbh.c index fe0b2b987..3008c9b4e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -74,7 +74,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = }, #endif - #if HOST_CLASS_HID + #if CFG_TUH_HID { DRIVER_NAME("HID") .class_code = TUSB_CLASS_HID, diff --git a/src/tusb.h b/src/tusb.h index cc82c440d..1678ef5d8 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -42,7 +42,7 @@ #if TUSB_OPT_HOST_ENABLED #include "host/usbh.h" - #if HOST_CLASS_HID + #if CFG_TUH_HID #include "class/hid/hid_host.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 53d3d9d20..97e12806b 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -266,9 +266,6 @@ #error there is no benefit enable hub with max device is 1. Please disable hub or increase CFG_TUSB_HOST_DEVICE_MAX #endif - //------------- HID CLASS -------------// - #define HOST_CLASS_HID ( CFG_TUH_HID_KEYBOARD + CFG_TUH_HID_MOUSE + CFG_TUSB_HOST_HID_GENERIC ) - #ifndef CFG_TUH_ENUMERATION_BUFSZIE #define CFG_TUH_ENUMERATION_BUFSZIE 256 #endif -- cgit v1.3.1 From 69defb5edc34979c9476533ba3bb49e070879ceb Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 20:19:00 +0700 Subject: rename and moving --- src/class/hid/hid_host.c | 87 +++++++++++++++++++++++++----------------------- src/host/usbh.c | 16 +++++---- 2 files changed, 55 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 6e8ec47c8..80680894f 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -82,45 +82,10 @@ typedef struct static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t _report_desc_buf[256]; - -// Get Device by address -TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) -{ - return &_hidh_dev[dev_addr-1]; -} - -// Get Interface by instance number -TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) -{ - return &_hidh_dev[dev_addr-1].instances[instance]; -} - -// Get instance ID by interface number -static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf) -{ - for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) - { - hidh_interface_t *hid = get_instance(dev_addr, inst); - - if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return inst; - } - - return 0xff; -} - -// Get Interface by interface number -static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) -{ - for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) - { - hidh_interface_t *hid = get_instance(dev_addr, inst); - - if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return hid; - } - - return NULL; -} +TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); +static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf); +static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf); //--------------------------------------------------------------------+ // Application API @@ -290,8 +255,6 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor hid_itf->valid = true; - TU_LOG2_HEX(hid_itf->ep_in); - // Assume bNumDescriptors = 1 hid_itf->report_desc_type = desc_hid->bReportType; hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); @@ -414,4 +377,46 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co return true; } +//--------------------------------------------------------------------+ +// Instance helper +//--------------------------------------------------------------------+ + +// Get Device by address +TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr) +{ + return &_hidh_dev[dev_addr-1]; +} + +// Get Interface by instance number +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance) +{ + return &_hidh_dev[dev_addr-1].instances[instance]; +} + +// Get instance ID by interface number +static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return inst; + } + + return 0xff; +} + +// Get Interface by interface number +static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return hid; + } + + return NULL; +} + #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index 3008c9b4e..7a021c11c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -282,7 +282,7 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ return hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes); } -bool usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) +bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) { tusb_desc_endpoint_t ep0_desc = { @@ -297,9 +297,11 @@ bool usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) return hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc); } -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) { - bool ret = hcd_edpt_open(rhport, dev_addr, ep_desc); + TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); + + bool ret = hcd_edpt_open(rhport, dev_addr, desc_ep); if (ret) { @@ -315,7 +317,7 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const } TU_ASSERT(drvid < USBH_CLASS_DRIVER_COUNT); - uint8_t const ep_addr = ep_desc->bEndpointAddress; + uint8_t const ep_addr = desc_ep->bEndpointAddress; dev->ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = drvid; } @@ -526,7 +528,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) if (drv_id != 0xff) { usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; - TU_LOG2("%s set config itf = %u\r\n", driver->name, itf_num); + TU_LOG2("%s set config: itf = %u\r\n", driver->name, itf_num); driver->set_config(dev_addr, itf_num); break; } @@ -702,7 +704,7 @@ static bool enum_new_device(hcd_event_t* event) static bool enum_request_addr0_device_desc(void) { // TODO probably doesn't need to open/close each enumeration - TU_ASSERT( usbh_pipe_control_open(0, 8) ); + TU_ASSERT( usbh_edpt_control_open(0, 8) ); //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// TU_LOG2("Get 8 byte of Device Descriptor\r\n"); @@ -786,7 +788,7 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c dev0->state = TUSB_DEVICE_STATE_UNPLUG; // open control pipe for new address - TU_ASSERT ( usbh_pipe_control_open(new_addr, new_dev->ep0_packet_size) ); + TU_ASSERT ( usbh_edpt_control_open(new_addr, new_dev->ep0_packet_size) ); // Get full device descriptor TU_LOG2("Get Device Descriptor\r\n"); -- cgit v1.3.1 From b7a8b278c83b9b8e03a328e17f4b833f925226a2 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 May 2021 21:40:17 +0700 Subject: rename tuh_device_is_configured() to tuh_device_configured() - remove tuh_device_get_state() - more hid mouse clean up --- examples/host/cdc_msc_hid/src/keyboard_helper.h | 59 ------------------------- examples/host/cdc_msc_hid/src/main.c | 12 ++--- src/class/hid/hid_host.c | 38 +++++++++++----- src/class/hid/hid_host.h | 19 +++----- src/host/usbh.c | 5 +-- src/host/usbh.h | 6 +-- 6 files changed, 42 insertions(+), 97 deletions(-) delete mode 100644 examples/host/cdc_msc_hid/src/keyboard_helper.h (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/keyboard_helper.h b/examples/host/cdc_msc_hid/src/keyboard_helper.h deleted file mode 100644 index 1fde2768c..000000000 --- a/examples/host/cdc_msc_hid/src/keyboard_helper.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef KEYBOARD_HELPER_H -#define KEYBAORD_HELPER_H - -#include -#include - -#include "tusb.h" - -// look up new key in previous keys -inline bool find_key_in_report(hid_keyboard_report_t const *p_report, uint8_t keycode) -{ - for(uint8_t i = 0; i < 6; i++) - { - if (p_report->keycode[i] == keycode) return true; - } - - return false; -} - -inline uint8_t keycode_to_ascii(uint8_t modifier, uint8_t keycode) -{ - return keycode > 128 ? 0 : - hid_keycode_to_ascii_tbl [keycode][modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT) ? 1 : 0]; -} - -void print_kbd_report(hid_keyboard_report_t *prev_report, hid_keyboard_report_t const *new_report) -{ - - printf("Report: "); - uint8_t c; - - // I assume it's possible to have up to 6 keypress events per report? - for (uint8_t i = 0; i < 6; i++) - { - // Check for key presses - if (new_report->keycode[i]) - { - // If not in prev report then it is newly pressed - if ( !find_key_in_report(prev_report, new_report->keycode[i]) ) - c = keycode_to_ascii(new_report->modifier, new_report->keycode[i]); - printf("press %c ", c); - } - - // Check for key depresses (i.e. was present in prev report but not here) - if (prev_report->keycode[i]) - { - // If not present in the current report then depressed - if (!find_key_in_report(new_report, prev_report->keycode[i])) - { - c = keycode_to_ascii(prev_report->modifier, prev_report->keycode[i]); - printf("depress %c ", c); - } - } - } - - printf("\n"); -} - -#endif \ No newline at end of file diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index ccc50bbf2..6b2d0affb 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -156,16 +156,18 @@ static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) { - // application set-up - printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); + printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); +// printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); + if (instance == 0) { tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); + } } void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) { - // application tear-down - printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); + printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); +// printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); } #endif @@ -255,7 +257,7 @@ void hid_task(void) #endif #if CFG_TUH_HID_MOUSE - if ( tuh_hid_mouse_mounted(addr) ) + if ( tuh_n_hid_n_mouse_mounted(addr, 0) ) { if ( !tuh_hid_mouse_is_busy(addr) ) { diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 80680894f..72cecb8d1 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -104,7 +104,7 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int { //------------- parameters validation -------------// // TODO change to use is configured function - TU_ASSERT(TUSB_DEVICE_STATE_CONFIGURED == tuh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); + TU_ASSERT(tuh_device_configured(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); TU_VERIFY(report, TUSB_ERROR_INVALID_PARA); TU_VERIFY(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); @@ -113,32 +113,45 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int return TUSB_ERROR_NONE; } +//bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) +//{ +// +//} + //--------------------------------------------------------------------+ // KEYBOARD //--------------------------------------------------------------------+ -bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) +bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) +{ + hidh_interface_t* hid_itf = get_instance(daddr, instance); + + // TODO check rid_keyboard + return tuh_device_configured(daddr) && (hid_itf->ep_in != 0); +} + +bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance) { - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + hidh_interface_t* hid_itf = get_instance(daddr, instance); // TODO check rid_keyboard - return tuh_device_is_configured(dev_addr) && (hid_itf->ep_in != 0); + return tuh_device_configured(daddr) && (hid_itf->ep_in != 0); } tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* buffer) { - uint8_t itf = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, itf); + uint8_t inst = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, inst); return hidh_interface_get_report(dev_addr, buffer, hid_itf); } bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) { - uint8_t instance = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + uint8_t inst = 0; + hidh_interface_t* hid_itf = get_instance(dev_addr, inst); - return tuh_n_hid_n_keyboard_mounted(dev_addr, instance) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); + return tuh_n_hid_n_keyboard_mounted(dev_addr, inst) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); } //--------------------------------------------------------------------+ @@ -149,14 +162,15 @@ bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- Public API -------------// -bool tuh_hid_mouse_mounted(uint8_t dev_addr) +bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance) { - return tuh_device_is_configured(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); +// hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return tuh_device_configured(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); } bool tuh_hid_mouse_is_busy(uint8_t dev_addr) { - return tuh_hid_mouse_mounted(dev_addr) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); + return tuh_n_hid_n_mouse_mounted(dev_addr, 0) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); } tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index c45ca9bd4..0052a2b0c 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -60,10 +60,14 @@ // Get the number of HID instances uint8_t tuh_n_hid_instance_count(uint8_t daddr); -// Check if HID instance has keyboard -bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); +// Check if HID instance is mounted +//bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance); +// Check if HID instance with Keyboard is mounted +bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); +// Check if HID instance with Mouse is mounted +bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance); //--------------------------------------------------------------------+ // Application API (Single device) @@ -101,10 +105,6 @@ TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); * The interface API includes status checking function, data transferring function and callback functions * @{ */ -// TODO used weak attr if build failed without KEYBOARD enabled -// TODO remove -extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; - /** \brief Check if device supports Keyboard interface or not * \param[in] dev_addr device address * \retval true if device supports Keyboard interface @@ -170,13 +170,6 @@ void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr); * The interface API includes status checking function, data transferring function and callback functions * @{ */ -/** \brief Check if device supports Mouse interface or not - * \param[in] dev_addr device address - * \retval true if device supports Mouse interface - * \retval false if device does not support Mouse interface or is not mounted - */ -bool tuh_hid_mouse_mounted(uint8_t dev_addr); - /** \brief Check if the interface is currently busy or not * \param[in] dev_addr device address * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device diff --git a/src/host/usbh.c b/src/host/usbh.c index 7a021c11c..f1c386a4d 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -152,10 +152,9 @@ uint8_t* usbh_get_enum_buf(void) //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) //--------------------------------------------------------------------+ -tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr) +bool tuh_device_configured(uint8_t dev_addr) { - TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_DEVICE_STATE_UNPLUG); - return (tusb_device_state_t) _usbh_devices[dev_addr].state; + return _usbh_devices[dev_addr].configured; } tusb_speed_t tuh_device_get_speed (uint8_t const dev_addr) diff --git a/src/host/usbh.h b/src/host/usbh.h index 5e7abe868..e503ef8fb 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -88,13 +88,9 @@ void tuh_task(void); extern void hcd_int_handler(uint8_t rhport); #define tuh_int_handler hcd_int_handler -tusb_device_state_t tuh_device_get_state (uint8_t dev_addr); tusb_speed_t tuh_device_get_speed (uint8_t dev_addr); -static inline bool tuh_device_is_configured(uint8_t dev_addr) -{ - return tuh_device_get_state(dev_addr) == TUSB_DEVICE_STATE_CONFIGURED; -} +bool tuh_device_configured(uint8_t dev_addr); bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); //--------------------------------------------------------------------+ -- cgit v1.3.1 From 791efecfdfd650e7287388e3f3210b18f7262934 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 00:11:20 +0700 Subject: add tuh_device_ready() --- src/device/usbd.h | 1 + src/host/usbh.h | 10 ++++++++++ 2 files changed, 11 insertions(+) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index c0bec9566..c707cecfc 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -70,6 +70,7 @@ bool tud_mounted(void); bool tud_suspended(void); // Check if device is ready to transfer +TU_ATTR_ALWAYS_INLINE static inline bool tud_ready(void) { return tud_mounted() && !tud_suspended(); diff --git a/src/host/usbh.h b/src/host/usbh.h index e503ef8fb..590c8a359 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -90,7 +90,17 @@ extern void hcd_int_handler(uint8_t rhport); tusb_speed_t tuh_device_get_speed (uint8_t dev_addr); +// Check if device is configured bool tuh_device_configured(uint8_t dev_addr); + +// Check if device is ready to communicate with +TU_ATTR_ALWAYS_INLINE +static inline bool tuh_device_ready(uint8_t dev_addr) +{ + return tuh_device_configured(dev_addr); +} + +// Carry out control transfer bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); //--------------------------------------------------------------------+ -- cgit v1.3.1 From db8ea7ea1c48a04fff6446df294123690dcb7012 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 12:21:12 +0700 Subject: clean up --- src/device/usbd.c | 3 +- src/host/usbh.c | 201 ++++++++++++++++++++++++++++-------------------------- 2 files changed, 107 insertions(+), 97 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 280235911..9fddbc299 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1090,7 +1090,7 @@ void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_ } //--------------------------------------------------------------------+ -// Helper +// USBD API For Class Driver //--------------------------------------------------------------------+ // Parse consecutive endpoint descriptors (IN & OUT) @@ -1184,7 +1184,6 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) #if CFG_TUSB_OS != OPT_OS_NONE // pre-check to help reducing mutex lock TU_VERIFY((_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0)); - osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER); #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index f1c386a4d..ac0b654ef 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -135,20 +135,11 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_EN //------------- Helper Function Prototypes -------------// static bool enum_new_device(hcd_event_t* event); +static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); // from usbh_control.c extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -uint8_t usbh_get_rhport(uint8_t dev_addr) -{ - return _usbh_devices[dev_addr].rhport; -} - -uint8_t* usbh_get_enum_buf(void) -{ - return _usbh_ctrl_buf; -} - //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) //--------------------------------------------------------------------+ @@ -223,6 +214,109 @@ bool tuh_init(uint8_t rhport) return true; } +/* USB Host Driver task + * This top level thread manages all host controller event and delegates events to class-specific drivers. + * This should be called periodically within the mainloop or rtos thread. + * + @code + int main(void) + { + application_init(); + tusb_init(); + + while(1) // the mainloop + { + application_code(); + tuh_task(); // tinyusb host task + } + } + @endcode + */ +void tuh_task(void) +{ + // Skip if stack is not initialized + if ( !tusb_inited() ) return; + + // Loop until there is no more events in the queue + while (1) + { + hcd_event_t event; + if ( !osal_queue_receive(_usbh_q, &event) ) return; + + switch (event.event_id) + { + case HCD_EVENT_DEVICE_ATTACH: + // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating + // one device before enumerating another one. + TU_LOG2("USBH DEVICE ATTACH\r\n"); + enum_new_device(&event); + break; + + case HCD_EVENT_DEVICE_REMOVE: + TU_LOG2("USBH DEVICE REMOVED\r\n"); + process_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port); + + #if CFG_TUH_HUB + // TODO remove + if ( event.connection.hub_addr != 0) + { + // done with hub, waiting for next data on status pipe + (void) hub_status_pipe_queue( event.connection.hub_addr ); + } + #endif + break; + + case HCD_EVENT_XFER_COMPLETE: + { + usbh_device_t* dev = &_usbh_devices[event.dev_addr]; + uint8_t const ep_addr = event.xfer_complete.ep_addr; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); + + TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); + + dev->ep_status[epnum][ep_dir].busy = false; + dev->ep_status[epnum][ep_dir].claimed = 0; + + if ( 0 == epnum ) + { + usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + }else + { + uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; + TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); + + TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); + usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + } + } + break; + + case USBH_EVENT_FUNC_CALL: + if ( event.func_call.func ) event.func_call.func(event.func_call.param); + break; + + default: break; + } + } +} + +//--------------------------------------------------------------------+ +// USBH API For Class Driver +//--------------------------------------------------------------------+ + +uint8_t usbh_get_rhport(uint8_t dev_addr) +{ + return _usbh_devices[dev_addr].rhport; +} + +uint8_t* usbh_get_enum_buf(void) +{ + return _usbh_ctrl_buf; +} + +//------------- Endpoint API -------------// + bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -278,6 +372,7 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { usbh_device_t* dev = &_usbh_devices[dev_addr]; + TU_LOG2(" Queue EP %02X with %u bytes ... OK\r\n", ep_addr, total_bytes); return hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes); } @@ -387,7 +482,7 @@ void hcd_event_device_remove(uint8_t hostid, bool in_isr) // a device unplugged on hostid, hub_addr, hub_port // return true if found and unmounted device, false if cannot find -static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) +void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { //------------- find the all devices (star-network) under port that is unplugged -------------// for (uint8_t dev_addr = 0; dev_addr <= CFG_TUSB_HOST_DEVICE_MAX; dev_addr ++) @@ -420,90 +515,6 @@ static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_ } } -/* USB Host Driver task - * This top level thread manages all host controller event and delegates events to class-specific drivers. - * This should be called periodically within the mainloop or rtos thread. - * - @code - int main(void) - { - application_init(); - tusb_init(); - - while(1) // the mainloop - { - application_code(); - tuh_task(); // tinyusb host task - } - } - @endcode - */ -void tuh_task(void) -{ - // Skip if stack is not initialized - if ( !tusb_inited() ) return; - - // Loop until there is no more events in the queue - while (1) - { - hcd_event_t event; - if ( !osal_queue_receive(_usbh_q, &event) ) return; - - switch (event.event_id) - { - case HCD_EVENT_DEVICE_ATTACH: - // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating - // one device before enumerating another one. - TU_LOG2("USBH DEVICE ATTACH\r\n"); - enum_new_device(&event); - break; - - case HCD_EVENT_DEVICE_REMOVE: - TU_LOG2("USBH DEVICE REMOVED\r\n"); - usbh_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port); - - #if CFG_TUH_HUB - // TODO remove - if ( event.connection.hub_addr != 0) - { - // done with hub, waiting for next data on status pipe - (void) hub_status_pipe_queue( event.connection.hub_addr ); - } - #endif - break; - - case HCD_EVENT_XFER_COMPLETE: - { - usbh_device_t* dev = &_usbh_devices[event.dev_addr]; - uint8_t const ep_addr = event.xfer_complete.ep_addr; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const ep_dir = tu_edpt_dir(ep_addr); - - TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); - - if ( 0 == epnum ) - { - usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - }else - { - uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; - TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); - - TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name); - usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len); - } - } - break; - - case USBH_EVENT_FUNC_CALL: - if ( event.func_call.func ) event.func_call.func(event.func_call.param); - break; - - default: break; - } - } -} - //--------------------------------------------------------------------+ // INTERNAL HELPER //--------------------------------------------------------------------+ -- cgit v1.3.1 From 7305fec4db13e846aa945b26d18418ec1e5e4ce7 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 12:27:09 +0700 Subject: change hid device report len from uint8 to uint16 --- src/class/hid/hid_device.c | 6 +++--- src/class/hid/hid_device.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 18d35bc20..ccd47a290 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -76,7 +76,7 @@ bool tud_hid_n_ready(uint8_t itf) return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } -bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len) +bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint16_t len) { uint8_t const rhport = 0; hidd_interface_t * p_hid = &_hidd_itf[itf]; @@ -87,7 +87,7 @@ bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_ // prepare data if (report_id) { - len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE-1); + len = tu_min16(len, CFG_TUD_HID_EP_BUFSIZE-1); p_hid->epin_buf[0] = report_id; memcpy(p_hid->epin_buf+1, report, len); @@ -95,7 +95,7 @@ bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_ }else { // If report id = 0, skip ID field - len = tu_min8(len, CFG_TUD_HID_EP_BUFSIZE); + len = tu_min16(len, CFG_TUD_HID_EP_BUFSIZE); memcpy(p_hid->epin_buf, report, len); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 7520d3453..a36f7e623 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -61,7 +61,7 @@ bool tud_hid_n_ready(uint8_t itf); bool tud_hid_n_boot_mode(uint8_t itf); // Send report to host -bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint8_t len); +bool tud_hid_n_report(uint8_t itf, uint8_t report_id, void const* report, uint16_t len); // KEYBOARD: convenient helper to send keyboard report if application // use template layout report as defined by hid_keyboard_report_t @@ -128,7 +128,7 @@ static inline bool tud_hid_boot_mode(void) return tud_hid_n_boot_mode(0); } -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len) +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len) { return tud_hid_n_report(0, report_id, report, len); } -- cgit v1.3.1 From 9324fd8f2e549434fd2a399500ae1dc766530046 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 13:42:52 +0700 Subject: more hid host API rework --- examples/host/cdc_msc_hid/src/main.c | 28 ++++++----- src/class/hid/hid_host.c | 94 ++++++++++++------------------------ src/class/hid/hid_host.h | 42 +++------------- 3 files changed, 53 insertions(+), 111 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 6b2d0affb..c37cad15d 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -160,7 +160,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) // printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); if (instance == 0) { - tuh_hid_keyboard_get_report(dev_addr, &usb_keyboard_report); + tuh_n_hid_n_get_report(dev_addr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); } } @@ -243,28 +243,30 @@ void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr) void hid_task(void) { - uint8_t const addr = 1; + uint8_t const daddr = 1; + uint8_t const instance = 0; #if CFG_TUH_HID_KEYBOARD - if ( tuh_n_hid_n_keyboard_mounted(addr, 0) ) + if ( tuh_n_hid_n_keyboard_mounted(daddr, instance) ) { - if ( !tuh_hid_keyboard_is_busy(addr) ) + if ( tuh_n_hid_n_ready(daddr, instance) ) { process_kbd_report(&usb_keyboard_report); - tuh_hid_keyboard_get_report(addr, &usb_keyboard_report); + tuh_n_hid_n_get_report(daddr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); } } #endif #if CFG_TUH_HID_MOUSE - if ( tuh_n_hid_n_mouse_mounted(addr, 0) ) - { - if ( !tuh_hid_mouse_is_busy(addr) ) - { - process_mouse_report(&usb_mouse_report); - tuh_hid_mouse_get_report(addr, &usb_mouse_report); - } - } + (void) usb_mouse_report; +// if ( tuh_n_hid_n_mouse_mounted(daddr, instance) ) +// { +// if ( tuh_n_hid_n_ready(daddr, instance) ) +// { +// process_mouse_report(&usb_mouse_report); +// tuh_n_hid_n_get_report(daddr, instance, &usb_mouse_report, sizeof(usb_mouse_report)); +// } +// } #endif } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 72cecb8d1..83e65dc52 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -52,19 +52,19 @@ typedef struct uint8_t report_desc_type; uint16_t report_desc_len; - - bool valid; - uint16_t report_size; // TODO remove later + uint16_t ep_size; uint8_t boot_protocol; // None, Keyboard, Mouse bool boot_mode; // Boot or Report protocol - uint8_t report_count; // Number of reports + uint8_t report_count; // Number of reports struct { - uint8_t in_len; // length of IN report - uint8_t out_len; // length of OUT report uint8_t usage_page; uint8_t usage; + + // TODO just use the endpint size for now + uint8_t in_len; // length of IN report + uint8_t out_len; // length of OUT report }reports[CFG_TUH_HID_REPORT_MAX]; // Parsed Report ID for convenient API @@ -99,59 +99,43 @@ uint8_t tuh_n_hid_instance_count(uint8_t daddr) // HID Interface common functions //--------------------------------------------------------------------+ -// called from public API need to validate parameters -tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_t *p_hid) +bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) { - //------------- parameters validation -------------// - // TODO change to use is configured function - TU_ASSERT(tuh_device_configured(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); - TU_VERIFY(report, TUSB_ERROR_INVALID_PARA); - TU_VERIFY(!hcd_edpt_busy(dev_addr, p_hid->ep_in), TUSB_ERROR_INTERFACE_IS_BUSY); - - TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hid->ep_in, report, p_hid->report_size) ) ; - - return TUSB_ERROR_NONE; + hidh_interface_t* hid_itf = get_instance(daddr, instance); + return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } -//bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) -//{ -// -//} - -//--------------------------------------------------------------------+ -// KEYBOARD -//--------------------------------------------------------------------+ - -bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) +bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) { - hidh_interface_t* hid_itf = get_instance(daddr, instance); + TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); - // TODO check rid_keyboard - return tuh_device_configured(daddr) && (hid_itf->ep_in != 0); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); } -bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance) +bool tuh_n_hid_n_get_report(uint8_t daddr, uint8_t instance, void* report, uint16_t len) { + TU_VERIFY( tuh_device_ready(daddr) && report && len); hidh_interface_t* hid_itf = get_instance(daddr, instance); - // TODO check rid_keyboard - return tuh_device_configured(daddr) && (hid_itf->ep_in != 0); -} + // TODO change to claim endpoint + TU_VERIFY( !hcd_edpt_busy(daddr, hid_itf->ep_in) ); -tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void* buffer) -{ - uint8_t inst = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, inst); + len = tu_min16(len, hid_itf->ep_size); - return hidh_interface_get_report(dev_addr, buffer, hid_itf); + return usbh_edpt_xfer(daddr, hid_itf->ep_in, report, len); } -bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) +//--------------------------------------------------------------------+ +// KEYBOARD +//--------------------------------------------------------------------+ + +bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance) { - uint8_t inst = 0; - hidh_interface_t* hid_itf = get_instance(dev_addr, inst); + hidh_interface_t* hid_itf = get_instance(daddr, instance); - return tuh_n_hid_n_keyboard_mounted(dev_addr, inst) && hcd_edpt_busy(dev_addr, hid_itf->ep_in); + // TODO check rid_keyboard + return tuh_device_ready(daddr) && (hid_itf->ep_in != 0); } //--------------------------------------------------------------------+ @@ -165,26 +149,11 @@ static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance) { // hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return tuh_device_configured(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); -} - -bool tuh_hid_mouse_is_busy(uint8_t dev_addr) -{ - return tuh_n_hid_n_mouse_mounted(dev_addr, 0) && hcd_edpt_busy(dev_addr, mouseh_data[dev_addr-1].ep_in); -} - -tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) -{ - return hidh_interface_get_report(dev_addr, report, &mouseh_data[dev_addr-1]); + return tuh_device_ready(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); } #endif -//--------------------------------------------------------------------+ -// GENERIC -//--------------------------------------------------------------------+ - - //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ @@ -264,10 +233,9 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); hid_dev->inst_count++; - hid_itf->itf_num = desc_itf->bInterfaceNumber; - hid_itf->ep_in = desc_ep->bEndpointAddress; - hid_itf->report_size = desc_ep->wMaxPacketSize.size; // TODO get size from report descriptor - hid_itf->valid = true; + hid_itf->itf_num = desc_itf->bInterfaceNumber; + hid_itf->ep_in = desc_ep->bEndpointAddress; + hid_itf->ep_size = desc_ep->wMaxPacketSize.size; // Assume bNumDescriptors = 1 hid_itf->report_desc_type = desc_hid->bReportType; diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 0052a2b0c..23b23e657 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -61,7 +61,12 @@ uint8_t tuh_n_hid_instance_count(uint8_t daddr); // Check if HID instance is mounted -//bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance); +bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance); + +// Check if the interface is ready to use +bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); + +bool tuh_n_hid_n_get_report(uint8_t daddr, uint8_t instance, void* report, uint16_t len); // Check if HID instance with Keyboard is mounted bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); @@ -69,6 +74,7 @@ bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); // Check if HID instance with Mouse is mounted bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance); + //--------------------------------------------------------------------+ // Application API (Single device) //--------------------------------------------------------------------+ @@ -119,19 +125,6 @@ bool tuh_hid_keyboard_mounted(uint8_t dev_addr); * \note This function is primarily used for polling/waiting result after \ref tuh_hid_keyboard_get_report. * Alternatively, asynchronous event API can be used */ -bool tuh_hid_keyboard_is_busy(uint8_t dev_addr); - -/** \brief Perform a get report from Keyboard interface - * \param[in] dev_addr device address - * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref CFG_TUSB_MEM_SECTION) - * \returns \ref tusb_error_t type to indicate success or error condition. - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of usb transfer will be reported by the interface's callback function - */ -tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void * p_report); //------------- Application Callback -------------// /** \brief Callback function that is invoked when an transferring event occurred @@ -170,27 +163,6 @@ void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr); * The interface API includes status checking function, data transferring function and callback functions * @{ */ -/** \brief Check if the interface is currently busy or not - * \param[in] dev_addr device address - * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device - * \retval false if the interface is not busy meaning the stack successfully transferred data from/to device - * \note This function is primarily used for polling/waiting result after \ref tuh_hid_mouse_get_report. - * Alternatively, asynchronous event API can be used - */ -bool tuh_hid_mouse_is_busy(uint8_t dev_addr); - -/** \brief Perform a get report from Mouse interface - * \param[in] dev_addr device address - * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref CFG_TUSB_MEM_SECTION) - * \returns \ref tusb_error_t type to indicate success or error condition. - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. The result of usb transfer will be reported by the interface's callback function - */ -tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void* p_report); - //------------- Application Callback -------------// /** \brief Callback function that is invoked when an transferring event occurred * \param[in] dev_addr Address of device -- cgit v1.3.1 From cc1b83412a0263f0f3d5db492f5680f4a9bb179b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 14:09:33 +0700 Subject: continue with hid host rework --- src/class/hid/hid_host.c | 92 +++++++++++++++++----------------- src/class/hid/hid_host.h | 126 ++++++++++------------------------------------- 2 files changed, 72 insertions(+), 146 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 83e65dc52..dc29f7322 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -82,26 +82,25 @@ typedef struct static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; +//------------- Internal prototypes -------------// TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); -static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf); -static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf); +static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); +static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf); +static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr); //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ -uint8_t tuh_n_hid_instance_count(uint8_t daddr) + +uint8_t tuh_n_hid_instance_count(uint8_t dev_addr) { - return get_dev(daddr)->inst_count; + return get_dev(dev_addr)->inst_count; } -//--------------------------------------------------------------------+ -// HID Interface common functions -//--------------------------------------------------------------------+ - -bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance) +bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance) { - hidh_interface_t* hid_itf = get_instance(daddr, instance); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } @@ -113,29 +112,29 @@ bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); } -bool tuh_n_hid_n_get_report(uint8_t daddr, uint8_t instance, void* report, uint16_t len) +bool tuh_n_hid_n_get_report(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len) { - TU_VERIFY( tuh_device_ready(daddr) && report && len); - hidh_interface_t* hid_itf = get_instance(daddr, instance); + TU_VERIFY( tuh_device_ready(dev_addr) && report && len); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); // TODO change to claim endpoint - TU_VERIFY( !hcd_edpt_busy(daddr, hid_itf->ep_in) ); + TU_VERIFY( !hcd_edpt_busy(dev_addr, hid_itf->ep_in) ); len = tu_min16(len, hid_itf->ep_size); - return usbh_edpt_xfer(daddr, hid_itf->ep_in, report, len); + return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, report, len); } //--------------------------------------------------------------------+ // KEYBOARD //--------------------------------------------------------------------+ -bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance) +bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) { - hidh_interface_t* hid_itf = get_instance(daddr, instance); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); // TODO check rid_keyboard - return tuh_device_ready(daddr) && (hid_itf->ep_in != 0); + return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); } //--------------------------------------------------------------------+ @@ -164,26 +163,16 @@ void hidh_init(void) bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { - (void) xferred_bytes; // TODO may need to use this para later + uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const instance = get_instance_id_by_epaddr(dev_addr, ep_addr); -// uint8_t itf = 0; -// hidh_interface_t* hid_itf = &_hidh_itf[itf]; - -#if CFG_TUH_HID_KEYBOARD -// if ( ep_addr == keyboardh_data[dev_addr-1].ep_in ) -// { -// tuh_hid_keyboard_isr(dev_addr, event); -// return true; -// } -#endif - -#if CFG_TUH_HID_MOUSE -// if ( ep_addr == mouseh_data[dev_addr-1].ep_in ) -// { -// tuh_hid_mouse_isr(dev_addr, event); -// return true; -// } -#endif + if ( dir == TUSB_DIR_IN ) + { + if (tuh_hid_get_report_complete_cb) tuh_hid_get_report_complete_cb(dev_addr, instance, xferred_bytes); + }else + { + if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); + } return true; } @@ -311,7 +300,7 @@ bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * r uint8_t const itf_num = (uint8_t) request->wIndex; - hidh_interface_t* hid_itf = get_interface(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance_by_itfnum(dev_addr, itf_num); // Get Report Descriptor // using usbh enumeration buffer since report descriptor can be very long @@ -340,7 +329,7 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co { TU_ASSERT(XFER_RESULT_SUCCESS == result); uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const inst = get_instance_id(dev_addr, itf_num); + uint8_t const inst = get_instance_id_by_itfnum(dev_addr, itf_num); //hidh_interface_t* hid_itf = get_instance(dev_addr, inst); if (tuh_hid_descriptor_report_cb) @@ -375,30 +364,43 @@ TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_a return &_hidh_dev[dev_addr-1].instances[instance]; } +// Get instance by interface number +static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf) +{ + for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) + { + hidh_interface_t *hid = get_instance(dev_addr, inst); + + if ( (hid->itf_num == itf) && (hid->ep_in || hid->ep_out) ) return hid; + } + + return NULL; +} + // Get instance ID by interface number -static uint8_t get_instance_id(uint8_t dev_addr, uint8_t itf) +static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf) { for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) { hidh_interface_t *hid = get_instance(dev_addr, inst); - if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return inst; + if ( (hid->itf_num == itf) && (hid->ep_in || hid->ep_out) ) return inst; } return 0xff; } -// Get Interface by interface number -static hidh_interface_t* get_interface(uint8_t dev_addr, uint8_t itf) +// Get instance ID by endpoint address +static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr) { for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) { hidh_interface_t *hid = get_instance(dev_addr, inst); - if ( (hid->itf_num == itf) && (hid->ep_in != 0) ) return hid; + if ( (ep_addr == hid->ep_in) || ( ep_addr == hid->ep_out) ) return inst; } - return NULL; + return 0xff; } #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 23b23e657..45f03a192 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -58,134 +58,58 @@ //--------------------------------------------------------------------+ // Get the number of HID instances -uint8_t tuh_n_hid_instance_count(uint8_t daddr); +uint8_t tuh_n_hid_instance_count(uint8_t dev_addr); // Check if HID instance is mounted -bool tuh_n_hid_n_mounted(uint8_t daddr, uint8_t instance); +bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance); // Check if the interface is ready to use bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); -bool tuh_n_hid_n_get_report(uint8_t daddr, uint8_t instance, void* report, uint16_t len); +// Get Report from device +bool tuh_n_hid_n_get_report(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len); -// Check if HID instance with Keyboard is mounted -bool tuh_n_hid_n_keyboard_mounted(uint8_t daddr, uint8_t instance); - -// Check if HID instance with Mouse is mounted -bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance); -//--------------------------------------------------------------------+ -// Application API (Single device) -//--------------------------------------------------------------------+ +//------------- -------------// -// Get the number of HID instances -TU_ATTR_ALWAYS_INLINE static inline -uint8_t tuh_hid_instance_count(void) -{ - return tuh_n_hid_instance_count(1); -} +// Check if HID instance with Keyboard is mounted +bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance); -//bool tuh_hid_get_report(uint8_t dev_addr, uint8_t report_id, void * p_report, uint8_t len); +// Check if HID instance with Mouse is mounted +bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance); //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ // Invoked when report descriptor is received -// Note: enumeration is still not complete yet -TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t daddr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); +// Note: enumeration is still not complete yet at this time +TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); +// Invoked when device with hid interface is mounted TU_ATTR_WEAK void tuh_hid_mounted_cb (uint8_t dev_addr, uint8_t instance); -TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); - +// Invoked when device with hid interface is un-mounted +TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); -//--------------------------------------------------------------------+ -// KEYBOARD Application API -//--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Keyboard Keyboard - * @{ */ - -/** \defgroup Keyboard_Host Host - * The interface API includes status checking function, data transferring function and callback functions - * @{ */ - -/** \brief Check if device supports Keyboard interface or not - * \param[in] dev_addr device address - * \retval true if device supports Keyboard interface - * \retval false if device does not support Keyboard interface or is not mounted - */ -bool tuh_hid_keyboard_mounted(uint8_t dev_addr); - -/** \brief Check if the interface is currently busy or not - * \param[in] dev_addr device address - * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device - * \retval false if the interface is not busy meaning the stack successfully transferred data from/to device - * \note This function is primarily used for polling/waiting result after \ref tuh_hid_keyboard_get_report. - * Alternatively, asynchronous event API can be used - */ - -//------------- Application Callback -------------// -/** \brief Callback function that is invoked when an transferring event occurred - * \param[in] dev_addr Address of device - * \param[in] event an value from \ref xfer_result_t - * \note event can be one of following - * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. - * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. - * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. - * \note Application should schedule the next report by calling \ref tuh_hid_keyboard_get_report within this callback - */ -void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event); - -/** \brief Callback function that will be invoked when a device with Keyboard interface is mounted - * \param[in] dev_addr Address of newly mounted device - * \note This callback should be used by Application to set-up interface-related data - */ -void tuh_hid_keyboard_mounted_cb(uint8_t dev_addr); - -/** \brief Callback function that will be invoked when a device with Keyboard interface is unmounted - * \param[in] dev_addr Address of newly unmounted device - * \note This callback should be used by Application to tear-down interface-related data - */ -void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr); +// Invoked when received Report from device +TU_ATTR_WEAK void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes); -/** @} */ // Keyboard_Host -/** @} */ // ClassDriver_HID_Keyboard +// Invoked when Sent Report to device +TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes); //--------------------------------------------------------------------+ -// MOUSE Application API +// Application API (Single device) //--------------------------------------------------------------------+ -/** \addtogroup ClassDriver_HID_Mouse Mouse - * @{ */ -/** \defgroup Mouse_Host Host - * The interface API includes status checking function, data transferring function and callback functions - * @{ */ - -//------------- Application Callback -------------// -/** \brief Callback function that is invoked when an transferring event occurred - * \param[in] dev_addr Address of device - * \param[in] event an value from \ref xfer_result_t - * \note event can be one of following - * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. - * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. - * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. - * \note Application should schedule the next report by calling \ref tuh_hid_mouse_get_report within this callback - */ -void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event); - -/** \brief Callback function that will be invoked when a device with Mouse interface is mounted - * \param[in] dev_addr Address of newly mounted device - * \note This callback should be used by Application to set-up interface-related data - */ -void tuh_hid_mouse_mounted_cb(uint8_t dev_addr); +// Get the number of HID instances +TU_ATTR_ALWAYS_INLINE static inline +uint8_t tuh_hid_instance_count(void) +{ + return tuh_n_hid_instance_count(1); +} -/** \brief Callback function that will be invoked when a device with Mouse interface is unmounted - * \param[in] dev_addr Address of newly unmounted device - * \note This callback should be used by Application to tear-down interface-related data - */ -void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API -- cgit v1.3.1 From 641f55f1f18234dbcf3f2b5d46d2231a5e9abae3 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 May 2021 15:44:00 +0700 Subject: remove CFG_TUH_HID_KEYBOARD and CFG_TUH_HID_MOUSE --- examples/host/cdc_msc_hid/src/main.c | 30 ++++------------------------- examples/host/cdc_msc_hid/src/tusb_config.h | 6 ------ src/class/hid/hid_host.c | 4 +--- src/host/hcd.h | 5 ++--- 4 files changed, 7 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index c37cad15d..17f649aa4 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -51,14 +51,13 @@ int main(void) { // tinyusb host task tuh_task(); - led_blinking_task(); #if CFG_TUH_CDC cdc_task(); #endif -#if CFG_TUH_HID_KEYBOARD || CFG_TUH_HID_MOUSE +#if CFG_TUH_HID hid_task(); #endif } @@ -109,8 +108,6 @@ void cdc_task(void) //--------------------------------------------------------------------+ // USB HID //--------------------------------------------------------------------+ -#if CFG_TUH_HID_KEYBOARD - CFG_TUSB_MEM_SECTION static hid_keyboard_report_t usb_keyboard_report; uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; @@ -158,6 +155,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) { printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); // printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); +// printf("A Mouse device (address %d) is mounted\r\n", dev_addr); if (instance == 0) { tuh_n_hid_n_get_report(dev_addr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); @@ -168,11 +166,9 @@ void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) { printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); // printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); +// printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); } -#endif - -#if CFG_TUH_HID_MOUSE CFG_TUSB_MEM_SECTION static hid_mouse_report_t usb_mouse_report; @@ -225,28 +221,12 @@ static inline void process_mouse_report(hid_mouse_report_t const * p_report) } -void tuh_hid_mouse_mounted_cb(uint8_t dev_addr) -{ - // application set-up - printf("A Mouse device (address %d) is mounted\r\n", dev_addr); -} - -void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr) -{ - // application tear-down - printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); -} - -#endif - - void hid_task(void) { uint8_t const daddr = 1; uint8_t const instance = 0; -#if CFG_TUH_HID_KEYBOARD if ( tuh_n_hid_n_keyboard_mounted(daddr, instance) ) { if ( tuh_n_hid_n_ready(daddr, instance) ) @@ -255,9 +235,8 @@ void hid_task(void) tuh_n_hid_n_get_report(daddr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); } } -#endif -#if CFG_TUH_HID_MOUSE +// #if CFG_TUH_HID_MOUSE (void) usb_mouse_report; // if ( tuh_n_hid_n_mouse_mounted(daddr, instance) ) // { @@ -267,7 +246,6 @@ void hid_task(void) // tuh_n_hid_n_get_report(daddr, instance, &usb_mouse_report, sizeof(usb_mouse_report)); // } // } -#endif } //--------------------------------------------------------------------+ diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index e1e02e31e..01296cd26 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -76,13 +76,7 @@ #define CFG_TUH_HUB 1 #define CFG_TUH_CDC 1 - #define CFG_TUH_HID 2 - -#define CFG_TUH_HID_KEYBOARD 1 -#define CFG_TUH_HID_MOUSE 1 -#define CFG_TUSB_HOST_HID_GENERIC 0 // (not yet supported) - #define CFG_TUH_MSC 1 #define CFG_TUH_VENDOR 0 diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index dc29f7322..60ee667d0 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -140,8 +140,8 @@ bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) //--------------------------------------------------------------------+ // MOUSE //--------------------------------------------------------------------+ -#if CFG_TUH_HID_MOUSE +// TODO remove static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 //------------- Public API -------------// @@ -151,8 +151,6 @@ bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance) return tuh_device_ready(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); } -#endif - //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ diff --git a/src/host/hcd.h b/src/host/hcd.h index 4810ef8da..a470a45e8 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -85,9 +85,8 @@ typedef struct #if TUSB_OPT_HOST_ENABLED // Max number of endpoints per device enum { - HCD_MAX_ENDPOINT = CFG_TUSB_HOST_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID_KEYBOARD + CFG_TUH_HID_MOUSE + CFG_TUSB_HOST_HID_GENERIC + - CFG_TUH_MSC*2 + CFG_TUH_CDC*3), - + // TODO better computation + HCD_MAX_ENDPOINT = CFG_TUSB_HOST_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3), HCD_MAX_XFER = HCD_MAX_ENDPOINT*2, }; -- cgit v1.3.1 From 9ddc3bfd6dc1450d30c16c0a1d07240ea74a13bf Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 May 2021 01:02:47 +0700 Subject: more host hid API adding hid parser --- examples/host/cdc_msc_hid/src/tusb_config.h | 6 +- src/class/hid/hid.h | 60 +++++++++-- src/class/hid/hid_host.c | 148 +++++++++++++++++++++------- src/class/hid/hid_host.h | 35 +++++-- 4 files changed, 196 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 01296cd26..fd0432799 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -86,11 +86,7 @@ // Max number of reports per interface // E.g composite HID with keyboard + mouse + gamepad will have 3 reports -#define CFG_TUH_HID_REPORT_MAX 4 - -// Max buffer -#define CFG_TUH_HID_REPORT_DESCRIPTOR_BUFSIZE 256 - +#define CFG_TUH_HID_REPORT_MAX 4 #ifdef __cplusplus } diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 351a4d600..f0ad03603 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -479,6 +479,7 @@ typedef enum //--------------------------------------------------------------------+ // REPORT DESCRIPTOR //--------------------------------------------------------------------+ + //------------- ITEM & TAG -------------// #define HID_REPORT_DATA_0(data) #define HID_REPORT_DATA_1(data) , data @@ -488,18 +489,31 @@ typedef enum #define HID_REPORT_ITEM(data, tag, type, size) \ (((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data) -#define RI_TYPE_MAIN 0 -#define RI_TYPE_GLOBAL 1 -#define RI_TYPE_LOCAL 2 +// Report Item Types +enum { + RI_TYPE_MAIN = 0, + RI_TYPE_GLOBAL = 1, + RI_TYPE_LOCAL = 2 +}; + +//------------- Main Items - HID 1.11 section 6.2.2.4 -------------// + +// Report Item Main group +enum { + RI_MAIN_INPUT = 8, + RI_MAIN_OUTPUT = 9, + RI_MAIN_COLLECTION = 10, + RI_MAIN_FEATURE = 11, + RI_MAIN_COLLECTION_END = 12 +}; -//------------- MAIN ITEMS 6.2.2.4 -------------// #define HID_INPUT(x) HID_REPORT_ITEM(x, 8, RI_TYPE_MAIN, 1) #define HID_OUTPUT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_MAIN, 1) #define HID_COLLECTION(x) HID_REPORT_ITEM(x, 10, RI_TYPE_MAIN, 1) #define HID_FEATURE(x) HID_REPORT_ITEM(x, 11, RI_TYPE_MAIN, 1) #define HID_COLLECTION_END HID_REPORT_ITEM(x, 12, RI_TYPE_MAIN, 0) -//------------- INPUT, OUTPUT, FEATURE 6.2.2.5 -------------// +//------------- Input, Output, Feature - HID 1.11 section 6.2.2.5 -------------// #define HID_DATA (0<<0) #define HID_CONSTANT (1<<0) @@ -527,7 +541,7 @@ typedef enum #define HID_BITFIELD (0<<8) #define HID_BUFFERED_BYTES (1<<8) -//------------- COLLECTION ITEM 6.2.2.6 -------------// +//------------- Collection Item - HID 1.11 section 6.2.2.6 -------------// enum { HID_COLLECTION_PHYSICAL = 0, HID_COLLECTION_APPLICATION, @@ -538,7 +552,24 @@ enum { HID_COLLECTION_USAGE_MODIFIER }; -//------------- GLOBAL ITEMS 6.2.2.7 -------------// +//------------- Global Items - HID 1.11 section 6.2.2.7 -------------// + +// Report Item Global group +enum { + RI_GLOBAL_USAGE_PAGE = 0, + RI_GLOBAL_LOGICAL_MIN = 1, + RI_GLOBAL_LOGICAL_MAX = 2, + RI_GLOBAL_PHYSICAL_MIN = 3, + RI_GLOBAL_PHYSICAL_MAX = 4, + RI_GLOBAL_UNIT_EXPONENT = 5, + RI_GLOBAL_UNIT = 6, + RI_GLOBAL_REPORT_SIZE = 7, + RI_GLOBAL_REPORT_ID = 8, + RI_GLOBAL_REPORT_COUNT = 9, + RI_GLOBAL_PUSH = 10, + RI_GLOBAL_POP = 11 +}; + #define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, 1) #define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, n) @@ -573,6 +604,21 @@ enum { #define HID_POP HID_REPORT_ITEM(x, 11, RI_TYPE_GLOBAL, 0) //------------- LOCAL ITEMS 6.2.2.8 -------------// + +enum { + RI_LOCAL_USAGE = 0, + RI_LOCAL_USAGE_MIN = 1, + RI_LOCAL_USAGE_MAX = 2, + RI_LOCAL_DESIGNATOR_INDEX = 3, + RI_LOCAL_DESIGNATOR_MIN = 4, + RI_LOCAL_DESIGNATOR_MAX = 5, + // 6 is reserved + RI_LOCAL_STRING_INDEX = 7, + RI_LOCAL_STRING_MIN = 8, + RI_LOCAL_STRING_MAX = 9, + RI_LOCAL_DELIMITER = 10, +}; + #define HID_USAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, 1) #define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, n) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 60ee667d0..862026b5b 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -35,14 +35,15 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -/* "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard - "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse - "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control - "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control - "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad - "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen - "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad - "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF +/* + "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard + "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse + "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control + "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control + "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad + "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen + "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad + "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF */ typedef struct { @@ -57,22 +58,14 @@ typedef struct uint8_t boot_protocol; // None, Keyboard, Mouse bool boot_mode; // Boot or Report protocol - uint8_t report_count; // Number of reports - struct { - uint8_t usage_page; - uint8_t usage; - - // TODO just use the endpint size for now - uint8_t in_len; // length of IN report - uint8_t out_len; // length of OUT report - }reports[CFG_TUH_HID_REPORT_MAX]; + tuh_hid_report_info_t report_info; // Parsed Report ID for convenient API uint8_t rid_keyboard; uint8_t rid_mouse; uint8_t rid_gamepad; uint8_t rid_consumer; -}hidh_interface_t; +} hidh_interface_t; typedef struct { @@ -104,6 +97,23 @@ bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance) return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } +uint8_t tuh_n_hid_n_boot_protocol(uint8_t dev_addr, uint8_t instance) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return hid_itf->boot_protocol; +} + +bool tuh_n_hid_n_boot_mode(uint8_t dev_addr, uint8_t instance) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return hid_itf->boot_mode; +} + +tuh_hid_report_info_t const* tuh_n_hid_n_get_report_info(uint8_t dev_addr, uint8_t instance) +{ + return &get_instance(dev_addr, instance)->report_info; +} + bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) { TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); @@ -190,6 +200,7 @@ void hidh_close(uint8_t dev_addr) // Enumeration //--------------------------------------------------------------------+ +static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* desc_report, uint16_t desc_len); static bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -235,23 +246,25 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { + TU_LOG2(" Boot Keyboard\r\n"); // TODO boot protocol may still have more report in report mode - hid_itf->report_count = 1; + hid_itf->report_info.count = 1; - hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; - hid_itf->reports[0].usage = HID_USAGE_DESKTOP_KEYBOARD; - hid_itf->reports[0].in_len = 8; - hid_itf->reports[0].out_len = 1; + hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; + hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_KEYBOARD; + hid_itf->report_info.info[0].in_len = 8; + hid_itf->report_info.info[0].out_len = 1; } else if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) { + TU_LOG2(" Boot Mouse\r\n"); // TODO boot protocol may still have more report in report mode - hid_itf->report_count = 1; + hid_itf->report_info.count = 1; - hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP; - hid_itf->reports[0].usage = HID_USAGE_DESKTOP_MOUSE; - hid_itf->reports[0].in_len = 8; - hid_itf->reports[0].out_len = 1; + hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; + hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_MOUSE; + hid_itf->report_info.info[0].in_len = 5; + hid_itf->report_info.info[0].out_len = 0; } else { @@ -326,19 +339,23 @@ bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * r bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { TU_ASSERT(XFER_RESULT_SUCCESS == result); - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const inst = get_instance_id_by_itfnum(dev_addr, itf_num); - //hidh_interface_t* hid_itf = get_instance(dev_addr, inst); + + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + uint8_t const* desc_report = usbh_get_enum_buf(); + uint16_t const desc_len = request->wLength; if (tuh_hid_descriptor_report_cb) { - tuh_hid_descriptor_report_cb(dev_addr, inst, usbh_get_enum_buf(), request->wLength); + tuh_hid_descriptor_report_cb(dev_addr, instance, desc_report, desc_len); } - // TODO Report descriptor parser + parse_report_descriptor(hid_itf, desc_report, desc_len); // enumeration is complete - if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, inst); + if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, instance); // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, itf_num); @@ -346,8 +363,69 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co return true; } +// Parse Report Descriptor to tuh_hid_report_info_t +static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* desc_report, uint16_t desc_len) +{ + enum + { + USAGE_PAGE = 0x05, + USAGE = 0x09, + USAGE_MIN = 0x19, + USAGE_MAX = 0x29, + LOGICAL_MIN = 0x15, + LOGICAL_MAX = 0x25, + REPORT_SIZE = 0x75, + REPORT_COUNT = 0x95 + }; + + // Short Item 6.2.2.2 USB HID 1.11 + union TU_ATTR_PACKED + { + uint8_t byte; + struct TU_ATTR_PACKED + { + uint8_t size : 2; + uint8_t type : 2; + uint8_t tag : 4; + }; + } header; + + while(desc_len) + { + header.byte = *desc_report++; + + uint8_t const tag = header.tag; + uint8_t const type = header.type; + uint8_t const size = header.size; + + desc_len--; + + TU_LOG2("tag = %d, type = %d, size = %d, data = ", tag, type, size); + for(uint32_t i=0; i Date: Fri, 14 May 2021 12:23:09 +0700 Subject: adding hid parser --- examples/host/cdc_msc_hid/src/tusb_config.h | 2 ++ src/class/hid/hid_host.c | 55 ++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index fd0432799..7c13cbd2f 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -84,6 +84,8 @@ //------------- HID -------------// +//#define CFG_TUH_HID_EP_BUFSIZE 64 + // Max number of reports per interface // E.g composite HID with keyboard + mouse + gamepad will have 3 reports #define CFG_TUH_HID_REPORT_MAX 4 diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 862026b5b..ba9707a69 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -366,19 +366,7 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co // Parse Report Descriptor to tuh_hid_report_info_t static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* desc_report, uint16_t desc_len) { - enum - { - USAGE_PAGE = 0x05, - USAGE = 0x09, - USAGE_MIN = 0x19, - USAGE_MAX = 0x29, - LOGICAL_MIN = 0x15, - LOGICAL_MAX = 0x25, - REPORT_SIZE = 0x75, - REPORT_COUNT = 0x95 - }; - - // Short Item 6.2.2.2 USB HID 1.11 + // Report Item 6.2.2.2 USB HID 1.11 union TU_ATTR_PACKED { uint8_t byte; @@ -407,12 +395,53 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de switch(type) { case RI_TYPE_MAIN: + switch (tag) + { + case RI_MAIN_INPUT: break; + case RI_MAIN_OUTPUT: break; + case RI_MAIN_FEATURE: break; + case RI_MAIN_COLLECTION: break; + case RI_MAIN_COLLECTION_END: break; + + default: break; + } break; case RI_TYPE_GLOBAL: + switch(tag) + { + case RI_GLOBAL_USAGE_PAGE : break; + case RI_GLOBAL_LOGICAL_MIN : break; + case RI_GLOBAL_LOGICAL_MAX : break; + case RI_GLOBAL_PHYSICAL_MIN : break; + case RI_GLOBAL_PHYSICAL_MAX : break; + case RI_GLOBAL_UNIT_EXPONENT : break; + case RI_GLOBAL_UNIT : break; + case RI_GLOBAL_REPORT_SIZE : break; + case RI_GLOBAL_REPORT_ID : break; + case RI_GLOBAL_REPORT_COUNT : break; + case RI_GLOBAL_PUSH : break; + case RI_GLOBAL_POP : break; + + default: break; + } break; case RI_TYPE_LOCAL: + switch(tag) + { + case RI_LOCAL_USAGE : break; + case RI_LOCAL_USAGE_MIN : break; + case RI_LOCAL_USAGE_MAX : break; + case RI_LOCAL_DESIGNATOR_INDEX : break; + case RI_LOCAL_DESIGNATOR_MIN : break; + case RI_LOCAL_DESIGNATOR_MAX : break; + case RI_LOCAL_STRING_INDEX : break; + case RI_LOCAL_STRING_MIN : break; + case RI_LOCAL_STRING_MAX : break; + case RI_LOCAL_DELIMITER : break; + default: break; + } break; // error -- cgit v1.3.1 From 93661042d96d08ad9f0de66fa44d22bdc4faeb08 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 May 2021 17:47:02 +0700 Subject: more API update - remove tuh_n_hid_n_get_report() - usbh auto queue get report and invoke callback when received data --- examples/host/cdc_msc_hid/src/main.c | 35 +++--------------- examples/host/cdc_msc_hid/src/tusb_config.h | 2 +- src/class/hid/hid_host.c | 55 ++++++++++++++--------------- src/class/hid/hid_host.h | 10 +++--- 4 files changed, 38 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 17f649aa4..40642561b 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -108,7 +108,6 @@ void cdc_task(void) //--------------------------------------------------------------------+ // USB HID //--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION static hid_keyboard_report_t usb_keyboard_report; uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; // look up new key in previous keys @@ -156,10 +155,6 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); // printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); // printf("A Mouse device (address %d) is mounted\r\n", dev_addr); - - if (instance == 0) { - tuh_n_hid_n_get_report(dev_addr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); - } } void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) @@ -169,9 +164,6 @@ void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) // printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); } - -CFG_TUSB_MEM_SECTION static hid_mouse_report_t usb_mouse_report; - void cursor_movement(int8_t x, int8_t y, int8_t wheel) { //------------- X -------------// @@ -220,32 +212,13 @@ static inline void process_mouse_report(hid_mouse_report_t const * p_report) cursor_movement(p_report->x, p_report->y, p_report->wheel); } - +void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) +{ + process_kbd_report( (hid_keyboard_report_t*) report ); +} void hid_task(void) { - uint8_t const daddr = 1; - uint8_t const instance = 0; - - if ( tuh_n_hid_n_keyboard_mounted(daddr, instance) ) - { - if ( tuh_n_hid_n_ready(daddr, instance) ) - { - process_kbd_report(&usb_keyboard_report); - tuh_n_hid_n_get_report(daddr, instance, &usb_keyboard_report, sizeof(usb_keyboard_report)); - } - } - -// #if CFG_TUH_HID_MOUSE - (void) usb_mouse_report; -// if ( tuh_n_hid_n_mouse_mounted(daddr, instance) ) -// { -// if ( tuh_n_hid_n_ready(daddr, instance) ) -// { -// process_mouse_report(&usb_mouse_report); -// tuh_n_hid_n_get_report(daddr, instance, &usb_mouse_report, sizeof(usb_mouse_report)); -// } -// } } //--------------------------------------------------------------------+ diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 7c13cbd2f..8c82c0fef 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -84,7 +84,7 @@ //------------- HID -------------// -//#define CFG_TUH_HID_EP_BUFSIZE 64 +#define CFG_TUH_HID_EP_BUFSIZE 64 // Max number of reports per interface // E.g composite HID with keyboard + mouse + gamepad will have 3 reports diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index ba9707a69..4c32d9b33 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -53,7 +53,9 @@ typedef struct uint8_t report_desc_type; uint16_t report_desc_len; - uint16_t ep_size; + + uint16_t epin_size; + uint16_t epout_size; uint8_t boot_protocol; // None, Keyboard, Mouse bool boot_mode; // Boot or Report protocol @@ -65,6 +67,9 @@ typedef struct uint8_t rid_mouse; uint8_t rid_gamepad; uint8_t rid_consumer; + + uint8_t epin_buf[CFG_TUH_HID_EP_BUFSIZE]; + uint8_t epout_buf[CFG_TUH_HID_EP_BUFSIZE]; } hidh_interface_t; typedef struct @@ -82,6 +87,11 @@ static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf); static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr); +TU_ATTR_ALWAYS_INLINE static inline bool hidh_get_report(uint8_t dev_addr, hidh_interface_t* hid_itf) +{ + return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size); +} + //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ @@ -122,19 +132,6 @@ bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); } -bool tuh_n_hid_n_get_report(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len) -{ - TU_VERIFY( tuh_device_ready(dev_addr) && report && len); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - // TODO change to claim endpoint - TU_VERIFY( !hcd_edpt_busy(dev_addr, hid_itf->ep_in) ); - - len = tu_min16(len, hid_itf->ep_size); - - return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, report, len); -} - //--------------------------------------------------------------------+ // KEYBOARD //--------------------------------------------------------------------+ @@ -147,18 +144,11 @@ bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); } -//--------------------------------------------------------------------+ -// MOUSE -//--------------------------------------------------------------------+ - // TODO remove -static hidh_interface_t mouseh_data[CFG_TUSB_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1 - -//------------- Public API -------------// bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance) { -// hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return tuh_device_ready(dev_addr) && (mouseh_data[dev_addr-1].ep_in != 0); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); } //--------------------------------------------------------------------+ @@ -173,10 +163,17 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 { uint8_t const dir = tu_edpt_dir(ep_addr); uint8_t const instance = get_instance_id_by_epaddr(dev_addr, ep_addr); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); if ( dir == TUSB_DIR_IN ) { - if (tuh_hid_get_report_complete_cb) tuh_hid_get_report_complete_cb(dev_addr, instance, xferred_bytes); + if (tuh_hid_get_report_cb) + { + tuh_hid_get_report_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); + } + + // queue next report + hidh_get_report(dev_addr, hid_itf); }else { if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); @@ -233,7 +230,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->itf_num = desc_itf->bInterfaceNumber; hid_itf->ep_in = desc_ep->bEndpointAddress; - hid_itf->ep_size = desc_ep->wMaxPacketSize.size; + hid_itf->epin_size = desc_ep->wMaxPacketSize.size; // Assume bNumDescriptors = 1 hid_itf->report_desc_type = desc_hid->bReportType; @@ -357,6 +354,9 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co // enumeration is complete if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, instance); + // queue transfer for IN endpoint + hidh_get_report(dev_addr, hid_itf); + // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, itf_num); @@ -381,13 +381,12 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de while(desc_len) { header.byte = *desc_report++; + desc_len--; - uint8_t const tag = header.tag; + uint8_t const tag = header.tag; uint8_t const type = header.type; uint8_t const size = header.size; - desc_len--; - TU_LOG2("tag = %d, type = %d, size = %d, data = ", tag, type, size); for(uint32_t i=0; i Date: Fri, 14 May 2021 18:07:58 +0700 Subject: fix compile --- src/class/hid/hid_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index a36f7e623..6b876ae74 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -80,7 +80,7 @@ bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, int8_t x, int8_t y //--------------------------------------------------------------------+ static inline bool tud_hid_ready(void); static inline bool tud_hid_boot_mode(void); -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); +static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len); static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); -- cgit v1.3.1 From da6a7fb2bbb5ee07914e684a5162a9534c10bbb1 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 17 May 2021 08:18:25 +0700 Subject: update hid report descriptor macro --- src/class/hid/hid.h | 66 ++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index f0ad03603..42e16b288 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -507,11 +507,11 @@ enum { RI_MAIN_COLLECTION_END = 12 }; -#define HID_INPUT(x) HID_REPORT_ITEM(x, 8, RI_TYPE_MAIN, 1) -#define HID_OUTPUT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_MAIN, 1) -#define HID_COLLECTION(x) HID_REPORT_ITEM(x, 10, RI_TYPE_MAIN, 1) -#define HID_FEATURE(x) HID_REPORT_ITEM(x, 11, RI_TYPE_MAIN, 1) -#define HID_COLLECTION_END HID_REPORT_ITEM(x, 12, RI_TYPE_MAIN, 0) +#define HID_INPUT(x) HID_REPORT_ITEM(x, RI_MAIN_INPUT , RI_TYPE_MAIN, 1) +#define HID_OUTPUT(x) HID_REPORT_ITEM(x, RI_MAIN_OUTPUT , RI_TYPE_MAIN, 1) +#define HID_COLLECTION(x) HID_REPORT_ITEM(x, RI_MAIN_COLLECTION , RI_TYPE_MAIN, 1) +#define HID_FEATURE(x) HID_REPORT_ITEM(x, RI_MAIN_FEATURE , RI_TYPE_MAIN, 1) +#define HID_COLLECTION_END HID_REPORT_ITEM(x, RI_MAIN_COLLECTION_END, RI_TYPE_MAIN, 0) //------------- Input, Output, Feature - HID 1.11 section 6.2.2.5 -------------// #define HID_DATA (0<<0) @@ -570,38 +570,38 @@ enum { RI_GLOBAL_POP = 11 }; -#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, 1) -#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, n) +#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, 1) +#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_USAGE_PAGE, RI_TYPE_GLOBAL, n) -#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, 1) -#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, n) +#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, 1) +#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MIN, RI_TYPE_GLOBAL, n) -#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, 1) -#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, n) +#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, 1) +#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_LOGICAL_MAX, RI_TYPE_GLOBAL, n) -#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, 1) -#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, n) +#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, 1) +#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MIN, RI_TYPE_GLOBAL, n) -#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, 1) -#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, n) +#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, 1) +#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_PHYSICAL_MAX, RI_TYPE_GLOBAL, n) -#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, 1) -#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, n) +#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, 1) +#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT_EXPONENT, RI_TYPE_GLOBAL, n) -#define HID_UNIT(x) HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, 1) -#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, n) +#define HID_UNIT(x) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, 1) +#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_UNIT, RI_TYPE_GLOBAL, n) -#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, n) +#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, 1) +#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_SIZE, RI_TYPE_GLOBAL, n) -#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, 1), -#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, n), +#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, 1), +#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_ID, RI_TYPE_GLOBAL, n), -#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, 1) -#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, n) +#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, 1) +#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, RI_GLOBAL_REPORT_COUNT, RI_TYPE_GLOBAL, n) -#define HID_PUSH HID_REPORT_ITEM(x, 10, RI_TYPE_GLOBAL, 0) -#define HID_POP HID_REPORT_ITEM(x, 11, RI_TYPE_GLOBAL, 0) +#define HID_PUSH HID_REPORT_ITEM(x, RI_GLOBAL_PUSH, RI_TYPE_GLOBAL, 0) +#define HID_POP HID_REPORT_ITEM(x, RI_GLOBAL_POP, RI_TYPE_GLOBAL, 0) //------------- LOCAL ITEMS 6.2.2.8 -------------// @@ -619,14 +619,14 @@ enum { RI_LOCAL_DELIMITER = 10, }; -#define HID_USAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, 1) -#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, n) +#define HID_USAGE(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, 1) +#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE, RI_TYPE_LOCAL, n) -#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, 1) -#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, n) +#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, 1) +#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MIN, RI_TYPE_LOCAL, n) -#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, 1) -#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, n) +#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, 1) +#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, RI_LOCAL_USAGE_MAX, RI_TYPE_LOCAL, n) //--------------------------------------------------------------------+ // Usage Table -- cgit v1.3.1 From ffdcf9a0d00ad8eba544c4404e27275685ef9cab Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 17 May 2021 13:54:39 +0700 Subject: move report_info to application update API accordingly, update hid parser for usage, and usage_page. --- examples/host/cdc_msc_hid/src/hid_app.c | 209 ++++++++++++++++++++++++++++++++ examples/host/cdc_msc_hid/src/main.c | 124 +------------------ src/class/hid/hid_host.c | 201 +++++++++++++++++------------- src/class/hid/hid_host.h | 54 ++++----- 4 files changed, 356 insertions(+), 232 deletions(-) create mode 100644 examples/host/cdc_msc_hid/src/hid_app.c (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c new file mode 100644 index 000000000..4f8556274 --- /dev/null +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -0,0 +1,209 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, 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. + * + */ + +#include "bsp/board.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ +#define MAX_REPORT 4 + +static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; + +static uint8_t _report_count[CFG_TUH_HID]; +static tuh_hid_report_info_t _report_info[CFG_TUH_HID][MAX_REPORT]; + +static void process_kbd_report(hid_keyboard_report_t const *report); +static void process_mouse_report(hid_mouse_report_t const * report); + +void hid_app_task(void) +{ +} + +//--------------------------------------------------------------------+ +// TinyUSB Callbacks +//--------------------------------------------------------------------+ + +void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) +{ + printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); + + // Parse report descriptor with built-in parser + _report_count[instance] = tuh_hid_parse_report_descriptor(_report_info[instance], MAX_REPORT, desc_report, desc_len); + + if (_report_count[instance]) + { + printf("Composite with %u reports", _report_count[instance]); + }else + { + printf("Single report"); + } + + // Interface protocol + const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t + uint8_t const interface_protocol = tuh_n_hid_n_interface_protocol(dev_addr, instance); + printf(", Interface protocol = %s, ", protocol_str[interface_protocol]); +} + +void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) +{ + printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); +} + +void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) +{ + uint8_t const rpt_count = _report_count[instance]; + tuh_hid_report_info_t* rpt_info; + + if (rpt_count) + { + // Composite report, 1st byte is report ID, data starts from 2nd byte + // Note: report index = report ID - 1 + uint8_t idx = report[0] - 1; + rpt_info = &_report_info[instance][idx]; + + report++; + }else + { + rpt_info = &_report_info[instance][0]; + } + + if ( rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP ) + { + switch (rpt_info->usage) + { + case HID_USAGE_DESKTOP_KEYBOARD: + TU_LOG1("HID receive keyboard report\r\n"); + // Assume keyboard follow boot report layout + process_kbd_report( (hid_keyboard_report_t const*) report ); + break; + + case HID_USAGE_DESKTOP_MOUSE: + TU_LOG1("HID receive mouse report\r\n"); + // Assume mouse follow boot report layout + process_mouse_report( (hid_mouse_report_t const*) report ); + break; + + default: break; + } + } +} + +//--------------------------------------------------------------------+ +// Keyboard +//--------------------------------------------------------------------+ + +// look up new key in previous keys +static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode) +{ + for(uint8_t i=0; i<6; i++) + { + if (report->keycode[i] == keycode) return true; + } + + return false; +} + +static void process_kbd_report(hid_keyboard_report_t const *report) +{ + static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released + + //------------- example code ignore control (non-printable) key affects -------------// + for(uint8_t i=0; i<6; i++) + { + if ( report->keycode[i] ) + { + if ( find_key_in_report(&prev_report, report->keycode[i]) ) + { + // exist in previous report means the current key is holding + }else + { + // not existed in previous report means the current key is pressed + bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); + uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0]; + putchar(ch); + if ( ch == '\r' ) putchar('\n'); // added new line for enter key + + fflush(stdout); // flush right away, else nanolib will wait for newline + } + } + // TODO example skips key released + } + + prev_report = *report; +} + +//--------------------------------------------------------------------+ +// Mouse +//--------------------------------------------------------------------+ + +void cursor_movement(int8_t x, int8_t y, int8_t wheel) +{ + // Move X using ansi escape + if ( x < 0) + { + printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left + }else if ( x > 0) + { + printf(ANSI_CURSOR_FORWARD(%d), x); // move right + } + + // Move Y using ansi escape + if ( y < 0) + { + printf(ANSI_CURSOR_UP(%d), (-y)); // move up + }else if ( y > 0) + { + printf(ANSI_CURSOR_DOWN(%d), y); // move down + } + + // Scroll using ansi escape + if (wheel < 0) + { + printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up + }else if (wheel > 0) + { + printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down + } +} + +static void process_mouse_report(hid_mouse_report_t const * report) +{ + static hid_mouse_report_t prev_report = { 0 }; + + //------------- button state -------------// + uint8_t button_changed_mask = report->buttons ^ prev_report.buttons; + if ( button_changed_mask & report->buttons) + { + printf(" %c%c%c ", + report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', + report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', + report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); + } + + //------------- cursor movement -------------// + cursor_movement(report->x, report->y, report->wheel); +} diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 40642561b..7ae814e38 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -37,7 +37,7 @@ void print_greeting(void); void led_blinking_task(void); extern void cdc_task(void); -extern void hid_task(void); +extern void hid_app_task(void); /*------------- MAIN -------------*/ int main(void) @@ -58,7 +58,7 @@ int main(void) #endif #if CFG_TUH_HID - hid_task(); + hid_app_task(); #endif } @@ -106,127 +106,11 @@ void cdc_task(void) #endif //--------------------------------------------------------------------+ -// USB HID -//--------------------------------------------------------------------+ -uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; - -// look up new key in previous keys -static inline bool find_key_in_report(hid_keyboard_report_t const *p_report, uint8_t keycode) -{ - for(uint8_t i=0; i<6; i++) - { - if (p_report->keycode[i] == keycode) return true; - } - - return false; -} - -static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) -{ - static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released - - //------------- example code ignore control (non-printable) key affects -------------// - for(uint8_t i=0; i<6; i++) - { - if ( p_new_report->keycode[i] ) - { - if ( find_key_in_report(&prev_report, p_new_report->keycode[i]) ) - { - // exist in previous report means the current key is holding - }else - { - // not existed in previous report means the current key is pressed - bool const is_shift = p_new_report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); - uint8_t ch = keycode2ascii[p_new_report->keycode[i]][is_shift ? 1 : 0]; - putchar(ch); - if ( ch == '\r' ) putchar('\n'); // added new line for enter key - - fflush(stdout); // flush right away, else nanolib will wait for newline - } - } - // TODO example skips key released - } - - prev_report = *p_new_report; -} - -void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance) -{ - printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); -// printf("A Keyboard device (address %d) is mounted\r\n", dev_addr); -// printf("A Mouse device (address %d) is mounted\r\n", dev_addr); -} - -void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) -{ - printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); -// printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr); -// printf("A Mouse device (address %d) is unmounted\r\n", dev_addr); -} - -void cursor_movement(int8_t x, int8_t y, int8_t wheel) -{ - //------------- X -------------// - if ( x < 0) - { - printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left - }else if ( x > 0) - { - printf(ANSI_CURSOR_FORWARD(%d), x); // move right - }else { } - - //------------- Y -------------// - if ( y < 0) - { - printf(ANSI_CURSOR_UP(%d), (-y)); // move up - }else if ( y > 0) - { - printf(ANSI_CURSOR_DOWN(%d), y); // move down - }else { } - - //------------- wheel -------------// - if (wheel < 0) - { - printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up - }else if (wheel > 0) - { - printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down - }else { } -} - -static inline void process_mouse_report(hid_mouse_report_t const * p_report) -{ - static hid_mouse_report_t prev_report = { 0 }; - - //------------- button state -------------// - uint8_t button_changed_mask = p_report->buttons ^ prev_report.buttons; - if ( button_changed_mask & p_report->buttons) - { - printf(" %c%c%c ", - p_report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', - p_report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', - p_report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); - } - - //------------- cursor movement -------------// - cursor_movement(p_report->x, p_report->y, p_report->wheel); -} - -void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) -{ - process_kbd_report( (hid_keyboard_report_t*) report ); -} - -void hid_task(void) -{ -} - -//--------------------------------------------------------------------+ -// tinyusb callbacks +// TinyUSB Callbacks //--------------------------------------------------------------------+ //--------------------------------------------------------------------+ -// BLINKING TASK +// Blinking Task //--------------------------------------------------------------------+ void led_blinking_task(void) { diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 4c32d9b33..0ffd32617 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -57,16 +57,8 @@ typedef struct uint16_t epin_size; uint16_t epout_size; - uint8_t boot_protocol; // None, Keyboard, Mouse - bool boot_mode; // Boot or Report protocol - - tuh_hid_report_info_t report_info; - - // Parsed Report ID for convenient API - uint8_t rid_keyboard; - uint8_t rid_mouse; - uint8_t rid_gamepad; - uint8_t rid_consumer; + uint8_t boot_interface; // None, Keyboard, Mouse + bool boot_mode; // Boot or Report protocol uint8_t epin_buf[CFG_TUH_HID_EP_BUFSIZE]; uint8_t epout_buf[CFG_TUH_HID_EP_BUFSIZE]; @@ -107,49 +99,30 @@ bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance) return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } -uint8_t tuh_n_hid_n_boot_protocol(uint8_t dev_addr, uint8_t instance) +uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return hid_itf->boot_protocol; + return hid_itf->boot_interface; } -bool tuh_n_hid_n_boot_mode(uint8_t dev_addr, uint8_t instance) +bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->boot_mode; } -tuh_hid_report_info_t const* tuh_n_hid_n_get_report_info(uint8_t dev_addr, uint8_t instance) -{ - return &get_instance(dev_addr, instance)->report_info; -} - -bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) -{ - TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); - - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); -} - -//--------------------------------------------------------------------+ -// KEYBOARD -//--------------------------------------------------------------------+ - -bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - - // TODO check rid_keyboard - return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); -} +//bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, bool boot_mode) +//{ +// +//} -// TODO remove -bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance) -{ - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0); -} +//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) +//{ +// TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); +// +// hidh_interface_t* hid_itf = get_instance(dev_addr, instance); +// return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); +//} //--------------------------------------------------------------------+ // USBH API @@ -167,10 +140,9 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 if ( dir == TUSB_DIR_IN ) { - if (tuh_hid_get_report_cb) - { - tuh_hid_get_report_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); - } + TU_LOG2(" Get Report callback (%u, %u)\r\n", dev_addr, instance); + TU_LOG1_MEM(hid_itf->epin_buf, 8, 2); + tuh_hid_get_report_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); // queue next report hidh_get_report(dev_addr, hid_itf); @@ -197,7 +169,6 @@ void hidh_close(uint8_t dev_addr) // Enumeration //--------------------------------------------------------------------+ -static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* desc_report, uint16_t desc_len); static bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -228,40 +199,40 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); hid_dev->inst_count++; - hid_itf->itf_num = desc_itf->bInterfaceNumber; - hid_itf->ep_in = desc_ep->bEndpointAddress; + hid_itf->itf_num = desc_itf->bInterfaceNumber; + hid_itf->ep_in = desc_ep->bEndpointAddress; hid_itf->epin_size = desc_ep->wMaxPacketSize.size; // Assume bNumDescriptors = 1 hid_itf->report_desc_type = desc_hid->bReportType; - hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); + hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); hid_itf->boot_mode = false; // default is report mode if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { - hid_itf->boot_protocol = desc_itf->bInterfaceProtocol; + hid_itf->boot_interface = desc_itf->bInterfaceProtocol; if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { TU_LOG2(" Boot Keyboard\r\n"); // TODO boot protocol may still have more report in report mode - hid_itf->report_info.count = 1; +// hid_itf->report_info.count = 1; - hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; - hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_KEYBOARD; - hid_itf->report_info.info[0].in_len = 8; - hid_itf->report_info.info[0].out_len = 1; +// hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; +// hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_KEYBOARD; +// hid_itf->report_info.info[0].in_len = 8; +// hid_itf->report_info.info[0].out_len = 1; } else if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) { TU_LOG2(" Boot Mouse\r\n"); // TODO boot protocol may still have more report in report mode - hid_itf->report_info.count = 1; +// hid_itf->report_info.count = 1; - hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; - hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_MOUSE; - hid_itf->report_info.info[0].in_len = 5; - hid_itf->report_info.info[0].out_len = 0; +// hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; +// hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_MOUSE; +// hid_itf->report_info.info[0].in_len = 5; +// hid_itf->report_info.info[0].out_len = 0; } else { @@ -344,15 +315,8 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co uint8_t const* desc_report = usbh_get_enum_buf(); uint16_t const desc_len = request->wLength; - if (tuh_hid_descriptor_report_cb) - { - tuh_hid_descriptor_report_cb(dev_addr, instance, desc_report, desc_len); - } - - parse_report_descriptor(hid_itf, desc_report, desc_len); - // enumeration is complete - if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, instance); + tuh_hid_mounted_cb(dev_addr, instance, desc_report, desc_len); // queue transfer for IN endpoint hidh_get_report(dev_addr, hid_itf); @@ -363,8 +327,11 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co return true; } -// Parse Report Descriptor to tuh_hid_report_info_t -static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* desc_report, uint16_t desc_len) +//--------------------------------------------------------------------+ +// Report Descriptor Parser +//--------------------------------------------------------------------+ + +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) { // Report Item 6.2.2.2 USB HID 1.11 union TU_ATTR_PACKED @@ -378,7 +345,20 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de }; } header; - while(desc_len) + uint8_t report_num = 0; + tuh_hid_report_info_t* info = report_info; + + tu_memclr(report_info, arr_count*sizeof(tuh_hid_report_info_t)); + + // current parsed report count & size from descriptor +// uint8_t ri_report_count = 0; +// uint8_t ri_report_size = 0; + + uint8_t ri_collection_depth = 0; + uint16_t ri_usage_page = 0; + uint8_t ri_usage = 0; + + while(desc_len && report_num < arr_count) { header.byte = *desc_report++; desc_len--; @@ -387,6 +367,8 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de uint8_t const type = header.type; uint8_t const size = header.size; + uint8_t const data8 = desc_report[0]; + TU_LOG2("tag = %d, type = %d, size = %d, data = ", tag, type, size); for(uint32_t i=0; iusage_page = ri_usage_page; + info->usage = ri_usage; + }else + { + TU_LOG2("HID Skip a report with ID (%u) larger than array count (%u)\r\n", data8, arr_count); + } + break; + + case RI_GLOBAL_REPORT_SIZE: +// ri_report_size = data8; + break; + + case RI_GLOBAL_REPORT_COUNT: +// ri_report_count = data8; + break; + case RI_GLOBAL_UNIT_EXPONENT : break; case RI_GLOBAL_UNIT : break; - case RI_GLOBAL_REPORT_SIZE : break; - case RI_GLOBAL_REPORT_ID : break; - case RI_GLOBAL_REPORT_COUNT : break; case RI_GLOBAL_PUSH : break; case RI_GLOBAL_POP : break; @@ -429,7 +450,11 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de case RI_TYPE_LOCAL: switch(tag) { - case RI_LOCAL_USAGE : break; + case RI_LOCAL_USAGE: + // only take in account the "usage" before starting COLLECTION + if ( ri_collection_depth == 0) ri_usage = data8; + break; + case RI_LOCAL_USAGE_MIN : break; case RI_LOCAL_USAGE_MAX : break; case RI_LOCAL_DESIGNATOR_INDEX : break; @@ -448,8 +473,22 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de } desc_report += size; - desc_len -= size; + desc_len -= size; } + + if ( report_num == 0 ) + { + report_info[0].usage_page = ri_usage_page; + report_info[0].usage = ri_usage; + } + + for ( uint8_t i = 0; (i < report_num) || (!i && !report_num); i++ ) + { + info = report_info+i; + TU_LOG2("%u: usage_page = %u, usage = %u\r\n", i, info->usage_page, info->usage); + } + + return report_num; } //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index b000cdfcb..122f57088 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -53,17 +53,12 @@ typedef struct { - uint8_t count; // number of info + uint16_t usage_page; + uint8_t usage; - struct - { - uint8_t usage_page; - uint8_t usage; - - // TODO still use the endpoint size for now - uint8_t in_len; // length of IN report - uint8_t out_len; // length of OUT report - } info[CFG_TUH_HID_REPORT_MAX]; + // TODO still use the endpoint size for now +// uint8_t in_len; // length of IN report +// uint8_t out_len; // length of OUT report } tuh_hid_report_info_t; //--------------------------------------------------------------------+ @@ -79,47 +74,44 @@ uint8_t tuh_n_hid_instance_count(uint8_t dev_addr); // Check if HID instance is mounted bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance); -// Get boot protocol check out hid_protocol_type_t for possible value -uint8_t tuh_n_hid_n_boot_protocol(uint8_t dev_addr, uint8_t instance); +// Get boot interface protocol check out hid_protocol_type_t for possible value +uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance); + +// Get current protocol mode: Boot (true) or Report (false) +// By HID spec, device will be initialized in Report mode +bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance); -// Check if current mode is Boot (true) or Report (false) -bool tuh_n_hid_n_boot_mode(uint8_t dev_addr, uint8_t instance); +// Set protocol to Boot or Report mode. +// This function is only supported by Boot interface tuh_n_hid_n_boot_interface() +bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, bool boot_mode); -// Get Report information parsed from report descriptor. Data must not be modified by application -// If report information does not match the actual device descriptor, that is because the built-in parser -// has its limit. Application could use tuh_hid_descriptor_report_cb() callback to parse descriptor by itself. -tuh_hid_report_info_t const* tuh_n_hid_n_get_report_info(uint8_t dev_addr, uint8_t instance); +// Parse report descriptor into array of report_info struct and return number of reports. +// If return 0, this is a ingle report, otherwise it is composite report with 1st byte as ID. +// For complicated report, application should write its own parser. +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; // Check if the interface is ready to use -bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); +//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); // Set Report using control endpoint //bool tuh_n_hid_n_set_report_control(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len); //------------- -------------// -// Check if HID instance with Keyboard is mounted -bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance); - -// Check if HID instance with Mouse is mounted -bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance); - //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ -// Invoked when report descriptor is received -// Note: enumeration is still not complete yet at this time -TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); - // Invoked when device with hid interface is mounted -TU_ATTR_WEAK void tuh_hid_mounted_cb (uint8_t dev_addr, uint8_t instance); +// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() +// can be used to parse common/simple enough descriptor. +void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); // Invoked when device with hid interface is un-mounted TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); // Invoked when received Report from device via either regular or control endpoint -TU_ATTR_WEAK void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); +void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); // Invoked when Sent Report to device via either regular or control endpoint TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes); -- cgit v1.3.1 From 2df5a5367f6b8a6649d39d3ba7ebc0af56db9ad2 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 18 May 2021 13:12:33 +0700 Subject: update hid host get/set protocol to match device --- src/class/hid/hid_device.h | 2 +- src/class/hid/hid_host.c | 12 ++++++------ src/class/hid/hid_host.h | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index bccfb8d4d..bfaa35f7d 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -57,7 +57,7 @@ // Check if the interface is ready to use bool tud_hid_n_ready(uint8_t instance); -// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible value +// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values uint8_t tud_hid_n_interface_protocol(uint8_t instance); // Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 8d60ceb71..62e6c4b76 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -57,8 +57,8 @@ typedef struct uint16_t epin_size; uint16_t epout_size; - uint8_t boot_interface; // None, Keyboard, Mouse - bool boot_mode; // Boot or Report protocol + uint8_t itf_protocol; // None, Keyboard, Mouse + bool boot_mode; // Boot or Report protocol uint8_t epin_buf[CFG_TUH_HID_EP_BUFSIZE]; uint8_t epout_buf[CFG_TUH_HID_EP_BUFSIZE]; @@ -102,16 +102,16 @@ bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance) uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return hid_itf->boot_interface; + return hid_itf->itf_protocol; } bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return hid_itf->boot_mode; + return hid_itf->boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; } -//bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, bool boot_mode) +// bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) //{ // //} @@ -212,7 +212,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->boot_mode = false; // default is report mode if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) { - hid_itf->boot_interface = desc_itf->bInterfaceProtocol; + hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; if ( HID_ITF_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) { diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 87b86c90b..677c8c9de 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -74,16 +74,16 @@ uint8_t tuh_n_hid_instance_count(uint8_t dev_addr); // Check if HID instance is mounted bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance); -// Get boot interface protocol check out hid_protocol_type_t for possible value +// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance); -// Get current protocol mode: Boot (true) or Report (false) -// By HID spec, device will be initialized in Report mode +// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +// Note: as HID spec, device will be initialized in Report mode bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance); -// Set protocol to Boot or Report mode. +// Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // This function is only supported by Boot interface tuh_n_hid_n_boot_interface() -bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, bool boot_mode); +bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); // Parse report descriptor into array of report_info struct and return number of reports. // If return 0, this is a ingle report, otherwise it is composite report with 1st byte as ID. -- cgit v1.3.1 From 99add05aa78a0fd5d462ab822d0c4656c41c59d7 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 16:27:28 +0700 Subject: simplify hid api add hid set_protocol() and set_protocol_complete_cb() --- examples/host/cdc_msc_hid/src/hid_app.c | 2 +- src/class/hid/hid_host.c | 113 +++++++++++++++----------------- src/class/hid/hid_host.h | 13 ++-- 3 files changed, 61 insertions(+), 67 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index de92ab841..72e7c30db 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -64,7 +64,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_ // Interface protocol const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t - uint8_t const interface_protocol = tuh_n_hid_n_interface_protocol(dev_addr, instance); + uint8_t const interface_protocol = tuh_n_hid_interface_protocol(dev_addr, instance); printf(", Interface protocol = %s, ", protocol_str[interface_protocol]); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 62e6c4b76..e35e4e4da 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -51,15 +51,15 @@ typedef struct uint8_t ep_in; uint8_t ep_out; + uint8_t itf_protocol; // None, Keyboard, Mouse + uint8_t protocol_mode; // Boot (0) or Report protocol (1) + uint8_t report_desc_type; uint16_t report_desc_len; uint16_t epin_size; uint16_t epout_size; - uint8_t itf_protocol; // None, Keyboard, Mouse - bool boot_mode; // Boot or Report protocol - uint8_t epin_buf[CFG_TUH_HID_EP_BUFSIZE]; uint8_t epout_buf[CFG_TUH_HID_EP_BUFSIZE]; } hidh_interface_t; @@ -76,7 +76,6 @@ static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); -static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf); static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr); TU_ATTR_ALWAYS_INLINE static inline bool hidh_get_report(uint8_t dev_addr, hidh_interface_t* hid_itf) @@ -93,28 +92,64 @@ uint8_t tuh_n_hid_instance_count(uint8_t dev_addr) return get_dev(dev_addr)->inst_count; } -bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance) +bool tuh_n_hid_mounted(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } -uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance) +uint8_t tuh_n_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->itf_protocol; } -bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance) +bool tuh_n_hid_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - return hid_itf->boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; + return hid_itf->protocol_mode; } -// bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) -//{ -// -//} +static bool set_protocol_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + if (XFER_RESULT_SUCCESS == result) hid_itf->protocol_mode = (uint8_t) request->wValue; + + if (tuh_hid_set_protocol_complete_cb) + { + tuh_hid_set_protocol_complete_cb(dev_addr, instance, hid_itf->protocol_mode); + } + + return true; +} + +bool tuh_n_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE); + + TU_LOG2("Set Protocol = %d\r\n", protocol); + + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, + .wValue = protocol, + .wIndex = hid_itf->itf_num, + .wLength = 0 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, set_protocol_complete) ); + return true; +} //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) //{ @@ -209,39 +244,8 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->report_desc_type = desc_hid->bReportType; hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); - hid_itf->boot_mode = false; // default is report mode - if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) - { - hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; - - if ( HID_ITF_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol) - { - TU_LOG2(" Boot Keyboard\r\n"); - // TODO boot protocol may still have more report in report mode -// hid_itf->report_info.count = 1; - -// hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; -// hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_KEYBOARD; -// hid_itf->report_info.info[0].in_len = 8; -// hid_itf->report_info.info[0].out_len = 1; - } - else if ( HID_ITF_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol) - { - TU_LOG2(" Boot Mouse\r\n"); - // TODO boot protocol may still have more report in report mode -// hid_itf->report_info.count = 1; - -// hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP; -// hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_MOUSE; -// hid_itf->report_info.info[0].in_len = 5; -// hid_itf->report_info.info[0].out_len = 0; - } - else - { - // Unknown protocol - TU_ASSERT(false); - } - } + hid_itf->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode + if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); @@ -279,9 +283,9 @@ bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * r // Stall is a valid response for SET_IDLE, therefore we could ignore its result (void) result; - uint8_t const itf_num = (uint8_t) request->wIndex; - - hidh_interface_t* hid_itf = get_instance_by_itfnum(dev_addr, itf_num); + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); // Get Report Descriptor // using usbh enumeration buffer since report descriptor can be very long @@ -509,19 +513,6 @@ TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_a return &_hidh_dev[dev_addr-1].instances[instance]; } -// Get instance by interface number -static hidh_interface_t* get_instance_by_itfnum(uint8_t dev_addr, uint8_t itf) -{ - for ( uint8_t inst = 0; inst < CFG_TUH_HID; inst++ ) - { - hidh_interface_t *hid = get_instance(dev_addr, inst); - - if ( (hid->itf_num == itf) && (hid->ep_in || hid->ep_out) ) return hid; - } - - return NULL; -} - // Get instance ID by interface number static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf) { diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 677c8c9de..dc0d8c935 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -72,18 +72,18 @@ typedef struct uint8_t tuh_n_hid_instance_count(uint8_t dev_addr); // Check if HID instance is mounted -bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance); +bool tuh_n_hid_mounted(uint8_t dev_addr, uint8_t instance); // Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values -uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance); +uint8_t tuh_n_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); // Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // Note: as HID spec, device will be initialized in Report mode -bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance); +bool tuh_n_hid_get_protocol(uint8_t dev_addr, uint8_t instance); // Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// This function is only supported by Boot interface tuh_n_hid_n_boot_interface() -bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); +// This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) +bool tuh_n_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); // Parse report descriptor into array of report_info struct and return number of reports. // If return 0, this is a ingle report, otherwise it is composite report with 1st byte as ID. @@ -116,6 +116,9 @@ void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* re // Invoked when Sent Report to device via either regular or control endpoint TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes); +// Invoked when Set Protocol request is complete +TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t protocol); + //--------------------------------------------------------------------+ // Application API (Single device) //--------------------------------------------------------------------+ -- cgit v1.3.1 From 89dad1ad414e36aa3f0d69b35d06ec82c3e0f168 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 16:48:07 +0700 Subject: update app --- examples/host/cdc_msc_hid/src/hid_app.c | 10 ++++++++++ src/class/hid/hid_host.h | 4 +--- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 72e7c30db..628ab3e7d 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -29,6 +29,10 @@ //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ + +// If your host terminal support ansi escape code, it can be use to simulate mouse cursor +#define USE_ANSI_ESCAPE 0 + #define MAX_REPORT 4 static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; @@ -165,6 +169,7 @@ static void process_kbd_report(hid_keyboard_report_t const *report) void cursor_movement(int8_t x, int8_t y, int8_t wheel) { +#if USE_ANSI_ESCAPE // Move X using ansi escape if ( x < 0) { @@ -191,6 +196,11 @@ void cursor_movement(int8_t x, int8_t y, int8_t wheel) { printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down } + + printf("\r\n"); +#else + printf("(%d %d %d)\r\n", x, y, wheel); +#endif } static void process_mouse_report(hid_mouse_report_t const * report) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index dc0d8c935..1537216bb 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -63,9 +63,7 @@ typedef struct //--------------------------------------------------------------------+ // Application API (Multiple devices) -// Note: -// - tud_n : is multiple devices API -// - class_n : is multiple instances API +// - tud_n : is multiple devices API //--------------------------------------------------------------------+ // Get the number of HID instances -- cgit v1.3.1 From 350dfb2ea37cebc59ef9fd6b63d2aae1b8cb48da Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 18:17:32 +0700 Subject: more hid api rename --- examples/host/cdc_msc_hid/src/hid_app.c | 2 +- src/class/hid/hid_host.c | 10 +++++----- src/class/hid/hid_host.h | 27 ++++++--------------------- 3 files changed, 12 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 628ab3e7d..eab555fc1 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -68,7 +68,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_ // Interface protocol const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t - uint8_t const interface_protocol = tuh_n_hid_interface_protocol(dev_addr, instance); + uint8_t const interface_protocol = tuh_hid_interface_protocol(dev_addr, instance); printf(", Interface protocol = %s, ", protocol_str[interface_protocol]); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index e35e4e4da..90a848fc1 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -87,24 +87,24 @@ TU_ATTR_ALWAYS_INLINE static inline bool hidh_get_report(uint8_t dev_addr, hidh_ // Application API //--------------------------------------------------------------------+ -uint8_t tuh_n_hid_instance_count(uint8_t dev_addr) +uint8_t tuh_hid_instance_count(uint8_t dev_addr) { return get_dev(dev_addr)->inst_count; } -bool tuh_n_hid_mounted(uint8_t dev_addr, uint8_t instance) +bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } -uint8_t tuh_n_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) +uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->itf_protocol; } -bool tuh_n_hid_get_protocol(uint8_t dev_addr, uint8_t instance) +bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->protocol_mode; @@ -126,7 +126,7 @@ static bool set_protocol_complete(uint8_t dev_addr, tusb_control_request_t const return true; } -bool tuh_n_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) +bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 1537216bb..3cf8dc70f 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -62,26 +62,25 @@ typedef struct } tuh_hid_report_info_t; //--------------------------------------------------------------------+ -// Application API (Multiple devices) -// - tud_n : is multiple devices API +// Application API //--------------------------------------------------------------------+ // Get the number of HID instances -uint8_t tuh_n_hid_instance_count(uint8_t dev_addr); +uint8_t tuh_hid_instance_count(uint8_t dev_addr); // Check if HID instance is mounted -bool tuh_n_hid_mounted(uint8_t dev_addr, uint8_t instance); +bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance); // Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values -uint8_t tuh_n_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); +uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); // Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // Note: as HID spec, device will be initialized in Report mode -bool tuh_n_hid_get_protocol(uint8_t dev_addr, uint8_t instance); +bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); // Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) -bool tuh_n_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); +bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); // Parse report descriptor into array of report_info struct and return number of reports. // If return 0, this is a ingle report, otherwise it is composite report with 1st byte as ID. @@ -94,8 +93,6 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint // Set Report using control endpoint //bool tuh_n_hid_n_set_report_control(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len); -//------------- -------------// - //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ @@ -117,18 +114,6 @@ TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t insta // Invoked when Set Protocol request is complete TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t protocol); -//--------------------------------------------------------------------+ -// Application API (Single device) -//--------------------------------------------------------------------+ - -// Get the number of HID instances -TU_ATTR_ALWAYS_INLINE static inline -uint8_t tuh_hid_instance_count(void) -{ - return tuh_n_hid_instance_count(1); -} - - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -- cgit v1.3.1 From ad845db6a50c1d90e4f7cc45ca16a8861ee2da4d Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 20:54:59 +0700 Subject: improve hid parser --- examples/host/cdc_msc_hid/src/hid_app.c | 50 +++++++++++++++++------------ src/class/hid/hid_host.c | 56 ++++++++++----------------------- src/class/hid/hid_host.h | 6 ++-- 3 files changed, 50 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index eab555fc1..71904245a 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -37,14 +37,16 @@ static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; +// Each HID instance can has multiple reports static uint8_t _report_count[CFG_TUH_HID]; -static tuh_hid_report_info_t _report_info[CFG_TUH_HID][MAX_REPORT]; +static tuh_hid_report_info_t _report_info_arr[CFG_TUH_HID][MAX_REPORT]; static void process_kbd_report(hid_keyboard_report_t const *report); static void process_mouse_report(hid_mouse_report_t const * report); void hid_app_task(void) { + // nothing to do } //--------------------------------------------------------------------+ @@ -55,21 +57,13 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_ { printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); - // Parse report descriptor with built-in parser - _report_count[instance] = tuh_hid_parse_report_descriptor(_report_info[instance], MAX_REPORT, desc_report, desc_len); - - if (_report_count[instance]) - { - printf("Composite with %u reports", _report_count[instance]); - }else - { - printf("Single report"); - } - // Interface protocol const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t uint8_t const interface_protocol = tuh_hid_interface_protocol(dev_addr, instance); - printf(", Interface protocol = %s, ", protocol_str[interface_protocol]); + + // Parse report descriptor with built-in parser + _report_count[instance] = tuh_hid_parse_report_descriptor(_report_info_arr[instance], MAX_REPORT, desc_report, desc_len); + printf("HID has %u reports and interface protocol = %s\r\n", _report_count[instance], protocol_str[interface_protocol]); } void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) @@ -82,20 +76,36 @@ void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* re (void) dev_addr; uint8_t const rpt_count = _report_count[instance]; - tuh_hid_report_info_t* rpt_info; + tuh_hid_report_info_t* rpt_info_arr = _report_info_arr[instance]; + tuh_hid_report_info_t* rpt_info = NULL; - if (rpt_count) + if ( rpt_count == 1 && rpt_info_arr[0].report_id == 0) + { + // Simple report without report ID as 1st byte + rpt_info = &rpt_info_arr[0]; + }else { // Composite report, 1st byte is report ID, data starts from 2nd byte - // Note: report index = report ID - 1 - uint8_t idx = report[0] - 1; - rpt_info = &_report_info[instance][idx]; + uint8_t const rpt_id = report[0]; + + // Find report id in the arrray + for(uint8_t i=0; iusage_page == HID_USAGE_PAGE_DESKTOP ) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 90a848fc1..15533cf3a 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -337,7 +337,7 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co // Report Descriptor Parser //--------------------------------------------------------------------+ -uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) { // Report Item 6.2.2.2 USB HID 1.11 union TU_ATTR_PACKED @@ -351,18 +351,16 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint }; } header; - uint8_t report_num = 0; - tuh_hid_report_info_t* info = report_info; + tu_memclr(report_info_arr, arr_count*sizeof(tuh_hid_report_info_t)); - tu_memclr(report_info, arr_count*sizeof(tuh_hid_report_info_t)); + uint8_t report_num = 0; + tuh_hid_report_info_t* info = report_info_arr; // current parsed report count & size from descriptor // uint8_t ri_report_count = 0; // uint8_t ri_report_size = 0; uint8_t ri_collection_depth = 0; - uint16_t ri_usage_page = 0; - uint8_t ri_usage = 0; while(desc_len && report_num < arr_count) { @@ -394,6 +392,11 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint case RI_MAIN_COLLECTION_END: ri_collection_depth--; + if (ri_collection_depth == 0) + { + info++; + report_num++; + } break; default: break; @@ -404,11 +407,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint switch(tag) { case RI_GLOBAL_USAGE_PAGE: - // only take in account the "usage page" before starting COLLECTION - if ( ri_collection_depth == 0) - { - memcpy(&ri_usage_page, desc_report, size); - } + // only take in account the "usage page" before REPORT ID + if ( ri_collection_depth == 0 ) memcpy(&info->usage_page, desc_report, size); break; case RI_GLOBAL_LOGICAL_MIN : break; @@ -417,23 +417,7 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint case RI_GLOBAL_PHYSICAL_MAX : break; case RI_GLOBAL_REPORT_ID: - report_num++; - if (data8 <= arr_count) - { - uint8_t const idx = data8 - 1; - if ( info != &report_info[idx] ) - { - // copy info so far to its correct report ID, and update info pointer - report_info[idx] = *info; - info = &report_info[idx]; - } - - info->usage_page = ri_usage_page; - info->usage = ri_usage; - }else - { - TU_LOG2("HID Skip a report with ID (%u) larger than array count (%u)\r\n", data8, arr_count); - } + info->report_id = data8; break; case RI_GLOBAL_REPORT_SIZE: @@ -457,8 +441,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint switch(tag) { case RI_LOCAL_USAGE: - // only take in account the "usage" before starting COLLECTION - if ( ri_collection_depth == 0) ri_usage = data8; + // only take in account the "usage" before starting REPORT ID + if ( ri_collection_depth == 0 ) info->usage = data8; break; case RI_LOCAL_USAGE_MIN : break; @@ -482,16 +466,10 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint desc_len -= size; } - if ( report_num == 0 ) - { - report_info[0].usage_page = ri_usage_page; - report_info[0].usage = ri_usage; - } - - for ( uint8_t i = 0; (i < report_num) || (!i && !report_num); i++ ) + for ( uint8_t i = 0; i < report_num; i++ ) { - info = report_info+i; - TU_LOG2("%u: usage_page = %u, usage = %u\r\n", i, info->usage_page, info->usage); + info = report_info_arr+i; + TU_LOG2("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage); } return report_num; diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 3cf8dc70f..1b8acda05 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -53,8 +53,9 @@ typedef struct { + uint8_t report_id; + uint8_t usage; uint16_t usage_page; - uint8_t usage; // TODO still use the endpoint size for now // uint8_t in_len; // length of IN report @@ -83,9 +84,8 @@ bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); // Parse report descriptor into array of report_info struct and return number of reports. -// If return 0, this is a ingle report, otherwise it is composite report with 1st byte as ID. // For complicated report, application should write its own parser. -uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; // Check if the interface is ready to use //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); -- cgit v1.3.1 From 63c57ed1a4285671ba38d87b8b77fd68c55880e6 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 20:55:42 +0700 Subject: clean p --- examples/host/cdc_msc_hid/src/tusb_config.h | 4 ---- src/class/hid/hid_host.h | 4 ---- 2 files changed, 8 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 8c82c0fef..8253964c0 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -86,10 +86,6 @@ #define CFG_TUH_HID_EP_BUFSIZE 64 -// Max number of reports per interface -// E.g composite HID with keyboard + mouse + gamepad will have 3 reports -#define CFG_TUH_HID_REPORT_MAX 4 - #ifdef __cplusplus } #endif diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 1b8acda05..3ac1f7c69 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -42,10 +42,6 @@ // Class Driver Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUH_HID_REPORT_MAX -#define CFG_TUH_HID_REPORT_MAX 4 -#endif - // TODO Highspeed interrupt can be up to 512 bytes #ifndef CFG_TUH_HID_EP_BUFSIZE #define CFG_TUH_HID_EP_BUFSIZE 64 -- cgit v1.3.1 From df65c35b31581881b2bf49d9e16608d46f98fe4b Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 21:48:42 +0700 Subject: implement hid host set report with control transfer rename mount, umount callback --- examples/host/cdc_msc_hid/src/hid_app.c | 4 +-- examples/host/cdc_msc_hid/src/msc_app.c | 2 +- src/class/hid/hid_host.c | 54 ++++++++++++++++++++++++++++++--- src/class/hid/hid_host.h | 16 +++++----- src/class/msc/msc_host.c | 2 +- src/class/msc/msc_host.h | 2 +- 6 files changed, 63 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 71904245a..79f10251f 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -53,7 +53,7 @@ void hid_app_task(void) // TinyUSB Callbacks //--------------------------------------------------------------------+ -void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) +void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); @@ -66,7 +66,7 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_ printf("HID has %u reports and interface protocol = %s\r\n", _report_count[instance], protocol_str[interface_protocol]); } -void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance) +void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) { printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); } diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 3a8ef3a07..3657a3d35 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -80,7 +80,7 @@ void tuh_msc_mount_cb(uint8_t dev_addr) // } } -void tuh_msc_unmount_cb(uint8_t dev_addr) +void tuh_msc_umount_cb(uint8_t dev_addr) { (void) dev_addr; printf("A MassStorage device is unmounted\r\n"); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 15533cf3a..f15f0b72a 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -73,6 +73,8 @@ typedef struct static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1]; //------------- Internal prototypes -------------// + +// Get HID device & interface TU_ATTR_ALWAYS_INLINE static inline hidh_device_t* get_dev(uint8_t dev_addr); TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_addr, uint8_t instance); static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf); @@ -131,7 +133,7 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) hidh_interface_t* hid_itf = get_instance(dev_addr, instance); TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE); - TU_LOG2("Set Protocol = %d\r\n", protocol); + TU_LOG2("HID Set Protocol = %d\r\n", protocol); tusb_control_request_t const request = { @@ -151,6 +153,48 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol) return true; } +static bool set_report_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_LOG2("HID Set Report complete\r\n"); + + if (tuh_hid_set_report_complete_cb) + { + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + + uint8_t const report_type = tu_u16_high(request->wValue); + uint8_t const report_id = tu_u16_low(request->wValue); + + tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, (result == XFER_RESULT_SUCCESS) ? request->wLength : 0); + } + + return true; +} + + +bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + TU_LOG2("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); + + tusb_control_request_t const request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_REPORT, + .wValue = tu_u16(report_type, report_id), + .wIndex = hid_itf->itf_num, + .wLength = len + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, set_report_complete) ); + return true; +} + //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance) //{ // TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); @@ -185,7 +229,7 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 hidh_get_report(dev_addr, hid_itf); }else { - if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); +// if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); } return true; @@ -194,9 +238,9 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 void hidh_close(uint8_t dev_addr) { hidh_device_t* hid_dev = get_dev(dev_addr); - if (tuh_hid_unmounted_cb) + if (tuh_hid_umount_cb) { - for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++) tuh_hid_unmounted_cb(dev_addr, inst); + for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++) tuh_hid_umount_cb(dev_addr, inst); } tu_memclr(hid_dev, sizeof(hidh_device_t)); @@ -322,7 +366,7 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co uint16_t const desc_len = request->wLength; // enumeration is complete - tuh_hid_mounted_cb(dev_addr, instance, desc_report, desc_len); + tuh_hid_mount_cb(dev_addr, instance, desc_report, desc_len); // queue transfer for IN endpoint hidh_get_report(dev_addr, hid_itf); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 3ac1f7c69..f962f5b0a 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -79,6 +79,10 @@ bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); // This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol); +// Set Report using control endpoint +// report_type is either Intput, Output or Feature, (value from hid_report_type_t) +bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len); + // Parse report descriptor into array of report_info struct and return number of reports. // For complicated report, application should write its own parser. uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED; @@ -86,9 +90,6 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, // Check if the interface is ready to use //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); -// Set Report using control endpoint -//bool tuh_n_hid_n_set_report_control(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len); - //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ @@ -96,16 +97,17 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, // Invoked when device with hid interface is mounted // Report descriptor is also available for use. tuh_hid_parse_report_descriptor() // can be used to parse common/simple enough descriptor. -void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); +void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); // Invoked when device with hid interface is un-mounted -TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance); +TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance); // Invoked when received Report from device via either regular or control endpoint void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); -// Invoked when Sent Report to device via either regular or control endpoint -TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes); +// Invoked when Sent Report to device via either control endpoint +// len = 0 indicate there is error in the transfer e.g stalled response +TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); // Invoked when Set Protocol request is complete TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t protocol); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 4869c8c03..08b4db9e1 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -300,7 +300,7 @@ void msch_close(uint8_t dev_addr) tu_memclr(p_msc, sizeof(msch_interface_t)); // invoke Application Callback - if (tuh_msc_unmount_cb) tuh_msc_unmount_cb(dev_addr); + if (tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); } bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 7ebc9b5a8..b5ffcd401 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -109,7 +109,7 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r TU_ATTR_WEAK void tuh_msc_mount_cb(uint8_t dev_addr); // Invoked when a device with MassStorage interface is unmounted -TU_ATTR_WEAK void tuh_msc_unmount_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API -- cgit v1.3.1 From b8e019da321512758959f6fb3b2f0192bda698dc Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 21:51:30 +0700 Subject: rename tuh_hid_get_report_cb to tuh_hid_report_received_cb() --- examples/host/cdc_msc_hid/src/hid_app.c | 7 ++++++- src/class/hid/hid_host.c | 2 +- src/class/hid/hid_host.h | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 79f10251f..67be8d50f 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -53,6 +53,9 @@ void hid_app_task(void) // TinyUSB Callbacks //--------------------------------------------------------------------+ +// Invoked when device with hid interface is mounted +// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() +// can be used to parse common/simple enough descriptor. void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); @@ -66,12 +69,14 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re printf("HID has %u reports and interface protocol = %s\r\n", _report_count[instance], protocol_str[interface_protocol]); } +// Invoked when device with hid interface is un-mounted void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) { printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); } -void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) +// Invoked when received Report from device via either regular endpoint +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) { (void) dev_addr; diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index f15f0b72a..63983ca5f 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -223,7 +223,7 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 { TU_LOG2(" Get Report callback (%u, %u)\r\n", dev_addr, instance); TU_LOG1_MEM(hid_itf->epin_buf, 8, 2); - tuh_hid_get_report_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); + tuh_hid_report_received_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes); // queue next report hidh_get_report(dev_addr, hid_itf); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index f962f5b0a..3f9979f52 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -102,8 +102,8 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_ // Invoked when device with hid interface is un-mounted TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance); -// Invoked when received Report from device via either regular or control endpoint -void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); +// Invoked when received Report from device via either regular endpoint +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); // Invoked when Sent Report to device via either control endpoint // len = 0 indicate there is error in the transfer e.g stalled response -- cgit v1.3.1 From a2c4a48dd627828f5899e5ab70412594b60f37c6 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 22:03:21 +0700 Subject: add tuh_hid_report_sent_cb() --- examples/host/cdc_msc_hid/src/hid_app.c | 2 +- src/class/hid/hid_host.c | 5 +++-- src/class/hid/hid_host.h | 10 +++++++++- 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 67be8d50f..23ab12404 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -75,7 +75,7 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); } -// Invoked when received Report from device via either regular endpoint +// Invoked when received report from device via interrupt endpoint void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) { (void) dev_addr; diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 63983ca5f..778a897be 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -171,7 +171,6 @@ static bool set_report_complete(uint8_t dev_addr, tusb_control_request_t const * return true; } - bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); @@ -203,6 +202,8 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u // return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); //} +//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); + //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ @@ -229,7 +230,7 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3 hidh_get_report(dev_addr, hid_itf); }else { -// if (tuh_hid_set_report_complete_cb) tuh_hid_set_report_complete_cb(dev_addr, instance, xferred_bytes); + if (tuh_hid_report_sent_cb) tuh_hid_report_sent_cb(dev_addr, instance, hid_itf->epout_buf, xferred_bytes); } return true; diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 3f9979f52..ea693df69 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -90,6 +90,10 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, // Check if the interface is ready to use //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance); +// Send report using interrupt endpoint +// If report_id > 0 (composite), it will be sent as 1st byte, then report contents. Otherwise only report content is sent. +//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); + //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ @@ -102,9 +106,13 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_ // Invoked when device with hid interface is un-mounted TU_ATTR_WEAK void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance); -// Invoked when received Report from device via either regular endpoint +// Invoked when received report from device via interrupt endpoint +// Note: if there is report ID (composite), it is 1st byte of report void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); +// Invoked when sent report to device successfully via interrupt endpoint +TU_ATTR_WEAK void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); + // Invoked when Sent Report to device via either control endpoint // len = 0 indicate there is error in the transfer e.g stalled response TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, uint16_t len); -- cgit v1.3.1 From f13a3c04f790a865472a7ed0b57182f401189977 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 22:43:55 +0700 Subject: fix missing report in tuh_hid_set_report() --- src/class/hid/hid_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 778a897be..6c0c97095 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -190,7 +190,7 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u .wLength = len }; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, set_report_complete) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &request, report, set_report_complete) ); return true; } -- cgit v1.3.1 From a1dab1611bad43cfc3c2dcce58c1dce442287eb9 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 22 May 2021 23:30:41 +0700 Subject: get protocol when enum with hid boot interface --- src/class/hid/hid_host.c | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 6c0c97095..e3ae5a155 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -251,8 +251,9 @@ void hidh_close(uint8_t dev_addr) // Enumeration //--------------------------------------------------------------------+ -static bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_get_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) { @@ -299,11 +300,14 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) { + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + // Idle rate = 0 mean only report when there is changes uint16_t const idle_rate = 0; // SET IDLE request, device can stall if not support this request - TU_LOG2("Set Idle \r\n"); + TU_LOG2("HID Set Idle \r\n"); tusb_control_request_t const request = { .bmRequestType_bit = @@ -318,14 +322,42 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) .wLength = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, config_set_idle_complete) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_get_protocol : config_get_report_desc) ); return true; } -bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool config_get_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + // Stall is a valid response for SET_IDLE GET_PROTOCOL, therefore we could ignore its result + (void) result; + + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + + TU_LOG2("HID Get Protocol\r\n"); + tusb_control_request_t const new_request = + { + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = HID_REQ_CONTROL_GET_PROTOCOL, + .wValue = 0, + .wIndex = hid_itf->itf_num, + .wLength = 1 + }; + + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, &hid_itf->protocol_mode, config_get_report_desc) ); + return false; +} + +static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - // Stall is a valid response for SET_IDLE, therefore we could ignore its result + // Stall is a valid response for SET_IDLE GET_PROTOCOL, therefore we could ignore its result (void) result; uint8_t const itf_num = (uint8_t) request->wIndex; @@ -355,7 +387,7 @@ bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * r return true; } -bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { TU_ASSERT(XFER_RESULT_SUCCESS == result); -- cgit v1.3.1 From 8cffe4897eb114d65ff60685e111ff3e03d0fd74 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 23 May 2021 13:56:32 +0700 Subject: change hid device internal boot_mode to protocol_mode --- src/class/hid/hid_device.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index ab9ef3ad8..0d9cdb22b 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -45,7 +45,7 @@ typedef struct uint8_t ep_out; // optional Out endpoint uint8_t itf_protocol; // Boot mouse or keyboard - bool boot_mode; // default = false (Report) + uint8_t protocol_mode; // Boot (0) or Report protocol (1) uint8_t idle_rate; // up to application to handle idle rate uint16_t report_desc_len; @@ -112,7 +112,7 @@ uint8_t tud_hid_n_interface_protocol(uint8_t instance) uint8_t tud_hid_n_get_protocol(uint8_t instance) { - return _hidd_itf[instance].boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT; + return _hidd_itf[instance].protocol_mode; } bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) @@ -213,7 +213,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->itf_protocol = desc_itf->bInterfaceProtocol; - p_hid->boot_mode = false; // default mode is REPORT + p_hid->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode p_hid->itf_num = desc_itf->bInterfaceNumber; // Use offsetof to avoid pointer to the odd/misaligned address @@ -326,8 +326,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t case HID_REQ_CONTROL_GET_PROTOCOL: if ( stage == CONTROL_STAGE_SETUP ) { - uint8_t protocol = (p_hid->boot_mode ? HID_PROTOCOL_BOOT : HID_PROTOCOL_REPORT); - tud_control_xfer(rhport, request, &protocol, 1); + tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1); } break; @@ -338,10 +337,10 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t } else if ( stage == CONTROL_STAGE_ACK ) { - p_hid->boot_mode = (request->wValue == HID_PROTOCOL_BOOT); + p_hid->protocol_mode = (uint8_t) request->wValue; if (tud_hid_set_protocol_cb) { - tud_hid_set_protocol_cb(hid_itf, (uint8_t) request->wValue); + tud_hid_set_protocol_cb(hid_itf, p_hid->protocol_mode); } } break; -- cgit v1.3.1 From 3654d96e07f63e041f750aafd125c2c8bca27aa5 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 23 May 2021 14:11:12 +0700 Subject: only invoke tuh_msc_umount_cb() if needed --- src/class/hid/hid_host.c | 2 +- src/class/msc/msc_host.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index e3ae5a155..1bc86e4ad 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -241,7 +241,7 @@ void hidh_close(uint8_t dev_addr) hidh_device_t* hid_dev = get_dev(dev_addr); if (tuh_hid_umount_cb) { - for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++) tuh_hid_umount_cb(dev_addr, inst); + for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++ ) tuh_hid_umount_cb(dev_addr, inst); } tu_memclr(hid_dev, sizeof(hidh_device_t)); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 08b4db9e1..ca360ca2a 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -297,10 +297,11 @@ void msch_init(void) void msch_close(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); - tu_memclr(p_msc, sizeof(msch_interface_t)); // invoke Application Callback - if (tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); + if (p_msc->mounted && tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); + + tu_memclr(p_msc, sizeof(msch_interface_t)); } bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -- cgit v1.3.1 From 4f033321189eb572c870d08281dd06e044c7597e Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 23 May 2021 20:14:01 +0700 Subject: clean up --- src/device/dcd.h | 6 ------ src/host/hcd.h | 44 ++++++++++++++++++++++++++++---------------- 2 files changed, 28 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index 1e5b3ff1e..71e88054c 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -24,10 +24,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_usbd - * \defgroup group_dcd Device Controller Driver (DCD) - * @{ */ - #ifndef _TUSB_DCD_H_ #define _TUSB_DCD_H_ @@ -168,5 +164,3 @@ extern void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t x #endif #endif /* _TUSB_DCD_H_ */ - -/// @} diff --git a/src/host/hcd.h b/src/host/hcd.h index a470a45e8..ba6a9c5ca 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -24,14 +24,10 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_usbh - * \defgroup Group_HCD Host Controller Driver (HCD) - * @{ */ - #ifndef _TUSB_HCD_H_ #define _TUSB_HCD_H_ -#include +#include "common/tusb_common.h" #ifdef __cplusplus extern "C" { @@ -95,27 +91,46 @@ enum { #endif //--------------------------------------------------------------------+ -// Controller & Port API +// Controller API //--------------------------------------------------------------------+ + +// Initialize controller to host mode bool hcd_init(uint8_t rhport); + +// Interrupt Handler void hcd_int_handler(uint8_t rhport); + +// Enable USB interrupt void hcd_int_enable (uint8_t rhport); + +// Disable USB interrupt void hcd_int_disable(uint8_t rhport); // Get micro frame number (125 us) uint32_t hcd_uframe_number(uint8_t rhport); // Get frame number (1ms) -static inline uint32_t hcd_frame_number(uint8_t rhport) +TU_ATTR_ALWAYS_INLINE static inline +uint32_t hcd_frame_number(uint8_t rhport) { return hcd_uframe_number(rhport) >> 3; } -/// return the current connect status of roothub port -bool hcd_port_connect_status(uint8_t hostid); -void hcd_port_reset(uint8_t hostid); +//--------------------------------------------------------------------+ +// Port API +//--------------------------------------------------------------------+ + +// Get the current connect status of roothub port +bool hcd_port_connect_status(uint8_t rhport); + +// Reset USB bus on the port +void hcd_port_reset(uint8_t rhport); + +// TODO implement later void hcd_port_reset_end(uint8_t rhport); -tusb_speed_t hcd_port_speed_get(uint8_t hostid); + +// Get port link speed +tusb_speed_t hcd_port_speed_get(uint8_t rhport); // HCD closes all opened endpoints belong to this device void hcd_device_close(uint8_t rhport, uint8_t dev_addr); @@ -123,6 +138,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); //--------------------------------------------------------------------+ // Endpoints API //--------------------------------------------------------------------+ + bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); @@ -134,14 +150,12 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); //--------------------------------------------------------------------+ -// PIPE API +// PIPE API - TODO remove later //--------------------------------------------------------------------+ // TODO control xfer should be used via usbh layer bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes); // only queue, not transferring yet bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete); -// tusb_error_t hcd_pipe_cancel(); - //--------------------------------------------------------------------+ // Event API (implemented by stack) //--------------------------------------------------------------------+ @@ -163,5 +177,3 @@ extern void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t #endif #endif /* _TUSB_HCD_H_ */ - -/// @} -- cgit v1.3.1 From 954056da0ca4633d27f022858600164721963104 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 25 May 2021 21:02:40 +0700 Subject: fix warnings cast function type for nrf, fix pico osal warning add TODO for overflow in tusb_fifo.c --- examples/make.mk | 4 +++- hw/bsp/nrf/family.c | 7 ++++++- src/common/tusb_fifo.c | 2 ++ src/osal/osal_pico.h | 2 ++ 4 files changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/examples/make.mk b/examples/make.mk index 6366d6cef..df8bfd617 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -88,6 +88,7 @@ CFLAGS += \ -fno-strict-aliasing \ -Wdouble-promotion \ -Wstrict-prototypes \ + -Wstrict-overflow \ -Wall \ -Wextra \ -Werror \ @@ -100,7 +101,8 @@ CFLAGS += \ -Wsign-compare \ -Wmissing-format-attribute \ -Wunreachable-code \ - -Wcast-align + -Wcast-align \ + -Wcast-function-type # Debugging/Optimization ifeq ($(DEBUG), 1) diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index fc5e805d9..f117fbe33 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -55,6 +55,11 @@ static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(0); // We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. extern void tusb_hal_nrf_power_event(uint32_t event); +static void power_event_handler(nrfx_power_usb_evt_t event) +{ + tusb_hal_nrf_power_event((uint32_t) event); +} + void board_init(void) { // stop LF clock just in case we jump from application without reset @@ -121,7 +126,7 @@ void board_init(void) // Register tusb function as USB power handler // cause cast-function-type warning - const nrfx_power_usbevt_config_t config = { .handler = ((nrfx_power_usb_event_handler_t) tusb_hal_nrf_power_event) }; + const nrfx_power_usbevt_config_t config = { .handler = power_event_handler }; nrfx_power_usbevt_init(&config); nrfx_power_usbevt_enable(); diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 81e11eb01..5f7b6a26d 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -325,6 +325,8 @@ static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) // We limit the index space of p such that a correct wrap around happens // Check for a wrap around or if we are in unused index space - This has to be checked first!! // We are exploiting the wrap around to the correct index + + // TODO warning: assuming signed overflow does not occur when assuming that (X + c) < X is always false [-Wstrict-overflow] if ((p > p + offset) || (p + offset > f->max_pointer_idx)) { p = (p + offset) + f->non_used_index_space; diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index bae1217eb..1c3366e01 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -57,6 +57,7 @@ static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semde static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { + (void) in_isr; sem_release(sem_hdl); return true; } @@ -158,6 +159,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in // however osal_queue_recieve may be. therefore my assumption is that // the fifo mutex is not populated for queues used from an IRQ context //assert(!qhdl->ff.mutex); + (void) in_isr; _osal_q_lock(qhdl); bool success = tu_fifo_write(&qhdl->ff, data); -- cgit v1.3.1 From f9c542aa52f7f2e5e532343384441234a019e53d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 May 2021 18:16:56 +0700 Subject: fix dfu example build --- examples/device/dfu/.skip.MCU_SAMD11 | 0 examples/device/dfu/CMakeLists.txt | 10 +++------- examples/device/dfu/src/main.c | 15 +++++++-------- examples/device/dfu/src/tusb_config.h | 2 +- examples/device/dfu/src/usb_descriptors.c | 6 +++--- examples/rules.mk | 3 ++- hw/bsp/rp2040/family.cmake | 1 + hw/bsp/samd11/boards/luna_d11/samd11d14am_flash.ld | 1 + hw/bsp/samd11/boards/samd11_xplained/board.mk | 1 - hw/bsp/samd11/boards/samd11_xplained/samd11d14am_flash.ld | 1 + hw/bsp/samd11/family.mk | 3 ++- hw/bsp/saml22/boards/saml22_feather/saml22_feather.ld | 1 + hw/bsp/saml22/boards/sensorwatch_m0/sensorwatch_m0.ld | 1 + src/class/dfu/dfu_device.c | 2 ++ 14 files changed, 25 insertions(+), 22 deletions(-) create mode 100644 examples/device/dfu/.skip.MCU_SAMD11 (limited to 'src') diff --git a/examples/device/dfu/.skip.MCU_SAMD11 b/examples/device/dfu/.skip.MCU_SAMD11 new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/dfu/CMakeLists.txt b/examples/device/dfu/CMakeLists.txt index f4bf75c26..4160c0c88 100644 --- a/examples/device/dfu/CMakeLists.txt +++ b/examples/device/dfu/CMakeLists.txt @@ -9,10 +9,9 @@ get_filename_component(TOP "${TOP}" REALPATH) # Check for -DFAMILY= if(FAMILY STREQUAL "rp2040") cmake_minimum_required(VERSION 3.12) - set(PICO_SDK_PATH ${TOP}/hw/mcu/raspberrypi/pico-sdk) - include(${PICO_SDK_PATH}/pico_sdk_init.cmake) + + include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake) project(${PROJECT}) - pico_sdk_init() add_executable(${PROJECT}) include(${TOP}/hw/bsp/${FAMILY}/family.cmake) @@ -33,9 +32,6 @@ if(FAMILY STREQUAL "rp2040") CFG_TUSB_OS=OPT_OS_PICO ) - target_link_libraries(${PROJECT} pico_stdlib pico_fix_rp2040_usb_device_enumeration) - pico_add_extra_outputs(${PROJECT}) - else() - message(FATAL_ERROR "Invalid FAMILY specified") + message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}") endif() diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 3849de44d..1c09066a8 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -126,21 +126,20 @@ void tud_dfu_runtime_reboot_to_dfu_cb(void) //--------------------------------------------------------------------+ bool tud_dfu_firmware_valid_check_cb(void) { - TU_LOG2(" Firmware check\r\n"); + printf(" Firmware check\r\n"); return true; } void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length) { - TU_LOG2(" Received BlockNum %u of length %u\r\n", wBlockNum, length); + (void) data; + printf(" Received BlockNum %u of length %u\r\n", wBlockNum, length); #if DFU_VERBOSE for(uint16_t i=0; i ram /* stack section */ diff --git a/hw/bsp/samd11/boards/samd11_xplained/board.mk b/hw/bsp/samd11/boards/samd11_xplained/board.mk index 79ad87068..e351cf0b8 100644 --- a/hw/bsp/samd11/boards/samd11_xplained/board.mk +++ b/hw/bsp/samd11/boards/samd11_xplained/board.mk @@ -6,7 +6,6 @@ LD_FILE = $(BOARD_PATH)/samd11d14am_flash.ld # For flash-jlink target JLINK_DEVICE = ATSAMD11D14 - # flash using edbg flash: $(BUILD)/$(PROJECT).bin edbg -b -t samd11 -e -pv -f $< diff --git a/hw/bsp/samd11/boards/samd11_xplained/samd11d14am_flash.ld b/hw/bsp/samd11/boards/samd11_xplained/samd11d14am_flash.ld index 2153f5f50..8b3124c0e 100644 --- a/hw/bsp/samd11/boards/samd11_xplained/samd11d14am_flash.ld +++ b/hw/bsp/samd11/boards/samd11_xplained/samd11d14am_flash.ld @@ -126,6 +126,7 @@ SECTIONS . = ALIGN(4); _ebss = . ; _ezero = .; + end = .; } > ram /* stack section */ diff --git a/hw/bsp/samd11/family.mk b/hw/bsp/samd11/family.mk index 6fbdc35af..70120ec94 100644 --- a/hw/bsp/samd11/family.mk +++ b/hw/bsp/samd11/family.mk @@ -3,8 +3,9 @@ DEPS_SUBMODULES += hw/mcu/microchip include $(TOP)/$(BOARD_PATH)/board.mk CFLAGS += \ + -flto \ -mthumb \ - -mabi=aapcs-linux \ + -mabi=aapcs \ -mcpu=cortex-m0plus \ -nostdlib -nostartfiles \ -DCONF_DFLL_OVERWRITE_CALIBRATION=0 \ diff --git a/hw/bsp/saml22/boards/saml22_feather/saml22_feather.ld b/hw/bsp/saml22/boards/saml22_feather/saml22_feather.ld index 2e0e1b256..d1aaa44fc 100644 --- a/hw/bsp/saml22/boards/saml22_feather/saml22_feather.ld +++ b/hw/bsp/saml22/boards/saml22_feather/saml22_feather.ld @@ -128,6 +128,7 @@ SECTIONS . = ALIGN(4); _ebss = . ; _ezero = .; + end = .; } > ram /* stack section */ diff --git a/hw/bsp/saml22/boards/sensorwatch_m0/sensorwatch_m0.ld b/hw/bsp/saml22/boards/sensorwatch_m0/sensorwatch_m0.ld index 2e0e1b256..d1aaa44fc 100644 --- a/hw/bsp/saml22/boards/sensorwatch_m0/sensorwatch_m0.ld +++ b/hw/bsp/saml22/boards/sensorwatch_m0/sensorwatch_m0.ld @@ -128,6 +128,7 @@ SECTIONS . = ALIGN(4); _ebss = . ; _ezero = .; + end = .; } > ram /* stack section */ diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index da9f189aa..8496cb02b 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -150,6 +150,8 @@ void dfu_moded_init(void) void dfu_moded_reset(uint8_t rhport) { + (void) rhport; + _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.blk_transfer_in_proc = false; -- cgit v1.3.1 From faa31152b4473166e099fc02500534018ce8c465 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 May 2021 20:25:44 +0700 Subject: rename usbd_edpt_iso_xfer to usbd_edpt_xfer_fifo --- src/class/audio/audio_device.c | 6 +++--- src/device/usbd.c | 2 +- src/device/usbd_pvt.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 72533013c..3afe6ce3f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -548,7 +548,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else // Data is already placed in EP FIFO, schedule for next receive - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); #endif #endif @@ -852,7 +852,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); #else // Send everything in ISO EP FIFO - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); #endif #endif @@ -1611,7 +1611,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #if USE_LINEAR_BUFFER_RX TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); #else - TU_VERIFY(usbd_edpt_iso_xfer(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); #endif } diff --git a/src/device/usbd.c b/src/device/usbd.c index 8454a2951..71c5d4e6c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1271,7 +1271,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 44310f022..c42bfd97b 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -73,7 +73,7 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted -bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); +bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. -- cgit v1.3.1 From 814edec89f5440b5dad43cc405e97af4f8fae175 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 May 2021 20:29:18 +0700 Subject: clean up --- src/tusb_option.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/tusb_option.h b/src/tusb_option.h index b317f7630..feff013c7 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -55,11 +55,11 @@ #define OPT_MCU_NRF5X 100 ///< Nordic nRF5x series // SAM -#define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 #define OPT_MCU_SAMD21 200 ///< MicroChip SAMD21 #define OPT_MCU_SAMD51 201 ///< MicroChip SAMD51 -#define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMG 202 ///< MicroChip SAMDG series +#define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x +#define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 #define OPT_MCU_SAML22 205 ///< MicroChip SAML22 // STM32 -- cgit v1.3.1 From c7cecf28c8bd409c3032a11180333654c90020d4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 May 2021 00:13:07 +0700 Subject: clean up --- README.md | 2 +- src/common/tusb_fifo.h | 13 ++++++------- src/device/usbd.h | 4 ++-- src/device/usbd_pvt.h | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index bef49eea4..f7b2cd811 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ Supports multiple device configurations by dynamically changing usb descriptors. TinyUSB is completely thread-safe by pushing all ISR events into a central queue, then process it later in the non-ISR context task function. It also uses semaphore/mutex to access shared resources such as CDC FIFO. Therefore the stack needs to use some of OS's basic APIs. Following OSes are already supported out of the box. -- **No OS** : Disabling USB IRQ is used as way to provide mutex +- **No OS** - **FreeRTOS** - **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its [own repo](https://github.com/hathach/mynewt-tinyusb-example) diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 8d73911f0..1f9da94d1 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -53,9 +53,6 @@ extern "C" { #define tu_fifo_mutex_t osal_mutex_t #endif -/** \struct tu_fifo_t - * \brief Simple Circular FIFO - */ typedef struct { uint8_t* buffer ; ///< buffer pointer @@ -104,7 +101,8 @@ bool tu_fifo_clear(tu_fifo_t *f); bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); #if CFG_FIFO_MUTEX -static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mutex_hdl, tu_fifo_mutex_t read_mutex_hdl) +TU_ATTR_ALWAYS_INLINE static inline +void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t write_mutex_hdl, tu_fifo_mutex_t read_mutex_hdl) { f->mutex_wr = write_mutex_hdl; f->mutex_rd = read_mutex_hdl; @@ -129,15 +127,16 @@ uint16_t tu_fifo_remaining (tu_fifo_t* f); bool tu_fifo_overflowed (tu_fifo_t* f); void tu_fifo_correct_read_pointer (tu_fifo_t* f); -static inline uint16_t tu_fifo_depth(tu_fifo_t* f) +static inline +uint16_t tu_fifo_depth(tu_fifo_t* f) { return f->depth; } // Pointer modifications intended to be used in combinations with DMAs. // USE WITH CARE - NO SAFTY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED! -void tu_fifo_advance_write_pointer (tu_fifo_t *f, uint16_t n); -void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); +void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n); +void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n); // If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies // to handle a possible wrapping part. These functions deliver a pointer to start diff --git a/src/device/usbd.h b/src/device/usbd.h index 53519c4de..3857295d7 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -70,8 +70,8 @@ bool tud_mounted(void); bool tud_suspended(void); // Check if device is ready to transfer -TU_ATTR_ALWAYS_INLINE -static inline bool tud_ready(void) +TU_ATTR_ALWAYS_INLINE static inline +bool tud_ready(void) { return tud_mounted() && !tud_suspended(); } diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index c42bfd97b..65fdadf51 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -94,7 +94,7 @@ void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr); // Check if endpoint is stalled bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr); -static inline +TU_ATTR_ALWAYS_INLINE static inline bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) { return !usbd_edpt_busy(rhport, ep_addr) && !usbd_edpt_stalled(rhport, ep_addr); -- cgit v1.3.1 From 9736e54734a85c03d9055c24414e23f112a67968 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 May 2021 17:40:39 +0700 Subject: include clean up --- src/class/audio/audio_device.c | 3 +- src/class/audio/audio_device.h | 4 --- src/class/bth/bth_device.c | 1 - src/class/cdc/cdc_device.c | 4 ++- src/class/cdc/cdc_device.h | 1 - src/class/dfu/dfu_device.c | 4 ++- src/class/dfu/dfu_device.h | 2 -- src/class/dfu/dfu_rt_device.c | 4 ++- src/class/dfu/dfu_rt_device.h | 2 -- src/class/hid/hid_device.c | 5 +-- src/class/hid/hid_device.h | 2 -- src/class/midi/midi_device.c | 5 +-- src/class/midi/midi_device.h | 3 -- src/class/msc/msc_device.c | 5 +-- src/class/msc/msc_device.h | 72 +++++++++++++++++----------------------- src/class/net/net_device.c | 4 ++- src/class/net/net_device.h | 1 - src/class/usbtmc/usbtmc_device.c | 8 ++--- src/class/vendor/vendor_device.c | 4 ++- src/class/vendor/vendor_device.h | 1 - src/common/tusb_common.h | 5 +-- src/device/dcd.h | 1 + 22 files changed, 62 insertions(+), 79 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 3afe6ce3f..8e4420ed0 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -55,9 +55,10 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ +#include "device/usbd.h" #include "device/usbd_pvt.h" + #include "audio_device.h" -//#include "common/tusb_fifo.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index b8e6ef9c0..5a469523c 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -28,10 +28,6 @@ #ifndef _TUSB_AUDIO_DEVICE_H_ #define _TUSB_AUDIO_DEVICE_H_ -#include "assert.h" -#include "common/tusb_common.h" -#include "device/usbd.h" - #include "audio.h" //--------------------------------------------------------------------+ diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index 481dc134e..1d27ae7c5 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -32,7 +32,6 @@ // INCLUDE //--------------------------------------------------------------------+ #include "bth_device.h" -#include #include //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index f5853fddb..cac811c45 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -28,9 +28,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_CDC) -#include "cdc_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "cdc_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 986585c5b..7ff757add 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -28,7 +28,6 @@ #define _TUSB_CDC_DEVICE_H_ #include "common/tusb_common.h" -#include "device/usbd.h" #include "cdc.h" //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 8496cb02b..81045ff7b 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -28,9 +28,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE) -#include "dfu_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "dfu_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index c45c436c5..9a09a46b1 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -27,8 +27,6 @@ #ifndef _TUSB_DFU_DEVICE_H_ #define _TUSB_DFU_DEVICE_H_ -#include "common/tusb_common.h" -#include "device/usbd.h" #include "dfu.h" #ifdef __cplusplus diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index faeae9b68..07e6f30f3 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -28,9 +28,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME) -#include "dfu_rt_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "dfu_rt_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 0e5fd005a..babaa8214 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -27,8 +27,6 @@ #ifndef _TUSB_DFU_RT_DEVICE_H_ #define _TUSB_DFU_RT_DEVICE_H_ -#include "common/tusb_common.h" -#include "device/usbd.h" #include "dfu.h" #ifdef __cplusplus diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 0d9cdb22b..c7f5d04ec 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -31,10 +31,11 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ -#include "common/tusb_common.h" -#include "hid_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "hid_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 61274be4d..beb755888 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -27,8 +27,6 @@ #ifndef _TUSB_HID_DEVICE_H_ #define _TUSB_HID_DEVICE_H_ -#include "common/tusb_common.h" -#include "device/usbd.h" #include "hid.h" #ifdef __cplusplus diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 2c50bc4f3..953ca26e6 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -31,10 +31,11 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ -#include "midi_device.h" -#include "class/audio/audio.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "midi_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 67f03930c..211edc8d1 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -27,9 +27,6 @@ #ifndef _TUSB_MIDI_DEVICE_H_ #define _TUSB_MIDI_DEVICE_H_ -#include "common/tusb_common.h" -#include "device/usbd.h" - #include "class/audio/audio.h" #include "midi.h" diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 539941935..9b06b7a33 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -28,11 +28,12 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_MSC) -#include "common/tusb_common.h" -#include "msc_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" #include "device/dcd.h" // for faking dcd_event_xfer_complete +#include "msc_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 469f2f2f7..8f90ef4ad 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -28,7 +28,6 @@ #define _TUSB_MSC_DEVICE_H_ #include "common/tusb_common.h" -#include "device/usbd.h" #include "msc.h" #ifdef __cplusplus @@ -51,53 +50,45 @@ TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); -/** \addtogroup ClassDriver_MSC - * @{ - * \defgroup MSC_Device Device - * @{ */ +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ +// Set SCSI sense response bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier); //--------------------------------------------------------------------+ // Application Callbacks (WEAK is optional) //--------------------------------------------------------------------+ -/** - * Invoked when received \ref SCSI_CMD_READ_10 command - * \param[in] lun Logical unit number - * \param[in] lba Logical Block Address to be read - * \param[in] offset Byte offset from LBA - * \param[out] buffer Buffer which application need to update with the response data. - * \param[in] bufsize Requested bytes - * - * \return Number of byte read, if it is less than requested bytes by \a \b bufsize. Tinyusb will transfer - * this amount first and invoked this again for remaining data. - * - * \retval zero Indicate application is not ready yet to response e.g disk I/O is not complete. - * tinyusb will invoke this callback with the same parameters again some time later. - * - * \retval negative Indicate error e.g reading disk I/O. tinyusb will \b STALL the corresponding - * endpoint and return failed status in command status wrapper phase. - */ +// Invoked when received SCSI READ10 command +// - Address = lba * BLOCK_SIZE + offset +// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. +// +// - Application fill the buffer (up to bufsize) with address contents and return number of read byte. If +// - read < bufsize : These bytes are transferred first and callback invoked again for remaining data. +// +// - read == 0 : Indicate application is not ready yet e.g disk I/O busy. +// Callback invoked again with the same parameters later on. +// +// - read < 0 : Indicate application error e.g invalid address. This request will be STALLed +// and return failed status in command status wrapper phase. int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize); -/** - * Invoked when received \ref SCSI_CMD_WRITE_10 command - * \param[in] lun Logical unit number - * \param[in] lba Logical Block Address to be write - * \param[in] offset Byte offset from LBA - * \param[out] buffer Buffer which holds written data. - * \param[in] bufsize Requested bytes - * - * \return Number of byte written, if it is less than requested bytes by \a \b bufsize. Tinyusb will proceed with - * other work and invoked this again with adjusted parameters. - * - * \retval zero Indicate application is not ready yet e.g disk I/O is not complete. - * Tinyusb will invoke this callback with the same parameters again some time later. - * - * \retval negative Indicate error writing disk I/O. Tinyusb will \b STALL the corresponding - * endpoint and return failed status in command status wrapper phase. - */ +// Invoked when received SCSI WRITE10 command +// - Address = lba * BLOCK_SIZE + offset +// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. +// +// - Application write data from buffer to address contents (up to bufsize) and return number of written byte. If +// - write < bufsize : callback invoked again with remaining data later on. +// +// - write == 0 : Indicate application is not ready yet e.g disk I/O busy. +// Callback invoked again with the same parameters later on. +// +// - write < 0 : Indicate application error e.g invalid address. This request will be STALLed +// and return failed status in command status wrapper phase. +// +// TODO change buffer to const uint8_t* int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize); // Invoked when received SCSI_CMD_INQUIRY @@ -152,9 +143,6 @@ TU_ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[1 // Hook to make a mass storage device read-only. TODO remove TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun); -/** @} */ -/** @} */ - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c index ce1131223..9d9719ce4 100644 --- a/src/class/net/net_device.c +++ b/src/class/net/net_device.c @@ -29,8 +29,10 @@ #if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_NET ) -#include "net_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" + +#include "net_device.h" #include "rndis_protocol.h" void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */ diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 38c47d647..f5f0cd8f1 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -28,7 +28,6 @@ #ifndef _TUSB_NET_DEVICE_H_ #define _TUSB_NET_DEVICE_H_ -#include "common/tusb_common.h" #include "device/usbd.h" #include "class/cdc/cdc.h" diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index d5f8fe41d..c1ee49f45 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -77,15 +77,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_USBTMC) -#include -#include "usbtmc.h" -#include "usbtmc_device.h" #include "device/usbd.h" -#include "osal/osal.h" - -// FIXME: I shouldn't need to include _pvt headers, but it is necessary for usbd_edpt_xfer, _stall, and _busy #include "device/usbd_pvt.h" +#include "usbtmc_device.h" + #ifdef xDEBUG #include "uart_util.h" static char logMsg[150]; diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 5fc7dd569..081aac9f6 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -28,9 +28,11 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_VENDOR) -#include "vendor_device.h" +#include "device/usbd.h" #include "device/usbd_pvt.h" +#include "vendor_device.h" + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 2c3d79a3d..6d9c784c0 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -28,7 +28,6 @@ #define _TUSB_VENDOR_DEVICE_H_ #include "common/tusb_common.h" -#include "device/usbd.h" #ifndef CFG_TUD_VENDOR_EPSIZE #define CFG_TUD_VENDOR_EPSIZE 64 diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 88e85c9e0..1ebd8dd61 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -72,10 +72,11 @@ #include "tusb_option.h" #include "tusb_compiler.h" #include "tusb_verify.h" -#include "tusb_error.h" // TODO remove -#include "tusb_timeout.h" #include "tusb_types.h" +#include "tusb_error.h" // TODO remove +#include "tusb_timeout.h" // TODO remove + //------------- Mem -------------// #define tu_memclr(buffer, size) memset((buffer), 0, (size)) #define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) diff --git a/src/device/dcd.h b/src/device/dcd.h index 71e88054c..e17c62d4e 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -28,6 +28,7 @@ #define _TUSB_DCD_H_ #include "common/tusb_common.h" +#include "osal/osal.h" #include "common/tusb_fifo.h" #ifdef __cplusplus -- cgit v1.3.1 From b36b211c26d807214da1132b41669915fbd21c83 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 May 2021 17:58:42 +0700 Subject: clean up tusb_fifo.h include --- src/portable/espressif/esp32sx/dcd_esp32sx.c | 1 - src/portable/microchip/samg/dcd_samg.c | 1 - src/portable/nuvoton/nuc120/dcd_nuc120.c | 1 - src/portable/nuvoton/nuc121/dcd_nuc121.c | 1 - src/portable/nuvoton/nuc505/dcd_nuc505.c | 1 - src/portable/raspberrypi/rp2040/dcd_rp2040.c | 2 -- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 1 - src/portable/st/synopsys/dcd_synopsys.c | 2 -- src/portable/template/dcd_template.c | 1 - src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 1 - 10 files changed, 12 deletions(-) (limited to 'src') diff --git a/src/portable/espressif/esp32sx/dcd_esp32sx.c b/src/portable/espressif/esp32sx/dcd_esp32sx.c index 502273a9b..d728487c2 100644 --- a/src/portable/espressif/esp32sx/dcd_esp32sx.c +++ b/src/portable/espressif/esp32sx/dcd_esp32sx.c @@ -40,7 +40,6 @@ #include "soc/gpio_sig_map.h" #include "soc/usb_periph.h" -#include "common/tusb_fifo.h" #include "device/dcd.h" // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 9b6a1f9a5..d50621ce4 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -29,7 +29,6 @@ #if CFG_TUSB_MCU == OPT_MCU_SAMG #include "sam.h" -#include "common/tusb_fifo.h" #include "device/dcd.h" // TODO should support (SAM3S || SAM4S || SAM4E || SAMG55) diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 7aeb49f2a..047fa3fa6 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -37,7 +37,6 @@ #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC120) -#include "common/tusb_fifo.h" #include "device/dcd.h" #include "NUC100Series.h" diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index e76d7118c..37b7b0106 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -37,7 +37,6 @@ #if TUSB_OPT_DEVICE_ENABLED && ( (CFG_TUSB_MCU == OPT_MCU_NUC121) || (CFG_TUSB_MCU == OPT_MCU_NUC126) ) -#include "common/tusb_fifo.h" #include "device/dcd.h" #include "NuMicro.h" diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 46081d4d0..4e633086d 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -37,7 +37,6 @@ #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC505) -#include "common/tusb_fifo.h" #include "device/dcd.h" #include "NUC505Series.h" diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 7731078b5..0048270a6 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -35,8 +35,6 @@ #include "pico/fix/rp2040_usb_device_enumeration.h" #endif -#include "osal/osal.h" -#include "common/tusb_fifo.h" #include "device/dcd.h" /*------------------------------------------------------------------*/ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 0b7605a73..74c144107 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -120,7 +120,6 @@ // Some definitions are copied to our private include file. #undef USE_HAL_DRIVER -#include "common/tusb_fifo.h" #include "device/dcd.h" #include "portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h" diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 76f5c6050..8a196e061 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -94,10 +94,8 @@ #else #error "Unsupported MCUs" - #endif -#include "common/tusb_fifo.h" #include "device/dcd.h" //--------------------------------------------------------------------+ diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 92a9f3144..12b9144bf 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -28,7 +28,6 @@ #if CFG_TUSB_MCU == OPT_MCU_NONE -#include "common/tusb_fifo.h" #include "device/dcd.h" //--------------------------------------------------------------------+ diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index e13ee697e..027ed26c9 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -30,7 +30,6 @@ #if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MSP430x5xx ) #include "msp430.h" -#include "common/tusb_fifo.h" #include "device/dcd.h" /*------------------------------------------------------------------*/ -- cgit v1.3.1 From f384d6f67e200b855e7b07a1fc3218c874e43a42 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 May 2021 18:04:28 +0700 Subject: more with clean up --- src/common/tusb_fifo.c | 2 -- src/common/tusb_fifo.h | 15 +++++++-------- 2 files changed, 7 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 5f7b6a26d..1eb886aa1 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -25,8 +25,6 @@ * This file is part of the TinyUSB stack. */ -#include - #include "osal/osal.h" #include "tusb_fifo.h" diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 1f9da94d1..cf299269d 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -28,6 +28,10 @@ #ifndef _TUSB_FIFO_H_ #define _TUSB_FIFO_H_ +#ifdef __cplusplus +extern "C" { +#endif + // Due to the use of unmasked pointers, this FIFO does not suffer from loosing // one item slice. Furthermore, write and read operations are completely // decoupled as write and read functions do not modify a common state. Henceforth, @@ -37,17 +41,12 @@ // read pointers can be updated from within a DMA ISR. Overflows are detectable // within a certain number (see tu_fifo_overflow()). +#include "common/tusb_common.h" + // mutex is only needed for RTOS // for OS None, we don't get preempted #define CFG_FIFO_MUTEX (CFG_TUSB_OS != OPT_OS_NONE) -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - #if CFG_FIFO_MUTEX #include "osal/osal.h" #define tu_fifo_mutex_t osal_mutex_t @@ -127,7 +126,7 @@ uint16_t tu_fifo_remaining (tu_fifo_t* f); bool tu_fifo_overflowed (tu_fifo_t* f); void tu_fifo_correct_read_pointer (tu_fifo_t* f); -static inline +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_depth(tu_fifo_t* f) { return f->depth; -- cgit v1.3.1 From 9ad6fadf6a65363f9873178e7f80c923452bfb47 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 May 2021 18:18:30 +0700 Subject: more include clean up --- src/class/cdc/cdc_host.c | 2 +- src/class/cdc/cdc_host.h | 2 -- src/class/hid/hid_host.c | 2 +- src/class/hid/hid_host.h | 7 ------- src/class/msc/msc.h | 10 ---------- src/class/msc/msc_host.c | 5 +---- src/class/msc/msc_host.h | 2 -- src/class/vendor/vendor_host.c | 2 +- src/class/vendor/vendor_host.h | 7 ------- src/host/hub.c | 4 +--- src/host/hub.h | 1 - src/host/usbh.h | 9 +-------- src/portable/sony/cxd56/dcd_cxd56.c | 1 - 13 files changed, 6 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index a897fb58a..c22107bbb 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -28,7 +28,7 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC) -#include "common/tusb_common.h" +#include "host/usbh.h" #include "cdc_host.h" //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 66c2f0727..6ff392709 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -27,8 +27,6 @@ #ifndef _TUSB_CDC_HOST_H_ #define _TUSB_CDC_HOST_H_ -#include "common/tusb_common.h" -#include "host/usbh.h" #include "cdc.h" #ifdef __cplusplus diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 1bc86e4ad..83f3f3039 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -28,7 +28,7 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HID) -#include "common/tusb_common.h" +#include "host/usbh.h" #include "hid_host.h" //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index ea693df69..2e4cce600 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -24,14 +24,9 @@ * This file is part of the TinyUSB stack. */ -/** \addtogroup ClassDriver_HID - * @{ */ - #ifndef _TUSB_HID_HOST_H_ #define _TUSB_HID_HOST_H_ -#include "common/tusb_common.h" -#include "host/usbh.h" #include "hid.h" #ifdef __cplusplus @@ -134,5 +129,3 @@ void hidh_close(uint8_t dev_addr); #endif #endif /* _TUSB_HID_HOST_H_ */ - -/** @} */ // ClassDriver_HID diff --git a/src/class/msc/msc.h b/src/class/msc/msc.h index 0bdc00692..84b6e4d79 100644 --- a/src/class/msc/msc.h +++ b/src/class/msc/msc.h @@ -24,13 +24,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_class - * \defgroup ClassDriver_MSC MassStorage (MSC) - * @{ */ - -/** \defgroup ClassDriver_MSC_Common Common Definitions - * @{ */ - #ifndef _TUSB_MSC_H_ #define _TUSB_MSC_H_ @@ -387,6 +380,3 @@ TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); #endif #endif /* _TUSB_MSC_H_ */ - -/// @} -/// @} diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index ca360ca2a..5a4ffff48 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -28,10 +28,7 @@ #if TUSB_OPT_HOST_ENABLED & CFG_TUH_MSC -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "common/tusb_common.h" +#include "host/usbh.h" #include "msc_host.h" //--------------------------------------------------------------------+ diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index b5ffcd401..ce4fe64dc 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -27,8 +27,6 @@ #ifndef _TUSB_MSC_HOST_H_ #define _TUSB_MSC_HOST_H_ -#include "common/tusb_common.h" -#include "host/usbh.h" #include "msc.h" #ifdef __cplusplus diff --git a/src/class/vendor/vendor_host.c b/src/class/vendor/vendor_host.c index 0524cb981..1978ef61c 100644 --- a/src/class/vendor/vendor_host.c +++ b/src/class/vendor/vendor_host.c @@ -31,7 +31,7 @@ //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ -#include "common/tusb_common.h" +#include "host/usbh.h" #include "vendor_host.h" //--------------------------------------------------------------------+ diff --git a/src/class/vendor/vendor_host.h b/src/class/vendor/vendor_host.h index fa1879376..07fa56c61 100644 --- a/src/class/vendor/vendor_host.h +++ b/src/class/vendor/vendor_host.h @@ -24,15 +24,10 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_class - * \defgroup Group_Custom Custom Class (not supported yet) - * @{ */ - #ifndef _TUSB_VENDOR_HOST_H_ #define _TUSB_VENDOR_HOST_H_ #include "common/tusb_common.h" -#include "host/usbh.h" #ifdef __cplusplus extern "C" { @@ -70,5 +65,3 @@ void cush_close(uint8_t dev_addr); #endif #endif /* _TUSB_VENDOR_HOST_H_ */ - -/** @} */ diff --git a/src/host/hub.c b/src/host/hub.c index 2191c4560..4db680f9e 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -28,9 +28,7 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HUB) -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ +#include "usbh.h" #include "hub.h" //--------------------------------------------------------------------+ diff --git a/src/host/hub.h b/src/host/hub.h index 851bb8e66..2b2f39ee1 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -37,7 +37,6 @@ #define _TUSB_HUB_H_ #include "common/tusb_common.h" -#include "usbh.h" #ifdef __cplusplus extern "C" { diff --git a/src/host/usbh.h b/src/host/usbh.h index 590c8a359..a9790b484 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -34,10 +34,7 @@ extern "C" { #endif -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "osal/osal.h" // TODO refractor move to common.h ? +#include "common/tusb_common.h" #include "hcd.h" //--------------------------------------------------------------------+ @@ -67,10 +64,6 @@ typedef struct { typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 54958182b..834976468 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -33,7 +33,6 @@ #include #include "device/dcd.h" -#include "osal/osal.h" #define CXD56_EPNUM (7) #define CXD56_SETUP_QUEUE_DEPTH (4) -- cgit v1.3.1 From 7c66c5121b862443aacf7eadbef45153a3fa3060 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 May 2021 19:31:55 +0700 Subject: update doc --- CONTRIBUTORS.md | 10 +++++++- docs/changelog.md | 63 ++++++++++++++++++++++++++++++++++++++++------ src/class/net/net_device.h | 1 - 3 files changed, 64 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 5ce352f57..5fa3e5250 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -25,6 +25,10 @@ - Improve Audio driver and add uac2_headset example - Improve STM32 Synopsys DCD with various PRs +- **[J McCarthy](https://github.com/xmos-jmccarthy)** + - Add new DFU 1.1 class driver + - Add new example for dfu + - **[Kamil Tomaszewski](https://github.com/kamtom480)** - Add new DCD port for **Sony CXD56** (spresnese board) @@ -53,10 +57,14 @@ - **[Raspberry Pi Team](https://github.com/raspberrypi)** - Add new DCD port for **Raspberry Pi RP2040** + - Add new HCD port for **Raspberry Pi RP2040** - **[Reinhard Panhuber](https://github.com/PanRe)** - Add new class driver for **USB Audio Class 2.0 (UAC2)** - - Enhance tu_fifo with unmasked pointer, which better support DMA + - Rework tu_fifo with unmasked pointer, add DMA support, and constant address support + - Add new DCD/USBD edpt_xfer_fifo() API for optimizing endpoint transfer + - Add and greatly improve Isochronous transfer + - Add new audio examples: audio_test and audio_4_channel_mic - **[Scott Shawcroft](https://github.com/tannewt)** - Add new DCD port for **SAMD21 and SAMD51** diff --git a/docs/changelog.md b/docs/changelog.md index 436259cee..fba362904 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,18 +2,65 @@ ## WIP -- Add new port Silabs EFM32GG12, board EFM32GG12 Thunderboard Kit (SLTB009A) -- Add new port Renesas RX63N, board GR-CITRUS -- MIDI - - Fix MIDI buffer overflow issue +- Rework tu_fifo_t with separated mutex for read and write, better support DMA with read/write buffer info. And constant address mode +- Improve audio_test example and add audio_4_channel_mic example +- Add new dfu example +- Remove pico-sdk from submodule + +### Device Controller Driver (DCD) + +- Add new DCD port for Silabs EFM32GG12 with board Thunderboard Kit (SLTB009A) +- Add new DCD port Renesas RX63N, board GR-CITRUS +- Add new (optional) endpoint API dcd_edpt_xfer_fifo +- Fix build with nRF5340 +- Fix build with lpc15 and lpc54 +- Fix build with lpc177x_8x +- STM32 Synopsys: greatly improve Isochronous transfer with edpt_xfer_fifo API +- Support LPC55 port1 highspeed +- Add support for Espressif esp32s3 +- nRF: fix race condition that could cause drop packet of Bulk OUT transfer + +### USB Device Driver (USBD) + +- Add new (optional) endpoint ADPI usbd_edpt_xfer_fifo + +### Device Class Driver + +CDC + +- [Breaking] tud_cdc_peek(), tud_vendor_peek() dropped position parameter. If needed, tu_fifo_get_read_info() can be used to peek at random offset. + +DFU + +- Add new DFU 1.1 class driver (WIP) + +HID + +- Fix keyboard report descriptor template +- Add more hid keys constant from 0x6B to 0xA4 +- [Breaking] rename API + - HID_PROTOCOL_NONE/KEYBOARD/MOUST to HID_ITF_PROTOCOL_NONE/KEYBOARD/MOUSE + - tud_hid_boot_mode() to tud_hid_get_protocol() + - tud_hid_boot_mode_cb() to tud_hid_set_protocol_cb() + +MIDI + +- Fix MIDI buffer overflow issue +- [Breaking] rename API - Rename tud_midi_read() to tud_midi_stream_read() - Rename tud_midi_write() to tud_midi_stream_write() - Rename tud_midi_receive() to tud_midi_packet_read() - Rename tud_midi_send() to tud_midi_packet_write() -- New board stm32f072-eval -- Breaking changes - - tud_cdc_peek(), tud_vendor_peek() dropped position parameter. If needed, tu_fifo_get_read_info() can be used to peek - at random offset. + +### Host Controller Driver (HCD) + +### USB Host Driver (USBH) + +### Host Class Driver + +HID + +- Rework host hid driver, basically everything changes ## 0.9.0 - 2021.03.12 diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index f5f0cd8f1..f030f3077 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -28,7 +28,6 @@ #ifndef _TUSB_NET_DEVICE_H_ #define _TUSB_NET_DEVICE_H_ -#include "device/usbd.h" #include "class/cdc/cdc.h" /* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */ -- cgit v1.3.1 From e9c22e4a5c797e33c4ed5a735bf0d3d6e45b9a78 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 28 May 2021 17:24:35 +0700 Subject: increase version for release --- docs/changelog.md | 12 +++++++----- src/tusb_option.h | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/docs/changelog.md b/docs/changelog.md index fba362904..323b6b6e2 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,6 +1,6 @@ # TinyUSB Changelog -## WIP +## 0.10.0 - 2021.05.28 - Rework tu_fifo_t with separated mutex for read and write, better support DMA with read/write buffer info. And constant address mode - Improve audio_test example and add audio_4_channel_mic example @@ -28,7 +28,7 @@ CDC -- [Breaking] tud_cdc_peek(), tud_vendor_peek() dropped position parameter. If needed, tu_fifo_get_read_info() can be used to peek at random offset. +- [Breaking] tud_cdc_peek(), tud_vendor_peek() no longer support random offset and dropped position parameter. DFU @@ -54,13 +54,15 @@ MIDI ### Host Controller Driver (HCD) +- No noticable changes + ### USB Host Driver (USBH) -### Host Class Driver +- No noticable changes -HID +### Host Class Driver -- Rework host hid driver, basically everything changes +- HID: Rework host hid driver, basically everything changes ## 0.9.0 - 2021.03.12 diff --git a/src/tusb_option.h b/src/tusb_option.h index feff013c7..f8456ca4c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -28,7 +28,7 @@ #define _TUSB_OPTION_H_ #define TUSB_VERSION_MAJOR 0 -#define TUSB_VERSION_MINOR 9 +#define TUSB_VERSION_MINOR 10 #define TUSB_VERSION_REVISION 0 #define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION) -- cgit v1.3.1 From 164778a71682559670cc2549565b4d8d5f021fa9 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 28 May 2021 17:42:13 +0700 Subject: update limit each transfer not less than 64 --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 2 ++ src/portable/raspberrypi/rp2040/rp2040_usb.c | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 5201d1d4c..eff950de2 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -452,6 +452,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * if (ep_addr != ep->ep_addr) { // Direction has flipped so re init it but with same properties + // TODO treat IN and OUT as invidual endpoints _hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, ep->transfer_type, 0); } @@ -531,6 +532,7 @@ bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) { panic("hcd_pipe_stalled"); + return false; } bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 98ffea9a3..88d94aaec 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -161,7 +161,10 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t // Fill in info now that we're kicking off the hw ep->total_len = total_len; ep->len = 0; - ep->transfer_size = tu_min16(total_len, ep->wMaxPacketSize); + + // Limit by packet size but not less 64 (i.e low speed 8 bytes EP0) + ep->transfer_size = tu_min16(total_len, tu_max16(64, ep->wMaxPacketSize)); + ep->active = true; ep->user_buf = buffer; #if TUSB_OPT_HOST_ENABLED @@ -240,8 +243,9 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) _hw_endpoint_xfer_sync(ep); // Now we have synced our state with the hardware. Is there more data to transfer? + // Limit by packet size but not less 64 (i.e low speed 8 bytes EP0) uint16_t remaining_bytes = ep->total_len - ep->len; - ep->transfer_size = tu_min16(remaining_bytes, ep->wMaxPacketSize); + ep->transfer_size = tu_min16(remaining_bytes, tu_max16(64, ep->wMaxPacketSize)); #if TUSB_OPT_HOST_ENABLED _hw_endpoint_update_last_buf(ep); #endif -- cgit v1.3.1 From b4f092ec74d85d4e5567ebb45e1bd0dec20f0e02 Mon Sep 17 00:00:00 2001 From: Wini-Buh Date: Sat, 29 May 2021 21:23:39 +0200 Subject: Adaptations for Renesas CCRX toolchain and Rx72N controller performed --- src/class/cdc/cdc.h | 48 ++++++++++++-- src/class/cdc/cdc_device.c | 23 +++++-- src/class/cdc/cdc_device.h | 57 ++++++++++++++++ src/common/tusb_compiler.h | 92 ++++++++++++++++++++++++-- src/common/tusb_types.h | 39 ++++++++++- src/device/dcd.h | 42 ++++++++++-- src/device/usbd.c | 67 ++++++++++++------- src/device/usbd.h | 74 +++++++++++++++++++-- src/device/usbd_control.c | 15 ++++- src/device/usbd_pvt.h | 11 ++++ src/osal/osal_freertos.h | 25 +++++++ src/portable/renesas/usba/dcd_usba.c | 122 ++++++++++++++++++++++++++++------- src/tusb_option.h | 1 + 13 files changed, 543 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index f59bf0f1a..e5af9fc0c 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -216,6 +216,7 @@ typedef enum //--------------------------------------------------------------------+ /// Header Functional Descriptor (Communication Interface) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -223,8 +224,10 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUNC_DESC_ uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal }cdc_desc_func_header_t; +TU_PACK_STRUCT_END /// Union Functional Descriptor (Communication Interface) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -233,17 +236,21 @@ typedef struct TU_ATTR_PACKED uint8_t bControlInterface ; ///< Interface number of Communication Interface uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface }cdc_desc_func_union_t; +TU_PACK_STRUCT_END #define cdc_desc_func_union_n_t(no_slave)\ - struct TU_ATTR_PACKED { \ + TU_PACK_STRUCT_BEGIN \ + struct TU_ATTR_PACKED { \ uint8_t bLength ;\ uint8_t bDescriptorType ;\ uint8_t bDescriptorSubType ;\ uint8_t bControlInterface ;\ uint8_t bSubordinateInterface[no_slave] ;\ -} +} \ +TU_PACK_STRUCT_END /// Country Selection Functional Descriptor (Communication Interface) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -252,15 +259,18 @@ typedef struct TU_ATTR_PACKED uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes. uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. }cdc_desc_func_country_selection_t; +TU_PACK_STRUCT_END #define cdc_desc_func_country_selection_n_t(no_country) \ - struct TU_ATTR_PACKED {\ + TU_PACK_STRUCT_BEGIN \ + struct TU_ATTR_PACKED { \ uint8_t bLength ;\ uint8_t bDescriptorType ;\ uint8_t bDescriptorSubType ;\ uint8_t iCountryCodeRelDate ;\ uint16_t wCountryCode[no_country] ;\ -} +} \ +TU_PACK_STRUCT_END //--------------------------------------------------------------------+ // PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS @@ -268,22 +278,28 @@ typedef struct TU_ATTR_PACKED /// \brief Call Management Functional Descriptor /// \details This functional descriptor describes the processing of calls for the Communications Class interface. +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface. uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself. uint8_t TU_RESERVED : 6; } bmCapabilities; + TU_BIT_FIELD_ORDER_END uint8_t bDataInterface; }cdc_desc_func_call_management_t; +TU_PACK_STRUCT_END +TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature. @@ -292,11 +308,14 @@ typedef struct TU_ATTR_PACKED uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection. uint8_t TU_RESERVED : 4; }cdc_acm_capability_t; +TU_BIT_FIELD_ORDER_END +TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); /// \brief Abstract Control Management Functional Descriptor /// \details This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -304,25 +323,31 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ cdc_acm_capability_t bmCapabilities ; }cdc_desc_func_acm_t; +TU_PACK_STRUCT_END /// \brief Direct Line Management Functional Descriptor /// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit. uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State. uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time. uint8_t TU_RESERVED : 5; } bmCapabilities; + TU_BIT_FIELD_ORDER_END }cdc_desc_func_direct_line_management_t; +TU_PACK_STRUCT_END /// \brief Telephone Ringer Functional Descriptor /// \details The Telephone Ringer functional descriptor describes the ringer capabilities supported by the Communications Class interface, /// with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -331,31 +356,38 @@ typedef struct TU_ATTR_PACKED uint8_t bRingerVolSteps ; uint8_t bNumRingerPatterns ; }cdc_desc_func_telephone_ringer_t; +TU_PACK_STRUCT_END /// \brief Telephone Operational Modes Functional Descriptor /// \details The Telephone Operational Modes functional descriptor describes the operational modes supported by /// the Communications Class interface, with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t simple_mode : 1; uint8_t standalone_mode : 1; uint8_t computer_centric_mode : 1; uint8_t TU_RESERVED : 5; } bmCapabilities; + TU_BIT_FIELD_ORDER_END }cdc_desc_func_telephone_operational_modes_t; +TU_PACK_STRUCT_END /// \brief Telephone Call and Line State Reporting Capabilities Descriptor /// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a /// telephone device to report optional call and line states. +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ + TU_BIT_FIELD_ORDER_BEGIN struct { uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states. @@ -365,7 +397,9 @@ typedef struct TU_ATTR_PACKED uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification uint32_t TU_RESERVED : 26; } bmCapabilities; + TU_BIT_FIELD_ORDER_END }cdc_desc_func_telephone_call_state_reporting_capabilities_t; +TU_PACK_STRUCT_END static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) { @@ -375,6 +409,7 @@ static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) //--------------------------------------------------------------------+ // Requests //--------------------------------------------------------------------+ +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint32_t bit_rate; @@ -382,15 +417,20 @@ typedef struct TU_ATTR_PACKED uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16 } cdc_line_coding_t; +TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); +TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint16_t dte_is_present : 1; ///< Indicates to DCE if DTE is presentor not. This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR. uint16_t half_duplex_carrier_control : 1; uint16_t : 14; } cdc_line_control_state_t; +TU_BIT_FIELD_ORDER_END +TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index f5853fddb..cf2ec64c8 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -31,6 +31,15 @@ #include "cdc_device.h" #include "device/usbd_pvt.h" +#if defined(TU_HAS_NO_ATTR_WEAK) +static void (*const MAKE_WEAK_FUNC(tud_cdc_rx_cb))(uint8_t) = TUD_CDC_RX_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb))(uint8_t, char) = TUD_CDC_RX_WANTED_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb))(uint8_t) = TUD_CDC_TX_COMPLETE_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_line_state_cb))(uint8_t, bool, bool) = TUD_CDC_LINE_STATE_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_line_coding_cb))(uint8_t, cdc_line_coding_t const*) = TUD_CDC_LINE_CODING_CB; +static void (*const MAKE_WEAK_FUNC(tud_cdc_send_break_cb))(uint8_t, uint16_t) = TUD_CDC_SEND_BREAK_CB; +#endif + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -359,7 +368,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t } else if ( stage == CONTROL_STAGE_ACK) { - if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); + if ( MAKE_WEAK_FUNC(tud_cdc_line_coding_cb) ) MAKE_WEAK_FUNC(tud_cdc_line_coding_cb)(itf, &p_cdc->line_coding); } break; @@ -394,7 +403,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); // Invoke callback - if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); + if ( MAKE_WEAK_FUNC(tud_cdc_line_state_cb) ) MAKE_WEAK_FUNC(tud_cdc_line_state_cb)(itf, dtr, rts); } break; case CDC_REQUEST_SEND_BREAK: @@ -405,7 +414,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t else if (stage == CONTROL_STAGE_ACK) { TU_LOG2(" Send Break\r\n"); - if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); + if ( MAKE_WEAK_FUNC(tud_cdc_send_break_cb) ) MAKE_WEAK_FUNC(tud_cdc_send_break_cb)(itf, request->wValue); } break; @@ -436,19 +445,19 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); // Check for wanted char and invoke callback if needed - if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) ) + if ( MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb) && (((signed char) p_cdc->wanted_char) != -1) ) { for ( uint32_t i = 0; i < xferred_bytes; i++ ) { if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) ) { - tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); + MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb)(itf, p_cdc->wanted_char); } } } // invoke receive callback (if there is still data) - if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); + if (MAKE_WEAK_FUNC(tud_cdc_rx_cb) && !tu_fifo_empty(&p_cdc->rx_ff) ) MAKE_WEAK_FUNC(tud_cdc_rx_cb)(itf); // prepare for OUT transaction _prep_out_transaction(p_cdc); @@ -460,7 +469,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if ( ep_addr == p_cdc->ep_in ) { // invoke transmit callback to possibly refill tx fifo - if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); + if ( MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb) ) MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb)(itf); if ( 0 == tud_cdc_n_write_flush(itf) ) { diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 986585c5b..ed816b707 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -130,6 +130,7 @@ static inline bool tud_cdc_write_clear (void); // Application Callback API (weak is optional) //--------------------------------------------------------------------+ +#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when received new data TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); @@ -148,6 +149,62 @@ TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p // Invoked when received send break TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); +#else + #if ADD_WEAK_FUNC_TUD_CDC_RX_CB + #define TUD_CDC_RX_CB tud_cdc_rx_cb + #endif + #ifndef TUD_CDC_RX_CB + #define TUD_CDC_RX_CB NULL + #else + extern void TUD_CDC_RX_CB(uint8_t itf); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_RX_WANTED_CB + #define TUD_CDC_RX_WANTED_CB tud_cdc_rx_wanted_cb + #endif + #ifndef TUD_CDC_RX_WANTED_CB + #define TUD_CDC_RX_WANTED_CB NULL + #else + extern void TUD_CDC_RX_WANTED_CB(uint8_t itf, char wanted_char); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_TX_COMPLETE_CB + #define TUD_CDC_TX_COMPLETE_CB tud_cdc_tx_complete_cb + #endif + #ifndef TUD_CDC_TX_COMPLETE_CB + #define TUD_CDC_TX_COMPLETE_CB NULL + #else + extern void TUD_CDC_TX_COMPLETE_CB(uint8_t itf); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_LINE_STATE_CB + #define TUD_CDC_LINE_STATE_CB tud_cdc_line_state_cb + #endif + #ifndef TUD_CDC_LINE_STATE_CB + #define TUD_CDC_LINE_STATE_CB NULL + #else + extern void TUD_CDC_LINE_STATE_CB(uint8_t itf, bool dtr, bool rts); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_LINE_CODING_CB + #define TUD_CDC_LINE_CODING_CB tud_cdc_line_coding_cb + #endif + #ifndef TUD_CDC_LINE_CODING_CB + #define TUD_CDC_LINE_CODING_CB NULL + #else + extern void TUD_CDC_LINE_CODING_CB(uint8_t itf, cdc_line_coding_t const* p_line_coding); + #endif + + #if ADD_WEAK_FUNC_TUD_CDC_SEND_BREAK_CB + #define TUD_CDC_SEND_BREAK_CB tud_cdc_send_break_cb + #endif + #ifndef TUD_CDC_SEND_BREAK_CB + #define TUD_CDC_SEND_BREAK_CB NULL + #else + extern void TUD_CDC_SEND_BREAK_CB(uint8_t itf, uint16_t duration_ms); + #endif +#endif + //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 679060b20..508bb126e 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -48,6 +48,8 @@ #define TU_VERIFY_STATIC _Static_assert #elif defined (__cplusplus) && __cplusplus >= 201103L #define TU_VERIFY_STATIC static_assert +#elif defined(__CCRX__) + #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(Line, __LINE__)[(const_expr) ? 1 : 0]; #else #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } #endif @@ -62,6 +64,9 @@ // Compiler porting with Attribute and Endian //--------------------------------------------------------------------+ +// define the standard definition of this macro to construct a "weak" function name +#define MAKE_WEAK_FUNC(func_name) func_name + // TODO refactor since __attribute__ is supported across many compiler #if defined(__GNUC__) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) @@ -73,9 +78,17 @@ #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used + #define TU_PACK_STRUCT_BEGIN + #define TU_PACK_STRUCT_END + + #define TU_BIT_FIELD_ORDER_BEGIN + #define TU_BIT_FIELD_ORDER_END + // Endian conversion use well-known host to network (big endian) naming #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define TU_BYTE_ORDER TU_LITTLE_ENDIAN + #define TU_ENDIAN_LITTLE_BEGIN + #define TU_ENDIAN_LITTLE_END #else #define TU_BYTE_ORDER TU_BIG_ENDIAN #endif @@ -123,6 +136,77 @@ #define TU_BSWAP16(u16) (__iar_builtin_REV16(u16)) #define TU_BSWAP32(u32) (__iar_builtin_REV(u32)) + +#elif defined(__CCRX__) + #define TU_ATTR_ALIGNED(Bytes) + #define TU_ATTR_SECTION(sec_name) + #define TU_ATTR_PACKED + #define TU_ATTR_WEAK + #define TU_ATTR_ALWAYS_INLINE + #define TU_ATTR_DEPRECATED(mess) + #define TU_ATTR_UNUSED + #define TU_ATTR_USED + + #define TU_PACK_STRUCT_BEGIN _Pragma("pack") + #define TU_PACK_STRUCT_END _Pragma("packoption") + + #define TU_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right") + #define TU_BIT_FIELD_ORDER_END _Pragma("bit_order") + + // Endian conversion use well-known host to network (big endian) naming + #if defined(__LIT) + #define TU_BYTE_ORDER TU_LITTLE_ENDIAN + #define TU_ENDIAN_LITTLE_BEGIN + #define TU_ENDIAN_LITTLE_END + #else + #define TU_BYTE_ORDER TU_BIG_ENDIAN + #define TU_ENDIAN_LITTLE_BEGIN _Pragma("endian little") + #define TU_ENDIAN_LITTLE_END _Pragma("endian") + #endif + + #define TU_BSWAP16(u16) ((unsigned short)_builtin_revw((unsigned long)u16)) + #define TU_BSWAP32(u32) (_builtin_revl(u32)) + + /* activate the "aligned" emulation, because this toolchain does not know + the aligned attribute (or something similar yet) */ + #define TU_HAS_NO_ATTR_ALIGNED + + /* activate the "weak" function emulation, because this toolchain does not + know the weak attribute (or something similar yet) */ + #define TU_HAS_NO_ATTR_WEAK + + // make sure to define away the standard definition of this macro + #undef MAKE_WEAK_FUNC + // Helper macro to construct a "weak" function name + #define MAKE_WEAK_FUNC(func_name) weak_ ## func_name + + #if defined(TU_HAS_NO_ATTR_WEAK) + // "Weak function" emulation defined in cdc_device.h + #define ADD_WEAK_FUNC_TUD_CDC_RX_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_RX_WANTED_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_TX_COMPLETE_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_LINE_STATE_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_LINE_CODING_CB 0 + #define ADD_WEAK_FUNC_TUD_CDC_SEND_BREAK_CB 0 + + // "Weak function" emulation defined in usbd_pvt.h + #define ADD_WEAK_FUNC_USBD_APP_DRIVER_GET_CB 0 + + // "Weak function" emulation defined in usbd.h + #define ADD_WEAK_FUNC_TUD_DESCRIPTOR_BOS_CB 0 + #define ADD_WEAK_FUNC_TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB 0 + #define ADD_WEAK_FUNC_TUD_MOUNT_CB 0 + #define ADD_WEAK_FUNC_TUD_UMOUNT_CB 0 + #define ADD_WEAK_FUNC_TUD_SUSPEND_CB 0 + #define ADD_WEAK_FUNC_TUD_RESUME_CB 0 + #define ADD_WEAK_FUNC_TUD_VENDOR_CONTROL_XFER_CB 0 + + // "Weak function" emulation defined in dcd.h + #define ADD_WEAK_FUNC_DCD_EDPT0_STATUS_COMPLETE 0 + #define ADD_WEAK_FUNC_DCD_EDPT_CLOSE 0 + #define ADD_WEAK_FUNC_DCD_EDPT_XFER_FIFO 0 + #endif + #else #error "Compiler attribute porting is required" #endif @@ -149,11 +233,11 @@ #define tu_htonl(u32) (u32) #define tu_ntohl(u32) (u32) - #define tu_htole16(u16) (tu_bswap16(u16)) - #define tu_le16toh(u16) (tu_bswap16(u16)) + #define tu_htole16(u16) (TU_BSWAP16(u16)) + #define tu_le16toh(u16) (TU_BSWAP16(u16)) - #define tu_htole32(u32) (tu_bswap32(u32)) - #define tu_le32toh(u32) (tu_bswap32(u32)) + #define tu_htole32(u32) (TU_BSWAP32(u32)) + #define tu_le32toh(u32) (TU_BSWAP32(u32)) #else #error Byte order is undefined diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ec58a3181..b20ea2974 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -263,6 +263,7 @@ enum //--------------------------------------------------------------------+ /// USB Device Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -283,10 +284,12 @@ typedef struct TU_ATTR_PACKED uint8_t bNumConfigurations ; ///< Number of possible configurations. } tusb_desc_device_t; +TU_PACK_STRUCT_END TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); // USB Binary Device Object Store (BOS) Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -294,8 +297,10 @@ typedef struct TU_ATTR_PACKED uint16_t wTotalLength ; ///< Total length of data returned for this descriptor uint8_t bNumDeviceCaps ; ///< Number of device capability descriptors in the BOS } tusb_desc_bos_t; +TU_PACK_STRUCT_END /// USB Configuration Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -308,10 +313,10 @@ typedef struct TU_ATTR_PACKED uint8_t bmAttributes ; ///< Configuration characteristics \n D7: Reserved (set to one)\n D6: Self-powered \n D5: Remote Wakeup \n D4...0: Reserved (reset to zero) \n D7 is reserved and must be set to one for historical reasons. \n A device configuration that uses power from the bus and a local source reports a non-zero value in bMaxPower to indicate the amount of bus power required and sets D6. The actual power source at runtime may be determined using the GetStatus(DEVICE) request (see USB 2.0 spec Section 9.4.5). \n If a device configuration supports remote wakeup, D5 is set to one. uint8_t bMaxPower ; ///< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. Expressed in 2 mA units (i.e., 50 = 100 mA). } tusb_desc_configuration_t; - -TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct"); +TU_PACK_STRUCT_END /// USB Interface Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -325,8 +330,10 @@ typedef struct TU_ATTR_PACKED uint8_t bInterfaceProtocol ; ///< Protocol code (assigned by the USB). \n These codes are qualified by the value of the bInterfaceClass and the bInterfaceSubClass fields. If an interface supports class-specific requests, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use a class-specific protocol on this interface. \li If this field is set to FFH, the device uses a vendor-specific protocol for this interface. uint8_t iInterface ; ///< Index of string descriptor describing this interface } tusb_desc_interface_t; +TU_PACK_STRUCT_END /// USB Endpoint Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -334,23 +341,32 @@ typedef struct TU_ATTR_PACKED uint8_t bEndpointAddress ; ///< The address of the endpoint on the USB device described by this descriptor. The address is encoded as follows: \n Bit 3...0: The endpoint number \n Bit 6...4: Reserved, reset to zero \n Bit 7: Direction, ignored for control endpoints 0 = OUT endpoint 1 = IN endpoint. + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t xfer : 2; uint8_t sync : 2; uint8_t usage : 2; uint8_t : 2; } bmAttributes ; ///< This field describes the endpoint's attributes when it is configured using the bConfigurationValue. \n Bits 1..0: Transfer Type \n- 00 = Control \n- 01 = Isochronous \n- 10 = Bulk \n- 11 = Interrupt \n If not an isochronous endpoint, bits 5..2 are reserved and must be set to zero. If isochronous, they are defined as follows: \n Bits 3..2: Synchronization Type \n- 00 = No Synchronization \n- 01 = Asynchronous \n- 10 = Adaptive \n- 11 = Synchronous \n Bits 5..4: Usage Type \n- 00 = Data endpoint \n- 01 = Feedback endpoint \n- 10 = Implicit feedback Data endpoint \n- 11 = Reserved \n Refer to Chapter 5 of USB 2.0 specification for more information. \n All other bits are reserved and must be reset to zero. Reserved bits must be ignored by the host. + TU_BIT_FIELD_ORDER_END struct TU_ATTR_PACKED { +#if defined(__CCRX__) + //FIXME the original defined bit field has a problem with the CCRX toolchain, so only a size field is defined + uint16_t size; +#else uint16_t size : 11; ///< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. \n For isochronous endpoints, this value is used to reserve the bus time in the schedule, required for the per-(micro)frame data payloads. The pipe may, on an ongoing basis, actually use less bandwidth than that reserved. The device reports, if necessary, the actual bandwidth used via its normal, non-USB defined mechanisms. \n For all endpoints, bits 10..0 specify the maximum packet size (in bytes). \n For high-speed isochronous and interrupt endpoints: \n Bits 12..11 specify the number of additional transaction opportunities per microframe: \n- 00 = None (1 transaction per microframe) \n- 01 = 1 additional (2 per microframe) \n- 10 = 2 additional (3 per microframe) \n- 11 = Reserved \n Bits 15..13 are reserved and must be set to zero. uint16_t hs_period_mult : 2; uint16_t TU_RESERVED : 3; +#endif }wMaxPacketSize; uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. } tusb_desc_endpoint_t; +TU_PACK_STRUCT_END /// USB Other Speed Configuration Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -363,8 +379,10 @@ typedef struct TU_ATTR_PACKED uint8_t bmAttributes ; ///< Same as Configuration descriptor uint8_t bMaxPower ; ///< Same as Configuration descriptor } tusb_desc_other_speed_t; +TU_PACK_STRUCT_END /// USB Device Qualifier Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -378,8 +396,10 @@ typedef struct TU_ATTR_PACKED uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations uint8_t bReserved ; ///< Reserved for future use, must be zero } tusb_desc_device_qualifier_t; +TU_PACK_STRUCT_END /// USB Interface Association Descriptor (IAD ECN) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -394,16 +414,20 @@ typedef struct TU_ATTR_PACKED uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. } tusb_desc_interface_assoc_t; +TU_PACK_STRUCT_END // USB String Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< Descriptor Type uint16_t unicode_string[]; } tusb_desc_string_t; +TU_PACK_STRUCT_END // USB Binary Device Object Store (BOS) +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -413,8 +437,10 @@ typedef struct TU_ATTR_PACKED uint8_t PlatformCapabilityUUID[16]; uint8_t CapabilityData[]; } tusb_desc_bos_platform_t; +TU_PACK_STRUCT_END // USB WebuSB URL Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -422,14 +448,17 @@ typedef struct TU_ATTR_PACKED uint8_t bScheme; char url[]; } tusb_desc_webusb_url_t; +TU_PACK_STRUCT_END // DFU Functional Descriptor +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; union { + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t bitCanDnload : 1; uint8_t bitCanUpload : 1; @@ -437,6 +466,7 @@ typedef struct TU_ATTR_PACKED uint8_t bitWillDetach : 1; uint8_t reserved : 4; } bmAttributes; + TU_BIT_FIELD_ORDER_END uint8_t bAttributes; }; @@ -445,17 +475,21 @@ typedef struct TU_ATTR_PACKED uint16_t wTransferSize; uint16_t bcdDFUVersion; } tusb_desc_dfu_functional_t; +TU_PACK_STRUCT_END /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED{ union { + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. uint8_t type : 2; ///< Request type tusb_request_type_t. uint8_t direction : 1; ///< Direction type. tusb_dir_t } bmRequestType_bit; + TU_BIT_FIELD_ORDER_END uint8_t bmRequestType; }; @@ -465,6 +499,7 @@ typedef struct TU_ATTR_PACKED{ uint16_t wIndex; uint16_t wLength; } tusb_control_request_t; +TU_PACK_STRUCT_END TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); diff --git a/src/device/dcd.h b/src/device/dcd.h index 71e88054c..fd87686bf 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -116,24 +116,54 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; // Endpoint API //--------------------------------------------------------------------+ +#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; -// Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); - // Close an endpoint. // Since it is weak, caller must TU_ASSERT this function's existence before calling it. void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; -// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - // Submit an transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack // This API is optional, may be useful for register-based for transferring data. bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; +#else + #if ADD_WEAK_FUNC_DCD_EDPT0_STATUS_COMPLETE + #define DCD_EDPT0_STATUS_COMPLETE dcd_edpt0_status_complete + #endif + #ifndef DCD_EDPT0_STATUS_COMPLETE + #define DCD_EDPT0_STATUS_COMPLETE NULL + #else + extern void DCD_EDPT0_STATUS_COMPLETE(uint8_t rhport, tusb_control_request_t const * request); + #endif + + #if ADD_WEAK_FUNC_DCD_EDPT_CLOSE + #define DCD_EDPT_CLOSE dcd_edpt_close + #endif + #ifndef DCD_EDPT_CLOSE + #define DCD_EDPT_CLOSE NULL + #else + extern void DCD_EDPT_CLOSE(uint8_t rhport, uint8_t ep_addr); + #endif + + #if ADD_WEAK_FUNC_DCD_EDPT_XFER_FIFO + #define DCD_EDPT_XFER_FIFO dcd_edpt_xfer_fifo + #endif + #ifndef DCD_EDPT_XFER_FIFO + #define DCD_EDPT_XFER_FIFO NULL + #else + extern void DCD_EDPT_XFER_FIFO(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); + #endif +#endif + +// Configure endpoint's registers according to descriptor +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); + +// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index 8454a2951..fa86c28c7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -33,6 +33,19 @@ #include "device/usbd_pvt.h" #include "device/dcd.h" +#if defined(TU_HAS_NO_ATTR_WEAK) +static uint8_t const* (*const MAKE_WEAK_FUNC(tud_descriptor_bos_cb))(void) = TUD_DESCRIPTOR_BOS_CB; +static uint8_t const* (*const MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb))(void) = TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB; +static void (*const MAKE_WEAK_FUNC(tud_mount_cb))(void) = TUD_MOUNT_CB; +static void (*const MAKE_WEAK_FUNC(tud_umount_cb))(void) = TUD_UMOUNT_CB; +static void (*const MAKE_WEAK_FUNC(tud_suspend_cb))(_Bool) = TUD_SUSPEND_CB; +static void (*const MAKE_WEAK_FUNC(tud_resume_cb))(void) = TUD_RESUME_CB; +static _Bool (*const MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb))(uint8_t, uint8_t, tusb_control_request_t const *) = TUD_RESUME_CB; +static usbd_class_driver_t const* (*const MAKE_WEAK_FUNC(usbd_app_driver_get_cb))(uint8_t*) = USBD_APP_DRIVER_GET_CB; +static bool (*const MAKE_WEAK_FUNC(dcd_edpt_xfer_fifo))(uint8_t, uint8_t, tu_fifo_t *, uint16_t) = DCD_EDPT_XFER_FIFO; +static void (*const MAKE_WEAK_FUNC(dcd_edpt_close))(uint8_t, uint8_t) = DCD_EDPT_CLOSE; +#endif + #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif @@ -50,6 +63,8 @@ enum { DRVID_INVALID = 0xFFu }; typedef struct { + TU_PACK_STRUCT_BEGIN + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { volatile uint8_t connected : 1; @@ -60,6 +75,8 @@ typedef struct uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute uint8_t self_powered : 1; // configuration descriptor's attribute }; + TU_BIT_FIELD_ORDER_END + TU_PACK_STRUCT_END volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) uint8_t speed; @@ -67,6 +84,8 @@ typedef struct uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUD_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + TU_PACK_STRUCT_BEGIN + TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { volatile bool busy : 1; @@ -75,6 +94,8 @@ typedef struct // TODO merge ep2drv here, 4-bit should be sufficient }ep_status[CFG_TUD_EP_MAX][2]; + TU_BIT_FIELD_ORDER_END + TU_PACK_STRUCT_END }usbd_device_t; @@ -236,7 +257,7 @@ static uint8_t _app_driver_count = 0; static inline usbd_class_driver_t const * get_driver(uint8_t drvid) { // Application drivers - if ( usbd_app_driver_get_cb ) + if ( MAKE_WEAK_FUNC(usbd_app_driver_get_cb) ) { if ( drvid < _app_driver_count ) return &_app_driver[drvid]; drvid -= _app_driver_count; @@ -408,9 +429,9 @@ bool tud_init (uint8_t rhport) TU_ASSERT(_usbd_q); // Get application driver if available - if ( usbd_app_driver_get_cb ) + if ( MAKE_WEAK_FUNC(usbd_app_driver_get_cb) ) { - _app_driver = usbd_app_driver_get_cb(&_app_driver_count); + _app_driver = MAKE_WEAK_FUNC(usbd_app_driver_get_cb)(&_app_driver_count); } // Init class drivers @@ -501,7 +522,7 @@ void tud_task (void) usbd_reset(event.rhport); // invoke callback - if (tud_umount_cb) tud_umount_cb(); + if (MAKE_WEAK_FUNC(tud_umount_cb)) MAKE_WEAK_FUNC(tud_umount_cb)(); break; case DCD_EVENT_SETUP_RECEIVED: @@ -557,12 +578,12 @@ void tud_task (void) case DCD_EVENT_SUSPEND: TU_LOG2("\r\n"); - if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); + if (MAKE_WEAK_FUNC(tud_suspend_cb)) MAKE_WEAK_FUNC(tud_suspend_cb)(_usbd_dev.remote_wakeup_en); break; case DCD_EVENT_RESUME: TU_LOG2("\r\n"); - if (tud_resume_cb) tud_resume_cb(); + if (MAKE_WEAK_FUNC(tud_resume_cb)) MAKE_WEAK_FUNC(tud_resume_cb)(); break; case DCD_EVENT_SOF: @@ -609,10 +630,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { - TU_VERIFY(tud_vendor_control_xfer_cb); + TU_VERIFY(MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)); - usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); - return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); + usbd_control_set_complete_callback(MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)); + return MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)(rhport, CONTROL_STAGE_SETUP, p_request); } #if CFG_TUSB_DEBUG >= 2 @@ -831,7 +852,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // Parse interface descriptor uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t); - uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + desc_cfg->wTotalLength; + uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); while( p_desc < desc_end ) { @@ -892,7 +913,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } // invoke callback - if (tud_mount_cb) tud_mount_cb(); + if (MAKE_WEAK_FUNC(tud_mount_cb)) MAKE_WEAK_FUNC(tud_mount_cb)(); return true; } @@ -949,15 +970,15 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_LOG2(" BOS\r\n"); // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) - if (!tud_descriptor_bos_cb) return false; + if (!MAKE_WEAK_FUNC(tud_descriptor_bos_cb)) return false; - tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb(); + tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*)MAKE_WEAK_FUNC(tud_descriptor_bos_cb)(); uint16_t total_len; // Use offsetof to avoid pointer to the odd/misaligned address memcpy(&total_len, (uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength), 2); - return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); + return tud_control_xfer(rhport, p_request, (void*) desc_bos, tu_le16toh(total_len)); } break; @@ -972,7 +993,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // Use offsetof to avoid pointer to the odd/misaligned address memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); - return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); + return tud_control_xfer(rhport, p_request, (void*) desc_config, tu_le16toh(total_len)); } break; @@ -995,9 +1016,9 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // Host sends this request to ask why our device with USB BCD from 2.0 // but is running at Full/Low Speed. If not highspeed capable stall this request, // otherwise return the descriptor that could work in highspeed mode - if ( tud_descriptor_device_qualifier_cb ) + if (MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb)) { - uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); + uint8_t const* desc_qualifier = MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb)(); TU_ASSERT(desc_qualifier); // first byte of descriptor is its size @@ -1165,18 +1186,18 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) if (_usbd_dev.speed == TUSB_SPEED_HIGH) { // Bulk highspeed must be EXACTLY 512 - TU_ASSERT(desc_ep->wMaxPacketSize.size == 512); + TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) == 512); }else { // TODO Bulk fullspeed can only be 8, 16, 32, 64 - TU_ASSERT(desc_ep->wMaxPacketSize.size <= 64); + TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) <= 64); } break; case TUSB_XFER_INTERRUPT: { uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 64); - TU_ASSERT(desc_ep->wMaxPacketSize.size <= max_epsize); + TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) <= max_epsize); } break; @@ -1285,7 +1306,7 @@ bool usbd_edpt_iso_xfer(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) + if (MAKE_WEAK_FUNC(dcd_edpt_xfer_fifo)(rhport, ep_addr, ff, total_bytes)) { TU_LOG2("OK\r\n"); return true; @@ -1348,10 +1369,10 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) */ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - TU_ASSERT(dcd_edpt_close, /**/); + TU_ASSERT(MAKE_WEAK_FUNC(dcd_edpt_close), /**/); TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); - dcd_edpt_close(rhport, ep_addr); + MAKE_WEAK_FUNC(dcd_edpt_close(rhport, ep_addr)); return; } diff --git a/src/device/usbd.h b/src/device/usbd.h index 53519c4de..04597a215 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -103,10 +103,6 @@ bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request); // Application return pointer to descriptor uint8_t const * tud_descriptor_device_cb(void); -// Invoked when received GET BOS DESCRIPTOR request -// Application return pointer to descriptor -TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); - // Invoked when received GET CONFIGURATION DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index); @@ -115,6 +111,11 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index); // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); +#if !defined(TU_HAS_NO_ATTR_WEAK) +// Invoked when received GET BOS DESCRIPTOR request +// Application return pointer to descriptor +TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); + // Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void); @@ -135,6 +136,71 @@ TU_ATTR_WEAK void tud_resume_cb(void); // Invoked when received control request with VENDOR TYPE TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +#else + #if ADD_WEAK_FUNC_TUD_DESCRIPTOR_BOS_CB + #define TUD_DESCRIPTOR_BOS_CB tud_descriptor_bos_cb + #endif + #ifndef TUD_DESCRIPTOR_BOS_CB + #define TUD_DESCRIPTOR_BOS_CB NULL + #else + extern uint8_t const* TUD_DESCRIPTOR_BOS_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB + #define TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB tud_descriptor_device_qualifier_cb + #endif + #ifndef TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB + #define TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB NULL + #else + extern uint8_t const* TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_MOUNT_CB + #define TUD_MOUNT_CB tud_mount_cb + #endif + #ifndef TUD_MOUNT_CB + #define TUD_MOUNT_CB NULL + #else + extern void TUD_MOUNT_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_UMOUNT_CB + #define TUD_UMOUNT_CB tud_umount_cb + #endif + #ifndef TUD_UMOUNT_CB + #define TUD_UMOUNT_CB NULL + #else + extern void TUD_UMOUNT_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_SUSPEND_CB + #define TUD_SUSPEND_CB tud_suspend_cb + #endif + #ifndef TUD_SUSPEND_CB + #define TUD_SUSPEND_CB NULL + #else + extern void TUD_SUSPEND_CB(bool remote_wakeup_en); + #endif + + #if ADD_WEAK_FUNC_TUD_RESUME_CB + #define TUD_RESUME_CB tud_resume_cb + #endif + #ifndef TUD_RESUME_CB + #define TUD_RESUME_CB NULL + #else + extern void TUD_RESUME_CB(void); + #endif + + #if ADD_WEAK_FUNC_TUD_VENDOR_CONTROL_XFER_CB + #define TUD_VENDOR_CONTROL_XFER_CB tud_vendor_control_xfer_cb + #endif + #ifndef TUD_VENDOR_CONTROL_XFER_CB + #define TUD_VENDOR_CONTROL_XFER_CB NULL + #else + extern bool TUD_VENDOR_CONTROL_XFER_CB(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); + #endif +#endif + //--------------------------------------------------------------------+ // Binary Device Object Store (BOS) Descriptor Templates //--------------------------------------------------------------------+ diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 724c652e6..76f999f86 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -36,6 +36,10 @@ extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif +#if defined(TU_HAS_NO_ATTR_WEAK) +static void (*const MAKE_WEAK_FUNC(dcd_edpt0_status_complete))(uint8_t, tusb_control_request_t const *) = DCD_EDPT0_STATUS_COMPLETE; +#endif + enum { EDPT_CTRL_OUT = 0x00, @@ -55,8 +59,17 @@ typedef struct static usbd_control_xfer_t _ctrl_xfer; +#if defined(TU_HAS_NO_ATTR_ALIGNED) +// Helper union to overcome the lack of the alignment attribute/pragma +static union { + uint16_t : (sizeof(uint16_t) * 8); // Alignment of at least the size of the used type + uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; +} Align_usbd_ctrl_buf_; +static uint8_t *_usbd_ctrl_buf = (uint8_t*)&Align_usbd_ctrl_buf_; +#else CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; +#endif //--------------------------------------------------------------------+ // Application API @@ -171,7 +184,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result TU_ASSERT(0 == xferred_bytes); // invoke optional dcd hook if available - if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); + if (MAKE_WEAK_FUNC(dcd_edpt0_status_complete)) MAKE_WEAK_FUNC(dcd_edpt0_status_complete)(rhport, &_ctrl_xfer.request); if (_ctrl_xfer.complete_cb) { diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 44310f022..1d60e5ae2 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -51,10 +51,21 @@ typedef struct void (* sof ) (uint8_t rhport); /* optional */ } usbd_class_driver_t; +#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when initializing device stack to get additional class drivers. // Can optionally implemented by application to extend/overwrite class driver support. // Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; +#else + #if ADD_WEAK_FUNC_USBD_APP_DRIVER_GET_CB + #define USBD_APP_DRIVER_GET_CB usbd_app_driver_get_cb + #endif + #ifndef USBD_APP_DRIVER_GET_CB + #define USBD_APP_DRIVER_GET_CB NULL + #else + extern usbd_class_driver_t const* USBD_APP_DRIVER_GET_CB(uint8_t* driver_count); + #endif +#endif typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 66070c273..ec33b317d 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -51,6 +51,7 @@ static inline void osal_task_delay(uint32_t msec) typedef StaticSemaphore_t osal_semaphore_def_t; typedef SemaphoreHandle_t osal_semaphore_t; +#if (configSUPPORT_STATIC_ALLOCATION == 1) //FIXME Only static API supported static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { return xSemaphoreCreateBinaryStatic(semdef); @@ -76,6 +77,7 @@ static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) return res != 0; } } +#endif static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) { @@ -96,7 +98,12 @@ typedef SemaphoreHandle_t osal_mutex_t; static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { +#if (configSUPPORT_STATIC_ALLOCATION == 0) //FIXME Only static API supported + (void)mdef; + return xSemaphoreCreateMutex(); +#else return xSemaphoreCreateMutexStatic(mdef); +#endif } static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) @@ -131,7 +138,11 @@ typedef QueueHandle_t osal_queue_t; static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { +#if defined(__Tx36V5_Maincard__) + return xQueueCreate(qdef->depth, qdef->item_sz); +#else return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq); +#endif } static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) @@ -139,6 +150,19 @@ static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) return xQueueReceive(qhdl, data, portMAX_DELAY); } +#if defined(__Tx36V5_Maincard__) +extern BaseType_t UsbTaskWoken; +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +{ + if (!in_isr) { + return(xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER)); + + } else { + BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &UsbTaskWoken); + return(res != 0); + } +} +#else static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) { if ( !in_isr ) @@ -159,6 +183,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in return res != 0; } } +#endif static inline bool osal_queue_empty(osal_queue_t qhdl) { diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 06ea1a3f9..54410ff0b 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_RX63X ) +#if TUSB_OPT_DEVICE_ENABLED && (( CFG_TUSB_MCU == OPT_MCU_RX63X ) || ( CFG_TUSB_MCU == OPT_MCU_RX72N )) #include "device/dcd.h" #include "iodefine.h" @@ -38,6 +38,7 @@ #define SYSTEM_PRCR_PRKEY (0xA5u<<8) #define USB_FIFOSEL_TX ((uint16_t)(1u<<5)) +#define USB_FIFOSEL_BIGEND ((uint16_t)(1u<<8)) #define USB_FIFOSEL_MBW_8 ((uint16_t)(0u<<10)) #define USB_FIFOSEL_MBW_16 ((uint16_t)(1u<<10)) #define USB_IS0_CTSQ ((uint16_t)(7u)) @@ -91,39 +92,47 @@ typedef struct { union { + TU_BIT_FIELD_ORDER_BEGIN struct { uint16_t : 8; uint16_t TRCLR: 1; uint16_t TRENB: 1; uint16_t : 0; }; + TU_BIT_FIELD_ORDER_END uint16_t TRE; }; uint16_t TRN; } reg_pipetre_t; typedef union { + TU_BIT_FIELD_ORDER_BEGIN struct { volatile uint16_t u8: 8; volatile uint16_t : 0; }; + TU_BIT_FIELD_ORDER_END volatile uint16_t u16; } hw_fifo_t; +TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uintptr_t addr; /* the start address of a transfer data buffer */ uint16_t length; /* the number of bytes in the buffer */ uint16_t remaining; /* the number of bytes remaining in the buffer */ + TU_BIT_FIELD_ORDER_BEGIN struct { uint32_t ep : 8; /* an assigned endpoint address */ uint32_t : 0; }; + TU_BIT_FIELD_ORDER_END } pipe_state_t; +TU_PACK_STRUCT_END typedef struct { - pipe_state_t pipe[9]; + pipe_state_t pipe[10]; uint8_t ep[2][16]; /* a lookup table for a pipe index from an endpoint address */ } dcd_data_t; @@ -135,14 +144,23 @@ CFG_TUSB_MEM_SECTION static dcd_data_t _dcd; static uint32_t disable_interrupt(void) { uint32_t pswi; +#if defined(__CCRX__) + pswi = get_psw() & 0x010000; + clrpsw_i(); +#else pswi = __builtin_rx_mvfc(0) & 0x010000; __builtin_rx_clrpsw('I'); +#endif return pswi; } static void enable_interrupt(uint32_t pswi) { +#if defined(__CCRX__) + set_psw(get_psw() | pswi); +#else __builtin_rx_mvtc(0, __builtin_rx_mvfc(0) | pswi); +#endif } static unsigned find_pipe(unsigned xfer) @@ -226,7 +244,7 @@ static unsigned select_pipe(unsigned num, unsigned attr) { USB0.PIPESEL.WORD = num; USB0.D0FIFOSEL.WORD = num | attr; - while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; + while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ; return wait_for_pipe_ready(); } @@ -270,11 +288,11 @@ static int fifo_read(volatile void *fifo, pipe_state_t* pipe, unsigned mps, size if (rem < len) len = rem; pipe->remaining = rem - len; - hw_fifo_t *reg = (hw_fifo_t*)fifo; + uint8_t *reg = (uint8_t*)fifo; /* byte access is always at base register address */ uintptr_t addr = pipe->addr; unsigned loop = len; while (loop--) { - *(uint8_t *)addr = reg->u8; + *(uint8_t *)addr = *reg; ++addr; } pipe->addr = addr; @@ -292,6 +310,13 @@ static void process_setup_packet(uint8_t rhport) setup_packet[1] = USB0.USBVAL; setup_packet[2] = USB0.USBINDX; setup_packet[3] = USB0.USBLENG; +#if TU_BYTE_ORDER==TU_BIG_ENDIAN + #if defined(__CCRX__) + setup_packet[0] = tu_le16toh(setup_packet[0]); + #else + //FIXME needs to implemented for other tool chains + #endif +#endif USB0.INTSTS0.WORD = ~USB_IS0_VALID; dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet[0], true); } @@ -317,7 +342,11 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, pipe_state_t *pipe = &_dcd.pipe[0]; /* configure fifo direction and access unit settings */ if (ep_addr) { /* IN, 2 bytes */ +#if TU_BYTE_ORDER == TU_BIG_ENDIAN + USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND; +#else USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16; +#endif while (!(USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX)) ; } else { /* OUT, a byte */ USB0.CFIFOSEL.WORD = USB_FIFOSEL_MBW_8; @@ -329,7 +358,7 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, pipe->remaining = total_bytes; if (ep_addr) { /* IN */ TU_ASSERT(USB0.DCPCTR.BIT.BSTS && (USB0.USBREQ.WORD & 0x80)); - if (fifo_write(&USB0.CFIFO.WORD, pipe, 64)) { + if (fifo_write((void*)&USB0.CFIFO.WORD, pipe, 64)) { USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; } } @@ -350,7 +379,7 @@ static void process_edpt0_bemp(uint8_t rhport) const unsigned rem = pipe->remaining; if (rem > 64) { pipe->remaining = rem - 64; - int r = fifo_write(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); + int r = fifo_write((void*)&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); if (r) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; return; } @@ -363,7 +392,7 @@ static void process_edpt0_bemp(uint8_t rhport) static void process_edpt0_brdy(uint8_t rhport) { size_t len = USB0.CFIFOCTR.BIT.DTLN; - int cplt = fifo_read(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, len); + int cplt = fifo_read((void*)&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, len); if (cplt || (len < 64)) { if (2 != cplt) { USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; @@ -392,11 +421,16 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, USB0.PIPESEL.WORD = num; const unsigned mps = USB0.PIPEMAXP.WORD; if (dir) { /* IN */ +#if TU_BYTE_ORDER == TU_BIG_ENDIAN + USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND; +#else USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16; - while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ; - int r = fifo_write(&USB0.D0FIFO.WORD, pipe, mps); +#endif + while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ; + int r = fifo_write((void*)&USB0.D0FIFO.WORD, pipe, mps); if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ } else { volatile reg_pipetre_t *pt = get_pipetre(num); if (pt) { @@ -416,19 +450,25 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) { pipe_state_t *pipe = &_dcd.pipe[num]; if (tu_edpt_dir(pipe->ep)) { /* IN */ +#if TU_BYTE_ORDER == TU_BIG_ENDIAN + select_pipe(num, USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND); +#else select_pipe(num, USB_FIFOSEL_MBW_16); +#endif const unsigned mps = USB0.PIPEMAXP.WORD; unsigned rem = pipe->remaining; rem -= TU_MIN(rem, mps); pipe->remaining = rem; if (rem) { int r = 0; - r = fifo_write(&USB0.D0FIFO.WORD, pipe, mps); + r = fifo_write((void*)&USB0.D0FIFO.WORD, pipe, mps); if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ return; } USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ pipe->addr = 0; pipe->remaining = 0; dcd_event_xfer_complete(rhport, pipe->ep, pipe->length, @@ -437,18 +477,20 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) const unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_8); const unsigned len = ctr & USB_FIFOCTR_DTLN; const unsigned mps = USB0.PIPEMAXP.WORD; - int cplt = fifo_read(&USB0.D0FIFO.WORD, pipe, mps, len); + int cplt = fifo_read((void*)&USB0.D0FIFO.WORD, pipe, mps, len); if (cplt || (len < mps)) { if (2 != cplt) { USB0.D0FIFO.WORD = USB_FIFOCTR_BCLR; } USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ dcd_event_xfer_complete(rhport, pipe->ep, pipe->length - pipe->remaining, XFER_RESULT_SUCCESS, true); return; } USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ } } @@ -458,7 +500,9 @@ static void process_bus_reset(uint8_t rhport) USB0.BRDYENB.WORD = 1; USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ USB0.D1FIFOSEL.WORD = 0; + while (USB0.D1FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ volatile uint16_t *ctr = (volatile uint16_t*)((uintptr_t)(&USB0.PIPE1CTR.WORD)); volatile uint16_t *tre = (volatile uint16_t*)((uintptr_t)(&USB0.PIPE1TRE.WORD)); for (int i = 1; i <= 5; ++i) { @@ -485,13 +529,22 @@ static void process_set_address(uint8_t rhport) { const uint32_t addr = USB0.USBADDR.BIT.USBADDR; if (!addr) return; +#if defined(__CCRX__) + tusb_control_request_t setup_packet; + setup_packet.bmRequestType = 0; + setup_packet.bRequest = 5; + setup_packet.wValue = addr; + setup_packet.wIndex = 0; + setup_packet.wLength = 0; +#else const tusb_control_request_t setup_packet = { - .bmRequestType = 0, - .bRequest = 5, - .wValue = addr, - .wIndex = 0, - .wLength = 0, - }; + .bmRequestType = 0, + .bRequest = 5, + .wValue = addr, + .wIndex = 0, + .wLength = 0, + }; +#endif dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet, true); } @@ -513,7 +566,13 @@ void dcd_init(uint8_t rhport) USB0.SYSCFG.BIT.DCFM = 0; USB0.SYSCFG.BIT.USBE = 1; + USB0.PHYSLEW.LONG = 0x5; + USB.DPUSR0R.BIT.FIXPHY0 = 0u; /* USB0 Transceiver Output fixed */ +#if ( CFG_TUSB_MCU == OPT_MCU_RX72N ) + IR(PERIB, INTB185) = 0; +#else IR(USB0, USBI0) = 0; +#endif /* Setup default control pipe */ USB0.DCPMAXP.BIT.MXPS = 64; @@ -529,13 +588,21 @@ void dcd_init(uint8_t rhport) void dcd_int_enable(uint8_t rhport) { (void)rhport; +#if ( CFG_TUSB_MCU == OPT_MCU_RX72N ) + IEN(PERIB, INTB185) = 1; +#else IEN(USB0, USBI0) = 1; +#endif } void dcd_int_disable(uint8_t rhport) { (void)rhport; +#if ( CFG_TUSB_MCU == OPT_MCU_RX72N ) + IEN(PERIB, INTB185) = 0; +#else IEN(USB0, USBI0) = 0; +#endif } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) @@ -574,7 +641,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) const unsigned dir = tu_edpt_dir(ep_addr); const unsigned xfer = ep_desc->bmAttributes.xfer; - const unsigned mps = ep_desc->wMaxPacketSize.size; + const unsigned mps = tu_le16toh(ep_desc->wMaxPacketSize.size); if (xfer == TUSB_XFER_ISOCHRONOUS && mps > 256) { /* USBa supports up to 256 bytes */ return false; @@ -680,8 +747,8 @@ void dcd_int_handler(uint8_t rhport) (void)rhport; unsigned is0 = USB0.INTSTS0.WORD; - /* clear bits except VALID */ - USB0.INTSTS0.WORD = USB_IS0_VALID; + /* clear active bits except VALID (don't write 0 to already cleared bits according to the HW manual) */ + USB0.INTSTS0.WORD = ~((USB_IS0_CTRT | USB_IS0_DVST | USB_IS0_SOFR | USB_IS0_RESM | USB_IS0_VBINT) & is0) | USB_IS0_VALID; if (is0 & USB_IS0_VBINT) { if (USB0.INTSTS0.BIT.VBSTS) { dcd_connect(rhport); @@ -720,13 +787,24 @@ void dcd_int_handler(uint8_t rhport) if (is0 & USB_IS0_BRDY) { const unsigned m = USB0.BRDYENB.WORD; unsigned s = USB0.BRDYSTS.WORD & m; - USB0.BRDYSTS.WORD = 0; + /* clear active bits (don't write 0 to already cleared bits according to the HW manual) */ + USB0.BRDYSTS.WORD = ~s; if (s & 1) { process_edpt0_brdy(rhport); s &= ~1; } while (s) { +#if defined(__CCRX__) + static const int Mod37BitPosition[] = { + -1, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, + 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, + 20, 8, 19, 18 + }; + + const unsigned num = Mod37BitPosition[(-s & s) % 37]; +#else const unsigned num = __builtin_ctz(s); +#endif process_pipe_brdy(rhport, num); s &= ~TU_BIT(num); } diff --git a/src/tusb_option.h b/src/tusb_option.h index b317f7630..d04542e61 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -112,6 +112,7 @@ // Renesas RX #define OPT_MCU_RX63X 1400 ///< Renesas RX63N/631 +#define OPT_MCU_RX72N 1401 ///< Renesas RX72N /** @} */ -- cgit v1.3.1 From 3973ec4b5e457aecf742da47dac3c91d1a143865 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Thu, 8 Apr 2021 12:15:15 -0500 Subject: rp2040: fix debug compilation error --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 5201d1d4c..48cf8b602 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -294,7 +294,6 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t uint8_t const num = tu_edpt_number(ep_addr); tusb_dir_t const dir = tu_edpt_dir(ep_addr); - bool in = ep_addr & TUSB_DIR_IN_MASK; ep->ep_addr = ep_addr; ep->dev_addr = dev_addr; -- cgit v1.3.1 From eb8ca14bf8171b48832410ed5e3f888df6564800 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 30 May 2021 22:19:46 +0700 Subject: add level 3 log for info, add generic TU_LOG() --- src/common/tusb_common.h | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 1ebd8dd61..6f2905697 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -307,25 +307,40 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize) for(uint32_t i=0; i 1 +// Log Level 2: Warn +#if CFG_TUSB_DEBUG >= 2 #define TU_LOG2 TU_LOG1 #define TU_LOG2_MEM TU_LOG1_MEM #define TU_LOG2_VAR TU_LOG1_VAR #define TU_LOG2_INT TU_LOG1_INT #define TU_LOG2_HEX TU_LOG1_HEX - #define TU_LOG2_LOCATION() TU_LOG1_LOCATION() #endif +// Log Level 3: Info +#if CFG_TUSB_DEBUG >= 3 + #define TU_LOG3 TU_LOG1 + #define TU_LOG3_MEM TU_LOG1_MEM + #define TU_LOG3_VAR TU_LOG1_VAR + #define TU_LOG3_INT TU_LOG1_INT + #define TU_LOG3_HEX TU_LOG1_HEX +#endif typedef struct { @@ -370,6 +385,15 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #define TU_LOG2_LOCATION() #endif +#ifndef TU_LOG3 + #define TU_LOG3(...) + #define TU_LOG3_MEM(...) + #define TU_LOG3_VAR(...) + #define TU_LOG3_INT(...) + #define TU_LOG3_HEX(...) + #define TU_LOG3_LOCATION() +#endif + #ifdef __cplusplus } #endif -- cgit v1.3.1 From 6498ee19966d394113530c44c91deb860ce37d78 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 30 May 2021 23:35:54 +0700 Subject: fix incorrect data toggle when max packet size < 64 fix host buf_sel panic with "already available" --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 2 ++ src/portable/raspberrypi/rp2040/rp2040_usb.c | 28 +++++++++++++++++- src/portable/raspberrypi/rp2040/rp2040_usb.h | 44 ++++++++++++++++++++++++++-- 3 files changed, 70 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index eff950de2..c09469ff5 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -212,6 +212,7 @@ static void hcd_rp2040_irq(void) if (status & USB_INTS_BUFF_STATUS_BITS) { handled |= USB_INTS_BUFF_STATUS_BITS; + // print_bufctrl32(*epx.buffer_control); hw_handle_buff_status(); } @@ -233,6 +234,7 @@ static void hcd_rp2040_irq(void) if (status & USB_INTS_ERROR_DATA_SEQ_BITS) { usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS; + // print_bufctrl32(*epx.buffer_control); panic("Data Seq Error \n"); } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 88d94aaec..60a039556 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -46,7 +46,7 @@ static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) { #if TUSB_OPT_HOST_ENABLED static inline void _hw_endpoint_update_last_buf(struct hw_endpoint *ep) { - ep->last_buf = ep->len + ep->transfer_size == ep->total_len; + ep->last_buf = (ep->len + ep->transfer_size == ep->total_len); } #endif @@ -126,8 +126,29 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) // PID val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; + +#if TUSB_OPT_DEVICE_ENABLED ep->next_pid ^= 1u; +#else + // For Host (also device but since we dictate the endpoint size, following scenario does not occur) + // Next PID depends on the number of packet in case wMaxPacketSize < 64 (e.g Interrupt Endpoint 8, or 12) + // Special case with control status stage where PID is always DATA1 + if ( ep->transfer_size == 0 ) + { + ep->next_pid ^= 1u; + }else + { + uint32_t packet_count = 1 + ((ep->transfer_size - 1) / ep->wMaxPacketSize); + + if ( packet_count & 0x01 ) + { + ep->next_pid ^= 1u; + } + } +#endif + + #if TUSB_OPT_HOST_ENABLED // Is this the last buffer? Only really matters for host mode. Will trigger // the trans complete irq but also stop it polling. We only really care about @@ -143,6 +164,7 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) // the next time the controller polls this dpram address _hw_endpoint_buffer_control_set_value32(ep, val); pico_trace("buffer control (0x%p) <- 0x%x\n", ep->buffer_control, val); + //print_bufctrl16(val); } @@ -189,10 +211,14 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) #if TUSB_OPT_HOST_ENABLED // tag::host_buf_sel_fix[] + // TODO need changes to support double buffering if (ep->buf_sel == 1) { // Host can erroneously write status to top half of buf_ctrl register buf_ctrl = buf_ctrl >> 16; + + // update buf1 -> buf0 to prevent panic with "already available" + *ep->buffer_control = buf_ctrl; } // Flip buf sel for host ep->buf_sel ^= 1u; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index bb88d977f..32d20051f 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -16,8 +16,6 @@ #define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX #endif -// For memset -#include #if false && !defined(NDEBUG) #define pico_trace(format,args...) printf(format, ## args) @@ -78,7 +76,7 @@ struct hw_endpoint #if TUSB_OPT_HOST_ENABLED // Only needed for host mode bool last_buf; - // HOST BUG. Host will incorrect write status to top half of buffer + // RP2040-E4: HOST BUG. Host will incorrect write status to top half of buffer // control register when doing transfers > 1 packet uint8_t buf_sel; // Only needed for host @@ -119,4 +117,44 @@ static inline uintptr_t hw_data_offset(uint8_t *buf) extern const char *ep_dir_string[]; +typedef union TU_ATTR_PACKED +{ + uint16_t u16; + struct TU_ATTR_PACKED + { + uint16_t xfer_len : 10; + uint16_t available : 1; + uint16_t stall : 1; + uint16_t reset_bufsel : 1; + uint16_t data_toggle : 1; + uint16_t last_buf : 1; + uint16_t full : 1; + }; +} rp2040_buffer_control_t; + +TU_VERIFY_STATIC(sizeof(rp2040_buffer_control_t) == 2, "size is not correct"); + +static inline void print_bufctrl16(uint32_t u16) +{ + rp2040_buffer_control_t bufctrl; + + bufctrl.u16 = u16; + + TU_LOG(2, "len = %u, available = %u, stall = %u, reset = %u, toggle = %u, last = %u, full = %u\r\n", + bufctrl.xfer_len, bufctrl.available, bufctrl.stall, bufctrl.reset_bufsel, bufctrl.data_toggle, bufctrl.last_buf, bufctrl.full); +} + +static inline void print_bufctrl32(uint32_t u32) +{ + uint16_t u16; + + u16 = u32 >> 16; + TU_LOG(2, "Buffer Control 1 0x%x: ", u16); + print_bufctrl16(u16); + + u16 = u32 & 0x0000ffff; + TU_LOG(2, "Buffer Control 0 0x%x: ", u16); + print_bufctrl16(u16); +} + #endif -- cgit v1.3.1 From 54c915057484d4d63d0697114f156aef2837b728 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 30 May 2021 23:41:59 +0700 Subject: add errata number --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 60a039556..7718293e5 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -210,6 +210,7 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) uint16_t transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; #if TUSB_OPT_HOST_ENABLED + // RP2040-E4 // tag::host_buf_sel_fix[] // TODO need changes to support double buffering if (ep->buf_sel == 1) -- cgit v1.3.1 From c2a0c1507b0db15a06773e321bd5c782bac54d39 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 30 May 2021 23:44:29 +0700 Subject: add more comment --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 7718293e5..a0263612f 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -136,6 +136,7 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) // Special case with control status stage where PID is always DATA1 if ( ep->transfer_size == 0 ) { + // ZLP also toggle data ep->next_pid ^= 1u; }else { -- cgit v1.3.1 From 5cf930d78a9e31924008ac6bd145ddf2af76b42f Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 31 May 2021 11:11:00 +0700 Subject: fix cast-align warning in msc host --- src/class/msc/msc_host.c | 7 ++++--- src/host/hcd.h | 2 ++ src/portable/ehci/ehci.c | 1 - 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 5a4ffff48..205f0fd2d 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -71,7 +71,8 @@ CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUSB_HOST_DEVICE_MAX] // buffer used to read scsi information when mounted // largest response data currently is inquiry TODO Inquiry is not part of enum anymore -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) +static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; static inline msch_interface_t* get_itf(uint8_t dev_addr) { @@ -438,7 +439,7 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c { // Unit is ready, read its capacity TU_LOG2("SCSI Read Capacity\r\n"); - tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) _msch_buffer, config_read_capacity_complete); + tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), config_read_capacity_complete); }else { // Note: During enumeration, some device fails Test Unit Ready and require a few retries @@ -465,7 +466,7 @@ static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw msch_interface_t* p_msc = get_itf(dev_addr); // Capacity response field: Block size and Last LBA are both Big-Endian - scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) _msch_buffer; + scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer); p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1; p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size); diff --git a/src/host/hcd.h b/src/host/hcd.h index ba6a9c5ca..df19f3e22 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -28,6 +28,8 @@ #define _TUSB_HCD_H_ #include "common/tusb_common.h" +#include "osal/osal.h" +#include "common/tusb_fifo.h" #ifdef __cplusplus extern "C" { diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index eab1f8928..a1c12e70d 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -302,7 +302,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - // FIXME control only for now if ( epnum == 0 ) { ehci_qhd_t* qhd = qhd_control(dev_addr); -- cgit v1.3.1 From 3fb80e76ce554018fd81b2922c1db9121f446ac1 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 31 May 2021 12:08:37 +0700 Subject: remove obsolete hcd_pipe_queue_xfer()/hcd_pipe_xfer() --- src/class/cdc/cdc_host.c | 6 +- src/class/cdc/cdc_rndis_host.c | 2 +- src/class/vendor/vendor_host.c | 4 +- src/host/hcd.h | 11 +--- src/host/hub.c | 2 +- src/portable/ehci/ehci.c | 82 ++++++++-------------------- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 10 ---- 7 files changed, 33 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index c22107bbb..facf86d56 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -96,24 +96,26 @@ bool tuh_cdc_serial_is_mounted(uint8_t dev_addr) bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify) { + (void) is_notify; TU_VERIFY( tuh_cdc_mounted(dev_addr) ); TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA); uint8_t const ep_out = cdch_data[dev_addr-1].ep_out; if ( hcd_edpt_busy(dev_addr, ep_out) ) return false; - return hcd_pipe_xfer(dev_addr, ep_out, (void *) p_data, length, is_notify); + return usbh_edpt_xfer(dev_addr, ep_out, (void *) p_data, length); } bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify) { + (void) is_notify; TU_VERIFY( tuh_cdc_mounted(dev_addr) ); TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA); uint8_t const ep_in = cdch_data[dev_addr-1].ep_in; if ( hcd_edpt_busy(dev_addr, ep_in) ) return false; - return hcd_pipe_xfer(dev_addr, ep_in, p_buffer, length, is_notify); + return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, length); } bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_complete_cb_t complete_cb) diff --git a/src/class/cdc/cdc_rndis_host.c b/src/class/cdc/cdc_rndis_host.c index 767b917a1..42b9993bc 100644 --- a/src/class/cdc/cdc_rndis_host.c +++ b/src/class/cdc/cdc_rndis_host.c @@ -239,7 +239,7 @@ static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_da if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); //------------- waiting for Response Available notification -------------// - (void) hcd_pipe_xfer(p_cdc->pipe_notification, msg_notification[dev_addr-1], 8, true); + (void) usbh_edpt_xfer(p_cdc->pipe_notification, msg_notification[dev_addr-1], 8); osal_semaphore_wait(rndish_data[dev_addr-1].sem_notification_hdl, OSAL_TIMEOUT_NORMAL, &error); if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); STASK_ASSERT(msg_notification[dev_addr-1][0] == 1); diff --git a/src/class/vendor/vendor_host.c b/src/class/vendor/vendor_host.c index 1978ef61c..f7a6b2bf0 100644 --- a/src/class/vendor/vendor_host.c +++ b/src/class/vendor/vendor_host.c @@ -66,7 +66,7 @@ tusb_error_t tusbh_custom_read(uint8_t dev_addr, uint16_t vendor_id, uint16_t pr return TUSB_ERROR_INTERFACE_IS_BUSY; } - (void) hcd_pipe_xfer( custom_interface[dev_addr-1].pipe_in, p_buffer, length, true); + (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_in, p_buffer, length); return TUSB_ERROR_NONE; } @@ -80,7 +80,7 @@ tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t p return TUSB_ERROR_INTERFACE_IS_BUSY; } - (void) hcd_pipe_xfer( custom_interface[dev_addr-1].pipe_out, p_data, length, true); + (void) usbh_edpt_xfer( custom_interface[dev_addr-1].pipe_out, p_data, length); return TUSB_ERROR_NONE; } diff --git a/src/host/hcd.h b/src/host/hcd.h index df19f3e22..0a9f00a0c 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -143,21 +143,12 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); -// TODO merge with pipe_xfer -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); - -//--------------------------------------------------------------------+ -// PIPE API - TODO remove later -//--------------------------------------------------------------------+ -// TODO control xfer should be used via usbh layer -bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes); // only queue, not transferring yet -bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete); - //--------------------------------------------------------------------+ // Event API (implemented by stack) //--------------------------------------------------------------------+ diff --git a/src/host/hub.c b/src/host/hub.c index 4db680f9e..2d4033a26 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -352,7 +352,7 @@ void hub_close(uint8_t dev_addr) bool hub_status_pipe_queue(uint8_t dev_addr) { usbh_hub_t * p_hub = &hub_data[dev_addr-1]; - return hcd_pipe_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1, true); + return usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1); } diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index a1c12e70d..70a497f0a 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -293,8 +293,31 @@ static void ehci_stop(uint8_t rhport) #endif //--------------------------------------------------------------------+ -// CONTROL PIPE API +// Endpoint API //--------------------------------------------------------------------+ + +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) +{ + (void) rhport; + + ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd; + ehci_qtd_t* td = &ehci_data.control[dev_addr].qtd; + + qtd_init(td, (void*) setup_packet, 8); + td->pid = EHCI_PID_SETUP; + td->int_on_complete = 1; + td->next.terminate = 1; + + // sw region + qhd->p_qtd_list_head = td; + qhd->p_qtd_list_tail = td; + + // attach TD + qhd->qtd_overlay.next.address = (uint32_t) td; + + return true; +} + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { (void) rhport; @@ -342,31 +365,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * return true; } -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) -{ - (void) rhport; - - ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd; - ehci_qtd_t* td = &ehci_data.control[dev_addr].qtd; - - qtd_init(td, (void*) setup_packet, 8); - td->pid = EHCI_PID_SETUP; - td->int_on_complete = 1; - td->next.terminate = 1; - - // sw region - qhd->p_qtd_list_head = td; - qhd->p_qtd_list_tail = td; - - // attach TD - qhd->qtd_overlay.next.address = (uint32_t) td; - - return true; -} - -//--------------------------------------------------------------------+ -// BULK/INT/ISO PIPE API -//--------------------------------------------------------------------+ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { (void) rhport; @@ -420,38 +418,6 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } -bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes) -{ - //------------- set up QTD -------------// - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - ehci_qtd_t *p_qtd = qtd_find_free(); - - TU_ASSERT(p_qtd); - - qtd_init(p_qtd, buffer, total_bytes); - p_qtd->pid = p_qhd->pid; - - //------------- insert TD to TD list -------------// - qtd_insert_to_qhd(p_qhd, p_qtd); - - return true; -} - -bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) -{ - TU_ASSERT ( hcd_pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes) ); - - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - - if ( int_on_complete ) - { // the just added qtd is pointed by list_tail - p_qhd->p_qtd_list_tail->int_on_complete = 1; - } - p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; // attach head QTD to QHD start transferring - - return true; -} - bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) { ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index c09469ff5..b8833fbec 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -543,14 +543,4 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) return true; } -bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) -{ - pico_trace("hcd_pipe_xfer dev_addr %d, ep_addr 0x%x, total_bytes %d, int_on_complete %d\n", - dev_addr, ep_addr, total_bytes, int_on_complete); - - // Same logic as hcd_edpt_xfer as far as I am concerned - hcd_edpt_xfer(0, dev_addr, ep_addr, buffer, total_bytes); - - return true; -} #endif -- cgit v1.3.1 From 65e5872d8109f7f12c48c52a5fdd537e676b0514 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 31 May 2021 15:18:24 +0700 Subject: add hub_port_set_feature() --- src/host/hub.c | 96 +++++++++++++++++++++++++++++++++++++++------------------- src/host/hub.h | 4 ++- 2 files changed, 68 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/host/hub.c b/src/host/hub.c index 2d4033a26..6eea6ee4e 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -42,13 +42,30 @@ typedef struct uint8_t status_change; // data from status change interrupt endpoint hub_port_status_response_t port_status; -}usbh_hub_t; +} hub_interface_t; -CFG_TUSB_MEM_SECTION static usbh_hub_t hub_data[CFG_TUSB_HOST_DEVICE_MAX]; +CFG_TUSB_MEM_SECTION static hub_interface_t hub_data[CFG_TUSB_HOST_DEVICE_MAX]; TU_ATTR_ALIGNED(4) CFG_TUSB_MEM_SECTION static uint8_t _hub_buffer[sizeof(descriptor_hub_desc_t)]; -//OSAL_SEM_DEF(hub_enum_semaphore); -//static osal_semaphore_handle_t hub_enum_sem_hdl; +#if CFG_TUSB_DEBUG +static char const* const _hub_feature_str[] = +{ + [HUB_FEATURE_PORT_CONNECTION ] = "PORT_CONNECTION", + [HUB_FEATURE_PORT_ENABLE ] = "PORT_ENABLE", + [HUB_FEATURE_PORT_SUSPEND ] = "PORT_SUSPEND", + [HUB_FEATURE_PORT_OVER_CURRENT ] = "PORT_OVER_CURRENT", + [HUB_FEATURE_PORT_RESET ] = "PORT_RESET", + [HUB_FEATURE_PORT_POWER ] = "PORT_POWER", + [HUB_FEATURE_PORT_LOW_SPEED ] = "PORT_LOW_SPEED", + [HUB_FEATURE_PORT_CONNECTION_CHANGE ] = "PORT_CONNECTION_CHANGE", + [HUB_FEATURE_PORT_ENABLE_CHANGE ] = "PORT_ENABLE_CHANGE", + [HUB_FEATURE_PORT_SUSPEND_CHANGE ] = "PORT_SUSPEND_CHANGE", + [HUB_FEATURE_PORT_OVER_CURRENT_CHANGE ] = "PORT_OVER_CURRENT_CHANGE", + [HUB_FEATURE_PORT_RESET_CHANGE ] = "PORT_RESET_CHANGE", + [HUB_FEATURE_PORT_TEST ] = "PORT_TEST", + [HUB_FEATURE_PORT_INDICATOR ] = "PORT_INDICATOR", +}; +#endif //--------------------------------------------------------------------+ // HUB @@ -69,12 +86,12 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, .wLength = 0 }; - TU_LOG2("HUB Clear Port Feature: addr = %u port = %u, feature = %u\r\n", hub_addr, hub_port, feature); + TU_LOG2("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); return true; } -bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb) +bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb) { tusb_control_request_t const request = { @@ -82,20 +99,25 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_con { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN + .direction = TUSB_DIR_OUT }, - .bRequest = HUB_REQUEST_GET_STATUS, - .wValue = 0, + .bRequest = HUB_REQUEST_SET_FEATURE, + .wValue = feature, .wIndex = hub_port, - .wLength = 4 + .wLength = 0 }; - TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer( hub_addr, &request, resp, complete_cb) ); + TU_LOG2("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); + TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); return true; } bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb) +{ + return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb); +} + +bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb) { tusb_control_request_t const request = { @@ -103,16 +125,16 @@ bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_ { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT + .direction = TUSB_DIR_IN }, - .bRequest = HUB_REQUEST_SET_FEATURE, - .wValue = HUB_FEATURE_PORT_RESET, + .bRequest = HUB_REQUEST_GET_STATUS, + .wValue = 0, .wIndex = hub_port, - .wLength = 0 + .wLength = 4 }; - TU_LOG2("HUB Reset Port: addr = %u port = %u\r\n", hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer(hub_addr, &request, NULL, complete_cb) ); + TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port); + TU_ASSERT( tuh_control_xfer( hub_addr, &request, resp, complete_cb) ); return true; } @@ -121,7 +143,7 @@ bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_ //--------------------------------------------------------------------+ void hub_init(void) { - tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof(usbh_hub_t)); + tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof( hub_interface_t)); // hub_enum_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(hub_enum_semaphore) ); } @@ -147,6 +169,10 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf return true; } +//--------------------------------------------------------------------+ +// Set Configure +//--------------------------------------------------------------------+ + static bool config_get_hub_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -155,7 +181,7 @@ static bool config_get_hub_desc_complete (uint8_t dev_addr, tusb_control_request (void) request; TU_ASSERT(XFER_RESULT_SUCCESS == result); - usbh_hub_t* p_hub = &hub_data[dev_addr-1]; + hub_interface_t* p_hub = &hub_data[dev_addr-1]; // only use number of ports in hub descriptor descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer; @@ -163,7 +189,7 @@ static bool config_get_hub_desc_complete (uint8_t dev_addr, tusb_control_request // May need to GET_STATUS - // Ports must be powered on to be able to detect connection + // Set Port Power to be able to detect connection tusb_control_request_t const new_request = { .bmRequestType_bit = @@ -178,6 +204,8 @@ static bool config_get_hub_desc_complete (uint8_t dev_addr, tusb_control_request .wLength = 0 }; + TU_LOG(2, "HUB Set Port Power: port = %u\r\n", new_request.wIndex); + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_port_power_complete) ); return true; @@ -186,7 +214,7 @@ static bool config_get_hub_desc_complete (uint8_t dev_addr, tusb_control_request static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { TU_ASSERT(XFER_RESULT_SUCCESS == result); - usbh_hub_t* p_hub = &hub_data[dev_addr-1]; + hub_interface_t* p_hub = &hub_data[dev_addr-1]; if (request->wIndex == p_hub->port_count) { @@ -200,6 +228,8 @@ static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t tusb_control_request_t new_request = *request; new_request.wIndex++; // power next port + TU_LOG(2, "HUB Set Port Power: port = %u\r\n", new_request.wIndex); + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_port_power_complete) ); } @@ -208,7 +238,7 @@ static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) { - usbh_hub_t* p_hub = &hub_data[dev_addr-1]; + hub_interface_t* p_hub = &hub_data[dev_addr-1]; TU_ASSERT(itf_num == p_hub->itf_num); //------------- Get Hub Descriptor -------------// @@ -231,6 +261,10 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) return true; } +//--------------------------------------------------------------------+ +// Connection Changes +//--------------------------------------------------------------------+ + static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -263,7 +297,7 @@ static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_contro { TU_ASSERT(result == XFER_RESULT_SUCCESS); - usbh_hub_t * p_hub = &hub_data[dev_addr-1]; + hub_interface_t * p_hub = &hub_data[dev_addr-1]; uint8_t const port_num = (uint8_t) request->wIndex; if ( p_hub->port_status.status.connection ) @@ -293,7 +327,7 @@ static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_contro static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { TU_ASSERT(result == XFER_RESULT_SUCCESS); - usbh_hub_t * p_hub = &hub_data[dev_addr-1]; + hub_interface_t * p_hub = &hub_data[dev_addr-1]; uint8_t const port_num = (uint8_t) request->wIndex; // Connection change @@ -325,12 +359,13 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 (void) ep_addr; TU_ASSERT( result == XFER_RESULT_SUCCESS); - usbh_hub_t * p_hub = &hub_data[dev_addr-1]; + hub_interface_t * p_hub = &hub_data[dev_addr-1]; + + TU_LOG2(" Port Status Change = 0x%02X\r\n", p_hub->status_change); - TU_LOG2("Port Status Change = 0x%02X\r\n", p_hub->status_change); + // Hub ignore bit0 in status change for (uint8_t port=1; port <= p_hub->port_count; port++) { - // TODO HUB ignore bit0 hub_status_change if ( tu_bit_test(p_hub->status_change, port) ) { hub_port_get_status(dev_addr, port, &p_hub->port_status, connection_get_status_complete); @@ -345,13 +380,12 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 void hub_close(uint8_t dev_addr) { - tu_memclr(&hub_data[dev_addr-1], sizeof(usbh_hub_t)); -// osal_semaphore_reset(hub_enum_sem_hdl); + tu_memclr(&hub_data[dev_addr-1], sizeof( hub_interface_t)); } bool hub_status_pipe_queue(uint8_t dev_addr) { - usbh_hub_t * p_hub = &hub_data[dev_addr-1]; + hub_interface_t * p_hub = &hub_data[dev_addr-1]; return usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1); } diff --git a/src/host/hub.h b/src/host/hub.h index 2b2f39ee1..a5111b8e7 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -171,9 +171,11 @@ typedef struct { TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); +bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb); +bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb); + bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_control_complete_cb_t complete_cb); bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_control_complete_cb_t complete_cb); -bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_control_complete_cb_t complete_cb); bool hub_status_pipe_queue(uint8_t dev_addr); //--------------------------------------------------------------------+ -- cgit v1.3.1 From 4b2f32b7786674a1a5ccf7347a2e67e68665e1c3 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 31 May 2021 15:41:40 +0700 Subject: update hub --- src/host/hub.c | 220 +++++++++++++++++++++++++------------------------------- src/host/usbh.c | 4 +- 2 files changed, 101 insertions(+), 123 deletions(-) (limited to 'src') diff --git a/src/host/hub.c b/src/host/hub.c index 6eea6ee4e..f921027c7 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -144,7 +144,6 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_con void hub_init(void) { tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof( hub_interface_t)); -// hub_enum_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(hub_enum_semaphore) ); } bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) @@ -169,48 +168,68 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf return true; } +void hub_close(uint8_t dev_addr) +{ + tu_memclr(&hub_data[dev_addr-1], sizeof( hub_interface_t)); +} + +bool hub_status_pipe_queue(uint8_t dev_addr) +{ + hub_interface_t * p_hub = &hub_data[dev_addr-1]; + return usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1); +} + + //--------------------------------------------------------------------+ // Set Configure //--------------------------------------------------------------------+ -static bool config_get_hub_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool config_get_hub_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) { - (void) request; - TU_ASSERT(XFER_RESULT_SUCCESS == result); - hub_interface_t* p_hub = &hub_data[dev_addr-1]; + TU_ASSERT(itf_num == p_hub->itf_num); - // only use number of ports in hub descriptor - descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer; - p_hub->port_count = desc_hub->bNbrPorts; - - // May need to GET_STATUS - - // Set Port Power to be able to detect connection - tusb_control_request_t const new_request = + // Get Hub Descriptor + tusb_control_request_t const request = { .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_OTHER, + .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT + .direction = TUSB_DIR_IN }, - .bRequest = HUB_REQUEST_SET_FEATURE, - .wValue = HUB_FEATURE_PORT_POWER, - .wIndex = 1, // starting with port 1 - .wLength = 0 + .bRequest = HUB_REQUEST_GET_DESCRIPTOR, + .wValue = 0, + .wIndex = 0, + .wLength = sizeof(descriptor_hub_desc_t) }; - TU_LOG(2, "HUB Set Port Power: port = %u\r\n", new_request.wIndex); - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_port_power_complete) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &request, _hub_buffer, config_set_port_power) ); return true; } +static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + (void) request; + TU_ASSERT(XFER_RESULT_SUCCESS == result); + + hub_interface_t* p_hub = &hub_data[dev_addr-1]; + + // only use number of ports in hub descriptor + descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer; + p_hub->port_count = desc_hub->bNbrPorts; + + // May need to GET_STATUS + + // Set Port Power to be able to detect connection, starting with port 1 + uint8_t const hub_port = 1; + return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete); +} + static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { TU_ASSERT(XFER_RESULT_SUCCESS == result); @@ -225,70 +244,71 @@ static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t usbh_driver_set_config_complete(dev_addr, p_hub->itf_num); }else { - tusb_control_request_t new_request = *request; - new_request.wIndex++; // power next port - - TU_LOG(2, "HUB Set Port Power: port = %u\r\n", new_request.wIndex); - - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_port_power_complete) ); + // power next port + uint8_t const hub_port = (uint8_t) (request->wIndex + 1); + return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete); } return true; } -bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) -{ - hub_interface_t* p_hub = &hub_data[dev_addr-1]; - TU_ASSERT(itf_num == p_hub->itf_num); - - //------------- Get Hub Descriptor -------------// - tusb_control_request_t request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = HUB_REQUEST_GET_DESCRIPTOR, - .wValue = 0, - .wIndex = 0, - .wLength = sizeof(descriptor_hub_desc_t) - }; - - TU_ASSERT( tuh_control_xfer(dev_addr, &request, _hub_buffer, config_get_hub_desc_complete) ); - - return true; -} - //--------------------------------------------------------------------+ // Connection Changes //--------------------------------------------------------------------+ -static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +// callback as response of interrupt endpoint polling +bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports + (void) ep_addr; TU_ASSERT(result == XFER_RESULT_SUCCESS); - // usbh_hub_t * p_hub = &hub_data[dev_addr-1]; - uint8_t const port_num = (uint8_t) request->wIndex; + hub_interface_t * p_hub = &hub_data[dev_addr-1]; - // submit attach event - hcd_event_t event = + TU_LOG2(" Port Status Change = 0x%02X\r\n", p_hub->status_change); + + // Hub ignore bit0 in status change + for (uint8_t port=1; port <= p_hub->port_count; port++) { - .rhport = usbh_get_rhport(dev_addr), - .event_id = HCD_EVENT_DEVICE_ATTACH, - .connection = + if ( tu_bit_test(p_hub->status_change, port) ) { - .hub_addr = dev_addr, - .hub_port = port_num + hub_port_get_status(dev_addr, port, &p_hub->port_status, connection_get_status_complete); + break; } - }; + } - hcd_event_handler(&event, false); + // NOTE: next status transfer is queued by usbh.c after handling this request + + return true; +} + +static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +{ + TU_ASSERT(result == XFER_RESULT_SUCCESS); + hub_interface_t * p_hub = &hub_data[dev_addr-1]; + uint8_t const port_num = (uint8_t) request->wIndex; + + // Connection change + if (p_hub->port_status.change.connection) + { + // Port is powered and enabled + //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); + + // Acknowledge Port Connection Change + hub_port_clear_feature(dev_addr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete); + }else + { + // Other changes are: Enable, Suspend, Over Current, Reset, L1 state + // TODO clear change + + // prepare for next hub status + // TODO continue with status_change, or maybe we can do it again with status + hub_status_pipe_queue(dev_addr); + } return true; } @@ -324,70 +344,28 @@ static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_contro return true; } -static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { TU_ASSERT(result == XFER_RESULT_SUCCESS); - hub_interface_t * p_hub = &hub_data[dev_addr-1]; - uint8_t const port_num = (uint8_t) request->wIndex; - - // Connection change - if (p_hub->port_status.change.connection) - { - // Port is powered and enabled - //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); - - // Acknowledge Port Connection Change - hub_port_clear_feature(dev_addr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete); - }else - { - // Other changes are: Enable, Suspend, Over Current, Reset, L1 state - // TODO clear change - - // prepare for next hub status - // TODO continue with status_change, or maybe we can do it again with status - hub_status_pipe_queue(dev_addr); - } - - return true; -} - -// is the response of interrupt endpoint polling -#include "usbh_hcd.h" // FIXME remove -bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports - (void) ep_addr; - TU_ASSERT( result == XFER_RESULT_SUCCESS); - - hub_interface_t * p_hub = &hub_data[dev_addr-1]; - TU_LOG2(" Port Status Change = 0x%02X\r\n", p_hub->status_change); + // usbh_hub_t * p_hub = &hub_data[dev_addr-1]; + uint8_t const port_num = (uint8_t) request->wIndex; - // Hub ignore bit0 in status change - for (uint8_t port=1; port <= p_hub->port_count; port++) + // submit attach event + hcd_event_t event = { - if ( tu_bit_test(p_hub->status_change, port) ) + .rhport = usbh_get_rhport(dev_addr), + .event_id = HCD_EVENT_DEVICE_ATTACH, + .connection = { - hub_port_get_status(dev_addr, port, &p_hub->port_status, connection_get_status_complete); - break; + .hub_addr = dev_addr, + .hub_port = port_num } - } + }; - // NOTE: next status transfer is queued by usbh.c after handling this request + hcd_event_handler(&event, false); return true; } -void hub_close(uint8_t dev_addr) -{ - tu_memclr(&hub_data[dev_addr-1], sizeof( hub_interface_t)); -} - -bool hub_status_pipe_queue(uint8_t dev_addr) -{ - hub_interface_t * p_hub = &hub_data[dev_addr-1]; - return usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1); -} - - #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index ac0b654ef..e50421b43 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -455,7 +455,7 @@ void hcd_event_device_attach(uint8_t rhport, bool in_isr) { hcd_event_t event = { - .rhport = rhport, + .rhport = rhport, .event_id = HCD_EVENT_DEVICE_ATTACH }; @@ -469,7 +469,7 @@ void hcd_event_device_remove(uint8_t hostid, bool in_isr) { hcd_event_t event = { - .rhport = hostid, + .rhport = hostid, .event_id = HCD_EVENT_DEVICE_REMOVE }; -- cgit v1.3.1 From 04797bc5a5e90304e5882ebc29c4c0f7d81ae012 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 31 May 2021 16:05:55 +0700 Subject: clean up --- src/host/usbh_control.c | 4 +- src/portable/ehci/ehci.c | 131 ++++++++++++++++++++++++++++------------------- src/portable/ehci/ehci.h | 45 ++-------------- 3 files changed, 84 insertions(+), 96 deletions(-) (limited to 'src') diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 974d10662..4dbf8592a 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -108,7 +108,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu _ctrl_xfer.stage = STAGE_DATA; if (request->wLength) { - // Note: initial data toggle is always 1 + // DATA stage: initial data toggle is always 1 hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); return true; } @@ -123,7 +123,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2); } - // data toggle is always 1 + // ACK stage: toggle is always 1 hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); break; diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 70a497f0a..1462d0c6a 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -44,6 +44,28 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +typedef struct +{ + ehci_link_t period_framelist[EHCI_FRAMELIST_SIZE]; + + // for NXP ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist) + // [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms + ehci_qhd_t period_head_arr[4]; + + // Note control qhd of dev0 is used as head of async list + struct { + ehci_qhd_t qhd; + ehci_qtd_t qtd; + }control[CFG_TUSB_HOST_DEVICE_MAX+1]; + + ehci_qhd_t qhd_pool[HCD_MAX_ENDPOINT]; + ehci_qtd_t qtd_pool[HCD_MAX_XFER] TU_ATTR_ALIGNED(32); + + ehci_registers_t* regs; + + volatile uint32_t uframe_number; +}ehci_data_t; + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -67,7 +89,8 @@ static inline ehci_qhd_t* qhd_control(uint8_t dev_addr) static inline ehci_qhd_t* qhd_async_head(uint8_t rhport) { (void) rhport; - return qhd_control(0); // control qhd of dev0 is used as async head + // control qhd of dev0 is used as async head + return qhd_control(0); } static inline ehci_qtd_t* qtd_control(uint8_t dev_addr) @@ -296,6 +319,59 @@ static void ehci_stop(uint8_t rhport) // Endpoint API //--------------------------------------------------------------------+ +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +{ + (void) rhport; + + // TODO not support ISO yet + TU_ASSERT (ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); + + //------------- Prepare Queue Head -------------// + ehci_qhd_t * p_qhd; + + if ( ep_desc->bEndpointAddress == 0 ) + { + p_qhd = qhd_control(dev_addr); + }else + { + p_qhd = qhd_find_free(); + } + TU_ASSERT(p_qhd); + + qhd_init(p_qhd, dev_addr, ep_desc); + + // control of dev0 is always present as async head + if ( dev_addr == 0 ) return true; + + // Insert to list + ehci_link_t * list_head = NULL; + + switch (ep_desc->bmAttributes.xfer) + { + case TUSB_XFER_CONTROL: + case TUSB_XFER_BULK: + list_head = (ehci_link_t*) qhd_async_head(rhport); + break; + + case TUSB_XFER_INTERRUPT: + list_head = get_period_head(rhport, p_qhd->interval_ms); + break; + + case TUSB_XFER_ISOCHRONOUS: + // TODO iso is not supported + break; + + default: break; + } + + TU_ASSERT(list_head); + + // TODO might need to disable async/period list + list_insert(list_head, (ehci_link_t*) p_qhd, EHCI_QTYPE_QHD); + + return true; +} + bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { (void) rhport; @@ -365,59 +441,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * return true; } -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; - - // TODO not support ISO yet - TU_ASSERT (ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); - - //------------- Prepare Queue Head -------------// - ehci_qhd_t * p_qhd; - - if ( ep_desc->bEndpointAddress == 0 ) - { - p_qhd = qhd_control(dev_addr); - }else - { - p_qhd = qhd_find_free(); - } - TU_ASSERT(p_qhd); - - qhd_init(p_qhd, dev_addr, ep_desc); - - // control of dev0 is always present as async head - if ( dev_addr == 0 ) return true; - - // Insert to list - ehci_link_t * list_head = NULL; - - switch (ep_desc->bmAttributes.xfer) - { - case TUSB_XFER_CONTROL: - case TUSB_XFER_BULK: - list_head = (ehci_link_t*) qhd_async_head(rhport); - break; - - case TUSB_XFER_INTERRUPT: - list_head = get_period_head(rhport, p_qhd->interval_ms); - break; - - case TUSB_XFER_ISOCHRONOUS: - // TODO iso is not supported - break; - - default: break; - } - - TU_ASSERT(list_head); - - // TODO might need to disable async/period list - list_insert(list_head, (ehci_link_t*) p_qhd, EHCI_QTYPE_QHD); - - return true; -} - bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) { ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index 212f605b1..874195a0c 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -24,12 +24,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup Group_HCD - * @{ - * \defgroup EHCI - * \brief EHCI driver. All documents sources mentioned here (eg section 3.5) is referring to EHCI Specs unless state otherwise - * @{ */ - #ifndef _TUSB_EHCI_H_ #define _TUSB_EHCI_H_ @@ -309,12 +303,11 @@ enum ehci_usbcmd_pos_ { enum ehci_portsc_change_mask_{ EHCI_PORTSC_MASK_CURRENT_CONNECT_STATUS = TU_BIT(0), - EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE = TU_BIT(1), - EHCI_PORTSC_MASK_PORT_EANBLED = TU_BIT(2), - EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE = TU_BIT(3), - EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE = TU_BIT(5), - - EHCI_PORTSC_MASK_PORT_RESET = TU_BIT(8), + EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE = TU_BIT(1), + EHCI_PORTSC_MASK_PORT_EANBLED = TU_BIT(2), + EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE = TU_BIT(3), + EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE = TU_BIT(5), + EHCI_PORTSC_MASK_PORT_RESET = TU_BIT(8), EHCI_PORTSC_MASK_ALL = EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE | @@ -425,36 +418,8 @@ typedef volatile struct }; }ehci_registers_t; -//--------------------------------------------------------------------+ -// EHCI Data Organization -//--------------------------------------------------------------------+ -typedef struct -{ - ehci_link_t period_framelist[EHCI_FRAMELIST_SIZE]; - - // for NXP ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist) - // [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms - ehci_qhd_t period_head_arr[4]; - - // Note control qhd of dev0 is used as head of async list - struct { - ehci_qhd_t qhd; - ehci_qtd_t qtd; - }control[CFG_TUSB_HOST_DEVICE_MAX+1]; - - ehci_qhd_t qhd_pool[HCD_MAX_ENDPOINT]; - ehci_qtd_t qtd_pool[HCD_MAX_XFER] TU_ATTR_ALIGNED(32); - - ehci_registers_t* regs; - - volatile uint32_t uframe_number; -}ehci_data_t; - #ifdef __cplusplus } #endif #endif /* _TUSB_EHCI_H_ */ - -/** @} */ -/** @} */ -- cgit v1.3.1 From da8000d42d6d6252eef9627efb6cf2557dfcf1d2 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 31 May 2021 16:34:07 +0700 Subject: clean up ohci, remove obsolete api --- src/portable/ohci/ohci.c | 157 +++++++++++++++++------------------------------ 1 file changed, 58 insertions(+), 99 deletions(-) (limited to 'src') diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index ee294856b..e6bd446ea 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -27,7 +27,7 @@ #include #if TUSB_OPT_HOST_ENABLED && \ - (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC40XX) + (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX) //--------------------------------------------------------------------+ // INCLUDE @@ -244,7 +244,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) //--------------------------------------------------------------------+ //--------------------------------------------------------------------+ -// CONTROL PIPE API +// List Helper //--------------------------------------------------------------------+ static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_t const * const p_ed) { @@ -310,57 +310,6 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet return true; } -// TODO move around -static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr); -static ohci_gtd_t * gtd_find_free(void); -static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd); - -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) -{ - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - // FIXME control only for now - if ( epnum == 0 ) - { - ohci_ed_t* const p_ed = &ohci_data.control[dev_addr].ed; - ohci_gtd_t *p_data = &ohci_data.control[dev_addr].gtd; - - gtd_init(p_data, buffer, buflen); - - p_data->index = dev_addr; - p_data->pid = dir ? OHCI_PID_IN : OHCI_PID_OUT; - p_data->data_toggle = TU_BIN8(11); // DATA1 - p_data->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - - p_ed->td_head.address = (uint32_t) p_data; - - OHCI_REG->command_status_bit.control_list_filled = 1; - }else - { - ohci_ed_t * p_ed = ed_from_addr(dev_addr, ep_addr); - ohci_gtd_t* p_gtd = gtd_find_free(); - - TU_ASSERT(p_gtd); - - gtd_init(p_gtd, buffer, buflen); - p_gtd->index = p_ed-ohci_data.ed_pool; - p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - - td_insert_to_ed(p_ed, p_gtd); - - tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); - if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; - } - - return true; -} - -//--------------------------------------------------------------------+ -// BULK/INT/ISO PIPE API -//--------------------------------------------------------------------+ static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) { if ( tu_edpt_number(ep_addr) == 0 ) return &ohci_data.control[dev_addr].ed; @@ -420,9 +369,36 @@ static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr) } } +static ohci_gtd_t * gtd_find_free(void) +{ + for(uint8_t i=0; i < HCD_MAX_XFER; i++) + { + if ( !ohci_data.gtd_pool[i].used ) return &ohci_data.gtd_pool[i]; + } + + return NULL; +} + +static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd) +{ + // tail is always NULL + if ( tu_align16(p_ed->td_head.address) == 0 ) + { // TD queue is empty --> head = TD + p_ed->td_head.address |= (uint32_t) p_gtd; + } + else + { // TODO currently only support queue up to 2 TD each endpoint at a time + ((ohci_gtd_t*) tu_align16(p_ed->td_head.address))->next = (uint32_t) p_gtd; + } +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { - (void) rhport; + (void) rhport; // TODO iso support TU_ASSERT(ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); @@ -454,62 +430,45 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } -static ohci_gtd_t * gtd_find_free(void) -{ - for(uint8_t i=0; i < HCD_MAX_XFER; i++) - { - if ( !ohci_data.gtd_pool[i].used ) return &ohci_data.gtd_pool[i]; - } - - return NULL; -} - -static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd) -{ - // tail is always NULL - if ( tu_align16(p_ed->td_head.address) == 0 ) - { // TD queue is empty --> head = TD - p_ed->td_head.address |= (uint32_t) p_gtd; - } - else - { // TODO currently only support queue up to 2 TD each endpoint at a time - ((ohci_gtd_t*) tu_align16(p_ed->td_head.address))->next = (uint32_t) p_gtd; - } -} - -static bool pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { - ohci_ed_t* const p_ed = ed_from_addr(dev_addr, ep_addr); + (void) rhport; - // not support ISO yet - TU_VERIFY ( !p_ed->is_iso ); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - ohci_gtd_t * const p_gtd = gtd_find_free(); - TU_ASSERT(p_gtd); // not enough gtd + // FIXME control only for now + if ( epnum == 0 ) + { + ohci_ed_t* ed = &ohci_data.control[dev_addr].ed; + ohci_gtd_t* gtd = &ohci_data.control[dev_addr].gtd; - gtd_init(p_gtd, buffer, total_bytes); - p_gtd->index = p_ed-ohci_data.ed_pool; + gtd_init(gtd, buffer, buflen); - if ( int_on_complete ) p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + gtd->index = dev_addr; + gtd->pid = dir ? OHCI_PID_IN : OHCI_PID_OUT; + gtd->data_toggle = 3; // Both Data and Ack stage start with DATA1 + gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - td_insert_to_ed(p_ed, p_gtd); + ed->td_head.address = (uint32_t) gtd; - return true; -} + OHCI_REG->command_status_bit.control_list_filled = 1; + }else + { + ohci_ed_t * ed = ed_from_addr(dev_addr, ep_addr); + ohci_gtd_t* gtd = gtd_find_free(); -bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes) -{ - return pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes, false); -} + TU_ASSERT(gtd); -bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) -{ - (void) int_on_complete; - TU_ASSERT( pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes, true) ); + gtd_init(gtd, buffer, buflen); + gtd->index = ed-ohci_data.ed_pool; + gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); + td_insert_to_ed(ed, gtd); - if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; + tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); + if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; + } return true; } -- cgit v1.3.1 From 4e98ce914774390adcdbe9e2a299f6d47852cd07 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 31 May 2021 18:15:47 +0700 Subject: use hcd_frame_number() instead of uframe --- src/host/hcd.h | 9 +-------- src/host/usbh.c | 2 ++ src/portable/ehci/ehci.c | 5 ++--- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 5 ++--- 4 files changed, 7 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/host/hcd.h b/src/host/hcd.h index 0a9f00a0c..46209dc45 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -108,15 +108,8 @@ void hcd_int_enable (uint8_t rhport); // Disable USB interrupt void hcd_int_disable(uint8_t rhport); -// Get micro frame number (125 us) -uint32_t hcd_uframe_number(uint8_t rhport); - // Get frame number (1ms) -TU_ATTR_ALWAYS_INLINE static inline -uint32_t hcd_frame_number(uint8_t rhport) -{ - return hcd_uframe_number(rhport) >> 3; -} +uint32_t hcd_frame_number(uint8_t rhport); //--------------------------------------------------------------------+ // Port API diff --git a/src/host/usbh.c b/src/host/usbh.c index e50421b43..ca0653409 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -378,6 +378,8 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) { + TU_LOG2("Open EP Control with Size = %u\r\n", max_packet_size); + tusb_desc_endpoint_t ep0_desc = { .bLength = sizeof(tusb_desc_endpoint_t), diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 1462d0c6a..bcba360bb 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -65,7 +65,6 @@ typedef struct volatile uint32_t uframe_number; }ehci_data_t; - //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -125,10 +124,10 @@ static inline ehci_link_t* list_next (ehci_link_t *p_link_pointer); // HCD API //--------------------------------------------------------------------+ -uint32_t hcd_uframe_number(uint8_t rhport) +uint32_t hcd_frame_number(uint8_t rhport) { (void) rhport; - return ehci_data.uframe_number + ehci_data.regs->frame_index; + return (ehci_data.uframe_number + ehci_data.regs->frame_index) >> 3; } void hcd_port_reset(uint8_t rhport) diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index b8833fbec..864c6253e 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -504,10 +504,9 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet return true; } -uint32_t hcd_uframe_number(uint8_t rhport) +uint32_t hcd_frame_number(uint8_t rhport) { - // Microframe number is (125us) but we are max full speed so return miliseconds * 8 - return usb_hw->sof_rd * 8; + return usb_hw->sof_rd; } bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) -- cgit v1.3.1 From 31077f48d2f54dde8e692179761df17beafa7770 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 31 May 2021 18:16:07 +0700 Subject: correct ohci endpoint address in xfer complete --- src/portable/ohci/ohci.c | 129 +++++++++++++++++++++++++++-------------------- src/portable/ohci/ohci.h | 18 +------ 2 files changed, 76 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index e6bd446ea..459e583cb 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -123,6 +123,23 @@ enum { OHCI_INT_ON_COMPLETE_YES = 0, OHCI_INT_ON_COMPLETE_NO = TU_BIN8(111) }; + +enum { + GTD_DT_TOGGLE_CARRY = 0, + GTD_DT_DATA0 = TU_BIT(1) | 0, + GTD_DT_DATA1 = TU_BIT(1) | 1, +}; + +enum { + PID_SETUP = 0, + PID_OUT, + PID_IN, +}; + +enum { + PID_FROM_TD = 0, +}; + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -185,10 +202,10 @@ bool hcd_init(uint8_t rhport) return true; } -uint32_t hcd_uframe_number(uint8_t rhport) +uint32_t hcd_frame_number(uint8_t rhport) { (void) rhport; - return (ohci_data.frame_number_hi << 16 | OHCI_REG->frame_number) << 3; + return (ohci_data.frame_number_hi << 16) | OHCI_REG->frame_number; } @@ -248,12 +265,12 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) //--------------------------------------------------------------------+ static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_t const * const p_ed) { - return (p_ed->ep_number == 0 ) ? TUSB_XFER_CONTROL : - (p_ed->is_iso ) ? TUSB_XFER_ISOCHRONOUS : - (p_ed->is_interrupt_xfer ) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK; + return (p_ed->ep_number == 0 ) ? TUSB_XFER_CONTROL : + (p_ed->is_iso ) ? TUSB_XFER_ISOCHRONOUS : + (p_ed->is_interrupt_xfer) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK; } -static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type, uint8_t interval) +static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t ep_addr, uint8_t xfer_type, uint8_t interval) { (void) interval; @@ -263,18 +280,18 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t max_packet_size, tu_memclr(p_ed, sizeof(ohci_ed_t)); } - p_ed->dev_addr = dev_addr; - p_ed->ep_number = endpoint_addr & 0x0F; - p_ed->pid = (xfer_type == TUSB_XFER_CONTROL) ? OHCI_PID_SETUP : ( (endpoint_addr & TUSB_DIR_IN_MASK) ? OHCI_PID_IN : OHCI_PID_OUT ); + p_ed->dev_addr = dev_addr; + p_ed->ep_number = ep_addr & 0x0F; + p_ed->pid = (xfer_type == TUSB_XFER_CONTROL) ? PID_FROM_TD : (tu_edpt_dir(ep_addr) ? PID_IN : PID_OUT); p_ed->speed = _usbh_devices[dev_addr].speed; p_ed->is_iso = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; - p_ed->max_packet_size = max_packet_size; + p_ed->max_packet_size = ep_size; p_ed->used = 1; p_ed->is_interrupt_xfer = (xfer_type == TUSB_XFER_INTERRUPT ? 1 : 0); } -static void gtd_init(ohci_gtd_t* p_td, void* data_ptr, uint16_t total_bytes) +static void gtd_init(ohci_gtd_t* p_td, uint8_t* data_ptr, uint16_t total_bytes) { tu_memclr(p_td, sizeof(ohci_gtd_t)); @@ -286,28 +303,7 @@ static void gtd_init(ohci_gtd_t* p_td, void* data_ptr, uint16_t total_bytes) p_td->condition_code = OHCI_CCODE_NOT_ACCESSED; p_td->current_buffer_pointer = data_ptr; - p_td->buffer_end = total_bytes ? (((uint8_t*) data_ptr) + total_bytes-1) : NULL; -} - -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) -{ - (void) rhport; - - ohci_ed_t* p_ed = &ohci_data.control[dev_addr].ed; - ohci_gtd_t *p_setup = &ohci_data.control[dev_addr].gtd; - - gtd_init(p_setup, (void*) setup_packet, 8); - p_setup->index = dev_addr; - p_setup->pid = OHCI_PID_SETUP; - p_setup->data_toggle = TU_BIN8(10); // DATA0 - p_setup->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - - //------------- Attach TDs list to Control Endpoint -------------// - p_ed->td_head.address = (uint32_t) p_setup; - - OHCI_REG->command_status_bit.control_list_filled = 1; - - return true; + p_td->buffer_end = total_bytes ? (data_ptr + total_bytes-1) : data_ptr; } static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) @@ -319,7 +315,7 @@ static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) for(uint32_t i=0; iindex = dev_addr; + qtd->pid = PID_SETUP; + qtd->data_toggle = GTD_DT_DATA0; + qtd->delay_interrupt = 0; + + //------------- Attach TDs list to Control Endpoint -------------// + ed->td_head.address = (uint32_t) qtd; + + OHCI_REG->command_status_bit.control_list_filled = 1; + + return true; +} + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { (void) rhport; @@ -437,7 +454,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - // FIXME control only for now if ( epnum == 0 ) { ohci_ed_t* ed = &ohci_data.control[dev_addr].ed; @@ -446,9 +462,9 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * gtd_init(gtd, buffer, buflen); gtd->index = dev_addr; - gtd->pid = dir ? OHCI_PID_IN : OHCI_PID_OUT; - gtd->data_toggle = 3; // Both Data and Ack stage start with DATA1 - gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + gtd->pid = dir ? PID_IN : PID_OUT; + gtd->data_toggle = GTD_DT_DATA1; // Both Data and Ack stage start with DATA1 + gtd->delay_interrupt = 0; ed->td_head.address = (uint32_t) gtd; @@ -462,7 +478,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * gtd_init(gtd, buffer, buflen); gtd->index = ed-ohci_data.ed_pool; - gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + gtd->delay_interrupt = 0; td_insert_to_ed(ed, gtd); @@ -539,7 +555,12 @@ static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) } static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) -{ // 5.2.9 OHCI sample code +{ + // 5.2.9 OHCI sample code + + // CBP is 0 mean all data is transferred + if (current_buffer == 0) return 0; + return (tu_align4k(buffer_end ^ current_buffer) ? 0x1000 : 0) + tu_offset4k(buffer_end) - tu_offset4k(current_buffer) + 1; } @@ -555,16 +576,16 @@ static void done_queue_isr(uint8_t hostid) { // TODO check if td_head is iso td //------------- Non ISO transfer -------------// - ohci_gtd_t * const p_qtd = (ohci_gtd_t *) td_head; - xfer_result_t const event = (p_qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS : - (p_qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED; + ohci_gtd_t * const qtd = (ohci_gtd_t *) td_head; + xfer_result_t const event = (qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS : + (qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED; - p_qtd->used = 0; // free TD - if ( (p_qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) ) + qtd->used = 0; // free TD + if ( (qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) ) { - ohci_ed_t * const p_ed = gtd_get_ed(p_qtd); + ohci_ed_t * const ed = gtd_get_ed(qtd); - uint32_t const xferred_bytes = p_qtd->expected_bytes - gtd_xfer_byte_left((uint32_t) p_qtd->buffer_end, (uint32_t) p_qtd->current_buffer_pointer); + uint32_t const xferred_bytes = qtd->expected_bytes - gtd_xfer_byte_left((uint32_t) qtd->buffer_end, (uint32_t) qtd->current_buffer_pointer); // NOTE Assuming the current list is BULK and there is no other EDs in the list has queued TDs. // When there is a error resulting this ED is halted, and this EP still has other queued TD @@ -575,14 +596,14 @@ static void done_queue_isr(uint8_t hostid) // the TailP must be set back to NULL for processing remaining TDs if ((event != XFER_RESULT_SUCCESS)) { - p_ed->td_tail &= 0x0Ful; - p_ed->td_tail |= tu_align16(p_ed->td_head.address); // mark halted EP as empty queue - if ( event == XFER_RESULT_STALLED ) p_ed->is_stalled = 1; + ed->td_tail &= 0x0Ful; + ed->td_tail |= tu_align16(ed->td_head.address); // mark halted EP as empty queue + if ( event == XFER_RESULT_STALLED ) ed->is_stalled = 1; } - hcd_event_xfer_complete(p_ed->dev_addr, - tu_edpt_addr(p_ed->ep_number, p_ed->pid == OHCI_PID_IN), - xferred_bytes, event, true); + uint8_t dir = (ed->ep_number == 0) ? (qtd->pid == PID_IN) : (ed->pid == PID_IN); + + hcd_event_xfer_complete(ed->dev_addr, tu_edpt_addr(ed->ep_number, dir), xferred_bytes, event, true); } td_head = (ohci_td_item_t*) td_head->next; @@ -631,7 +652,7 @@ void hcd_int_handler(uint8_t hostid) } //------------- Transfer Complete -------------// - if ( int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK) + if (int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK) { done_queue_isr(hostid); } diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h index 7f9e55b21..6a634592a 100644 --- a/src/portable/ohci/ohci.h +++ b/src/portable/ohci/ohci.h @@ -24,12 +24,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup Group_HCD - * @{ - * \defgroup OHCI - * \brief OHCI driver. All documents sources mentioned here (eg section 3.5) is referring to OHCI Specs unless state otherwise - * @{ */ - #ifndef _TUSB_OHCI_H_ #define _TUSB_OHCI_H_ @@ -48,12 +42,6 @@ enum { OHCI_MAX_ITD = 4 }; -enum { - OHCI_PID_SETUP = 0, - OHCI_PID_OUT, - OHCI_PID_IN, -}; - //--------------------------------------------------------------------+ // OHCI Data Structure //--------------------------------------------------------------------+ @@ -73,7 +61,6 @@ typedef struct { uint32_t reserved2; }ohci_td_item_t; - typedef struct TU_ATTR_ALIGNED(16) { // Word 0 @@ -105,7 +92,7 @@ typedef struct TU_ATTR_ALIGNED(16) // Word 0 uint32_t dev_addr : 7; uint32_t ep_number : 4; - uint32_t pid : 2; // 00b from TD, 01b Out, 10b In + uint32_t pid : 2; uint32_t speed : 1; uint32_t skip : 1; uint32_t is_iso : 1; @@ -286,6 +273,3 @@ TU_VERIFY_STATIC( sizeof(ohci_registers_t) == 0x5c, "size is not correct"); #endif #endif /* _TUSB_OHCI_H_ */ - -/** @} */ -/** @} */ -- cgit v1.3.1 From bc0a0386e9aba4c3eccf9806a8ed7aecdefe23d6 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 31 May 2021 18:41:08 +0700 Subject: clean up --- src/portable/ohci/ohci.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index 459e583cb..dbd2cc793 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -84,23 +84,23 @@ enum { }; enum { - OHCI_RHPORT_CURRENT_CONNECT_STATUS_MASK = TU_BIT(0), - OHCI_RHPORT_PORT_ENABLE_STATUS_MASK = TU_BIT(1), - OHCI_RHPORT_PORT_SUSPEND_STATUS_MASK = TU_BIT(2), - OHCI_RHPORT_PORT_OVER_CURRENT_INDICATOR_MASK = TU_BIT(3), - OHCI_RHPORT_PORT_RESET_STATUS_MASK = TU_BIT(4), ///< write '1' to reset port - - OHCI_RHPORT_PORT_POWER_STATUS_MASK = TU_BIT(8), - OHCI_RHPORT_LOW_SPEED_DEVICE_ATTACHED_MASK = TU_BIT(9), - - OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK = TU_BIT(16), - OHCI_RHPORT_PORT_ENABLE_CHANGE_MASK = TU_BIT(17), - OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK = TU_BIT(18), - OHCI_RHPORT_OVER_CURRENT_CHANGE_MASK = TU_BIT(19), - OHCI_RHPORT_PORT_RESET_CHANGE_MASK = TU_BIT(20), - - OHCI_RHPORT_ALL_CHANGE_MASK = OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK | OHCI_RHPORT_PORT_ENABLE_CHANGE_MASK | - OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK | OHCI_RHPORT_OVER_CURRENT_CHANGE_MASK | OHCI_RHPORT_PORT_RESET_CHANGE_MASK + RHPORT_CURRENT_CONNECT_STATUS_MASK = TU_BIT(0), + RHPORT_PORT_ENABLE_STATUS_MASK = TU_BIT(1), + RHPORT_PORT_SUSPEND_STATUS_MASK = TU_BIT(2), + RHPORT_PORT_OVER_CURRENT_INDICATOR_MASK = TU_BIT(3), + RHPORT_PORT_RESET_STATUS_MASK = TU_BIT(4), ///< write '1' to reset port + + RHPORT_PORT_POWER_STATUS_MASK = TU_BIT(8), + RHPORT_LOW_SPEED_DEVICE_ATTACHED_MASK = TU_BIT(9), + + RHPORT_CONNECT_STATUS_CHANGE_MASK = TU_BIT(16), + RHPORT_PORT_ENABLE_CHANGE_MASK = TU_BIT(17), + RHPORT_PORT_SUSPEND_CHANGE_MASK = TU_BIT(18), + RHPORT_OVER_CURRENT_CHANGE_MASK = TU_BIT(19), + RHPORT_PORT_RESET_CHANGE_MASK = TU_BIT(20), + + RHPORT_ALL_CHANGE_MASK = RHPORT_CONNECT_STATUS_CHANGE_MASK | RHPORT_PORT_ENABLE_CHANGE_MASK | + RHPORT_PORT_SUSPEND_CHANGE_MASK | RHPORT_OVER_CURRENT_CHANGE_MASK | RHPORT_PORT_RESET_CHANGE_MASK }; enum { @@ -215,7 +215,7 @@ uint32_t hcd_frame_number(uint8_t rhport) void hcd_port_reset(uint8_t hostid) { (void) hostid; - OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK; + OHCI_REG->rhport_status[0] = RHPORT_PORT_RESET_STATUS_MASK; } bool hcd_port_connect_status(uint8_t hostid) @@ -626,16 +626,16 @@ void hcd_int_handler(uint8_t hostid) //------------- RootHub status -------------// if ( int_status & OHCI_INT_RHPORT_STATUS_CHANGE_MASK ) { - uint32_t const rhport_status = OHCI_REG->rhport_status[0] & OHCI_RHPORT_ALL_CHANGE_MASK; + uint32_t const rhport_status = OHCI_REG->rhport_status[0] & RHPORT_ALL_CHANGE_MASK; // TODO dual port is not yet supported - if ( rhport_status & OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK ) + if ( rhport_status & RHPORT_CONNECT_STATUS_CHANGE_MASK ) { // TODO check if remote wake-up if ( OHCI_REG->rhport_status_bit[0].current_connect_status ) { // TODO reset port immediately, without this controller will got 2-3 (debouncing connection status change) - OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK; + OHCI_REG->rhport_status[0] = RHPORT_PORT_RESET_STATUS_MASK; hcd_event_device_attach(hostid, true); }else { @@ -643,7 +643,7 @@ void hcd_int_handler(uint8_t hostid) } } - if ( rhport_status & OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK) + if ( rhport_status & RHPORT_PORT_SUSPEND_CHANGE_MASK) { } -- cgit v1.3.1 From 6e2cf2a3eec141e2714937532320c9fc46b95f9b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Jun 2021 00:10:35 +0700 Subject: clean up log --- src/class/hid/hid_device.c | 2 +- src/class/msc/msc_device.c | 2 +- src/class/vendor/vendor_device.c | 2 +- src/common/tusb_common.h | 4 ---- 4 files changed, 3 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index c7f5d04ec..151a36225 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -225,7 +225,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1 { if ( !usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)) ) { - TU_LOG1_FAILED(); + TU_LOG_FAILED(); TU_BREAKPOINT(); } } diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 9b06b7a33..7f13b4891 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -172,7 +172,7 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 // Prepare for Command Block Wrapper if ( !usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) ) { - TU_LOG1_FAILED(); + TU_LOG_FAILED(); TU_BREAKPOINT(); } diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 081aac9f6..6718a97bf 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -195,7 +195,7 @@ uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui // Prepare for incoming data if ( !usbd_edpt_xfer(rhport, p_vendor->ep_out, p_vendor->epout_buf, sizeof(p_vendor->epout_buf)) ) { - TU_LOG1_FAILED(); + TU_LOG_FAILED(); TU_BREAKPOINT(); } diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 6f2905697..d9b388916 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -372,8 +372,6 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #define TU_LOG1_VAR(...) #define TU_LOG1_INT(...) #define TU_LOG1_HEX(...) - #define TU_LOG1_LOCATION() - #define TU_LOG1_FAILED() #endif #ifndef TU_LOG2 @@ -382,7 +380,6 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #define TU_LOG2_VAR(...) #define TU_LOG2_INT(...) #define TU_LOG2_HEX(...) - #define TU_LOG2_LOCATION() #endif #ifndef TU_LOG3 @@ -391,7 +388,6 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #define TU_LOG3_VAR(...) #define TU_LOG3_INT(...) #define TU_LOG3_HEX(...) - #define TU_LOG3_LOCATION() #endif #ifdef __cplusplus -- cgit v1.3.1 From 54107100bbc32756324070a6a06146b958f653d6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Jun 2021 00:26:50 +0700 Subject: fix missing TU_LOG symbol --- src/common/tusb_common.h | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index d9b388916..3350ed86c 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -24,10 +24,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup Group_Common - * \defgroup Group_CommonH common.h - * @{ */ - #ifndef _TUSB_COMMON_H_ #define _TUSB_COMMON_H_ @@ -288,8 +284,9 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16 (void* mem, ui // CFG_TUSB_DEBUG for debugging // 0 : no debug -// 1 : print when there is error -// 2 : print out log +// 1 : print error +// 2 : print warning +// 3 : print info #if CFG_TUSB_DEBUG void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); @@ -316,7 +313,6 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize) #define TU_LOG_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__) #define TU_LOG_FAILED() tu_printf("%s: %d: Failed\r\n", __PRETTY_FUNCTION__, __LINE__) - // Log Level 1: Error #define TU_LOG1 tu_printf #define TU_LOG1_MEM tu_print_mem @@ -366,6 +362,17 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #endif // CFG_TUSB_DEBUG +#ifndef TU_LOG +#define TU_LOG(n, ...) +#define TU_LOG_MEM(n, ...) +#define TU_LOG_VAR(n, ...) +#define TU_LOG_INT(n, ...) +#define TU_LOG_HEX(n, ...) +#define TU_LOG_LOCATION() +#define TU_LOG_FAILED() +#endif + +// TODO replace all TU_LOGn with TU_LOG(n) #ifndef TU_LOG1 #define TU_LOG1(...) #define TU_LOG1_MEM(...) @@ -395,5 +402,3 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #endif #endif /* _TUSB_COMMON_H_ */ - -/** @} */ -- cgit v1.3.1 From a50fd963f530278585418708c6032277c6307643 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Jun 2021 01:13:22 +0700 Subject: increase version for release, update changelog --- docs/changelog.md | 12 ++++++++++++ src/tusb_option.h | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/docs/changelog.md b/docs/changelog.md index 323b6b6e2..3725c5a81 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,17 @@ # TinyUSB Changelog +## 0.10.1 - 2021.06.03 + +- rework rp2040 examples and CMake build, allow better integration with pico-sdk + +### Host Controller Driver (HCD) + +- Fix rp2040 host driver: incorrect PID with low speed device with max packet size of 8 bytes +- Improve hub driver +- Remove obsolete hcd_pipe_queue_xfer()/hcd_pipe_xfer() +- Use hcd_frame_number() instead of micro frame +- Fix OHCI endpoint address and xferred_bytes in xfer complete event + ## 0.10.0 - 2021.05.28 - Rework tu_fifo_t with separated mutex for read and write, better support DMA with read/write buffer info. And constant address mode diff --git a/src/tusb_option.h b/src/tusb_option.h index f8456ca4c..cdaf074db 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -29,7 +29,7 @@ #define TUSB_VERSION_MAJOR 0 #define TUSB_VERSION_MINOR 10 -#define TUSB_VERSION_REVISION 0 +#define TUSB_VERSION_REVISION 1 #define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION) /** \defgroup group_mcu Supported MCU -- cgit v1.3.1 From e26cf6b26ca0d7c54f71332896d4bed9c418844a Mon Sep 17 00:00:00 2001 From: Wini-Buh Date: Wed, 2 Jun 2021 21:33:32 +0200 Subject: Missing RX device dependency corrected --- src/portable/renesas/usba/dcd_usba.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 54410ff0b..0e7881383 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -566,9 +566,9 @@ void dcd_init(uint8_t rhport) USB0.SYSCFG.BIT.DCFM = 0; USB0.SYSCFG.BIT.USBE = 1; - USB0.PHYSLEW.LONG = 0x5; USB.DPUSR0R.BIT.FIXPHY0 = 0u; /* USB0 Transceiver Output fixed */ #if ( CFG_TUSB_MCU == OPT_MCU_RX72N ) + USB0.PHYSLEW.LONG = 0x5; IR(PERIB, INTB185) = 0; #else IR(USB0, USBI0) = 0; -- cgit v1.3.1 From c81bc38d422f419cd8949019fd5f2eadc9ec2333 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Thu, 3 Jun 2021 10:10:44 -0500 Subject: Add __unused to variables that are only used if TU_LOG does something --- src/portable/raspberrypi/rp2040/rp2040_usb.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 32d20051f..33f3ecd41 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -134,11 +134,11 @@ typedef union TU_ATTR_PACKED TU_VERIFY_STATIC(sizeof(rp2040_buffer_control_t) == 2, "size is not correct"); -static inline void print_bufctrl16(uint32_t u16) +static inline void print_bufctrl16(uint32_t __unused u16) { - rp2040_buffer_control_t bufctrl; - - bufctrl.u16 = u16; + rp2040_buffer_control_t __unused bufctrl = { + .u16 = u16 + }; TU_LOG(2, "len = %u, available = %u, stall = %u, reset = %u, toggle = %u, last = %u, full = %u\r\n", bufctrl.xfer_len, bufctrl.available, bufctrl.stall, bufctrl.reset_bufsel, bufctrl.data_toggle, bufctrl.last_buf, bufctrl.full); -- cgit v1.3.1 From 26b9fc38ed5a525428d81e4ebfc05bfc366083e8 Mon Sep 17 00:00:00 2001 From: zhangslice <54609269+zhangslice@users.noreply.github.com> Date: Mon, 7 Jun 2021 18:32:46 +0800 Subject: Add MM32 SDK and USB driver (#869) * Add MM32 SDK and USB driver * add mindmotion mm32sdk as submodule remove the local copy of mm32 * mit license Signed-off-by: zhangslice <1304224508@qq.com> Co-authored-by: hathach --- .gitmodules | 3 + hw/mcu/mindmotion/mm32sdk | 1 + src/portable/mm32/dcd_mm32f327x_otg.c | 471 ++++++++++++++++++++++++++++++++++ 3 files changed, 475 insertions(+) create mode 160000 hw/mcu/mindmotion/mm32sdk create mode 100644 src/portable/mm32/dcd_mm32f327x_otg.c (limited to 'src') diff --git a/.gitmodules b/.gitmodules index 79ef8e0ad..c0e6f8f91 100644 --- a/.gitmodules +++ b/.gitmodules @@ -121,3 +121,6 @@ [submodule "hw/mcu/nxp/nxp_sdk"] path = hw/mcu/nxp/nxp_sdk url = https://github.com/hathach/nxp_sdk.git +[submodule "hw/mcu/mindmotion/mm32sdk"] + path = hw/mcu/mindmotion/mm32sdk + url = https://github.com/zhangslice/mm32sdk.git diff --git a/hw/mcu/mindmotion/mm32sdk b/hw/mcu/mindmotion/mm32sdk new file mode 160000 index 000000000..b6b99de3a --- /dev/null +++ b/hw/mcu/mindmotion/mm32sdk @@ -0,0 +1 @@ +Subproject commit b6b99de3ab26218784ec158488bdd91377288f94 diff --git a/src/portable/mm32/dcd_mm32f327x_otg.c b/src/portable/mm32/dcd_mm32f327x_otg.c new file mode 100644 index 000000000..e7518830e --- /dev/null +++ b/src/portable/mm32/dcd_mm32f327x_otg.c @@ -0,0 +1,471 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 SE TEAM + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" +#include "reg_usb_otg_fs.h" +#include "mm32_device.h" +#include "hal_conf.h" + +#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MM32F327X ) + +#include "device/dcd.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +enum { + TOK_PID_OUT = 0x1u, + TOK_PID_IN = 0x9u, + TOK_PID_SETUP = 0xDu, +}; + +typedef struct TU_ATTR_PACKED +{ + union { + uint32_t head; + struct { + union { + struct { + uint16_t : 2; + uint16_t tok_pid : 4; + uint16_t data : 1; + uint16_t own : 1; + uint16_t : 8; + }; + struct { + uint16_t : 2; + uint16_t bdt_stall: 1; + uint16_t dts : 1; + uint16_t ninc : 1; + uint16_t keep : 1; + uint16_t : 10; + }; + }; + uint16_t bc : 10; + uint16_t : 6; + }; + }; + uint8_t *addr; +}buffer_descriptor_t; + +TU_VERIFY_STATIC( sizeof(buffer_descriptor_t) == 8, "size is not correct" ); + +typedef struct TU_ATTR_PACKED +{ + union { + uint32_t state; + struct { + uint32_t max_packet_size :11; + uint32_t : 5; + uint32_t odd : 1; + uint32_t :15; + }; + }; + uint16_t length; + uint16_t remaining; +}endpoint_state_t; + +TU_VERIFY_STATIC( sizeof(endpoint_state_t) == 8, "size is not correct" ); + +typedef struct +{ + union { + /* [#EP][OUT,IN][EVEN,ODD] */ + buffer_descriptor_t bdt[16][2][2]; + uint16_t bda[512]; + }; + TU_ATTR_ALIGNED(4) union { + endpoint_state_t endpoint[16][2]; + endpoint_state_t endpoint_unified[16 * 2]; + }; + uint8_t setup_packet[8]; + uint8_t addr; +}dcd_data_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +// BDT(Buffer Descriptor Table) must be 256-byte aligned +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(512) static dcd_data_t _dcd; + +TU_VERIFY_STATIC( sizeof(_dcd.bdt) == 512, "size is not correct" ); + +static void prepare_next_setup_packet(uint8_t rhport) +{ + const unsigned out_odd = _dcd.endpoint[0][0].odd; + const unsigned in_odd = _dcd.endpoint[0][1].odd; + if (_dcd.bdt[0][0][out_odd].own) { + TU_LOG1("DCD fail to prepare the next SETUP %d %d\r\n", out_odd, in_odd); + return; + } + _dcd.bdt[0][0][out_odd].data = 0; + _dcd.bdt[0][0][out_odd ^ 1].data = 1; + _dcd.bdt[0][1][in_odd].data = 1; + _dcd.bdt[0][1][in_odd ^ 1].data = 0; + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), + _dcd.setup_packet, sizeof(_dcd.setup_packet)); +} + +static void process_stall(uint8_t rhport) +{ + if (USB_OTG_FS->EP_CTL[0] & USB_ENDPT_EPSTALL_MASK) { + /* clear stall condition of the control pipe */ + prepare_next_setup_packet(rhport); + USB_OTG_FS->EP_CTL[0] &= ~USB_ENDPT_EPSTALL_MASK; + } +} + +static void process_tokdne(uint8_t rhport) +{ + const unsigned s = USB_OTG_FS->STAT; + USB_OTG_FS->INT_STAT = USB_ISTAT_TOKDNE_MASK; /* fetch the next token if received */ + buffer_descriptor_t *bd = (buffer_descriptor_t *)&_dcd.bda[s]; + endpoint_state_t *ep = &_dcd.endpoint_unified[s >> 3]; + unsigned odd = (s & USB_STAT_ODD_MASK) ? 1 : 0; + + /* fetch pid before discarded by the next steps */ + const unsigned pid = bd->tok_pid; + /* reset values for a next transfer */ + bd->bdt_stall = 0; + bd->dts = 1; + bd->ninc = 0; + bd->keep = 0; + /* update the odd variable to prepare for the next transfer */ + ep->odd = odd ^ 1; + if (pid == TOK_PID_SETUP) { + dcd_event_setup_received(rhport, bd->addr, true); + USB_OTG_FS->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; + return; + } + if (s >> 4) { + TU_LOG1("TKDNE %x\r\n", s); + } + + const unsigned bc = bd->bc; + const unsigned remaining = ep->remaining - bc; + if (remaining && bc == ep->max_packet_size) { + /* continue the transferring consecutive data */ + ep->remaining = remaining; + const int next_remaining = remaining - ep->max_packet_size; + if (next_remaining > 0) { + /* prepare to the after next transfer */ + bd->addr += ep->max_packet_size * 2; + bd->bc = next_remaining > ep->max_packet_size ? ep->max_packet_size: next_remaining; + __DSB(); + bd->own = 1; /* the own bit must set after addr */ + } + return; + } + const unsigned length = ep->length; + dcd_event_xfer_complete(rhport, + ((s & USB_STAT_TX_MASK) << 4) | (s >> USB_STAT_ENDP_SHIFT), + length - remaining, XFER_RESULT_SUCCESS, true); + if (0 == (s & USB_STAT_ENDP_MASK) && 0 == length) { + /* After completion a ZLP of control transfer, + * it prepares for the next steup transfer. */ + if (_dcd.addr) { + /* When the transfer was the SetAddress, + * the device address should be updated here. */ + USB_OTG_FS->ADDR = _dcd.addr; + _dcd.addr = 0; + } + prepare_next_setup_packet(rhport); + } +} + +static void process_bus_reset(uint8_t rhport) +{ + USB_OTG_FS->CTL |= USB_CTL_ODDRST_MASK; + USB_OTG_FS->ADDR = 0; + USB_OTG_FS->INT_ENB = (USB_OTG_FS->INT_ENB & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; + + USB_OTG_FS->EP_CTL[0] = USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPRXEN_MASK | USB_ENDPT_EPTXEN_MASK; + for (unsigned i = 1; i < 16; ++i) { + USB_OTG_FS->EP_CTL[i] = 0; + } + buffer_descriptor_t *bd = _dcd.bdt[0][0]; + for (unsigned i = 0; i < sizeof(_dcd.bdt)/sizeof(*bd); ++i, ++bd) { + bd->head = 0; + } + const endpoint_state_t ep0 = { + .max_packet_size = CFG_TUD_ENDPOINT0_SIZE, + .odd = 0, + .length = 0, + .remaining = 0, + }; + _dcd.endpoint[0][0] = ep0; + _dcd.endpoint[0][1] = ep0; + tu_memclr(_dcd.endpoint[1], sizeof(_dcd.endpoint) - sizeof(_dcd.endpoint[0])); + _dcd.addr = 0; + prepare_next_setup_packet(rhport); + USB_OTG_FS->CTL &= ~USB_CTL_ODDRST_MASK; + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); +} + +static void process_bus_inactive(uint8_t rhport) +{ + (void) rhport; + const unsigned inten = USB_OTG_FS->INT_ENB; + USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_SLEEPEN_MASK) | USB_INTEN_RESUMEEN_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); +} + +static void process_bus_active(uint8_t rhport) +{ + (void) rhport; + const unsigned inten = USB_OTG_FS->INT_ENB; + USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); +} + +/*------------------------------------------------------------------*/ +/* Device API + *------------------------------------------------------------------*/ +void dcd_init(uint8_t rhport) +{ + (void) rhport; + + tu_memclr(&_dcd, sizeof(_dcd)); + USB_OTG_FS->BDT_PAGE_01 = (uint8_t)((uintptr_t)_dcd.bdt >> 8); + USB_OTG_FS->BDT_PAGE_02 = (uint8_t)((uintptr_t)_dcd.bdt >> 16); + USB_OTG_FS->BDT_PAGE_03 = (uint8_t)((uintptr_t)_dcd.bdt >> 24); + + dcd_connect(rhport); + NVIC_ClearPendingIRQ(USB_FS_IRQn); +} +#define USB_DEVICE_INTERRUPT_PRIORITY (3U) +void dcd_int_enable(uint8_t rhport) +{ + uint8_t irqNumber; + irqNumber = USB_FS_IRQn; + (void) rhport; + USB_OTG_FS->INT_ENB = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK | + USB_INTEN_SLEEPEN_MASK | USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK; + NVIC_SetPriority((IRQn_Type)irqNumber, USB_DEVICE_INTERRUPT_PRIORITY); + NVIC_EnableIRQ(USB_FS_IRQn); +} + +void dcd_int_disable(uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ(USB_FS_IRQn); + USB_OTG_FS->INT_ENB = 0; +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void) rhport; + _dcd.addr = dev_addr & 0x7F; + /* Response with status first before changing device address */ + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} +extern u32 SystemCoreClock ; +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; + unsigned cnt = SystemCoreClock / 100; + USB_OTG_FS->CTL |= USB_CTL_RESUME_MASK; + while (cnt--) __NOP(); + USB_OTG_FS->CTL &= ~USB_CTL_RESUME_MASK; +} + +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + USB_OTG_FS->CTL |= USB_CTL_USBENSOFEN_MASK; +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + USB_OTG_FS->CTL = 0; +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) +{ + (void) rhport; + + const unsigned ep_addr = ep_desc->bEndpointAddress; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned xfer = ep_desc->bmAttributes.xfer; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + const unsigned odd = ep->odd; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; + + /* No support for control transfer */ + TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL)); + + ep->max_packet_size = ep_desc->wMaxPacketSize.size; + unsigned val = USB_ENDPT_EPCTLDIS_MASK; + val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0; + val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; + USB_OTG_FS->EP_CTL[epn] |= val; + + if (xfer != TUSB_XFER_ISOCHRONOUS) { + bd[odd].dts = 1; + bd[odd].data = 0; + bd[odd ^ 1].dts = 1; + bd[odd ^ 1].data = 1; + } + + return true; +} + +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; + const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; + USB_OTG_FS->EP_CTL[epn] &= ~msk; + ep->max_packet_size = 0; + ep->length = 0; + ep->remaining = 0; + bd->head = 0; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +{ + (void) rhport; + NVIC_DisableIRQ(USB_FS_IRQn); + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][ep->odd]; + + if (bd->own) { + TU_LOG1("DCD XFER fail %x %d %lx %lx\r\n", ep_addr, total_bytes, ep->state, bd->head); + return false; /* The last transfer has not completed */ + } + ep->length = total_bytes; + ep->remaining = total_bytes; + + const unsigned mps = ep->max_packet_size; + if (total_bytes > mps) { + buffer_descriptor_t *next = ep->odd ? bd - 1: bd + 1; + /* When total_bytes is greater than the max packet size, + * it prepares to the next transfer to avoid NAK in advance. */ + next->bc = total_bytes >= 2 * mps ? mps: total_bytes - mps; + next->addr = buffer + mps; + next->own = 1; + } + bd->bc = total_bytes >= mps ? mps: total_bytes; + bd->addr = buffer; + __DSB(); + bd->own = 1; /* the own bit must set after addr */ + NVIC_EnableIRQ(USB_FS_IRQn); + return true; +} + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + const unsigned epn = ep_addr & 0xFu; + if (0 == epn) { + USB_OTG_FS->EP_CTL[epn] |= USB_ENDPT_EPSTALL_MASK; + } else { + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; + bd[0].bdt_stall = 1; + bd[1].bdt_stall = 1; + } +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned odd = _dcd.endpoint[epn][dir].odd; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; + + bd[odd ^ 1].own = 0; + bd[odd ^ 1].data = 1; + bd[odd ^ 1].bdt_stall = 0; + bd[odd].own = 0; + bd[odd].data = 0; + bd[odd].bdt_stall = 0; +} + +//--------------------------------------------------------------------+ +// ISR +//--------------------------------------------------------------------+ +void dcd_int_handler(uint8_t rhport) +{ + (void) rhport; + + uint32_t is = USB_OTG_FS->INT_STAT; + uint32_t msk = USB_OTG_FS->INT_ENB; + USB_OTG_FS->INT_STAT = is & ~msk; + is &= msk; + if (is & USB_ISTAT_ERROR_MASK) { + /* TODO: */ + uint32_t es = USB_OTG_FS->ERR_STAT; + USB_OTG_FS->ERR_STAT = es; + USB_OTG_FS->INT_STAT = is; /* discard any pending events */ + return; + } + + if (is & USB_ISTAT_USBRST_MASK) { + USB_OTG_FS->INT_STAT = is; /* discard any pending events */ + process_bus_reset(rhport); + return; + } + if (is & USB_ISTAT_SLEEP_MASK) { + USB_OTG_FS->INT_STAT = USB_ISTAT_SLEEP_MASK; + process_bus_inactive(rhport); + return; + } + if (is & USB_ISTAT_RESUME_MASK) { + USB_OTG_FS->INT_STAT = USB_ISTAT_RESUME_MASK; + process_bus_active(rhport); + return; + } + if (is & USB_ISTAT_SOFTOK_MASK) { + USB_OTG_FS->INT_STAT = USB_ISTAT_SOFTOK_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); + return; + } + if (is & USB_ISTAT_STALL_MASK) { + USB_OTG_FS->INT_STAT = USB_ISTAT_STALL_MASK; + process_stall(rhport); + return; + } + if (is & USB_ISTAT_TOKDNE_MASK) { + process_tokdne(rhport); + return; + } +} + +#endif -- cgit v1.3.1 From c2b85c8d6d7fb0cc202e4f1dd0f5e8b359c27396 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 7 Jun 2021 18:51:44 +0700 Subject: add OPT_MCU_MM32F327X move dcd_mm32f into mindmotion folder --- src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c | 471 +++++++++++++++++++++++ src/portable/mm32/dcd_mm32f327x_otg.c | 471 ----------------------- src/tusb_option.h | 3 + 3 files changed, 474 insertions(+), 471 deletions(-) create mode 100644 src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c delete mode 100644 src/portable/mm32/dcd_mm32f327x_otg.c (limited to 'src') diff --git a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c new file mode 100644 index 000000000..59a40dc68 --- /dev/null +++ b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c @@ -0,0 +1,471 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 SE TEAM + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MM32F327X ) + +#include "reg_usb_otg_fs.h" +#include "mm32_device.h" +#include "hal_conf.h" +#include "device/dcd.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +enum { + TOK_PID_OUT = 0x1u, + TOK_PID_IN = 0x9u, + TOK_PID_SETUP = 0xDu, +}; + +typedef struct TU_ATTR_PACKED +{ + union { + uint32_t head; + struct { + union { + struct { + uint16_t : 2; + uint16_t tok_pid : 4; + uint16_t data : 1; + uint16_t own : 1; + uint16_t : 8; + }; + struct { + uint16_t : 2; + uint16_t bdt_stall: 1; + uint16_t dts : 1; + uint16_t ninc : 1; + uint16_t keep : 1; + uint16_t : 10; + }; + }; + uint16_t bc : 10; + uint16_t : 6; + }; + }; + uint8_t *addr; +}buffer_descriptor_t; + +TU_VERIFY_STATIC( sizeof(buffer_descriptor_t) == 8, "size is not correct" ); + +typedef struct TU_ATTR_PACKED +{ + union { + uint32_t state; + struct { + uint32_t max_packet_size :11; + uint32_t : 5; + uint32_t odd : 1; + uint32_t :15; + }; + }; + uint16_t length; + uint16_t remaining; +}endpoint_state_t; + +TU_VERIFY_STATIC( sizeof(endpoint_state_t) == 8, "size is not correct" ); + +typedef struct +{ + union { + /* [#EP][OUT,IN][EVEN,ODD] */ + buffer_descriptor_t bdt[16][2][2]; + uint16_t bda[512]; + }; + TU_ATTR_ALIGNED(4) union { + endpoint_state_t endpoint[16][2]; + endpoint_state_t endpoint_unified[16 * 2]; + }; + uint8_t setup_packet[8]; + uint8_t addr; +}dcd_data_t; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +// BDT(Buffer Descriptor Table) must be 256-byte aligned +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(512) static dcd_data_t _dcd; + +TU_VERIFY_STATIC( sizeof(_dcd.bdt) == 512, "size is not correct" ); + +static void prepare_next_setup_packet(uint8_t rhport) +{ + const unsigned out_odd = _dcd.endpoint[0][0].odd; + const unsigned in_odd = _dcd.endpoint[0][1].odd; + if (_dcd.bdt[0][0][out_odd].own) { + TU_LOG1("DCD fail to prepare the next SETUP %d %d\r\n", out_odd, in_odd); + return; + } + _dcd.bdt[0][0][out_odd].data = 0; + _dcd.bdt[0][0][out_odd ^ 1].data = 1; + _dcd.bdt[0][1][in_odd].data = 1; + _dcd.bdt[0][1][in_odd ^ 1].data = 0; + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), + _dcd.setup_packet, sizeof(_dcd.setup_packet)); +} + +static void process_stall(uint8_t rhport) +{ + if (USB_OTG_FS->EP_CTL[0] & USB_ENDPT_EPSTALL_MASK) { + /* clear stall condition of the control pipe */ + prepare_next_setup_packet(rhport); + USB_OTG_FS->EP_CTL[0] &= ~USB_ENDPT_EPSTALL_MASK; + } +} + +static void process_tokdne(uint8_t rhport) +{ + const unsigned s = USB_OTG_FS->STAT; + USB_OTG_FS->INT_STAT = USB_ISTAT_TOKDNE_MASK; /* fetch the next token if received */ + buffer_descriptor_t *bd = (buffer_descriptor_t *)&_dcd.bda[s]; + endpoint_state_t *ep = &_dcd.endpoint_unified[s >> 3]; + unsigned odd = (s & USB_STAT_ODD_MASK) ? 1 : 0; + + /* fetch pid before discarded by the next steps */ + const unsigned pid = bd->tok_pid; + /* reset values for a next transfer */ + bd->bdt_stall = 0; + bd->dts = 1; + bd->ninc = 0; + bd->keep = 0; + /* update the odd variable to prepare for the next transfer */ + ep->odd = odd ^ 1; + if (pid == TOK_PID_SETUP) { + dcd_event_setup_received(rhport, bd->addr, true); + USB_OTG_FS->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; + return; + } + if (s >> 4) { + TU_LOG1("TKDNE %x\r\n", s); + } + + const unsigned bc = bd->bc; + const unsigned remaining = ep->remaining - bc; + if (remaining && bc == ep->max_packet_size) { + /* continue the transferring consecutive data */ + ep->remaining = remaining; + const int next_remaining = remaining - ep->max_packet_size; + if (next_remaining > 0) { + /* prepare to the after next transfer */ + bd->addr += ep->max_packet_size * 2; + bd->bc = next_remaining > ep->max_packet_size ? ep->max_packet_size: next_remaining; + __DSB(); + bd->own = 1; /* the own bit must set after addr */ + } + return; + } + const unsigned length = ep->length; + dcd_event_xfer_complete(rhport, + ((s & USB_STAT_TX_MASK) << 4) | (s >> USB_STAT_ENDP_SHIFT), + length - remaining, XFER_RESULT_SUCCESS, true); + if (0 == (s & USB_STAT_ENDP_MASK) && 0 == length) { + /* After completion a ZLP of control transfer, + * it prepares for the next steup transfer. */ + if (_dcd.addr) { + /* When the transfer was the SetAddress, + * the device address should be updated here. */ + USB_OTG_FS->ADDR = _dcd.addr; + _dcd.addr = 0; + } + prepare_next_setup_packet(rhport); + } +} + +static void process_bus_reset(uint8_t rhport) +{ + USB_OTG_FS->CTL |= USB_CTL_ODDRST_MASK; + USB_OTG_FS->ADDR = 0; + USB_OTG_FS->INT_ENB = (USB_OTG_FS->INT_ENB & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; + + USB_OTG_FS->EP_CTL[0] = USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPRXEN_MASK | USB_ENDPT_EPTXEN_MASK; + for (unsigned i = 1; i < 16; ++i) { + USB_OTG_FS->EP_CTL[i] = 0; + } + buffer_descriptor_t *bd = _dcd.bdt[0][0]; + for (unsigned i = 0; i < sizeof(_dcd.bdt)/sizeof(*bd); ++i, ++bd) { + bd->head = 0; + } + const endpoint_state_t ep0 = { + .max_packet_size = CFG_TUD_ENDPOINT0_SIZE, + .odd = 0, + .length = 0, + .remaining = 0, + }; + _dcd.endpoint[0][0] = ep0; + _dcd.endpoint[0][1] = ep0; + tu_memclr(_dcd.endpoint[1], sizeof(_dcd.endpoint) - sizeof(_dcd.endpoint[0])); + _dcd.addr = 0; + prepare_next_setup_packet(rhport); + USB_OTG_FS->CTL &= ~USB_CTL_ODDRST_MASK; + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); +} + +static void process_bus_inactive(uint8_t rhport) +{ + (void) rhport; + const unsigned inten = USB_OTG_FS->INT_ENB; + USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_SLEEPEN_MASK) | USB_INTEN_RESUMEEN_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); +} + +static void process_bus_active(uint8_t rhport) +{ + (void) rhport; + const unsigned inten = USB_OTG_FS->INT_ENB; + USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); +} + +/*------------------------------------------------------------------*/ +/* Device API + *------------------------------------------------------------------*/ +void dcd_init(uint8_t rhport) +{ + (void) rhport; + + tu_memclr(&_dcd, sizeof(_dcd)); + USB_OTG_FS->BDT_PAGE_01 = (uint8_t)((uintptr_t)_dcd.bdt >> 8); + USB_OTG_FS->BDT_PAGE_02 = (uint8_t)((uintptr_t)_dcd.bdt >> 16); + USB_OTG_FS->BDT_PAGE_03 = (uint8_t)((uintptr_t)_dcd.bdt >> 24); + + dcd_connect(rhport); + NVIC_ClearPendingIRQ(USB_FS_IRQn); +} +#define USB_DEVICE_INTERRUPT_PRIORITY (3U) +void dcd_int_enable(uint8_t rhport) +{ + uint8_t irqNumber; + irqNumber = USB_FS_IRQn; + (void) rhport; + USB_OTG_FS->INT_ENB = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK | + USB_INTEN_SLEEPEN_MASK | USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK; + NVIC_SetPriority((IRQn_Type)irqNumber, USB_DEVICE_INTERRUPT_PRIORITY); + NVIC_EnableIRQ(USB_FS_IRQn); +} + +void dcd_int_disable(uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ(USB_FS_IRQn); + USB_OTG_FS->INT_ENB = 0; +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void) rhport; + _dcd.addr = dev_addr & 0x7F; + /* Response with status first before changing device address */ + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} +extern u32 SystemCoreClock ; +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; + unsigned cnt = SystemCoreClock / 100; + USB_OTG_FS->CTL |= USB_CTL_RESUME_MASK; + while (cnt--) __NOP(); + USB_OTG_FS->CTL &= ~USB_CTL_RESUME_MASK; +} + +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + USB_OTG_FS->CTL |= USB_CTL_USBENSOFEN_MASK; +} + +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + USB_OTG_FS->CTL = 0; +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) +{ + (void) rhport; + + const unsigned ep_addr = ep_desc->bEndpointAddress; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned xfer = ep_desc->bmAttributes.xfer; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + const unsigned odd = ep->odd; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; + + /* No support for control transfer */ + TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL)); + + ep->max_packet_size = ep_desc->wMaxPacketSize.size; + unsigned val = USB_ENDPT_EPCTLDIS_MASK; + val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0; + val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; + USB_OTG_FS->EP_CTL[epn] |= val; + + if (xfer != TUSB_XFER_ISOCHRONOUS) { + bd[odd].dts = 1; + bd[odd].data = 0; + bd[odd ^ 1].dts = 1; + bd[odd ^ 1].data = 1; + } + + return true; +} + +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; + const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; + USB_OTG_FS->EP_CTL[epn] &= ~msk; + ep->max_packet_size = 0; + ep->length = 0; + ep->remaining = 0; + bd->head = 0; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +{ + (void) rhport; + NVIC_DisableIRQ(USB_FS_IRQn); + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][ep->odd]; + + if (bd->own) { + TU_LOG1("DCD XFER fail %x %d %lx %lx\r\n", ep_addr, total_bytes, ep->state, bd->head); + return false; /* The last transfer has not completed */ + } + ep->length = total_bytes; + ep->remaining = total_bytes; + + const unsigned mps = ep->max_packet_size; + if (total_bytes > mps) { + buffer_descriptor_t *next = ep->odd ? bd - 1: bd + 1; + /* When total_bytes is greater than the max packet size, + * it prepares to the next transfer to avoid NAK in advance. */ + next->bc = total_bytes >= 2 * mps ? mps: total_bytes - mps; + next->addr = buffer + mps; + next->own = 1; + } + bd->bc = total_bytes >= mps ? mps: total_bytes; + bd->addr = buffer; + __DSB(); + bd->own = 1; /* the own bit must set after addr */ + NVIC_EnableIRQ(USB_FS_IRQn); + return true; +} + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + const unsigned epn = ep_addr & 0xFu; + if (0 == epn) { + USB_OTG_FS->EP_CTL[epn] |= USB_ENDPT_EPSTALL_MASK; + } else { + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; + bd[0].bdt_stall = 1; + bd[1].bdt_stall = 1; + } +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned odd = _dcd.endpoint[epn][dir].odd; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; + + bd[odd ^ 1].own = 0; + bd[odd ^ 1].data = 1; + bd[odd ^ 1].bdt_stall = 0; + bd[odd].own = 0; + bd[odd].data = 0; + bd[odd].bdt_stall = 0; +} + +//--------------------------------------------------------------------+ +// ISR +//--------------------------------------------------------------------+ +void dcd_int_handler(uint8_t rhport) +{ + (void) rhport; + + uint32_t is = USB_OTG_FS->INT_STAT; + uint32_t msk = USB_OTG_FS->INT_ENB; + USB_OTG_FS->INT_STAT = is & ~msk; + is &= msk; + if (is & USB_ISTAT_ERROR_MASK) { + /* TODO: */ + uint32_t es = USB_OTG_FS->ERR_STAT; + USB_OTG_FS->ERR_STAT = es; + USB_OTG_FS->INT_STAT = is; /* discard any pending events */ + return; + } + + if (is & USB_ISTAT_USBRST_MASK) { + USB_OTG_FS->INT_STAT = is; /* discard any pending events */ + process_bus_reset(rhport); + return; + } + if (is & USB_ISTAT_SLEEP_MASK) { + USB_OTG_FS->INT_STAT = USB_ISTAT_SLEEP_MASK; + process_bus_inactive(rhport); + return; + } + if (is & USB_ISTAT_RESUME_MASK) { + USB_OTG_FS->INT_STAT = USB_ISTAT_RESUME_MASK; + process_bus_active(rhport); + return; + } + if (is & USB_ISTAT_SOFTOK_MASK) { + USB_OTG_FS->INT_STAT = USB_ISTAT_SOFTOK_MASK; + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); + return; + } + if (is & USB_ISTAT_STALL_MASK) { + USB_OTG_FS->INT_STAT = USB_ISTAT_STALL_MASK; + process_stall(rhport); + return; + } + if (is & USB_ISTAT_TOKDNE_MASK) { + process_tokdne(rhport); + return; + } +} + +#endif diff --git a/src/portable/mm32/dcd_mm32f327x_otg.c b/src/portable/mm32/dcd_mm32f327x_otg.c deleted file mode 100644 index e7518830e..000000000 --- a/src/portable/mm32/dcd_mm32f327x_otg.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020 SE TEAM - * - * 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. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" -#include "reg_usb_otg_fs.h" -#include "mm32_device.h" -#include "hal_conf.h" - -#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MM32F327X ) - -#include "device/dcd.h" - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -enum { - TOK_PID_OUT = 0x1u, - TOK_PID_IN = 0x9u, - TOK_PID_SETUP = 0xDu, -}; - -typedef struct TU_ATTR_PACKED -{ - union { - uint32_t head; - struct { - union { - struct { - uint16_t : 2; - uint16_t tok_pid : 4; - uint16_t data : 1; - uint16_t own : 1; - uint16_t : 8; - }; - struct { - uint16_t : 2; - uint16_t bdt_stall: 1; - uint16_t dts : 1; - uint16_t ninc : 1; - uint16_t keep : 1; - uint16_t : 10; - }; - }; - uint16_t bc : 10; - uint16_t : 6; - }; - }; - uint8_t *addr; -}buffer_descriptor_t; - -TU_VERIFY_STATIC( sizeof(buffer_descriptor_t) == 8, "size is not correct" ); - -typedef struct TU_ATTR_PACKED -{ - union { - uint32_t state; - struct { - uint32_t max_packet_size :11; - uint32_t : 5; - uint32_t odd : 1; - uint32_t :15; - }; - }; - uint16_t length; - uint16_t remaining; -}endpoint_state_t; - -TU_VERIFY_STATIC( sizeof(endpoint_state_t) == 8, "size is not correct" ); - -typedef struct -{ - union { - /* [#EP][OUT,IN][EVEN,ODD] */ - buffer_descriptor_t bdt[16][2][2]; - uint16_t bda[512]; - }; - TU_ATTR_ALIGNED(4) union { - endpoint_state_t endpoint[16][2]; - endpoint_state_t endpoint_unified[16 * 2]; - }; - uint8_t setup_packet[8]; - uint8_t addr; -}dcd_data_t; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -// BDT(Buffer Descriptor Table) must be 256-byte aligned -CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(512) static dcd_data_t _dcd; - -TU_VERIFY_STATIC( sizeof(_dcd.bdt) == 512, "size is not correct" ); - -static void prepare_next_setup_packet(uint8_t rhport) -{ - const unsigned out_odd = _dcd.endpoint[0][0].odd; - const unsigned in_odd = _dcd.endpoint[0][1].odd; - if (_dcd.bdt[0][0][out_odd].own) { - TU_LOG1("DCD fail to prepare the next SETUP %d %d\r\n", out_odd, in_odd); - return; - } - _dcd.bdt[0][0][out_odd].data = 0; - _dcd.bdt[0][0][out_odd ^ 1].data = 1; - _dcd.bdt[0][1][in_odd].data = 1; - _dcd.bdt[0][1][in_odd ^ 1].data = 0; - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), - _dcd.setup_packet, sizeof(_dcd.setup_packet)); -} - -static void process_stall(uint8_t rhport) -{ - if (USB_OTG_FS->EP_CTL[0] & USB_ENDPT_EPSTALL_MASK) { - /* clear stall condition of the control pipe */ - prepare_next_setup_packet(rhport); - USB_OTG_FS->EP_CTL[0] &= ~USB_ENDPT_EPSTALL_MASK; - } -} - -static void process_tokdne(uint8_t rhport) -{ - const unsigned s = USB_OTG_FS->STAT; - USB_OTG_FS->INT_STAT = USB_ISTAT_TOKDNE_MASK; /* fetch the next token if received */ - buffer_descriptor_t *bd = (buffer_descriptor_t *)&_dcd.bda[s]; - endpoint_state_t *ep = &_dcd.endpoint_unified[s >> 3]; - unsigned odd = (s & USB_STAT_ODD_MASK) ? 1 : 0; - - /* fetch pid before discarded by the next steps */ - const unsigned pid = bd->tok_pid; - /* reset values for a next transfer */ - bd->bdt_stall = 0; - bd->dts = 1; - bd->ninc = 0; - bd->keep = 0; - /* update the odd variable to prepare for the next transfer */ - ep->odd = odd ^ 1; - if (pid == TOK_PID_SETUP) { - dcd_event_setup_received(rhport, bd->addr, true); - USB_OTG_FS->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; - return; - } - if (s >> 4) { - TU_LOG1("TKDNE %x\r\n", s); - } - - const unsigned bc = bd->bc; - const unsigned remaining = ep->remaining - bc; - if (remaining && bc == ep->max_packet_size) { - /* continue the transferring consecutive data */ - ep->remaining = remaining; - const int next_remaining = remaining - ep->max_packet_size; - if (next_remaining > 0) { - /* prepare to the after next transfer */ - bd->addr += ep->max_packet_size * 2; - bd->bc = next_remaining > ep->max_packet_size ? ep->max_packet_size: next_remaining; - __DSB(); - bd->own = 1; /* the own bit must set after addr */ - } - return; - } - const unsigned length = ep->length; - dcd_event_xfer_complete(rhport, - ((s & USB_STAT_TX_MASK) << 4) | (s >> USB_STAT_ENDP_SHIFT), - length - remaining, XFER_RESULT_SUCCESS, true); - if (0 == (s & USB_STAT_ENDP_MASK) && 0 == length) { - /* After completion a ZLP of control transfer, - * it prepares for the next steup transfer. */ - if (_dcd.addr) { - /* When the transfer was the SetAddress, - * the device address should be updated here. */ - USB_OTG_FS->ADDR = _dcd.addr; - _dcd.addr = 0; - } - prepare_next_setup_packet(rhport); - } -} - -static void process_bus_reset(uint8_t rhport) -{ - USB_OTG_FS->CTL |= USB_CTL_ODDRST_MASK; - USB_OTG_FS->ADDR = 0; - USB_OTG_FS->INT_ENB = (USB_OTG_FS->INT_ENB & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; - - USB_OTG_FS->EP_CTL[0] = USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPRXEN_MASK | USB_ENDPT_EPTXEN_MASK; - for (unsigned i = 1; i < 16; ++i) { - USB_OTG_FS->EP_CTL[i] = 0; - } - buffer_descriptor_t *bd = _dcd.bdt[0][0]; - for (unsigned i = 0; i < sizeof(_dcd.bdt)/sizeof(*bd); ++i, ++bd) { - bd->head = 0; - } - const endpoint_state_t ep0 = { - .max_packet_size = CFG_TUD_ENDPOINT0_SIZE, - .odd = 0, - .length = 0, - .remaining = 0, - }; - _dcd.endpoint[0][0] = ep0; - _dcd.endpoint[0][1] = ep0; - tu_memclr(_dcd.endpoint[1], sizeof(_dcd.endpoint) - sizeof(_dcd.endpoint[0])); - _dcd.addr = 0; - prepare_next_setup_packet(rhport); - USB_OTG_FS->CTL &= ~USB_CTL_ODDRST_MASK; - dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); -} - -static void process_bus_inactive(uint8_t rhport) -{ - (void) rhport; - const unsigned inten = USB_OTG_FS->INT_ENB; - USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_SLEEPEN_MASK) | USB_INTEN_RESUMEEN_MASK; - dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); -} - -static void process_bus_active(uint8_t rhport) -{ - (void) rhport; - const unsigned inten = USB_OTG_FS->INT_ENB; - USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; - dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); -} - -/*------------------------------------------------------------------*/ -/* Device API - *------------------------------------------------------------------*/ -void dcd_init(uint8_t rhport) -{ - (void) rhport; - - tu_memclr(&_dcd, sizeof(_dcd)); - USB_OTG_FS->BDT_PAGE_01 = (uint8_t)((uintptr_t)_dcd.bdt >> 8); - USB_OTG_FS->BDT_PAGE_02 = (uint8_t)((uintptr_t)_dcd.bdt >> 16); - USB_OTG_FS->BDT_PAGE_03 = (uint8_t)((uintptr_t)_dcd.bdt >> 24); - - dcd_connect(rhport); - NVIC_ClearPendingIRQ(USB_FS_IRQn); -} -#define USB_DEVICE_INTERRUPT_PRIORITY (3U) -void dcd_int_enable(uint8_t rhport) -{ - uint8_t irqNumber; - irqNumber = USB_FS_IRQn; - (void) rhport; - USB_OTG_FS->INT_ENB = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK | - USB_INTEN_SLEEPEN_MASK | USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK; - NVIC_SetPriority((IRQn_Type)irqNumber, USB_DEVICE_INTERRUPT_PRIORITY); - NVIC_EnableIRQ(USB_FS_IRQn); -} - -void dcd_int_disable(uint8_t rhport) -{ - (void) rhport; - NVIC_DisableIRQ(USB_FS_IRQn); - USB_OTG_FS->INT_ENB = 0; -} - -void dcd_set_address(uint8_t rhport, uint8_t dev_addr) -{ - (void) rhport; - _dcd.addr = dev_addr & 0x7F; - /* Response with status first before changing device address */ - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); -} -extern u32 SystemCoreClock ; -void dcd_remote_wakeup(uint8_t rhport) -{ - (void) rhport; - unsigned cnt = SystemCoreClock / 100; - USB_OTG_FS->CTL |= USB_CTL_RESUME_MASK; - while (cnt--) __NOP(); - USB_OTG_FS->CTL &= ~USB_CTL_RESUME_MASK; -} - -void dcd_connect(uint8_t rhport) -{ - (void) rhport; - USB_OTG_FS->CTL |= USB_CTL_USBENSOFEN_MASK; -} - -void dcd_disconnect(uint8_t rhport) -{ - (void) rhport; - USB_OTG_FS->CTL = 0; -} - -//--------------------------------------------------------------------+ -// Endpoint API -//--------------------------------------------------------------------+ -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; - - const unsigned ep_addr = ep_desc->bEndpointAddress; - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - const unsigned xfer = ep_desc->bmAttributes.xfer; - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - const unsigned odd = ep->odd; - buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; - - /* No support for control transfer */ - TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL)); - - ep->max_packet_size = ep_desc->wMaxPacketSize.size; - unsigned val = USB_ENDPT_EPCTLDIS_MASK; - val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0; - val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; - USB_OTG_FS->EP_CTL[epn] |= val; - - if (xfer != TUSB_XFER_ISOCHRONOUS) { - bd[odd].dts = 1; - bd[odd].data = 0; - bd[odd ^ 1].dts = 1; - bd[odd ^ 1].data = 1; - } - - return true; -} - -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; - const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; - USB_OTG_FS->EP_CTL[epn] &= ~msk; - ep->max_packet_size = 0; - ep->length = 0; - ep->remaining = 0; - bd->head = 0; -} - -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) -{ - (void) rhport; - NVIC_DisableIRQ(USB_FS_IRQn); - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][ep->odd]; - - if (bd->own) { - TU_LOG1("DCD XFER fail %x %d %lx %lx\r\n", ep_addr, total_bytes, ep->state, bd->head); - return false; /* The last transfer has not completed */ - } - ep->length = total_bytes; - ep->remaining = total_bytes; - - const unsigned mps = ep->max_packet_size; - if (total_bytes > mps) { - buffer_descriptor_t *next = ep->odd ? bd - 1: bd + 1; - /* When total_bytes is greater than the max packet size, - * it prepares to the next transfer to avoid NAK in advance. */ - next->bc = total_bytes >= 2 * mps ? mps: total_bytes - mps; - next->addr = buffer + mps; - next->own = 1; - } - bd->bc = total_bytes >= mps ? mps: total_bytes; - bd->addr = buffer; - __DSB(); - bd->own = 1; /* the own bit must set after addr */ - NVIC_EnableIRQ(USB_FS_IRQn); - return true; -} - -void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - const unsigned epn = ep_addr & 0xFu; - if (0 == epn) { - USB_OTG_FS->EP_CTL[epn] |= USB_ENDPT_EPSTALL_MASK; - } else { - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; - bd[0].bdt_stall = 1; - bd[1].bdt_stall = 1; - } -} - -void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - const unsigned odd = _dcd.endpoint[epn][dir].odd; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; - - bd[odd ^ 1].own = 0; - bd[odd ^ 1].data = 1; - bd[odd ^ 1].bdt_stall = 0; - bd[odd].own = 0; - bd[odd].data = 0; - bd[odd].bdt_stall = 0; -} - -//--------------------------------------------------------------------+ -// ISR -//--------------------------------------------------------------------+ -void dcd_int_handler(uint8_t rhport) -{ - (void) rhport; - - uint32_t is = USB_OTG_FS->INT_STAT; - uint32_t msk = USB_OTG_FS->INT_ENB; - USB_OTG_FS->INT_STAT = is & ~msk; - is &= msk; - if (is & USB_ISTAT_ERROR_MASK) { - /* TODO: */ - uint32_t es = USB_OTG_FS->ERR_STAT; - USB_OTG_FS->ERR_STAT = es; - USB_OTG_FS->INT_STAT = is; /* discard any pending events */ - return; - } - - if (is & USB_ISTAT_USBRST_MASK) { - USB_OTG_FS->INT_STAT = is; /* discard any pending events */ - process_bus_reset(rhport); - return; - } - if (is & USB_ISTAT_SLEEP_MASK) { - USB_OTG_FS->INT_STAT = USB_ISTAT_SLEEP_MASK; - process_bus_inactive(rhport); - return; - } - if (is & USB_ISTAT_RESUME_MASK) { - USB_OTG_FS->INT_STAT = USB_ISTAT_RESUME_MASK; - process_bus_active(rhport); - return; - } - if (is & USB_ISTAT_SOFTOK_MASK) { - USB_OTG_FS->INT_STAT = USB_ISTAT_SOFTOK_MASK; - dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); - return; - } - if (is & USB_ISTAT_STALL_MASK) { - USB_OTG_FS->INT_STAT = USB_ISTAT_STALL_MASK; - process_stall(rhport); - return; - } - if (is & USB_ISTAT_TOKDNE_MASK) { - process_tokdne(rhport); - return; - } -} - -#endif diff --git a/src/tusb_option.h b/src/tusb_option.h index cdaf074db..5cfcc08e2 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -113,6 +113,9 @@ // Renesas RX #define OPT_MCU_RX63X 1400 ///< Renesas RX63N/631 +// Mind Motion +#define OPT_MCU_MM32F327X 1500 ///< Mind Motion MM32F327 + /** @} */ /** \defgroup group_supported_os Supported RTOS -- cgit v1.3.1 From 501de2a5e8232752defb28f8cd97f24595a61cf2 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 7 Jun 2021 14:33:24 +0700 Subject: fix computing transferred bytes with E4 --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index a0263612f..31381e6c2 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -205,10 +205,7 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) // Update hw endpoint struct with info from hardware // after a buff status interrupt - // Get the buffer state and amount of bytes we have - // transferred uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); - uint16_t transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; #if TUSB_OPT_HOST_ENABLED // RP2040-E4 @@ -227,6 +224,9 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) // end::host_buf_sel_fix[] #endif + // Get tranferred bytes after adjusted buf sel + uint16_t const transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; + // We are continuing a transfer here. If we are TX, we have successfullly // sent some data can increase the length we have sent if (!ep->rx) @@ -249,7 +249,7 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) // Sometimes the host will send less data than we expect... // If this is a short out transfer update the total length of the transfer // to be the current length - if ((ep->rx) && (transferred_bytes < ep->transfer_size)) + if ((ep->rx) && (transferred_bytes < ep->wMaxPacketSize)) { pico_trace("Short rx transfer\n"); // Reduce total length as this is last packet @@ -289,8 +289,7 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) { pico_trace("Completed transfer of %d bytes on ep %d %s\n", ep->len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); - // Notify caller we are done so it can notify the tinyusb - // stack + // Notify caller we are done so it can notify the tinyusb stack _hw_endpoint_lock_update(ep, -1); return true; } -- cgit v1.3.1 From d5f8da44d13d3410f6c710432062807b52ebf407 Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Mon, 7 Jun 2021 19:04:21 +0200 Subject: Add optional support for 32 gamepad buttons --- src/class/hid/hid.h | 40 ++++++++++++++++++++++++++++++++++++++-- src/class/hid/hid_device.h | 9 ++++----- src/tusb_option.h | 6 ++++++ 3 files changed, 48 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 5cc9233b5..3c45dc6c1 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -33,10 +33,12 @@ #include "common/tusb_common.h" + #ifdef __cplusplus extern "C" { #endif + //--------------------------------------------------------------------+ // Common Definitions //--------------------------------------------------------------------+ @@ -150,6 +152,22 @@ typedef enum /** @} */ +#ifndef CFG_TUD_HID_EP_BUFSIZE + #define CFG_TUD_HID_EP_BUFSIZE 64 +#endif + +#ifndef CFG_TUSB_MAX_BUTTONS + #define CFG_TUSB_MAX_BUTTONS 16 +#endif + +#if (CFG_TUSB_MAX_BUTTONS == 16) + typedef uint16_t hid_gamepad_buttons_t; +#elif (CFG_TUSB_MAX_BUTTONS == 32) + typedef uint32_t hid_gamepad_buttons_t; +#else + #error "Invalid CFG_TUSB_MAX_BUTTONS value." +#endif + //--------------------------------------------------------------------+ // GAMEPAD //--------------------------------------------------------------------+ @@ -201,7 +219,7 @@ typedef struct TU_ATTR_PACKED int8_t rx; ///< Delta Rx movement of analog left trigger int8_t ry; ///< Delta Ry movement of analog right trigger uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat - uint16_t buttons; ///< Buttons mask for currently pressed buttons + hid_gamepad_buttons_t buttons; ///< Buttons mask for currently pressed buttons }hid_gamepad_report_t; /// Standard Gamepad Buttons Bitmap (from Linux input event codes) @@ -222,7 +240,25 @@ typedef enum GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button -//GAMEPAD_BUTTON_ = TU_BIT(15), ///< Undefined button + GAMEPAD_BUTTON_15 = TU_BIT(15), ///< Button 15 +#ifdef CFG_TUSB_MAX_BUTTONS_32 + GAMEPAD_BUTTON_17 = TU_BIT(16), ///< Button 17 + GAMEPAD_BUTTON_18 = TU_BIT(17), ///< Button 16 + GAMEPAD_BUTTON_19 = TU_BIT(18), ///< Button 16 + GAMEPAD_BUTTON_20 = TU_BIT(19), ///< Button 16 + GAMEPAD_BUTTON_21 = TU_BIT(20), ///< Button 16 + GAMEPAD_BUTTON_22 = TU_BIT(21), ///< Button 16 + GAMEPAD_BUTTON_23 = TU_BIT(22), ///< Button 16 + GAMEPAD_BUTTON_24 = TU_BIT(23), ///< Button 16 + GAMEPAD_BUTTON_25 = TU_BIT(24), ///< Button 16 + GAMEPAD_BUTTON_26 = TU_BIT(25), ///< Button 16 + GAMEPAD_BUTTON_27 = TU_BIT(26), ///< Button 16 + GAMEPAD_BUTTON_28 = TU_BIT(27), ///< Button 16 + GAMEPAD_BUTTON_29 = TU_BIT(28), ///< Button 16 + GAMEPAD_BUTTON_30 = TU_BIT(29), ///< Button 16 + GAMEPAD_BUTTON_31 = TU_BIT(30), ///< Button 16 + GAMEPAD_BUTTON_32 = TU_BIT(31), ///< Button 16 +#endif }hid_gamepad_button_bm_t; /// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index beb755888..0ff5cab3f 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -43,9 +43,8 @@ #define CFG_TUD_HID_EP_BUFSIZE CFG_TUD_HID_BUFSIZE #endif -#ifndef CFG_TUD_HID_EP_BUFSIZE - #define CFG_TUD_HID_EP_BUFSIZE 64 -#endif + + //--------------------------------------------------------------------+ // Application API (Multiple Instances) @@ -344,10 +343,10 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y /* 16 bit Button Map */ \ HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( 16 ) ,\ + HID_USAGE_MAX ( CFG_TUSB_MAX_BUTTONS ) ,\ HID_LOGICAL_MIN ( 0 ) ,\ HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( 16 ) ,\ + HID_REPORT_COUNT ( CFG_TUSB_MAX_BUTTONS ) ,\ HID_REPORT_SIZE ( 1 ) ,\ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ HID_COLLECTION_END \ diff --git a/src/tusb_option.h b/src/tusb_option.h index 5cfcc08e2..a7939d9c7 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -316,6 +316,12 @@ #error Control Endpoint Max Packet Size cannot be larger than 64 #endif +#ifndef TUD_OPT_GAMEPAD_32_BUTTONS + #define CFG_TUSB_MAX_BUTTONS 16 +#else + #define CFG_TUSB_MAX_BUTTONS 32 +#endif + #endif /* _TUSB_OPTION_H_ */ /** @} */ -- cgit v1.3.1 From 3842c806a6bd90a3be8431c4fa3fb8c46220a6bf Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Mon, 7 Jun 2021 20:16:05 +0200 Subject: clean up --- src/class/hid/hid.h | 16 ++++++---------- src/class/hid/hid_device.h | 4 ++-- src/tusb_option.h | 17 +++++++++++++---- 3 files changed, 21 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 3c45dc6c1..eac30c62e 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -152,20 +152,16 @@ typedef enum /** @} */ -#ifndef CFG_TUD_HID_EP_BUFSIZE - #define CFG_TUD_HID_EP_BUFSIZE 64 +#ifndef CFG_TUD_MAX_BUTTONS + #define CFG_TUD_MAX_BUTTONS 16 #endif -#ifndef CFG_TUSB_MAX_BUTTONS - #define CFG_TUSB_MAX_BUTTONS 16 -#endif - -#if (CFG_TUSB_MAX_BUTTONS == 16) +#if (CFG_TUD_MAX_BUTTONS == 16) typedef uint16_t hid_gamepad_buttons_t; -#elif (CFG_TUSB_MAX_BUTTONS == 32) +#elif (CFG_TUD_MAX_BUTTONS == 32) typedef uint32_t hid_gamepad_buttons_t; #else - #error "Invalid CFG_TUSB_MAX_BUTTONS value." + #error "Invalid CFG_TUD_MAX_BUTTONS value." #endif //--------------------------------------------------------------------+ @@ -241,7 +237,7 @@ typedef enum GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button GAMEPAD_BUTTON_15 = TU_BIT(15), ///< Button 15 -#ifdef CFG_TUSB_MAX_BUTTONS_32 +#if (CFG_TUD_MAX_BUTTONS > 16) GAMEPAD_BUTTON_17 = TU_BIT(16), ///< Button 17 GAMEPAD_BUTTON_18 = TU_BIT(17), ///< Button 16 GAMEPAD_BUTTON_19 = TU_BIT(18), ///< Button 16 diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 0ff5cab3f..39ec6be76 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -343,10 +343,10 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y /* 16 bit Button Map */ \ HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( CFG_TUSB_MAX_BUTTONS ) ,\ + HID_USAGE_MAX ( CFG_TUD_MAX_BUTTONS ) ,\ HID_LOGICAL_MIN ( 0 ) ,\ HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( CFG_TUSB_MAX_BUTTONS ) ,\ + HID_REPORT_COUNT ( CFG_TUD_MAX_BUTTONS ) ,\ HID_REPORT_SIZE ( 1 ) ,\ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ HID_COLLECTION_END \ diff --git a/src/tusb_option.h b/src/tusb_option.h index a7939d9c7..3adb4fcf9 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -309,6 +309,16 @@ #define TUP_MCU_STRICT_ALIGN 0 #endif +//--------------------------------------------------------------------+ +// HID Gamepad options +//--------------------------------------------------------------------+ + +// CFG_TUD_MAX_BUTTONS lets you choose if you want 16 or 32 buttons on you HID gamepad +#ifndef CFG_TUD_MAX_BUTTONS + #define CFG_TUD_MAX_BUTTONS 16 +#endif + + //------------------------------------------------------------------ // Configuration Validation //------------------------------------------------------------------ @@ -316,10 +326,9 @@ #error Control Endpoint Max Packet Size cannot be larger than 64 #endif -#ifndef TUD_OPT_GAMEPAD_32_BUTTONS - #define CFG_TUSB_MAX_BUTTONS 16 -#else - #define CFG_TUSB_MAX_BUTTONS 32 + +#if (CFG_TUD_MAX_BUTTONS != 16 && CFG_TUD_MAX_BUTTONS != 32) + #error "Unsupported CFG_TUD_MAX_BUTTONS" #endif #endif /* _TUSB_OPTION_H_ */ -- cgit v1.3.1 From ce634f226e59cccfb236371f85a62cb610ef80f6 Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Mon, 7 Jun 2021 20:44:53 +0200 Subject: remove excess empty lines --- src/class/hid/hid.h | 2 -- src/tusb_option.h | 1 - 2 files changed, 3 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index eac30c62e..0764bc228 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -33,12 +33,10 @@ #include "common/tusb_common.h" - #ifdef __cplusplus extern "C" { #endif - //--------------------------------------------------------------------+ // Common Definitions //--------------------------------------------------------------------+ diff --git a/src/tusb_option.h b/src/tusb_option.h index 3adb4fcf9..6a6e31ee9 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -318,7 +318,6 @@ #define CFG_TUD_MAX_BUTTONS 16 #endif - //------------------------------------------------------------------ // Configuration Validation //------------------------------------------------------------------ -- cgit v1.3.1 From e12195705c2b849379145618691c2e8564762aa7 Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Tue, 8 Jun 2021 09:24:50 +0200 Subject: Pull request changes Remove configuration options and just bump number of buttons to 32 Fix button numbereing and comments in --- examples/device/hid_composite/src/tusb_config.h | 4 --- src/class/hid/hid.h | 48 +++++++++---------------- src/class/hid/hid_device.h | 4 +-- src/tusb_option.h | 14 -------- 4 files changed, 19 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index bc9192d13..3e608ed37 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -104,10 +104,6 @@ // HID buffer size Should be sufficient to hold ID (if any) + Data #define CFG_TUD_HID_EP_BUFSIZE 16 -// Number of button on the gamepad 16 or 32 -#define CFG_TUD_MAX_BUTTONS 16 - - #ifdef __cplusplus } #endif diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 0764bc228..a344c9100 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -150,18 +150,6 @@ typedef enum /** @} */ -#ifndef CFG_TUD_MAX_BUTTONS - #define CFG_TUD_MAX_BUTTONS 16 -#endif - -#if (CFG_TUD_MAX_BUTTONS == 16) - typedef uint16_t hid_gamepad_buttons_t; -#elif (CFG_TUD_MAX_BUTTONS == 32) - typedef uint32_t hid_gamepad_buttons_t; -#else - #error "Invalid CFG_TUD_MAX_BUTTONS value." -#endif - //--------------------------------------------------------------------+ // GAMEPAD //--------------------------------------------------------------------+ @@ -213,7 +201,7 @@ typedef struct TU_ATTR_PACKED int8_t rx; ///< Delta Rx movement of analog left trigger int8_t ry; ///< Delta Ry movement of analog right trigger uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat - hid_gamepad_buttons_t buttons; ///< Buttons mask for currently pressed buttons + uint32_t buttons; ///< Buttons mask for currently pressed buttons }hid_gamepad_report_t; /// Standard Gamepad Buttons Bitmap (from Linux input event codes) @@ -234,25 +222,23 @@ typedef enum GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button - GAMEPAD_BUTTON_15 = TU_BIT(15), ///< Button 15 -#if (CFG_TUD_MAX_BUTTONS > 16) + GAMEPAD_BUTTON_16 = TU_BIT(15), ///< Button 15 GAMEPAD_BUTTON_17 = TU_BIT(16), ///< Button 17 - GAMEPAD_BUTTON_18 = TU_BIT(17), ///< Button 16 - GAMEPAD_BUTTON_19 = TU_BIT(18), ///< Button 16 - GAMEPAD_BUTTON_20 = TU_BIT(19), ///< Button 16 - GAMEPAD_BUTTON_21 = TU_BIT(20), ///< Button 16 - GAMEPAD_BUTTON_22 = TU_BIT(21), ///< Button 16 - GAMEPAD_BUTTON_23 = TU_BIT(22), ///< Button 16 - GAMEPAD_BUTTON_24 = TU_BIT(23), ///< Button 16 - GAMEPAD_BUTTON_25 = TU_BIT(24), ///< Button 16 - GAMEPAD_BUTTON_26 = TU_BIT(25), ///< Button 16 - GAMEPAD_BUTTON_27 = TU_BIT(26), ///< Button 16 - GAMEPAD_BUTTON_28 = TU_BIT(27), ///< Button 16 - GAMEPAD_BUTTON_29 = TU_BIT(28), ///< Button 16 - GAMEPAD_BUTTON_30 = TU_BIT(29), ///< Button 16 - GAMEPAD_BUTTON_31 = TU_BIT(30), ///< Button 16 - GAMEPAD_BUTTON_32 = TU_BIT(31), ///< Button 16 -#endif + GAMEPAD_BUTTON_18 = TU_BIT(17), ///< Button 18 + GAMEPAD_BUTTON_19 = TU_BIT(18), ///< Button 19 + GAMEPAD_BUTTON_20 = TU_BIT(19), ///< Button 20 + GAMEPAD_BUTTON_21 = TU_BIT(20), ///< Button 21 + GAMEPAD_BUTTON_22 = TU_BIT(21), ///< Button 22 + GAMEPAD_BUTTON_23 = TU_BIT(22), ///< Button 23 + GAMEPAD_BUTTON_24 = TU_BIT(23), ///< Button 24 + GAMEPAD_BUTTON_25 = TU_BIT(24), ///< Button 25 + GAMEPAD_BUTTON_26 = TU_BIT(25), ///< Button 26 + GAMEPAD_BUTTON_27 = TU_BIT(26), ///< Button 27 + GAMEPAD_BUTTON_28 = TU_BIT(27), ///< Button 28 + GAMEPAD_BUTTON_29 = TU_BIT(28), ///< Button 29 + GAMEPAD_BUTTON_30 = TU_BIT(29), ///< Button 30 + GAMEPAD_BUTTON_31 = TU_BIT(30), ///< Button 31 + GAMEPAD_BUTTON_32 = TU_BIT(31), ///< Button 32 }hid_gamepad_button_bm_t; /// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 39ec6be76..543bc3b3b 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -343,10 +343,10 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y /* 16 bit Button Map */ \ HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ HID_USAGE_MIN ( 1 ) ,\ - HID_USAGE_MAX ( CFG_TUD_MAX_BUTTONS ) ,\ + HID_USAGE_MAX ( 32 ) ,\ HID_LOGICAL_MIN ( 0 ) ,\ HID_LOGICAL_MAX ( 1 ) ,\ - HID_REPORT_COUNT ( CFG_TUD_MAX_BUTTONS ) ,\ + HID_REPORT_COUNT ( 32 ) ,\ HID_REPORT_SIZE ( 1 ) ,\ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ HID_COLLECTION_END \ diff --git a/src/tusb_option.h b/src/tusb_option.h index 6a6e31ee9..5cfcc08e2 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -309,15 +309,6 @@ #define TUP_MCU_STRICT_ALIGN 0 #endif -//--------------------------------------------------------------------+ -// HID Gamepad options -//--------------------------------------------------------------------+ - -// CFG_TUD_MAX_BUTTONS lets you choose if you want 16 or 32 buttons on you HID gamepad -#ifndef CFG_TUD_MAX_BUTTONS - #define CFG_TUD_MAX_BUTTONS 16 -#endif - //------------------------------------------------------------------ // Configuration Validation //------------------------------------------------------------------ @@ -325,11 +316,6 @@ #error Control Endpoint Max Packet Size cannot be larger than 64 #endif - -#if (CFG_TUD_MAX_BUTTONS != 16 && CFG_TUD_MAX_BUTTONS != 32) - #error "Unsupported CFG_TUD_MAX_BUTTONS" -#endif - #endif /* _TUSB_OPTION_H_ */ /** @} */ -- cgit v1.3.1 From de71e72e31ca1d534e5e0413f9da0a0e84a9aa69 Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Tue, 8 Jun 2021 09:26:17 +0200 Subject: Fix comment in hid.h --- src/class/hid/hid.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index a344c9100..8ab24ab3e 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -217,12 +217,12 @@ typedef enum GAMEPAD_BUTTON_TR = TU_BIT(7), ///< R1 button GAMEPAD_BUTTON_TL2 = TU_BIT(8), ///< L2 button GAMEPAD_BUTTON_TR2 = TU_BIT(9), ///< R2 button - GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button + GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button GAMEPAD_BUTTON_START = TU_BIT(11), ///< Start button GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button - GAMEPAD_BUTTON_16 = TU_BIT(15), ///< Button 15 + GAMEPAD_BUTTON_16 = TU_BIT(15), ///< Button 16 GAMEPAD_BUTTON_17 = TU_BIT(16), ///< Button 17 GAMEPAD_BUTTON_18 = TU_BIT(17), ///< Button 18 GAMEPAD_BUTTON_19 = TU_BIT(18), ///< Button 19 -- cgit v1.3.1 From d3b6e28387c63a1519cd1958ee7e21bd2980d099 Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Tue, 8 Jun 2021 09:31:40 +0200 Subject: indent fix --- src/class/hid/hid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 8ab24ab3e..782a1a552 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -217,7 +217,7 @@ typedef enum GAMEPAD_BUTTON_TR = TU_BIT(7), ///< R1 button GAMEPAD_BUTTON_TL2 = TU_BIT(8), ///< L2 button GAMEPAD_BUTTON_TR2 = TU_BIT(9), ///< R2 button - GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button + GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button GAMEPAD_BUTTON_START = TU_BIT(11), ///< Start button GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button -- cgit v1.3.1 From e393fb32a0830e9d371f3e335cc0cca92b75cbbb Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Tue, 8 Jun 2021 09:39:53 +0200 Subject: re-adding ifdef removed accidentally --- src/class/hid/hid_device.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 543bc3b3b..1d1213e3f 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -43,8 +43,9 @@ #define CFG_TUD_HID_EP_BUFSIZE CFG_TUD_HID_BUFSIZE #endif - - +#ifndef CFG_TUD_HID_EP_BUFSIZE + #define CFG_TUD_HID_EP_BUFSIZE 64 +#endif //--------------------------------------------------------------------+ // Application API (Multiple Instances) -- cgit v1.3.1 From 2c0947ebb621e3e53933300cbfd1dce7e0f31338 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Jun 2021 10:30:13 +0700 Subject: update gamepad helper --- src/class/hid/hid.h | 1 + src/class/hid/hid_device.c | 2 +- src/class/hid/hid_device.h | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 782a1a552..b4e8a9c4c 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -222,6 +222,7 @@ typedef enum GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button + // Note: Button number start from 1 on host OS GAMEPAD_BUTTON_16 = TU_BIT(15), ///< Button 16 GAMEPAD_BUTTON_17 = TU_BIT(16), ///< Button 17 GAMEPAD_BUTTON_18 = TU_BIT(17), ///< Button 18 diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 151a36225..e44f282c4 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -149,7 +149,7 @@ bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, } bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, - int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) + int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) { hid_gamepad_report_t report = { diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 1d1213e3f..19e9315f4 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -72,9 +72,9 @@ bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modi // use template layout report as defined by hid_mouse_report_t bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); -// Gamepad: convenient helper to send mouse report if application +// Gamepad: convenient helper to send gamepad report if application // use template layout report TUD_HID_REPORT_DESC_GAMEPAD -bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); +bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); //--------------------------------------------------------------------+ // Application API (Single Port) @@ -85,7 +85,7 @@ static inline uint8_t tud_hid_get_protocol(void); static inline bool tud_hid_report(uint8_t report_id, void const* report, uint8_t len); static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons); +static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); //--------------------------------------------------------------------+ // Callbacks (Weak is optional) -- cgit v1.3.1 From dca9bc97d66fe2912d2643e4f36cb839d08a31da Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Jun 2021 10:45:37 +0700 Subject: miss a helper --- src/class/hid/hid_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 19e9315f4..e2c950dd1 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -152,7 +152,7 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8 return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); } -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons) +static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) { return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); } -- cgit v1.3.1 From d81a37d1bed3e9a905a1472eaafe2f750892eaac Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Jun 2021 12:10:44 +0700 Subject: fix enum overflow with msp430 --- src/common/tusb_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 3350ed86c..889ad7b25 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -51,7 +51,7 @@ #define U32_TO_U8S_BE(u32) TU_U32_BYTE3(u32), TU_U32_BYTE2(u32), TU_U32_BYTE1(u32), TU_U32_BYTE0(u32) #define U32_TO_U8S_LE(u32) TU_U32_BYTE0(u32), TU_U32_BYTE1(u32), TU_U32_BYTE2(u32), TU_U32_BYTE3(u32) -#define TU_BIT(n) (1U << (n)) +#define TU_BIT(n) (1UL << (n)) //--------------------------------------------------------------------+ // Includes -- cgit v1.3.1 From a8abbcc34df72ff5a63d5567d26276ce84e6d162 Mon Sep 17 00:00:00 2001 From: Marcelo Bezerra <23555060+mmosca@users.noreply.github.com> Date: Wed, 9 Jun 2021 12:14:04 +0200 Subject: Change buttons to start from 0 --- src/class/hid/hid.h | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index b4e8a9c4c..3c616d691 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -222,24 +222,23 @@ typedef enum GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button - // Note: Button number start from 1 on host OS - GAMEPAD_BUTTON_16 = TU_BIT(15), ///< Button 16 - GAMEPAD_BUTTON_17 = TU_BIT(16), ///< Button 17 - GAMEPAD_BUTTON_18 = TU_BIT(17), ///< Button 18 - GAMEPAD_BUTTON_19 = TU_BIT(18), ///< Button 19 - GAMEPAD_BUTTON_20 = TU_BIT(19), ///< Button 20 - GAMEPAD_BUTTON_21 = TU_BIT(20), ///< Button 21 - GAMEPAD_BUTTON_22 = TU_BIT(21), ///< Button 22 - GAMEPAD_BUTTON_23 = TU_BIT(22), ///< Button 23 - GAMEPAD_BUTTON_24 = TU_BIT(23), ///< Button 24 - GAMEPAD_BUTTON_25 = TU_BIT(24), ///< Button 25 - GAMEPAD_BUTTON_26 = TU_BIT(25), ///< Button 26 - GAMEPAD_BUTTON_27 = TU_BIT(26), ///< Button 27 - GAMEPAD_BUTTON_28 = TU_BIT(27), ///< Button 28 - GAMEPAD_BUTTON_29 = TU_BIT(28), ///< Button 29 - GAMEPAD_BUTTON_30 = TU_BIT(29), ///< Button 30 - GAMEPAD_BUTTON_31 = TU_BIT(30), ///< Button 31 - GAMEPAD_BUTTON_32 = TU_BIT(31), ///< Button 32 + GAMEPAD_BUTTON_15 = TU_BIT(15), ///< Button 15 + GAMEPAD_BUTTON_16 = TU_BIT(16), ///< Button 16 + GAMEPAD_BUTTON_17 = TU_BIT(17), ///< Button 17 + GAMEPAD_BUTTON_18 = TU_BIT(18), ///< Button 18 + GAMEPAD_BUTTON_19 = TU_BIT(19), ///< Button 19 + GAMEPAD_BUTTON_20 = TU_BIT(20), ///< Button 20 + GAMEPAD_BUTTON_21 = TU_BIT(21), ///< Button 21 + GAMEPAD_BUTTON_22 = TU_BIT(22), ///< Button 22 + GAMEPAD_BUTTON_23 = TU_BIT(23), ///< Button 23 + GAMEPAD_BUTTON_24 = TU_BIT(24), ///< Button 24 + GAMEPAD_BUTTON_25 = TU_BIT(25), ///< Button 25 + GAMEPAD_BUTTON_26 = TU_BIT(26), ///< Button 26 + GAMEPAD_BUTTON_27 = TU_BIT(27), ///< Button 27 + GAMEPAD_BUTTON_28 = TU_BIT(28), ///< Button 28 + GAMEPAD_BUTTON_29 = TU_BIT(29), ///< Button 29 + GAMEPAD_BUTTON_30 = TU_BIT(30), ///< Button 30 + GAMEPAD_BUTTON_31 = TU_BIT(31), ///< Button 31 }hid_gamepad_button_bm_t; /// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) -- cgit v1.3.1 From cffa666bd1fd8f0ab45336b36eb79ab1a8f4663d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Jun 2021 17:45:14 +0700 Subject: use alias for button naming --- src/class/hid/hid.h | 93 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 3c616d691..ec14c9c7c 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -204,43 +204,70 @@ typedef struct TU_ATTR_PACKED uint32_t buttons; ///< Buttons mask for currently pressed buttons }hid_gamepad_report_t; -/// Standard Gamepad Buttons Bitmap (from Linux input event codes) +/// Standard Gamepad Buttons Bitmap typedef enum { - GAMEPAD_BUTTON_A = TU_BIT(0), ///< A/South button - GAMEPAD_BUTTON_B = TU_BIT(1), ///< B/East button - GAMEPAD_BUTTON_C = TU_BIT(2), ///< C button - GAMEPAD_BUTTON_X = TU_BIT(3), ///< X/North button - GAMEPAD_BUTTON_Y = TU_BIT(4), ///< Y/West button - GAMEPAD_BUTTON_Z = TU_BIT(5), ///< Z button - GAMEPAD_BUTTON_TL = TU_BIT(6), ///< L1 button - GAMEPAD_BUTTON_TR = TU_BIT(7), ///< R1 button - GAMEPAD_BUTTON_TL2 = TU_BIT(8), ///< L2 button - GAMEPAD_BUTTON_TR2 = TU_BIT(9), ///< R2 button - GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button - GAMEPAD_BUTTON_START = TU_BIT(11), ///< Start button - GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button - GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button - GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button - GAMEPAD_BUTTON_15 = TU_BIT(15), ///< Button 15 - GAMEPAD_BUTTON_16 = TU_BIT(16), ///< Button 16 - GAMEPAD_BUTTON_17 = TU_BIT(17), ///< Button 17 - GAMEPAD_BUTTON_18 = TU_BIT(18), ///< Button 18 - GAMEPAD_BUTTON_19 = TU_BIT(19), ///< Button 19 - GAMEPAD_BUTTON_20 = TU_BIT(20), ///< Button 20 - GAMEPAD_BUTTON_21 = TU_BIT(21), ///< Button 21 - GAMEPAD_BUTTON_22 = TU_BIT(22), ///< Button 22 - GAMEPAD_BUTTON_23 = TU_BIT(23), ///< Button 23 - GAMEPAD_BUTTON_24 = TU_BIT(24), ///< Button 24 - GAMEPAD_BUTTON_25 = TU_BIT(25), ///< Button 25 - GAMEPAD_BUTTON_26 = TU_BIT(26), ///< Button 26 - GAMEPAD_BUTTON_27 = TU_BIT(27), ///< Button 27 - GAMEPAD_BUTTON_28 = TU_BIT(28), ///< Button 28 - GAMEPAD_BUTTON_29 = TU_BIT(29), ///< Button 29 - GAMEPAD_BUTTON_30 = TU_BIT(30), ///< Button 30 - GAMEPAD_BUTTON_31 = TU_BIT(31), ///< Button 31 + GAMEPAD_BUTTON_0 = TU_BIT(0), + GAMEPAD_BUTTON_1 = TU_BIT(1), + GAMEPAD_BUTTON_2 = TU_BIT(2), + GAMEPAD_BUTTON_3 = TU_BIT(3), + GAMEPAD_BUTTON_4 = TU_BIT(4), + GAMEPAD_BUTTON_5 = TU_BIT(5), + GAMEPAD_BUTTON_6 = TU_BIT(6), + GAMEPAD_BUTTON_7 = TU_BIT(7), + GAMEPAD_BUTTON_8 = TU_BIT(8), + GAMEPAD_BUTTON_9 = TU_BIT(9), + GAMEPAD_BUTTON_10 = TU_BIT(10), + GAMEPAD_BUTTON_11 = TU_BIT(11), + GAMEPAD_BUTTON_12 = TU_BIT(12), + GAMEPAD_BUTTON_13 = TU_BIT(13), + GAMEPAD_BUTTON_14 = TU_BIT(14), + GAMEPAD_BUTTON_15 = TU_BIT(15), + GAMEPAD_BUTTON_16 = TU_BIT(16), + GAMEPAD_BUTTON_17 = TU_BIT(17), + GAMEPAD_BUTTON_18 = TU_BIT(18), + GAMEPAD_BUTTON_19 = TU_BIT(19), + GAMEPAD_BUTTON_20 = TU_BIT(20), + GAMEPAD_BUTTON_21 = TU_BIT(21), + GAMEPAD_BUTTON_22 = TU_BIT(22), + GAMEPAD_BUTTON_23 = TU_BIT(23), + GAMEPAD_BUTTON_24 = TU_BIT(24), + GAMEPAD_BUTTON_25 = TU_BIT(25), + GAMEPAD_BUTTON_26 = TU_BIT(26), + GAMEPAD_BUTTON_27 = TU_BIT(27), + GAMEPAD_BUTTON_28 = TU_BIT(28), + GAMEPAD_BUTTON_29 = TU_BIT(29), + GAMEPAD_BUTTON_30 = TU_BIT(30), + GAMEPAD_BUTTON_31 = TU_BIT(31), }hid_gamepad_button_bm_t; +/// Standard Gamepad Buttons Naming from Linux input event codes +/// https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h +#define GAMEPAD_BUTTON_A GAMEPAD_BUTTON_0 +#define GAMEPAD_BUTTON_SOUTH GAMEPAD_BUTTON_0 + +#define GAMEPAD_BUTTON_B GAMEPAD_BUTTON_1 +#define GAMEPAD_BUTTON_EAST GAMEPAD_BUTTON_1 + +#define GAMEPAD_BUTTON_C GAMEPAD_BUTTON_2 + +#define GAMEPAD_BUTTON_X GAMEPAD_BUTTON_3 +#define GAMEPAD_BUTTON_NORTH GAMEPAD_BUTTON_3 + +#define GAMEPAD_BUTTON_Y GAMEPAD_BUTTON_4 +#define GAMEPAD_BUTTON_WEST GAMEPAD_BUTTON_4 + +#define GAMEPAD_BUTTON_Z GAMEPAD_BUTTON_5 +#define GAMEPAD_BUTTON_TL GAMEPAD_BUTTON_6 +#define GAMEPAD_BUTTON_TR GAMEPAD_BUTTON_7 +#define GAMEPAD_BUTTON_TL2 GAMEPAD_BUTTON_8 +#define GAMEPAD_BUTTON_TR2 GAMEPAD_BUTTON_9 +#define GAMEPAD_BUTTON_SELECT GAMEPAD_BUTTON_10 +#define GAMEPAD_BUTTON_START GAMEPAD_BUTTON_11 +#define GAMEPAD_BUTTON_MODE GAMEPAD_BUTTON_12 +#define GAMEPAD_BUTTON_THUMBL GAMEPAD_BUTTON_13 +#define GAMEPAD_BUTTON_THUMBR GAMEPAD_BUTTON_14 + /// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) typedef enum { -- cgit v1.3.1 From 13cb0160421a6a66429e99ed103afba4f1c345ce Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Jun 2021 16:48:20 +0700 Subject: add usbh_classdriver.h --- src/class/cdc/cdc_host.c | 2 ++ src/class/hid/hid_host.c | 2 ++ src/class/msc/msc_host.c | 2 ++ src/device/usbd_pvt.h | 2 +- src/host/hub.c | 1 + src/host/usbh.c | 7 ++--- src/host/usbh.h | 43 ++----------------------- src/host/usbh_classdriver.h | 76 +++++++++++++++++++++++++++++++++++++++++++++ src/host/usbh_hcd.h | 6 ---- 9 files changed, 89 insertions(+), 52 deletions(-) create mode 100644 src/host/usbh_classdriver.h (limited to 'src') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index facf86d56..dbe5341e9 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -29,6 +29,8 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_CDC) #include "host/usbh.h" +#include "host/usbh_classdriver.h" + #include "cdc_host.h" //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 83f3f3039..ec50f55f9 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -29,6 +29,8 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HID) #include "host/usbh.h" +#include "host/usbh_classdriver.h" + #include "hid_host.h" //--------------------------------------------------------------------+ diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 205f0fd2d..176403e86 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -29,6 +29,8 @@ #if TUSB_OPT_HOST_ENABLED & CFG_TUH_MSC #include "host/usbh.h" +#include "host/usbh_classdriver.h" + #include "msc_host.h" //--------------------------------------------------------------------+ diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 65fdadf51..b8d34d7b6 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -34,7 +34,7 @@ #endif //--------------------------------------------------------------------+ -// Class Drivers +// Class Driver API //--------------------------------------------------------------------+ typedef struct diff --git a/src/host/hub.c b/src/host/hub.c index f921027c7..b2761184d 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -29,6 +29,7 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_HUB) #include "usbh.h" +#include "usbh_classdriver.h" #include "hub.h" //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index ca0653409..ff66d5afd 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -24,7 +24,7 @@ * This file is part of the TinyUSB stack. */ -#include "common/tusb_common.h" +#include "tusb_option.h" #if TUSB_OPT_HOST_ENABLED @@ -32,10 +32,9 @@ #define CFG_TUH_TASK_QUEUE_SZ 16 #endif -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ #include "tusb.h" +#include "host/usbh.h" +#include "host/usbh_classdriver.h" #include "hub.h" #include "usbh_hcd.h" diff --git a/src/host/usbh.h b/src/host/usbh.h index a9790b484..edc9e0808 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -40,27 +40,6 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -typedef enum tusb_interface_status_{ - TUSB_INTERFACE_STATUS_READY = 0, - TUSB_INTERFACE_STATUS_BUSY, - TUSB_INTERFACE_STATUS_COMPLETE, - TUSB_INTERFACE_STATUS_ERROR, - TUSB_INTERFACE_STATUS_INVALID_PARA -} tusb_interface_status_t; - -typedef struct { - #if CFG_TUSB_DEBUG >= 2 - char const* name; - #endif - - uint8_t class_code; - - void (* const init )(void); - bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); - bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); - bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* const close )(uint8_t dev_addr); -} usbh_class_driver_t; typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -101,30 +80,12 @@ bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, //--------------------------------------------------------------------+ //TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); -/** Callback invoked when device is mounted (configured) */ +// Invoked when device is mounted (configured) TU_ATTR_WEAK void tuh_mount_cb (uint8_t dev_addr); -/** Callback invoked when device is unmounted (bus reset/unplugged) */ +/// Invoked when device is unmounted (bus reset/unplugged) TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); -//--------------------------------------------------------------------+ -// CLASS-USBH & INTERNAL API -// TODO move to usbh_pvt.h -//--------------------------------------------------------------------+ - -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); - -// Claim an endpoint before submitting a transfer. -// If caller does not make any transfer, it must release endpoint for others. -bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); - -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); - -uint8_t usbh_get_rhport(uint8_t dev_addr); - -uint8_t* usbh_get_enum_buf(void); - #ifdef __cplusplus } #endif diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h new file mode 100644 index 000000000..2b1523855 --- /dev/null +++ b/src/host/usbh_classdriver.h @@ -0,0 +1,76 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_USBH_CLASSDRIVER_H_ +#define _TUSB_USBH_CLASSDRIVER_H_ + +#include "osal/osal.h" +#include "common/tusb_fifo.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Class Driver API +//--------------------------------------------------------------------+ + +typedef struct { + #if CFG_TUSB_DEBUG >= 2 + char const* name; + #endif + + uint8_t class_code; + + void (* const init )(void); + bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); + bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); + bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + void (* const close )(uint8_t dev_addr); +} usbh_class_driver_t; + +//--------------------------------------------------------------------+ +// USBH Endpoint API +//--------------------------------------------------------------------+ + +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + +// Claim an endpoint before submitting a transfer. +// If caller does not make any transfer, it must release endpoint for others. +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); + +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); + +uint8_t usbh_get_rhport(uint8_t dev_addr); + +uint8_t* usbh_get_enum_buf(void); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index abc7fd250..b3856d6b7 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -97,12 +97,6 @@ typedef struct { extern usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including zero-address -//--------------------------------------------------------------------+ -// callback from HCD ISR -//--------------------------------------------------------------------+ - - - #ifdef __cplusplus } #endif -- cgit v1.3.1 From 7e6cba7359dd362548026578dd48fe1f26312db3 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Jun 2021 16:55:12 +0700 Subject: remove hcd_edpt_stalled() --- src/host/hcd.h | 1 - src/host/usbh.h | 7 +------ src/portable/ehci/ehci.c | 6 ------ src/portable/ohci/ohci.c | 6 ------ src/portable/raspberrypi/rp2040/hcd_rp2040.c | 6 ------ 5 files changed, 1 insertion(+), 25 deletions(-) (limited to 'src') diff --git a/src/host/hcd.h b/src/host/hcd.h index 46209dc45..8cb5b3772 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -139,7 +139,6 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); -bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); //--------------------------------------------------------------------+ diff --git a/src/host/usbh.h b/src/host/usbh.h index edc9e0808..4de6e7ba6 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -24,9 +24,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_usbh USB Host Core (USBH) - * @{ */ - #ifndef _TUSB_USBH_H_ #define _TUSB_USBH_H_ @@ -90,6 +87,4 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); } #endif -#endif /* _TUSB_USBH_H_ */ - -/** @} */ +#endif diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index bcba360bb..be3030676 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -446,12 +446,6 @@ bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) return !p_qhd->qtd_overlay.halted && (p_qhd->p_qtd_list_head != NULL); } -bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) -{ - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - return p_qhd->qtd_overlay.halted && !qhd_has_xact_error(p_qhd); -} - bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index dbd2cc793..cbb72c726 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -495,12 +495,6 @@ bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) return tu_align16(p_ed->td_head.address) != tu_align16(p_ed->td_tail); } -bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) -{ - ohci_ed_t const * const p_ed = ed_from_addr(dev_addr, ep_addr); - return p_ed->td_head.halted && p_ed->is_stalled; -} - bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr); diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 3c62b5732..aeee93324 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -529,12 +529,6 @@ bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) return busy; } -bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) -{ - panic("hcd_pipe_stalled"); - return false; -} - bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { panic("hcd_clear_stall"); -- cgit v1.3.1 From c7f51cde40afbefe3f1d57b9dbdaaca0abed424e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Jun 2021 17:19:21 +0700 Subject: implement usbh_edpt_busy (WIP), remove hcd_edpt_busy --- src/class/cdc/cdc_host.c | 10 +++--- src/class/hid/hid_host.c | 2 +- src/class/msc/msc_host.c | 2 +- src/device/dcd.h | 2 +- src/device/usbd.c | 4 +-- src/host/hcd.h | 2 -- src/host/usbh.c | 46 ++++++++++++++++++++++++++-- src/host/usbh_classdriver.h | 19 ++++++++---- src/portable/ehci/ehci.c | 6 ---- src/portable/ohci/ohci.c | 6 ---- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 26 ++++++++-------- 11 files changed, 79 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index dbe5341e9..33f1a8ad3 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -73,13 +73,13 @@ bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid) switch (pipeid) { case CDC_PIPE_NOTIFICATION: - return hcd_edpt_busy(dev_addr, p_cdc->ep_notif ); + return usbh_edpt_busy(dev_addr, p_cdc->ep_notif ); case CDC_PIPE_DATA_IN: - return hcd_edpt_busy(dev_addr, p_cdc->ep_in ); + return usbh_edpt_busy(dev_addr, p_cdc->ep_in ); case CDC_PIPE_DATA_OUT: - return hcd_edpt_busy(dev_addr, p_cdc->ep_out ); + return usbh_edpt_busy(dev_addr, p_cdc->ep_out ); default: return false; @@ -103,7 +103,7 @@ bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool i TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA); uint8_t const ep_out = cdch_data[dev_addr-1].ep_out; - if ( hcd_edpt_busy(dev_addr, ep_out) ) return false; + if ( usbh_edpt_busy(dev_addr, ep_out) ) return false; return usbh_edpt_xfer(dev_addr, ep_out, (void *) p_data, length); } @@ -115,7 +115,7 @@ bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA); uint8_t const ep_in = cdch_data[dev_addr-1].ep_in; - if ( hcd_edpt_busy(dev_addr, ep_in) ) return false; + if ( usbh_edpt_busy(dev_addr, ep_in) ) return false; return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, length); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index ec50f55f9..cde5e23a5 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -201,7 +201,7 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u // TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance)); // // hidh_interface_t* hid_itf = get_instance(dev_addr, instance); -// return !hcd_edpt_busy(dev_addr, hid_itf->ep_in); +// return !usbh_edpt_busy(dev_addr, hid_itf->ep_in); //} //void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 176403e86..7f98ef9b1 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -111,7 +111,7 @@ bool tuh_msc_mounted(uint8_t dev_addr) bool tuh_msc_ready(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted && !hcd_edpt_busy(dev_addr, p_msc->ep_in); + return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in); } //--------------------------------------------------------------------+ diff --git a/src/device/dcd.h b/src/device/dcd.h index e17c62d4e..63e97df96 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -122,7 +122,7 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; // Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); // Close an endpoint. // Since it is weak, caller must TU_ASSERT this function's existence before calling it. diff --git a/src/device/usbd.c b/src/device/usbd.c index 71c5d4e6c..2935defd0 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1248,8 +1248,8 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); - // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return - // and usbd task can preempt and clear the busy + // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() + // could return and USBD task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ) diff --git a/src/host/hcd.h b/src/host/hcd.h index 8cb5b3772..7a9aadc73 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -137,8 +137,6 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); - -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index ff66d5afd..59246a663 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -314,8 +314,11 @@ uint8_t* usbh_get_enum_buf(void) return _usbh_ctrl_buf; } -//------------- Endpoint API -------------// +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ +// TODO has some duplication code with device, refactor later bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -343,6 +346,7 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) return ret; } +// TODO has some duplication code with device, refactor later bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -368,11 +372,36 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) return ret; } +// TODO has some duplication code with device, refactor later bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + usbh_device_t* dev = &_usbh_devices[dev_addr]; - TU_LOG2(" Queue EP %02X with %u bytes ... OK\r\n", ep_addr, total_bytes); - return hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes); + + TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); + + // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() + // could return and USBH task can preempt and clear the busy + dev->ep_status[epnum][dir].busy = true; + + if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + // HCD error, mark endpoint as ready to allow next transfer + dev->ep_status[epnum][dir].busy = false; + dev->ep_status[epnum][dir].claimed = 0; + TU_LOG2("failed\r\n"); + TU_BREAKPOINT(); + return false; + } } bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) @@ -419,6 +448,17 @@ bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return ret; } +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + return dev->ep_status[epnum][dir].busy; +} + + //--------------------------------------------------------------------+ // HCD Event Handler //--------------------------------------------------------------------+ diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index 2b1523855..07480fe8e 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -52,22 +52,29 @@ typedef struct { void (* const close )(uint8_t dev_addr); } usbh_class_driver_t; +// Call by class driver to tell USBH that it has complete the enumeration +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); + +uint8_t usbh_get_rhport(uint8_t dev_addr); + +uint8_t* usbh_get_enum_buf(void); + //--------------------------------------------------------------------+ // USBH Endpoint API //--------------------------------------------------------------------+ -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +// Open an endpoint +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep); + +// Submit a usb transfer bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); - -uint8_t usbh_get_rhport(uint8_t dev_addr); - -uint8_t* usbh_get_enum_buf(void); +// Check if endpoint transferring is complete +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); #ifdef __cplusplus } diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index be3030676..48788ba06 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -440,12 +440,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * return true; } -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - return !p_qhd->qtd_overlay.halted && (p_qhd->p_qtd_list_head != NULL); -} - bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index cbb72c726..73489c764 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -489,12 +489,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * return true; } -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - ohci_ed_t const * const p_ed = ed_from_addr(dev_addr, ep_addr); - return tu_align16(p_ed->td_head.address) != tu_align16(p_ed->td_tail); -} - bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr); diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index aeee93324..b575c6afc 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -515,19 +515,19 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } -bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - // EPX is shared, so multiple device addresses and endpoint addresses share that - // so if any transfer is active on epx, we are busy. Interrupt endpoints have their own - // EPX so ep->active will only be busy if there is a pending transfer on that interrupt endpoint - // on that device - pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\n", dev_addr, ep_addr); - struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); - assert(ep); - bool busy = ep->active; - pico_trace("busy == %d\n", busy); - return busy; -} +//bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +//{ +// // EPX is shared, so multiple device addresses and endpoint addresses share that +// // so if any transfer is active on epx, we are busy. Interrupt endpoints have their own +// // EPX so ep->active will only be busy if there is a pending transfer on that interrupt endpoint +// // on that device +// pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\n", dev_addr, ep_addr); +// struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); +// assert(ep); +// bool busy = ep->active; +// pico_trace("busy == %d\n", busy); +// return busy; +//} bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { -- cgit v1.3.1 From cf0a475a2e501f21638369eca6ceb090ef47bd51 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Jun 2021 22:00:59 +0700 Subject: clean up --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 101 +++++++++++++++------------ 1 file changed, 56 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index b575c6afc..7042160ec 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -52,22 +52,23 @@ static_assert(PICO_USB_HOST_INTERRUPT_ENDPOINTS <= USB_MAX_ENDPOINTS, ""); // Host mode uses one shared endpoint register for non-interrupt endpoint -struct hw_endpoint eps[1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS]; -#define epx (eps[0]) +static struct hw_endpoint ep_pool[1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS]; +#define epx (ep_pool[0]) -#define usb_hw_set hw_set_alias(usb_hw) +#define usb_hw_set hw_set_alias(usb_hw) #define usb_hw_clear hw_clear_alias(usb_hw) -// Used for hcd pipe busy. // todo still a bit wasteful // top bit set if valid uint8_t dev_ep_map[CFG_TUSB_HOST_DEVICE_MAX][1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS][2]; // Flags we set by default in sie_ctrl (we add other bits on top) -static uint32_t sie_ctrl_base = USB_SIE_CTRL_SOF_EN_BITS | - USB_SIE_CTRL_KEEP_ALIVE_EN_BITS | - USB_SIE_CTRL_PULLDOWN_EN_BITS | - USB_SIE_CTRL_EP0_INT_1BUF_BITS; +enum { + sie_ctrl_base = USB_SIE_CTRL_SOF_EN_BITS | + USB_SIE_CTRL_KEEP_ALIVE_EN_BITS | + USB_SIE_CTRL_PULLDOWN_EN_BITS | + USB_SIE_CTRL_EP0_INT_1BUF_BITS +}; static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr) { @@ -78,19 +79,22 @@ static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr) uint8_t in = (ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0; uint mapping = dev_ep_map[dev_addr-1][num][in]; pico_trace("Get dev addr %d ep %d = %d\n", dev_addr, ep_addr, mapping); - return mapping >= 128 ? eps + (mapping & 0x7fu) : NULL; + return mapping >= 128 ? ep_pool + (mapping & 0x7fu) : NULL; } static void set_dev_ep(uint8_t dev_addr, uint8_t ep_addr, struct hw_endpoint *ep) { uint8_t num = tu_edpt_number(ep_addr); - uint8_t in = (ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0; - uint32_t index = ep - eps; - hard_assert(index < TU_ARRAY_SIZE(eps)); + uint8_t in = (uint8_t) tu_edpt_dir(ep_addr); + + uint32_t index = ep - ep_pool; + hard_assert(index < TU_ARRAY_SIZE(ep_pool)); + // todo revisit why dev_addr can be 0 here if (dev_addr) { dev_ep_map[dev_addr-1][num][in] = 128u | index; } + pico_trace("Set dev addr %d ep %d = %d\n", dev_addr, ep_addr, index); } @@ -153,7 +157,7 @@ static void hw_handle_buff_status(void) if (remaining_buffers & bit) { remaining_buffers &= ~bit; - _handle_buff_status_bit(bit, &eps[i]); + _handle_buff_status_bit(bit, &ep_pool[i]); } } @@ -206,13 +210,15 @@ static void hcd_rp2040_irq(void) { handled |= USB_INTS_TRANS_COMPLETE_BITS; usb_hw_clear->sie_status = USB_SIE_STATUS_TRANS_COMPLETE_BITS; + TU_LOG(2, "Transfer complete\n"); hw_trans_complete(); } if (status & USB_INTS_BUFF_STATUS_BITS) { handled |= USB_INTS_BUFF_STATUS_BITS; - // print_bufctrl32(*epx.buffer_control); + TU_LOG(2, "Buffer complete\n"); + print_bufctrl32(*epx.buffer_control); hw_handle_buff_status(); } @@ -234,7 +240,7 @@ static void hcd_rp2040_irq(void) if (status & USB_INTS_ERROR_DATA_SEQ_BITS) { usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS; - // print_bufctrl32(*epx.buffer_control); + print_bufctrl32(*epx.buffer_control); panic("Data Seq Error \n"); } @@ -247,9 +253,9 @@ static void hcd_rp2040_irq(void) static struct hw_endpoint *_next_free_interrupt_ep(void) { struct hw_endpoint *ep = NULL; - for (uint i = 1; i < TU_ARRAY_SIZE(eps); i++) + for (uint i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) { - ep = &eps[i]; + ep = &ep_pool[i]; if (!ep->configured) { // Will be configured by _hw_endpoint_init / _hw_endpoint_allocate @@ -263,6 +269,7 @@ static struct hw_endpoint *_next_free_interrupt_ep(void) static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type) { struct hw_endpoint *ep = NULL; + if (transfer_type == TUSB_XFER_INTERRUPT) { ep = _next_free_interrupt_ep(); @@ -283,6 +290,7 @@ static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type) ep->endpoint_control = &usbh_dpram->epx_ctrl; ep->hw_data_buf = &usbh_dpram->epx_data[0]; } + return ep; } @@ -345,24 +353,9 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t // If it's an interrupt endpoint we need to set up the buffer control // register - } } -static void hw_endpoint_init(uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc) -{ - // Allocated differently based on if it's an interrupt endpoint or not - struct hw_endpoint *ep = _hw_endpoint_allocate(ep_desc->bmAttributes.xfer); - _hw_endpoint_init(ep, - dev_addr, - ep_desc->bEndpointAddress, - ep_desc->wMaxPacketSize.size, - ep_desc->bmAttributes.xfer, - ep_desc->bInterval); - // Map this struct to ep@device address - set_dev_ep(dev_addr, ep_desc->bEndpointAddress, ep); -} - //--------------------------------------------------------------------+ // HCD API //--------------------------------------------------------------------+ @@ -377,7 +370,7 @@ bool hcd_init(uint8_t rhport) irq_set_exclusive_handler(USBCTRL_IRQ, hcd_rp2040_irq); // clear epx and interrupt eps - memset(&eps, 0, sizeof(eps)); + memset(&ep_pool, 0, sizeof(ep_pool)); // Enable in host mode with SOF / Keep alive on usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS | USB_MAIN_CTRL_HOST_NDEVICE_BITS; @@ -420,6 +413,7 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) return TUSB_SPEED_FULL; default: panic("Invalid speed\n"); + return TUSB_SPEED_INVALID; } } @@ -444,7 +438,7 @@ void hcd_int_disable(uint8_t rhport) bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { - pico_info("hcd_edpt_xfer dev_addr %d, ep_addr 0x%x, len %d\n", dev_addr, ep_addr, buflen); + pico_trace("hcd_edpt_xfer dev_addr %d, ep_addr 0x%x, len %d\n", dev_addr, ep_addr, buflen); // Get appropriate ep. Either EPX or interrupt endpoint struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); @@ -452,13 +446,12 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * if (ep_addr != ep->ep_addr) { - // Direction has flipped so re init it but with same properties - // TODO treat IN and OUT as invidual endpoints + // Direction has flipped on endpoint control so re init it but with same properties _hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, ep->transfer_type, 0); } // True indicates this is the start of the transfer - _hw_endpoint_xfer(ep, buffer, buflen, true); + _hw_endpoint_xfer_start(ep, buffer, buflen); // If a normal transfer (non-interrupt) then initiate using // sie ctrl registers. Otherwise interrupt ep registers should @@ -479,27 +472,30 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { - pico_info("hcd_setup_send dev_addr %d\n", dev_addr); - // Copy data into setup packet buffer memcpy((void*)&usbh_dpram->setup_packet[0], setup_packet, 8); // Configure EP0 struct with setup info for the trans complete struct hw_endpoint *ep = _hw_endpoint_allocate(0); + // EP0 out _hw_endpoint_init(ep, dev_addr, 0x00, ep->wMaxPacketSize, 0, 0); assert(ep->configured); - ep->total_len = 8; + + ep->total_len = 8; ep->transfer_size = 8; - ep->active = true; - ep->sent_setup = true; + ep->active = true; + ep->sent_setup = true; // Set device address usb_hw->dev_addr_ctrl = dev_addr; + // Set pre if we are a low speed device on full speed hub - uint32_t flags = sie_ctrl_base | USB_SIE_CTRL_SEND_SETUP_BITS | USB_SIE_CTRL_START_TRANS_BITS; - flags |= need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0; + uint32_t const flags = sie_ctrl_base | USB_SIE_CTRL_SEND_SETUP_BITS | USB_SIE_CTRL_START_TRANS_BITS | + (need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); + usb_hw->sie_ctrl = flags; + return true; } @@ -510,8 +506,23 @@ uint32_t hcd_frame_number(uint8_t rhport) bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { + (void) rhport; + pico_trace("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, ep_desc->bEndpointAddress); - hw_endpoint_init(dev_addr, ep_desc); + + // Allocated differently based on if it's an interrupt endpoint or not + struct hw_endpoint *ep = _hw_endpoint_allocate(ep_desc->bmAttributes.xfer); + + _hw_endpoint_init(ep, + dev_addr, + ep_desc->bEndpointAddress, + ep_desc->wMaxPacketSize.size, + ep_desc->bmAttributes.xfer, + ep_desc->bInterval); + + // Map this struct to ep@device address + set_dev_ep(dev_addr, ep_desc->bEndpointAddress, ep); + return true; } -- cgit v1.3.1 From 43656dc0a7a613f8d5f6533d2c68ca9f5824a5f4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Jun 2021 23:29:02 +0700 Subject: more clean up --- src/host/usbh_control.c | 2 +- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 77 +++++++++++++++++----------- 2 files changed, 48 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 4dbf8592a..aa82f14ba 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -68,7 +68,7 @@ bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, _ctrl_xfer.stage = STAGE_SETUP; _ctrl_xfer.complete_cb = complete_cb; - TU_LOG2("Control Setup: "); + TU_LOG2("Send Setup to address %u: ", dev_addr); TU_LOG2_VAR(request); TU_LOG2("\r\n"); diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 7042160ec..d6bcf5b82 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -420,9 +420,18 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) // Close all opened endpoint belong to this device void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { + (void) rhport; + (void) dev_addr; + pico_trace("hcd_device_close %d\n", dev_addr); } +uint32_t hcd_frame_number(uint8_t rhport) +{ + (void) rhport; + return usb_hw->sof_rd; +} + void hcd_int_enable(uint8_t rhport) { assert(rhport == 0); @@ -436,10 +445,37 @@ void hcd_int_disable(uint8_t rhport) irq_set_enabled(USBCTRL_IRQ, false); } +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +{ + (void) rhport; + + pico_trace("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, ep_desc->bEndpointAddress); + + // Allocated differently based on if it's an interrupt endpoint or not + struct hw_endpoint *ep = _hw_endpoint_allocate(ep_desc->bmAttributes.xfer); + + _hw_endpoint_init(ep, + dev_addr, + ep_desc->bEndpointAddress, + ep_desc->wMaxPacketSize.size, + ep_desc->bmAttributes.xfer, + ep_desc->bInterval); + + // Map this struct to ep@device address + set_dev_ep(dev_addr, ep_desc->bEndpointAddress, ep); + + return true; +} + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { + (void) rhport; + pico_trace("hcd_edpt_xfer dev_addr %d, ep_addr 0x%x, len %d\n", dev_addr, ep_addr, buflen); + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_t const ep_dir = tu_edpt_dir(ep_addr); + // Get appropriate ep. Either EPX or interrupt endpoint struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); assert(ep); @@ -450,7 +486,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * _hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, ep->transfer_type, 0); } - // True indicates this is the start of the transfer + // Start the transfer _hw_endpoint_xfer_start(ep, buffer, buflen); // If a normal transfer (non-interrupt) then initiate using @@ -459,11 +495,13 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * if (ep == &epx) { // That has set up buffer control, endpoint control etc // for host we have to initiate the transfer - usb_hw->dev_addr_ctrl = dev_addr | (tu_edpt_number(ep_addr) << USB_ADDR_ENDP_ENDPOINT_LSB); - uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | sie_ctrl_base; - flags |= ep->rx ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS; + usb_hw->dev_addr_ctrl = dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB); + + uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | sie_ctrl_base | + (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS); // Set pre if we are a low speed device on full speed hub flags |= need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0; + usb_hw->sie_ctrl = flags; } @@ -472,6 +510,8 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { + (void) rhport; + // Copy data into setup packet buffer memcpy((void*)&usbh_dpram->setup_packet[0], setup_packet, 8); @@ -499,32 +539,6 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet return true; } -uint32_t hcd_frame_number(uint8_t rhport) -{ - return usb_hw->sof_rd; -} - -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; - - pico_trace("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, ep_desc->bEndpointAddress); - - // Allocated differently based on if it's an interrupt endpoint or not - struct hw_endpoint *ep = _hw_endpoint_allocate(ep_desc->bmAttributes.xfer); - - _hw_endpoint_init(ep, - dev_addr, - ep_desc->bEndpointAddress, - ep_desc->wMaxPacketSize.size, - ep_desc->bmAttributes.xfer, - ep_desc->bInterval); - - // Map this struct to ep@device address - set_dev_ep(dev_addr, ep_desc->bEndpointAddress, ep); - - return true; -} //bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) //{ @@ -542,6 +556,9 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + (void) dev_addr; + panic("hcd_clear_stall"); return true; } -- cgit v1.3.1 From a1a03c92f66e0c2cae5198341c322182302a1229 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Jun 2021 17:05:49 +0700 Subject: double buffered work with host --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 10 +- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 103 ++++++++-- src/portable/raspberrypi/rp2040/rp2040_usb.c | 285 +++++++++++++-------------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 15 +- 4 files changed, 242 insertions(+), 171 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 0048270a6..ccdbb9c01 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -198,10 +198,10 @@ static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t b _hw_endpoint_init(ep, ep_addr, wMaxPacketSize, bmAttributes); } -static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool start) +static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); - _hw_endpoint_xfer(ep, buffer, total_bytes, start); + _hw_endpoint_xfer_start(ep, buffer, total_bytes); } static void hw_handle_buff_status(void) @@ -251,7 +251,7 @@ static void ep0_0len_status(void) { // Send 0len complete response on EP0 IN reset_ep0(); - hw_endpoint_xfer(0x80, NULL, 0, true); + hw_endpoint_xfer(0x80, NULL, 0); } static void _hw_endpoint_stall(struct hw_endpoint *ep) @@ -477,7 +477,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { - pico_trace("Set HW address %d\n", assigned_address); + pico_trace("Set HW address %d\n", request->wValue); usb_hw->dev_addr_ctrl = (uint8_t) request->wValue; } @@ -496,7 +496,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t { assert(rhport == 0); // True means start new xfer - hw_endpoint_xfer(ep_addr, buffer, total_bytes, true); + hw_endpoint_xfer(ep_addr, buffer, total_bytes); return true; } diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index d6bcf5b82..561656a10 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -115,9 +115,9 @@ static void hw_xfer_complete(struct hw_endpoint *ep, xfer_result_t xfer_result) // Mark transfer as done before we tell the tinyusb stack uint8_t dev_addr = ep->dev_addr; uint8_t ep_addr = ep->ep_addr; - uint total_len = ep->total_len; + uint xferred_len = ep->len; hw_endpoint_reset_transfer(ep); - hcd_event_xfer_complete(dev_addr, ep_addr, total_len, xfer_result, true); + hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, xfer_result, true); } static void _handle_buff_status_bit(uint bit, struct hw_endpoint *ep) @@ -141,6 +141,20 @@ static void hw_handle_buff_status(void) { remaining_buffers &= ~bit; struct hw_endpoint *ep = &epx; + + uint32_t ep_ctrl = *ep->endpoint_control; + if (ep_ctrl & EP_CTRL_DOUBLE_BUFFERED_BITS) + { + TU_LOG(2, "Double Buffered "); + }else + { + TU_LOG(2, "Single Buffered "); + } + + if (ep_ctrl & EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER) TU_LOG(2, "Interrupt per double "); + if (ep_ctrl & EP_CTRL_INTERRUPT_PER_BUFFER) TU_LOG(2, "Interrupt per single "); + TU_LOG_HEX(2, ep_ctrl); + _handle_buff_status_bit(bit, ep); } @@ -277,11 +291,11 @@ static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type) assert(ep); ep->buffer_control = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl; ep->endpoint_control = &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl; - // 0x180 for epx - // 0x1c0 for intep0 - // 0x200 for intep1 + // 0 for epx (double buffered): TODO increase to 1024 for ISO + // 2x64 for intep0 + // 3x64 for intep1 // etc - ep->hw_data_buf = &usbh_dpram->epx_data[64 * (ep->interrupt_num + 1)]; + ep->hw_data_buf = &usbh_dpram->epx_data[64 * (ep->interrupt_num + 2)]; } else { @@ -311,7 +325,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t ep->rx = (dir == TUSB_DIR_IN); // Response to a setup packet on EP0 starts with pid of 1 - ep->next_pid = num == 0 ? 1u : 0u; + ep->next_pid = (num == 0 ? 1u : 0u); ep->wMaxPacketSize = wMaxPacketSize; ep->transfer_type = transfer_type; @@ -340,6 +354,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t // preamble uint32_t reg = dev_addr | (num << USB_ADDR_ENDP1_ENDPOINT_LSB); // Assert the interrupt endpoint is IN_TO_HOST + // TODO Interrupt can also be OUT assert(dir == TUSB_DIR_IN); if (need_pre(dev_addr)) @@ -402,7 +417,6 @@ bool hcd_port_connect_status(uint8_t rhport) tusb_speed_t hcd_port_speed_get(uint8_t rhport) { - pico_trace("hcd_port_speed_get\n"); assert(rhport == 0); // TODO: Should enumval this register switch (dev_speed()) @@ -445,6 +459,10 @@ void hcd_int_disable(uint8_t rhport) irq_set_enabled(USBCTRL_IRQ, false); } +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { (void) rhport; @@ -467,6 +485,65 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } +// return true if double buffered +static bool xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len) +{ + // Fill in info now that we're kicking off the hw + ep->total_len = total_len; + ep->len = 0; + + // Limit by packet size + ep->user_buf = buffer; + + // Buffer 0 + ep->transfer_size = tu_min16(total_len, ep->wMaxPacketSize); + total_len -= ep->transfer_size; + + // Buffer 1 + ep->buf_1_len = tu_min16(total_len, ep->wMaxPacketSize); + total_len -= ep->buf_1_len; + + ep->active = true; + + // Write buffer control + + // Buffer 0 + uint32_t bufctrl = ep->transfer_size | USB_BUF_CTRL_AVAIL; + + // Copy data to DPB if tx + if (!ep->rx) + { + // Copy data from user buffer to hw buffer + memcpy(ep->hw_data_buf, ep->user_buf, ep->transfer_size + ep->buf_1_len); + + // Mark as full + bufctrl |= USB_BUF_CTRL_FULL | (ep->buf_1_len ? (USB_BUF_CTRL_FULL << 16) : 0); + } + + // PID + bufctrl |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; + ep->next_pid ^= 1u; + + if (ep->buf_1_len) + { + bufctrl |= (ep->buf_1_len | USB_BUF_CTRL_AVAIL) << 16; + bufctrl |= (ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID) << 16; + ep->next_pid ^= 1u; + } + + // determine which buffer is last + if (total_len == 0) + { + bufctrl |= USB_BUF_CTRL_LAST << (ep->buf_1_len ? 16 : 0); + } + + print_bufctrl32(bufctrl); + + _hw_endpoint_buffer_control_set_value32(ep, bufctrl); + + return ep->buf_1_len > 0; +} + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { (void) rhport; @@ -486,13 +563,12 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * _hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, ep->transfer_type, 0); } - // Start the transfer - _hw_endpoint_xfer_start(ep, buffer, buflen); - // If a normal transfer (non-interrupt) then initiate using // sie ctrl registers. Otherwise interrupt ep registers should // already be configured if (ep == &epx) { + _hw_endpoint_xfer_start(ep, buffer, buflen); + // That has set up buffer control, endpoint control etc // for host we have to initiate the transfer usb_hw->dev_addr_ctrl = dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB); @@ -503,6 +579,9 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * flags |= need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0; usb_hw->sie_ctrl = flags; + }else + { + _hw_endpoint_xfer_start(ep, buffer, buflen); } return true; @@ -556,8 +635,8 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { - (void) rhport; (void) dev_addr; + (void) ep_addr; panic("hcd_clear_stall"); return true; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 31381e6c2..5f61f90c5 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -61,11 +61,11 @@ void rp2040_usb_init(void) memset(usb_dpram, 0, sizeof(*usb_dpram)); // Mux the controller to the onboard usb phy - usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; + usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; // Force VBUS detect so the device thinks it is plugged into a host // TODO support VBUs detect - usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; + usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; } void hw_endpoint_reset_transfer(struct hw_endpoint *ep) @@ -111,150 +111,157 @@ void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_m *ep->buffer_control = value; } +// Prepare buffer control register value void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) { - // Prepare buffer control register value - uint32_t val = ep->transfer_size | USB_BUF_CTRL_AVAIL; - - if (!ep->rx) - { - // Copy data from user buffer to hw buffer - memcpy(ep->hw_data_buf, &ep->user_buf[ep->len], ep->transfer_size); - // Mark as full - val |= USB_BUF_CTRL_FULL; - } - - // PID - val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; - -#if TUSB_OPT_DEVICE_ENABLED + uint16_t remaining = ep->total_len - ep->len; + uint32_t ep_ctrl = *ep->endpoint_control; + uint32_t buf_ctrl; + + // Buffer 0 + ep->transfer_size = tu_min16(remaining, ep->wMaxPacketSize); + remaining -= ep->transfer_size; + + buf_ctrl = ep->transfer_size | USB_BUF_CTRL_AVAIL; + if ( !ep->rx ) + { + // Copy data from user buffer to hw buffer + memcpy(ep->hw_data_buf, ep->user_buf+ep->len, ep->transfer_size); + + // Mark as full + buf_ctrl |= USB_BUF_CTRL_FULL; + } + + // PID + buf_ctrl |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; + ep->next_pid ^= 1u; + + // Buffer 1 + ep->buf_1_len = tu_min16(remaining, ep->wMaxPacketSize); + remaining -= ep->buf_1_len; + + if (ep->buf_1_len) + { + buf_ctrl |= (ep->buf_1_len | USB_BUF_CTRL_AVAIL) << 16; + buf_ctrl |= (ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID) << 16; ep->next_pid ^= 1u; -#else - // For Host (also device but since we dictate the endpoint size, following scenario does not occur) - // Next PID depends on the number of packet in case wMaxPacketSize < 64 (e.g Interrupt Endpoint 8, or 12) - // Special case with control status stage where PID is always DATA1 - if ( ep->transfer_size == 0 ) - { - // ZLP also toggle data - ep->next_pid ^= 1u; - }else + if ( !ep->rx ) { - uint32_t packet_count = 1 + ((ep->transfer_size - 1) / ep->wMaxPacketSize); - - if ( packet_count & 0x01 ) - { - ep->next_pid ^= 1u; - } + // Copy data from user buffer to hw buffer + memcpy(ep->hw_data_buf+64, ep->user_buf+ep->len+ep->transfer_size, ep->buf_1_len); } -#endif + // Set endpoint control double buffered bit if needed + ep_ctrl &= ~EP_CTRL_INTERRUPT_PER_BUFFER; + ep_ctrl |= EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER; + }else + { + ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER); + ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER; + } + + *ep->endpoint_control = ep_ctrl; #if TUSB_OPT_HOST_ENABLED - // Is this the last buffer? Only really matters for host mode. Will trigger - // the trans complete irq but also stop it polling. We only really care about - // trans complete for setup packets being sent - if (ep->last_buf) - { - pico_trace("Last buf (%d bytes left)\n", ep->transfer_size); - val |= USB_BUF_CTRL_LAST; - } + // Is this the last buffer? Only really matters for host mode. Will trigger + // the trans complete irq but also stop it polling. We only really care about + // trans complete for setup packets being sent + if (remaining == 0) + { + buf_ctrl |= USB_BUF_CTRL_LAST << (ep->buf_1_len ? 16 : 0); + } #endif - // Finally, write to buffer_control which will trigger the transfer - // the next time the controller polls this dpram address - _hw_endpoint_buffer_control_set_value32(ep, val); - pico_trace("buffer control (0x%p) <- 0x%x\n", ep->buffer_control, val); - //print_bufctrl16(val); + print_bufctrl32(buf_ctrl); + + // Finally, write to buffer_control which will trigger the transfer + // the next time the controller polls this dpram address + _hw_endpoint_buffer_control_set_value32(ep, buf_ctrl); } void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len) { - _hw_endpoint_lock_update(ep, 1); - pico_trace("Start transfer of total len %d on ep %d %s\n", total_len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); - if (ep->active) - { - // TODO: Is this acceptable for interrupt packets? - pico_warn("WARN: starting new transfer on already active ep %d %s\n", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); - - hw_endpoint_reset_transfer(ep); - } - - // Fill in info now that we're kicking off the hw - ep->total_len = total_len; - ep->len = 0; - - // Limit by packet size but not less 64 (i.e low speed 8 bytes EP0) - ep->transfer_size = tu_min16(total_len, tu_max16(64, ep->wMaxPacketSize)); - - ep->active = true; - ep->user_buf = buffer; -#if TUSB_OPT_HOST_ENABLED - // Recalculate if this is the last buffer - _hw_endpoint_update_last_buf(ep); - ep->buf_sel = 0; -#endif - - _hw_endpoint_start_next_buffer(ep); - _hw_endpoint_lock_update(ep, -1); + _hw_endpoint_lock_update(ep, 1); + pico_trace("Start transfer of total len %d on ep %d %s\n", total_len, tu_edpt_number(ep->ep_addr), + ep_dir_string[tu_edpt_dir(ep->ep_addr)]); + if ( ep->active ) + { + // TODO: Is this acceptable for interrupt packets? + pico_warn("WARN: starting new transfer on already active ep %d %s\n", tu_edpt_number(ep->ep_addr), + ep_dir_string[tu_edpt_dir(ep->ep_addr)]); + + hw_endpoint_reset_transfer(ep); + } + + // Fill in info now that we're kicking off the hw + ep->total_len = total_len; + ep->len = 0; + ep->active = true; + ep->user_buf = buffer; + + _hw_endpoint_start_next_buffer(ep); + _hw_endpoint_lock_update(ep, -1); } -void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) +void _hw_endpoint_xfer_sync (struct hw_endpoint *ep) { - // Update hw endpoint struct with info from hardware - // after a buff status interrupt - - uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); - -#if TUSB_OPT_HOST_ENABLED - // RP2040-E4 - // tag::host_buf_sel_fix[] - // TODO need changes to support double buffering - if (ep->buf_sel == 1) + // Update hw endpoint struct with info from hardware + // after a buff status interrupt + + uint32_t const buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); + print_bufctrl32(buf_ctrl); + + // Transferred bytes for each buffer + uint16_t xferred_bytes[2]; + + xferred_bytes[0] = buf_ctrl & USB_BUF_CTRL_LEN_MASK; + + // double buffered: take buffer1 into account as well + if ( (*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS ) + { + xferred_bytes[1] = (buf_ctrl >> 16) & USB_BUF_CTRL_LEN_MASK; + }else + { + xferred_bytes[1] = 0; + } + + TU_LOG_INT(2, xferred_bytes[0]); + TU_LOG_INT(2, xferred_bytes[1]); + + // We are continuing a transfer here. If we are TX, we have successfully + // sent some data can increase the length we have sent + if ( !ep->rx ) + { + assert(!(buf_ctrl & USB_BUF_CTRL_FULL)); + ep->len += xferred_bytes[0] + xferred_bytes[1]; + } + else + { + // If we are OUT we have recieved some data, so can increase the length + // we have recieved AFTER we have copied it to the user buffer at the appropriate offset + assert(buf_ctrl & USB_BUF_CTRL_FULL); + + memcpy(&ep->user_buf[ep->len], ep->hw_data_buf, xferred_bytes[0]); + ep->len += xferred_bytes[0]; + + if (xferred_bytes[1]) { - // Host can erroneously write status to top half of buf_ctrl register - buf_ctrl = buf_ctrl >> 16; - - // update buf1 -> buf0 to prevent panic with "already available" - *ep->buffer_control = buf_ctrl; - } - // Flip buf sel for host - ep->buf_sel ^= 1u; - // end::host_buf_sel_fix[] -#endif - - // Get tranferred bytes after adjusted buf sel - uint16_t const transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; - - // We are continuing a transfer here. If we are TX, we have successfullly - // sent some data can increase the length we have sent - if (!ep->rx) - { - assert(!(buf_ctrl & USB_BUF_CTRL_FULL)); - pico_trace("tx %d bytes (buf_ctrl 0x%08x)\n", transferred_bytes, buf_ctrl); - ep->len += transferred_bytes; - } - else - { - // If we are OUT we have recieved some data, so can increase the length - // we have recieved AFTER we have copied it to the user buffer at the appropriate - // offset - pico_trace("rx %d bytes (buf_ctrl 0x%08x)\n", transferred_bytes, buf_ctrl); - assert(buf_ctrl & USB_BUF_CTRL_FULL); - memcpy(&ep->user_buf[ep->len], ep->hw_data_buf, transferred_bytes); - ep->len += transferred_bytes; - } - - // Sometimes the host will send less data than we expect... - // If this is a short out transfer update the total length of the transfer - // to be the current length - if ((ep->rx) && (transferred_bytes < ep->wMaxPacketSize)) - { - pico_trace("Short rx transfer\n"); - // Reduce total length as this is last packet - ep->total_len = ep->len; + memcpy(&ep->user_buf[ep->len], ep->hw_data_buf+64, xferred_bytes[1]); + ep->len += xferred_bytes[1]; } + } + + // Sometimes the host will send less data than we expect... + // If this is a short out transfer update the total length of the transfer + // to be the current length + if ( (ep->rx) && ((xferred_bytes[0] < ep->wMaxPacketSize) || (xferred_bytes[1] && (xferred_bytes[1] < ep->wMaxPacketSize))) ) + { + pico_trace("Short rx transfer\n"); + // Reduce total length as this is last packet + ep->total_len = ep->len; + } } // Returns true if transfer is complete @@ -271,12 +278,11 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) _hw_endpoint_xfer_sync(ep); // Now we have synced our state with the hardware. Is there more data to transfer? - // Limit by packet size but not less 64 (i.e low speed 8 bytes EP0) + // Limit by packet size uint16_t remaining_bytes = ep->total_len - ep->len; - ep->transfer_size = tu_min16(remaining_bytes, tu_max16(64, ep->wMaxPacketSize)); -#if TUSB_OPT_HOST_ENABLED - _hw_endpoint_update_last_buf(ep); -#endif + ep->transfer_size = tu_min16(remaining_bytes, ep->wMaxPacketSize); + + TU_LOG_INT(2, ep->transfer_size); // Can happen because of programmer error so check for it if (ep->len > ep->total_len) @@ -303,23 +309,4 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) return false; } -void _hw_endpoint_xfer(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len, bool start) -{ - // Trace - pico_trace("hw_endpoint_xfer ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); - pico_trace(" total_len %d, start=%d\n", total_len, start); - - assert(ep->configured); - - - if (start) - { - _hw_endpoint_xfer_start(ep, buffer, total_len); - } - else - { - _hw_endpoint_xfer_continue(ep); - } -} - #endif diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 33f3ecd41..d27f4157a 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -17,7 +17,7 @@ #endif -#if false && !defined(NDEBUG) +#if true || false && !defined(NDEBUG) #define pico_trace(format,args...) printf(format, ## args) #else #define pico_trace(format,...) ((void)0) @@ -50,6 +50,7 @@ struct hw_endpoint // Endpoint control register io_rw_32 *endpoint_control; + // Buffer control register io_rw_32 *buffer_control; @@ -63,8 +64,11 @@ struct hw_endpoint bool active; uint16_t total_len; uint16_t len; + // Amount of data with the hardware - uint16_t transfer_size; + uint16_t transfer_size; // buf0_len; + uint16_t buf_1_len; + // User buffer in main memory uint8_t *user_buf; @@ -76,6 +80,7 @@ struct hw_endpoint #if TUSB_OPT_HOST_ENABLED // Only needed for host mode bool last_buf; + // RP2040-E4: HOST BUG. Host will incorrect write status to top half of buffer // control register when doing transfers > 1 packet uint8_t buf_sel; @@ -90,11 +95,11 @@ struct hw_endpoint void rp2040_usb_init(void); void hw_endpoint_reset_transfer(struct hw_endpoint *ep); -void _hw_endpoint_xfer(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len, bool start); void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep); void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len); void _hw_endpoint_xfer_sync(struct hw_endpoint *ep); bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep); + void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask); static inline uint32_t _hw_endpoint_buffer_control_get_value32(struct hw_endpoint *ep) { return *ep->buffer_control; @@ -149,11 +154,11 @@ static inline void print_bufctrl32(uint32_t u32) uint16_t u16; u16 = u32 >> 16; - TU_LOG(2, "Buffer Control 1 0x%x: ", u16); + TU_LOG(2, " Buffer Control 1 0x%x: ", u16); print_bufctrl16(u16); u16 = u32 & 0x0000ffff; - TU_LOG(2, "Buffer Control 0 0x%x: ", u16); + TU_LOG(2, " Buffer Control 0 0x%x: ", u16); print_bufctrl16(u16); } -- cgit v1.3.1 From 572d986a0260543ada22592e3f2216a152ac632d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Jun 2021 17:14:22 +0700 Subject: improve usbh --- examples/host/cdc_msc_hid/src/hid_app.c | 12 +++++- src/class/hid/hid_host.c | 10 ----- src/common/tusb_common.h | 4 +- src/host/usbh.c | 74 ++++++++++++++++++--------------- src/host/usbh_control.c | 4 +- 5 files changed, 54 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 23ab12404..817646dab 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -30,7 +30,8 @@ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ -// If your host terminal support ansi escape code, it can be use to simulate mouse cursor +// If your host terminal support ansi escape code such as TeraTerm +// it can be use to simulate mouse cursor movement within terminal #define USE_ANSI_ESCAPE 0 #define MAX_REPORT 4 @@ -113,6 +114,13 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons return; } + // For complete list of Usage Page & Usage checkout src/class/hid/hid.h. For examples: + // - Keyboard : Desktop, Keyboard + // - Mouse : Desktop, Mouse + // - Gamepad : Desktop, Gamepad + // - Consumer Control (Media Key) : Consumer, Consumer Control + // - System Control (Power key) : Desktop, System Control + // - Generic (vendor) : 0xFFxx, xx if ( rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP ) { switch (rpt_info->usage) @@ -164,7 +172,7 @@ static void process_kbd_report(hid_keyboard_report_t const *report) }else { // not existed in previous report means the current key is pressed - bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); + bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0]; putchar(ch); if ( ch == '\r' ) putchar('\n'); // added new line for enter key diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index cde5e23a5..a227c2a86 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -37,16 +37,6 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -/* - "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard - "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse - "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control - "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control - "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad - "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen - "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad - "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF - */ typedef struct { uint8_t itf_num; diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 889ad7b25..fe5bf5f41 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -317,8 +317,8 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize) #define TU_LOG1 tu_printf #define TU_LOG1_MEM tu_print_mem #define TU_LOG1_VAR(_x) tu_print_var((uint8_t const*)(_x), sizeof(*(_x))) -#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\n", (uint32_t) (_x) ) -#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\n", (uint32_t) (_x) ) +#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\r\n", (uint32_t) (_x) ) +#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\r\n", (uint32_t) (_x) ) // Log Level 2: Warn #if CFG_TUSB_DEBUG >= 2 diff --git a/src/host/usbh.c b/src/host/usbh.c index 59246a663..81b9e84af 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -795,6 +795,8 @@ static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_r return false; } + TU_ASSERT(tu_desc_type(_usbh_ctrl_buf) == TUSB_DESC_DEVICE); + // Reset device again before Set Address TU_LOG2("Port reset \r\n"); @@ -938,7 +940,7 @@ static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request // Parse configuration & set up drivers // Driver open aren't allowed to make any usb transfer yet - parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf); + TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf) ); TU_LOG2("Set Configuration = %d\r\n", CONFIG_NUM); tusb_control_request_t const new_request = @@ -988,49 +990,53 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura // parse each interfaces while( p_desc < _usbh_ctrl_buf + desc_cfg->wTotalLength ) { - // skip until we see interface descriptor - if ( TUSB_DESC_INTERFACE != tu_desc_type(p_desc) ) + 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); // skip the descriptor, increase by the descriptor's length - }else + 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; + + // Check if class is supported + uint8_t drv_id; + for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) { - tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; + if ( usbh_class_drivers[drv_id].class_code == desc_itf->bInterfaceClass ) break; + } - // Check if class is supported - uint8_t drv_id; - for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) - { - if ( usbh_class_drivers[drv_id].class_code == desc_itf->bInterfaceClass ) break; - } + if( drv_id >= USBH_CLASS_DRIVER_COUNT ) + { + // skip unsupported class + p_desc = tu_desc_next(p_desc); + } + else + { + usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; - if( drv_id >= USBH_CLASS_DRIVER_COUNT ) + // Interface number must not be used already TODO alternate interface + TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff ); + dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; + + if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) { - // skip unsupported class + // TODO Attach hub to Hub is not currently supported + // skip this interface p_desc = tu_desc_next(p_desc); } else { - usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; - - // Interface number must not be used already TODO alternate interface - TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff ); - dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; + TU_LOG2("%s open\r\n", driver->name); - if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) - { - // TODO Attach hub to Hub is not currently supported - // skip this interface - p_desc = tu_desc_next(p_desc); - } - else - { - TU_LOG2("%s open\r\n", driver->name); - - uint16_t itf_len = 0; - TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) ); - TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); - p_desc += itf_len; - } + uint16_t itf_len = 0; + TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) ); + TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); + p_desc += itf_len; } } } diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index aa82f14ba..91dbdfe99 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -68,7 +68,7 @@ bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, _ctrl_xfer.stage = STAGE_SETUP; _ctrl_xfer.complete_cb = complete_cb; - TU_LOG2("Send Setup to address %u: ", dev_addr); + TU_LOG2("Control Setup (addr = %u): ", dev_addr); TU_LOG2_VAR(request); TU_LOG2("\r\n"); @@ -119,7 +119,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu if (request->wLength) { - TU_LOG2("Control data:\r\n"); + TU_LOG2("Control data (addr = %u):\r\n", dev_addr); TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2); } -- cgit v1.3.1 From f8aa4b3ff3e3db71e752d9278bc248fb9e066f75 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 3 Mar 2021 10:14:41 +0100 Subject: Add sketchy SAME70 DCD driver. --- examples/device/cdc_dual_ports/src/tusb_config.h | 2 +- .../device/cdc_dual_ports/src/usb_descriptors.c | 32 +- src/portable/microchip/same70/dcd_same70.c | 564 +++++++++++++++++++++ 3 files changed, 589 insertions(+), 9 deletions(-) create mode 100644 src/portable/microchip/same70/dcd_same70.c (limited to 'src') diff --git a/examples/device/cdc_dual_ports/src/tusb_config.h b/examples/device/cdc_dual_ports/src/tusb_config.h index c7e87bf67..45167da8e 100644 --- a/examples/device/cdc_dual_ports/src/tusb_config.h +++ b/examples/device/cdc_dual_ports/src/tusb_config.h @@ -48,7 +48,7 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_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) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAME70) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index 8e19678e5..e39c140cc 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -87,16 +87,32 @@ enum // 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 ... #define EPNUM_CDC_0_NOTIF 0x81 - #define EPNUM_CDC_0_DATA 0x02 + #define EPNUM_CDC_0_OUT 0x02 + #define EPNUM_CDC_0_IN 0x82 #define EPNUM_CDC_1_NOTIF 0x84 - #define EPNUM_CDC_1_DATA 0x05 + #define EPNUM_CDC_1_OUT 0x05 + #define EPNUM_CDC_1_IN 0x85 + +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAME70 + // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT + // e.g EP1 OUT & EP1 IN cannot exist together + #define EPNUM_CDC_0_NOTIF 0x81 + #define EPNUM_CDC_0_OUT 0x02 + #define EPNUM_CDC_0_IN 0x83 + + #define EPNUM_CDC_1_NOTIF 0x84 + #define EPNUM_CDC_1_OUT 0x05 + #define EPNUM_CDC_1_IN 0x86 + #else #define EPNUM_CDC_0_NOTIF 0x81 - #define EPNUM_CDC_0_DATA 0x02 + #define EPNUM_CDC_0_OUT 0x02 + #define EPNUM_CDC_0_IN 0x82 #define EPNUM_CDC_1_NOTIF 0x83 - #define EPNUM_CDC_1_DATA 0x04 + #define EPNUM_CDC_1_OUT 0x04 + #define EPNUM_CDC_1_IN 0x84 #endif uint8_t const desc_fs_configuration[] = @@ -105,10 +121,10 @@ uint8_t const desc_fs_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_DATA, 0x80 | EPNUM_CDC_0_DATA, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64), // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_DATA, 0x80 | EPNUM_CDC_1_DATA, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64), }; #if TUD_OPT_HIGH_SPEED @@ -118,10 +134,10 @@ uint8_t const desc_hs_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_DATA, 0x80 | EPNUM_CDC_0_DATA, 512), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 512), // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_DATA, 0x80 | EPNUM_CDC_1_DATA, 512), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 512), }; #endif diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c new file mode 100644 index 000000000..7fdc9dd08 --- /dev/null +++ b/src/portable/microchip/same70/dcd_same70.c @@ -0,0 +1,564 @@ +/* +* The MIT License (MIT) +* +* Copyright (c) 2018, hathach (tinyusb.org) +* Copyright (c) 2020, HiFiPhile +* +* 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. +* +* This file is part of the TinyUSB stack. +*/ + + + +#include "tusb_option.h" + +#if CFG_TUSB_MCU == OPT_MCU_SAME70 + +#include "device/dcd.h" + +#include "sam.h" + +#include "SEGGER_RTT.h" +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#ifndef USE_SOF +# define USE_SOF 0 +#endif + +#ifndef USBHS_RAM_ADDR +# define USBHS_RAM_ADDR 0xA0100000u +#endif + +#define get_ep_fifo_ptr(ep, scale) (((volatile TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) + +#define EP_MAX 10 + +typedef struct { + uint8_t * buffer; + uint16_t total_len; + uint16_t queued_len; + uint16_t max_packet_size; + uint8_t interval; +} xfer_ctl_t; + +xfer_ctl_t xfer_status[EP_MAX+1]; + +static const tusb_desc_endpoint_t ep0_desc = +{ + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + + .bEndpointAddress = 0x00, + .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, + .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, + .bInterval = 0 +}; + +static tusb_speed_t get_speed(void); +static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); +//------------------------------------------------------------------ +// Device API +//------------------------------------------------------------------ + +// Initialize controller to device mode +void dcd_init (uint8_t rhport) +{ + // Enable USBPLL + PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); + // Wait until USB UTMI stabilize + while (!(PMC->PMC_SR & PMC_SR_LOCKU)); + // Enable USB FS clk + PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); + PMC->PMC_SCER = PMC_SCER_USBCLK; + dcd_connect(rhport); +} + +// Enable device interrupt +void dcd_int_enable (uint8_t rhport) +{ + (void) rhport; + NVIC_EnableIRQ((IRQn_Type) ID_USBHS); +} + +// Disable device interrupt +void dcd_int_disable (uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ((IRQn_Type) ID_USBHS); +} + +// Receive Set Address request, mcu port must also include status IN response +void dcd_set_address (uint8_t rhport, uint8_t dev_addr) +{ + (void) rhport; + // Set the address but keep it disabled for now. It should be enabled + // only after the ack to the host completes. + USBHS->USBHS_DEVCTRL &= ~(USBHS_DEVCTRL_UADD_Msk | USBHS_DEVCTRL_ADDEN); + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_UADD(dev_addr); + + // Respond with status + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} + +// Wake up host +void dcd_remote_wakeup (uint8_t rhport) +{ + (void) rhport; + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_RMWKUP; +} + +// Connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) +{ + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + // Enable USB clock + PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); + // Enable the USB controller in device mode + USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE; + // Wait to unfreeze clock + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Attach the device + USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; + // Enable the End Of Reset, Suspend & Wakeup interrupts + USBHS->USBHS_DEVIER = (USBHS_DEVIER_EORSTES | USBHS_DEVIER_SUSPES | USBHS_DEVIER_WAKEUPES); +#if USE_SOF + USBHS->USBHS_DEVIER = USBHS_DEVIER_SOFES; +#endif + // Clear the End Of Reset, SOF & Wakeup interrupts + USBHS->USBHS_DEVICR = (USBHS_DEVICR_EORSTC | USBHS_DEVICR_SOFC | USBHS_DEVICR_WAKEUPC); + // Manually set the Suspend Interrupt + USBHS->USBHS_DEVIFR |= USBHS_DEVIFR_SUSPS; + // Ack the Wakeup Interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Freeze USB clock + USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; + __set_PRIMASK(irq_state); +} + +// Disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + // Disable all endpoints + USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + // Wait to unfreeze clock + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Clear all the pending interrupts + USBHS->USBHS_DEVICR = USBHS_DEVICR_Msk; + // Disable all interrupts + USBHS->USBHS_DEVIDR = USBHS_DEVCTRL_UADD_Msk; + // Detach the device + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH; + // Disable the device address + USBHS->USBHS_DEVCTRL &=~(USBHS_DEVCTRL_ADDEN | USBHS_DEVCTRL_UADD_Msk); + __set_PRIMASK(irq_state); +} + +static tusb_speed_t get_speed(void) +{ + switch((USBHS->USBHS_SR & USBHS_SR_SPEED_Msk) >> USBHS_SR_SPEED_Pos) + { + case USBHS_SR_SPEED_FULL_SPEED_Val: + default: + return TUSB_SPEED_FULL; + case USBHS_SR_SPEED_HIGH_SPEED_Val: + return TUSB_SPEED_HIGH; + case USBHS_SR_SPEED_LOW_SPEED_Val: + return TUSB_SPEED_LOW; + } +} + +static void dcd_ep_handler(uint8_t ep_ix) +{ + uint32_t int_status = USBHS->USBHS_DEVEPTISR[ep_ix] & USBHS->USBHS_DEVEPTIMR[ep_ix]; + uint32_t dev_ctrl = USBHS->USBHS_DEVCTRL; + uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & + USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; + SEGGER_RTT_printf(0, "ep: %u %u %u \r\n", ep_ix, count, int_status); + if(ep_ix == 0U) + { + if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) { + + // Get 8-bit access to endpoint 0 FIFO from USB RAM address + volatile uint8_t *ptr = get_ep_fifo_ptr(0,8); + SCB_InvalidateDCache_by_Addr((uint32_t *) ptr, 8); + dcd_event_setup_received(0, (uint8_t*)ptr, true); + + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXSTPIC; + } + if (int_status & USBHS_DEVEPTISR_RXOUTI) { + // Disable the interrupt + //USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_RXOUTEC; + + xfer_ctl_t *xfer = &xfer_status[0]; + + if(count) + { + volatile uint8_t *ptr = get_ep_fifo_ptr(0,8); + for (int i = 0; i < count; i++) { + xfer->buffer[xfer->queued_len + i] = ptr[i]; + } + xfer->queued_len = (uint16_t)(xfer->queued_len + count); + } + + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; + + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) + { + // RX COMPLETE + dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); + xfer->queued_len = 0; + SEGGER_RTT_printf(0, "rx: %u \r\n", xfer->queued_len); + // Though the host could still send, we don't know. + } + + + } + if (int_status & USBHS_DEVEPTISR_TXINI) { + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; + if (!(dev_ctrl & USBHS_DEVCTRL_ADDEN) && + (dev_ctrl & USBHS_DEVCTRL_UADD_Msk) != 0U) { + // Commit the pending address update. This + // must be done after the ack to the host + // completes else the ack will get dropped. + USBHS->USBHS_DEVCTRL = dev_ctrl | USBHS_DEVCTRL_ADDEN; + } + xfer_ctl_t * xfer = &xfer_status[EP_MAX]; + if((xfer->total_len != xfer->queued_len)) // TX not complete + { + dcd_transmit_packet(xfer, 0); + } + else // TX Complete + { + dcd_event_xfer_complete(0, (uint8_t)(0x80 + 0), xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + } + else + { + if (int_status & USBHS_DEVEPTISR_RXOUTI) { + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; + + xfer_ctl_t *xfer = &xfer_status[ep_ix]; + + if(count) + { + volatile uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); + for (int i = 0; i < count; i++) { + xfer->buffer[xfer->queued_len + i] = ptr[i]; + } + xfer->queued_len = (uint16_t)(xfer->queued_len + count); + } + // Clear the FIFO control flag to receive more data. + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) + { + // RX COMPLETE + dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); + xfer->queued_len = 0; + // Though the host could still send, we don't know. + } + } + if (int_status & USBHS_DEVEPTISR_TXINI) { + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; + xfer_ctl_t * xfer = &xfer_status[ep_ix];; + if((xfer->total_len != xfer->queued_len)) // TX not complete + { + dcd_transmit_packet(xfer, ep_ix); + } + else // TX Complete + { + dcd_event_xfer_complete(0, (uint8_t)(0x80 + ep_ix), xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + } +} + +void dcd_int_handler(uint8_t rhport) +{ + (void) rhport; + uint32_t int_status = USBHS->USBHS_DEVISR; + // End of reset interrupt + if (int_status & USBHS_DEVISR_EORST) { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Reset all endpoints + for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) + { + // Disable endpoint interrupt + USBHS->USBHS_DEVIDR = 1 << (USBHS_DEVIDR_PEP_0_Pos + ep_ix); + // Disable endpoint and SETUP, IN or OUT interrupts + USBHS->USBHS_DEVEPT &= ~ (1 << (USBHS_DEVEPT_EPEN0_Pos + ep_ix)); + // Free all endpoint memory + USBHS->USBHS_DEVEPTCFG[ep_ix] &= ~USBHS_DEVEPTCFG_ALLOC; + } + dcd_edpt_open (0, &ep0_desc); + // Acknowledge the End of Reset interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC; + // Acknowledge the Wakeup interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Acknowledge the suspend interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; + // Enable Suspend Interrupt + USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; + + dcd_event_bus_reset(rhport, get_speed(), true); + } + // End of Wakeup interrupt + if (int_status & USBHS_DEVISR_WAKEUP) { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + // Wait to unfreeze clock + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Acknowledge the Wakeup interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Disable Wakeup Interrupt + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; + // Enable Suspend Interrupt + USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; + + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + // Suspend interrupt + if (int_status & USBHS_DEVISR_SUSP) { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + // Wait to unfreeze clock + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Acknowledge the suspend interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; + // Disable Suspend Interrupt + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; + // Enable Wakeup Interrupt + USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; + // Freeze USB clock + USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; + + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + } +#if USE_SOF + if(int_status & USBHS_DEVISR_SOF) { + USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; + + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); + } +#endif + // Endpoints interrupt + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { + if (int_status & (1 << (USBHS_DEVISR_PEP_0_Pos + ep_ix))) { + dcd_ep_handler(ep_ix); + } + } +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +// Configure endpoint's registers according to descriptor +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_desc->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); + uint16_t const epMaxPktSize = ep_desc->wMaxPacketSize.size; + tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; + uint8_t fifoSize = 0; // FIFO size + uint16_t defaultEndpointSize = 8; // Default size of Endpoint + // Find upper 2 power number of epMaxPktSize + if(epMaxPktSize) + { + while (defaultEndpointSize < epMaxPktSize) + { + fifoSize++; + defaultEndpointSize <<= 1; + } + } + xfer_status[epnum].max_packet_size = epMaxPktSize; + + if(epnum == 0) + { + xfer_status[EP_MAX].max_packet_size = epMaxPktSize; + // Enable the control endpoint - Endpoint 0 + USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; + // Configure the Endpoint 0 configuration register + USBHS->USBHS_DEVEPTCFG[0] = + ( + USBHS_DEVEPTCFG_EPSIZE(fifoSize) | + USBHS_DEVEPTCFG_EPTYPE(TUSB_XFER_CONTROL) | + USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | + USBHS_DEVEPTCFG_ALLOC + ); + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_STALLRQC; + if(USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) + { + // Endpoint configuration is successful + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXSTPES | USBHS_DEVEPTIER_RXOUTES; + // Enable Endpoint 0 Interrupts + USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; + return true; + } + else + { + // Endpoint configuration is not successful + return false; + } + } + else + { + // Enable the endpoint + USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); + // Set up the maxpacket size, fifo start address fifosize + // and enable the interrupt. CLear the data toggle. + USBHS->USBHS_DEVEPTCFG[epnum] = + ( + USBHS_DEVEPTCFG_EPSIZE(fifoSize) | + USBHS_DEVEPTCFG_EPTYPE(eptype) | + USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | + USBHS_DEVEPTCFG_ALLOC | + ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) + ); + + if (eptype == TUSB_XFER_ISOCHRONOUS) + { + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); + } + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; + if(USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) + { + // Endpoint configuration is successful. Enable Endpoint Interrupts + if(dir == TUSB_DIR_OUT) + { + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } + else + { + USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_TXINIC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_TXINES; + } + USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); + return true; + } + else + { + // Endpoint configuration is not successful + return false; + } + } +} + +static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) +{ + uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); + + if(len > xfer->max_packet_size) // max packet size for FS transfer + { + len = xfer->max_packet_size; + } + + volatile uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); + for (int i = 0; i < len; i++) { + ptr[i] = xfer->buffer[xfer->queued_len + i]; + } + + xfer->queued_len = (uint16_t)(xfer->queued_len + len); + + if (ep_ix == 0U) { + + // Control endpoint: clear the interrupt flag to send the data, + // and re-enable the interrupts to trigger an interrupt at the + // end of the transfer. + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_TXINES; + } else { + + // Other endpoint types: clear the FIFO control flag to send the data. + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + } +} + + +// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = &xfer_status[epnum]; + if(ep_addr == 0x80) + xfer = &xfer_status[EP_MAX]; + + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + + SEGGER_RTT_printf(0, "xfer: %u %u %u \r\n", epnum, dir, total_bytes); + + if ( dir == TUSB_DIR_OUT ) + { + // Endpoint configuration is successful + // Acknowledge the interrupt + //USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_RXOUTIC; + + //USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } + else // IN + { + dcd_transmit_packet(xfer,epnum); + } + return true; +} + +// Stall endpoint +void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_STALLRQS; +} + +// clear stall, data toggle is also reset to DATA0 +void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_HSTPIPIER_RSTDTS; +} + +#endif -- cgit v1.3.1 From e7bee80948bdb5132e815eaaf957b75f691cfaa3 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 3 Mar 2021 19:33:36 +0100 Subject: Add OPT_MCU_SAME70 option value. --- src/tusb_option.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/tusb_option.h b/src/tusb_option.h index 5cfcc08e2..fb86d7f9c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -61,6 +61,7 @@ #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 #define OPT_MCU_SAML22 205 ///< MicroChip SAML22 +#define OPT_MCU_SAME70 206 ///< MicroChip SAME70 series // STM32 #define OPT_MCU_STM32F0 300 ///< ST STM32F0 -- cgit v1.3.1 From 4f4a33b3784729ff4d7bc91224350291d2367ea3 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 3 Mar 2021 19:34:53 +0100 Subject: Seems like fixed ep0 issues, code format. Signed-off-by: HiFiPhile --- src/portable/microchip/same70/dcd_same70.c | 747 ++++++++++++++--------------- 1 file changed, 349 insertions(+), 398 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c index 7fdc9dd08..98fe61360 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/same70/dcd_same70.c @@ -2,7 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2018, hathach (tinyusb.org) -* Copyright (c) 2020, HiFiPhile +* Copyright (c) 2021, HiFiPhile * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,7 +35,6 @@ #include "sam.h" -#include "SEGGER_RTT.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ @@ -50,7 +49,7 @@ # define USBHS_RAM_ADDR 0xA0100000u #endif -#define get_ep_fifo_ptr(ep, scale) (((volatile TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) +#define get_ep_fifo_ptr(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) #define EP_MAX 10 @@ -66,13 +65,8 @@ xfer_ctl_t xfer_status[EP_MAX+1]; static const tusb_desc_endpoint_t ep0_desc = { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = 0x00, - .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, - .bInterval = 0 }; static tusb_speed_t get_speed(void); @@ -84,481 +78,438 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); // Initialize controller to device mode void dcd_init (uint8_t rhport) { - // Enable USBPLL - PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); - // Wait until USB UTMI stabilize - while (!(PMC->PMC_SR & PMC_SR_LOCKU)); - // Enable USB FS clk - PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); - PMC->PMC_SCER = PMC_SCER_USBCLK; - dcd_connect(rhport); + // Enable USBPLL + PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); + // Wait until USB UTMI stabilize + while (!(PMC->PMC_SR & PMC_SR_LOCKU)); + // Enable USB FS clk + PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); + PMC->PMC_SCER = PMC_SCER_USBCLK; + dcd_connect(rhport); } // Enable device interrupt void dcd_int_enable (uint8_t rhport) { - (void) rhport; - NVIC_EnableIRQ((IRQn_Type) ID_USBHS); + (void) rhport; + NVIC_EnableIRQ((IRQn_Type) ID_USBHS); } // Disable device interrupt void dcd_int_disable (uint8_t rhport) { - (void) rhport; - NVIC_DisableIRQ((IRQn_Type) ID_USBHS); + (void) rhport; + NVIC_DisableIRQ((IRQn_Type) ID_USBHS); } // Receive Set Address request, mcu port must also include status IN response void dcd_set_address (uint8_t rhport, uint8_t dev_addr) { - (void) rhport; - // Set the address but keep it disabled for now. It should be enabled - // only after the ack to the host completes. - USBHS->USBHS_DEVCTRL &= ~(USBHS_DEVCTRL_UADD_Msk | USBHS_DEVCTRL_ADDEN); - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_UADD(dev_addr); - - // Respond with status - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + // DCD can only set address after status for this request is complete + // do it at dcd_edpt0_status_complete() + + // Response with zlp status + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } // Wake up host void dcd_remote_wakeup (uint8_t rhport) { - (void) rhport; - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_RMWKUP; + (void) rhport; + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_RMWKUP; } // Connect by enabling internal pull-up resistor on D+/D- void dcd_connect(uint8_t rhport) { - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - // Enable USB clock - PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); - // Enable the USB controller in device mode - USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE; - // Wait to unfreeze clock - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Attach the device - USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; - // Enable the End Of Reset, Suspend & Wakeup interrupts - USBHS->USBHS_DEVIER = (USBHS_DEVIER_EORSTES | USBHS_DEVIER_SUSPES | USBHS_DEVIER_WAKEUPES); + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + // Enable USB clock + PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); + // Enable the USB controller in device mode + USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE; + // Wait to unfreeze clock + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Attach the device + USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; + // Enable the End Of Reset, Suspend & Wakeup interrupts + USBHS->USBHS_DEVIER = (USBHS_DEVIER_EORSTES | USBHS_DEVIER_SUSPES | USBHS_DEVIER_WAKEUPES); #if USE_SOF - USBHS->USBHS_DEVIER = USBHS_DEVIER_SOFES; + USBHS->USBHS_DEVIER = USBHS_DEVIER_SOFES; #endif - // Clear the End Of Reset, SOF & Wakeup interrupts - USBHS->USBHS_DEVICR = (USBHS_DEVICR_EORSTC | USBHS_DEVICR_SOFC | USBHS_DEVICR_WAKEUPC); - // Manually set the Suspend Interrupt - USBHS->USBHS_DEVIFR |= USBHS_DEVIFR_SUSPS; - // Ack the Wakeup Interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - // Freeze USB clock - USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; - __set_PRIMASK(irq_state); + // Clear the End Of Reset, SOF & Wakeup interrupts + USBHS->USBHS_DEVICR = (USBHS_DEVICR_EORSTC | USBHS_DEVICR_SOFC | USBHS_DEVICR_WAKEUPC); + // Manually set the Suspend Interrupt + USBHS->USBHS_DEVIFR |= USBHS_DEVIFR_SUSPS; + // Ack the Wakeup Interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Freeze USB clock + USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; + __set_PRIMASK(irq_state); } // Disconnect by disabling internal pull-up resistor on D+/D- void dcd_disconnect(uint8_t rhport) { - (void) rhport; - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - // Disable all endpoints - USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); - // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - // Wait to unfreeze clock - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Clear all the pending interrupts - USBHS->USBHS_DEVICR = USBHS_DEVICR_Msk; - // Disable all interrupts - USBHS->USBHS_DEVIDR = USBHS_DEVCTRL_UADD_Msk; - // Detach the device - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH; - // Disable the device address - USBHS->USBHS_DEVCTRL &=~(USBHS_DEVCTRL_ADDEN | USBHS_DEVCTRL_UADD_Msk); - __set_PRIMASK(irq_state); + (void) rhport; + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + // Disable all endpoints + USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + // Wait to unfreeze clock + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Clear all the pending interrupts + USBHS->USBHS_DEVICR = USBHS_DEVICR_Msk; + // Disable all interrupts + USBHS->USBHS_DEVIDR = USBHS_DEVCTRL_UADD_Msk; + // Detach the device + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH; + // Disable the device address + USBHS->USBHS_DEVCTRL &=~(USBHS_DEVCTRL_ADDEN | USBHS_DEVCTRL_UADD_Msk); + __set_PRIMASK(irq_state); } static tusb_speed_t get_speed(void) { - switch((USBHS->USBHS_SR & USBHS_SR_SPEED_Msk) >> USBHS_SR_SPEED_Pos) - { - case USBHS_SR_SPEED_FULL_SPEED_Val: - default: - return TUSB_SPEED_FULL; - case USBHS_SR_SPEED_HIGH_SPEED_Val: - return TUSB_SPEED_HIGH; - case USBHS_SR_SPEED_LOW_SPEED_Val: - return TUSB_SPEED_LOW; + switch ((USBHS->USBHS_SR & USBHS_SR_SPEED_Msk) >> USBHS_SR_SPEED_Pos) { + case USBHS_SR_SPEED_FULL_SPEED_Val: + default: + return TUSB_SPEED_FULL; + case USBHS_SR_SPEED_HIGH_SPEED_Val: + return TUSB_SPEED_HIGH; + case USBHS_SR_SPEED_LOW_SPEED_Val: + return TUSB_SPEED_LOW; } } static void dcd_ep_handler(uint8_t ep_ix) { - uint32_t int_status = USBHS->USBHS_DEVEPTISR[ep_ix] & USBHS->USBHS_DEVEPTIMR[ep_ix]; - uint32_t dev_ctrl = USBHS->USBHS_DEVCTRL; - uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & - USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; - SEGGER_RTT_printf(0, "ep: %u %u %u \r\n", ep_ix, count, int_status); - if(ep_ix == 0U) - { - if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) { - - // Get 8-bit access to endpoint 0 FIFO from USB RAM address - volatile uint8_t *ptr = get_ep_fifo_ptr(0,8); - SCB_InvalidateDCache_by_Addr((uint32_t *) ptr, 8); - dcd_event_setup_received(0, (uint8_t*)ptr, true); - - // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXSTPIC; - } - if (int_status & USBHS_DEVEPTISR_RXOUTI) { - // Disable the interrupt - //USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_RXOUTEC; - - xfer_ctl_t *xfer = &xfer_status[0]; - - if(count) - { - volatile uint8_t *ptr = get_ep_fifo_ptr(0,8); - for (int i = 0; i < count; i++) { - xfer->buffer[xfer->queued_len + i] = ptr[i]; - } - xfer->queued_len = (uint16_t)(xfer->queued_len + count); - } - - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; - - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { - // RX COMPLETE - dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); - xfer->queued_len = 0; - SEGGER_RTT_printf(0, "rx: %u \r\n", xfer->queued_len); - // Though the host could still send, we don't know. - } - - - } - if (int_status & USBHS_DEVEPTISR_TXINI) { - // Disable the interrupt - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; - if (!(dev_ctrl & USBHS_DEVCTRL_ADDEN) && - (dev_ctrl & USBHS_DEVCTRL_UADD_Msk) != 0U) { - // Commit the pending address update. This - // must be done after the ack to the host - // completes else the ack will get dropped. - USBHS->USBHS_DEVCTRL = dev_ctrl | USBHS_DEVCTRL_ADDEN; - } - xfer_ctl_t * xfer = &xfer_status[EP_MAX]; - if((xfer->total_len != xfer->queued_len)) // TX not complete - { - dcd_transmit_packet(xfer, 0); - } - else // TX Complete - { - dcd_event_xfer_complete(0, (uint8_t)(0x80 + 0), xfer->total_len, XFER_RESULT_SUCCESS, true); - } - } + uint32_t int_status = USBHS->USBHS_DEVEPTISR[ep_ix]; + int_status &= USBHS->USBHS_DEVEPTIMR[ep_ix]; + uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & + USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; + if (ep_ix == 0U) { + if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) { + // Setup packet should always be 8 bytes. If not, ignore it, and try again. + if (count == 8) + { + uint8_t *ptr = get_ep_fifo_ptr(0,8); + dcd_event_setup_received(0, ptr, true); + } + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXSTPIC; } - else - { - if (int_status & USBHS_DEVEPTISR_RXOUTI) { - // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; - - xfer_ctl_t *xfer = &xfer_status[ep_ix]; - - if(count) - { - volatile uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); - for (int i = 0; i < count; i++) { - xfer->buffer[xfer->queued_len + i] = ptr[i]; - } - xfer->queued_len = (uint16_t)(xfer->queued_len + count); - } - // Clear the FIFO control flag to receive more data. - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { - // RX COMPLETE - dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); - xfer->queued_len = 0; - // Though the host could still send, we don't know. - } - } - if (int_status & USBHS_DEVEPTISR_TXINI) { - // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; - xfer_ctl_t * xfer = &xfer_status[ep_ix];; - if((xfer->total_len != xfer->queued_len)) // TX not complete - { - dcd_transmit_packet(xfer, ep_ix); - } - else // TX Complete - { - dcd_event_xfer_complete(0, (uint8_t)(0x80 + ep_ix), xfer->total_len, XFER_RESULT_SUCCESS, true); - } + if (int_status & USBHS_DEVEPTISR_RXOUTI) { + xfer_ctl_t *xfer = &xfer_status[0]; + if (count) { + uint8_t *ptr = get_ep_fifo_ptr(0,8); + for (int i = 0; i < count; i++) { + xfer->buffer[xfer->queued_len + i] = ptr[i]; } + xfer->queued_len = (uint16_t)(xfer->queued_len + count); + } + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { + // RX COMPLETE + dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; + // Though the host could still send, we don't know. + } + } + if (int_status & USBHS_DEVEPTISR_TXINI) { + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; + xfer_ctl_t * xfer = &xfer_status[EP_MAX]; + if ((xfer->total_len != xfer->queued_len)) { + // TX not complete + dcd_transmit_packet(xfer, 0); + } + else { + // TX complete + dcd_event_xfer_complete(0, (uint8_t)(0x80 + 0), xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + } + else { + if (int_status & USBHS_DEVEPTISR_RXOUTI) { + xfer_ctl_t *xfer = &xfer_status[ep_ix]; + if (count) { + uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); + memcpy(xfer->buffer + xfer->queued_len, ptr, count); + xfer->queued_len = (uint16_t)(xfer->queued_len + count); + } + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; + // Clear the FIFO control flag to receive more data. + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { + // RX COMPLETE + dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_RXOUTEC; + // Though the host could still send, we don't know. + } } + if (int_status & USBHS_DEVEPTISR_TXINI) { + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; + xfer_ctl_t * xfer = &xfer_status[ep_ix];; + if ((xfer->total_len != xfer->queued_len)) { + // TX not complete + dcd_transmit_packet(xfer, ep_ix); + } + else { + // TX complete + dcd_event_xfer_complete(0, (uint8_t)(0x80 + ep_ix), xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + } } void dcd_int_handler(uint8_t rhport) { - (void) rhport; - uint32_t int_status = USBHS->USBHS_DEVISR; - // End of reset interrupt - if (int_status & USBHS_DEVISR_EORST) { - // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Reset all endpoints - for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) - { - // Disable endpoint interrupt - USBHS->USBHS_DEVIDR = 1 << (USBHS_DEVIDR_PEP_0_Pos + ep_ix); - // Disable endpoint and SETUP, IN or OUT interrupts - USBHS->USBHS_DEVEPT &= ~ (1 << (USBHS_DEVEPT_EPEN0_Pos + ep_ix)); - // Free all endpoint memory - USBHS->USBHS_DEVEPTCFG[ep_ix] &= ~USBHS_DEVEPTCFG_ALLOC; - } - dcd_edpt_open (0, &ep0_desc); - // Acknowledge the End of Reset interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC; - // Acknowledge the Wakeup interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - // Acknowledge the suspend interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; - // Enable Suspend Interrupt - USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; - - dcd_event_bus_reset(rhport, get_speed(), true); - } - // End of Wakeup interrupt - if (int_status & USBHS_DEVISR_WAKEUP) { - // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - // Wait to unfreeze clock - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Acknowledge the Wakeup interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - // Disable Wakeup Interrupt - USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; - // Enable Suspend Interrupt - USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; - - dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); - } - // Suspend interrupt - if (int_status & USBHS_DEVISR_SUSP) { - // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - // Wait to unfreeze clock - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Acknowledge the suspend interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; - // Disable Suspend Interrupt - USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; - // Enable Wakeup Interrupt - USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; - // Freeze USB clock - USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; - - dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + (void) rhport; + uint32_t int_status = USBHS->USBHS_DEVISR; + // End of reset interrupt + if (int_status & USBHS_DEVISR_EORST) { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Reset all endpoints + for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) { + USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix); + USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix)); } + dcd_edpt_open (0, &ep0_desc); + // Acknowledge the End of Reset interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC; + // Acknowledge the Wakeup interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Acknowledge the suspend interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; + // Enable Suspend Interrupt + USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; + + dcd_event_bus_reset(rhport, get_speed(), true); + } + // End of Wakeup interrupt + if (int_status & USBHS_DEVISR_WAKEUP) { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + // Wait to unfreeze clock + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Acknowledge the Wakeup interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Disable Wakeup Interrupt + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; + // Enable Suspend Interrupt + USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; + + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + // Suspend interrupt + if (int_status & USBHS_DEVISR_SUSP) { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + // Wait to unfreeze clock + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Acknowledge the suspend interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; + // Disable Suspend Interrupt + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; + // Enable Wakeup Interrupt + USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; + // Freeze USB clock + USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; + + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + } #if USE_SOF - if(int_status & USBHS_DEVISR_SOF) { - USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; - - dcd_event_bus_signal(0, DCD_EVENT_SOF, true); - } + if(int_status & USBHS_DEVISR_SOF) { + USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; + + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); + } #endif - // Endpoints interrupt - for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { - if (int_status & (1 << (USBHS_DEVISR_PEP_0_Pos + ep_ix))) { - dcd_ep_handler(ep_ix); - } + // Endpoints interrupt + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { + if (int_status & (1 << (USBHS_DEVISR_PEP_0_Pos + ep_ix))) { + dcd_ep_handler(ep_ix); } + } } //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void) rhport; + + if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && + request->bRequest == TUSB_REQ_SET_ADDRESS ) + { + uint8_t const dev_addr = (uint8_t) request->wValue; + + USBHS->USBHS_DEVCTRL |= dev_addr | USBHS_DEVCTRL_ADDEN; + } +} // Configure endpoint's registers according to descriptor bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_desc->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); - uint16_t const epMaxPktSize = ep_desc->wMaxPacketSize.size; - tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; - uint8_t fifoSize = 0; // FIFO size - uint16_t defaultEndpointSize = 8; // Default size of Endpoint - // Find upper 2 power number of epMaxPktSize - if(epMaxPktSize) - { - while (defaultEndpointSize < epMaxPktSize) - { - fifoSize++; - defaultEndpointSize <<= 1; - } + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_desc->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); + uint16_t const epMaxPktSize = ep_desc->wMaxPacketSize.size; + tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; + uint8_t fifoSize = 0; // FIFO size + uint16_t defaultEndpointSize = 8; // Default size of Endpoint + // Find upper 2 power number of epMaxPktSize + if (epMaxPktSize) { + while (defaultEndpointSize < epMaxPktSize) { + fifoSize++; + defaultEndpointSize <<= 1; } - xfer_status[epnum].max_packet_size = epMaxPktSize; + } + xfer_status[epnum].max_packet_size = epMaxPktSize; + + USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + epnum); + USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + epnum)); - if(epnum == 0) - { - xfer_status[EP_MAX].max_packet_size = epMaxPktSize; - // Enable the control endpoint - Endpoint 0 - USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; - // Configure the Endpoint 0 configuration register - USBHS->USBHS_DEVEPTCFG[0] = - ( - USBHS_DEVEPTCFG_EPSIZE(fifoSize) | - USBHS_DEVEPTCFG_EPTYPE(TUSB_XFER_CONTROL) | - USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | - USBHS_DEVEPTCFG_ALLOC - ); - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_STALLRQC; - if(USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) - { - // Endpoint configuration is successful - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXSTPES | USBHS_DEVEPTIER_RXOUTES; - // Enable Endpoint 0 Interrupts - USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; - return true; - } - else - { - // Endpoint configuration is not successful - return false; - } + if (epnum == 0) { + xfer_status[EP_MAX].max_packet_size = epMaxPktSize; + // Enable the control endpoint - Endpoint 0 + USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; + // Configure the Endpoint 0 configuration register + USBHS->USBHS_DEVEPTCFG[0] = + ( + USBHS_DEVEPTCFG_EPSIZE(fifoSize) | + USBHS_DEVEPTCFG_EPTYPE(TUSB_XFER_CONTROL) | + USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | + USBHS_DEVEPTCFG_ALLOC + ); + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_STALLRQC; + if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) { + // Endpoint configuration is successful + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXSTPES; + // Enable Endpoint 0 Interrupts + USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; + return true; } - else - { - // Enable the endpoint - USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); - // Set up the maxpacket size, fifo start address fifosize - // and enable the interrupt. CLear the data toggle. - USBHS->USBHS_DEVEPTCFG[epnum] = - ( - USBHS_DEVEPTCFG_EPSIZE(fifoSize) | - USBHS_DEVEPTCFG_EPTYPE(eptype) | - USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | - USBHS_DEVEPTCFG_ALLOC | - ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) - ); - - if (eptype == TUSB_XFER_ISOCHRONOUS) - { - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); - } - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; - if(USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) - { - // Endpoint configuration is successful. Enable Endpoint Interrupts - if(dir == TUSB_DIR_OUT) - { - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } - else - { - USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_TXINIC; - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_TXINES; - } - USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); - return true; - } - else - { - // Endpoint configuration is not successful - return false; - } + else { + // Endpoint configuration is not successful + return false; } -} - -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) -{ - uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); + } + else { + // Enable the endpoint + USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); + // Set up the maxpacket size, fifo start address fifosize + // and enable the interrupt. CLear the data toggle. + USBHS->USBHS_DEVEPTCFG[epnum] = + ( + USBHS_DEVEPTCFG_EPSIZE(fifoSize) | + USBHS_DEVEPTCFG_EPTYPE(eptype) | + USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | + ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) + ); - if(len > xfer->max_packet_size) // max packet size for FS transfer - { - len = xfer->max_packet_size; + if (eptype == TUSB_XFER_ISOCHRONOUS){ + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1) | USBHS_DEVEPTCFG_EPBK_2_BANK; } - - volatile uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); - for (int i = 0; i < len; i++) { - ptr[i] = xfer->buffer[xfer->queued_len + i]; + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; + if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) { + // Endpoint configuration is successful. Enable Endpoint Interrupts + if (dir == TUSB_DIR_IN) { + USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_TXINIC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_TXINES; + } + USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); + return true; } - - xfer->queued_len = (uint16_t)(xfer->queued_len + len); - - if (ep_ix == 0U) { - - // Control endpoint: clear the interrupt flag to send the data, - // and re-enable the interrupts to trigger an interrupt at the - // end of the transfer. - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_TXINES; - } else { - - // Other endpoint types: clear the FIFO control flag to send the data. - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + else { + // Endpoint configuration is not successful + return false; } + } } +static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) +{ + uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); + + if (len > xfer->max_packet_size) { + len = xfer->max_packet_size; + } + + uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); + memcpy(ptr, xfer->buffer + xfer->queued_len, len); + + xfer->queued_len = (uint16_t)(xfer->queued_len + len); + + if (ep_ix == 0U) { + // Control endpoint: clear the interrupt flag to send the data, + // and re-enable the interrupts to trigger an interrupt at the + // end of the transfer. + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_TXINES; + } else { + // Other endpoint types: clear the FIFO control flag to send the data. + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + } +} // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t * xfer = &xfer_status[epnum]; - if(ep_addr == 0x80) - xfer = &xfer_status[EP_MAX]; - - xfer->buffer = buffer; - xfer->total_len = total_bytes; - xfer->queued_len = 0; - - SEGGER_RTT_printf(0, "xfer: %u %u %u \r\n", epnum, dir, total_bytes); - - if ( dir == TUSB_DIR_OUT ) - { - // Endpoint configuration is successful - // Acknowledge the interrupt - //USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_RXOUTIC; - - //USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } - else // IN - { - dcd_transmit_packet(xfer,epnum); - } - return true; + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = &xfer_status[epnum]; + if(ep_addr == 0x80) + xfer = &xfer_status[EP_MAX]; + + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + + if (dir == TUSB_DIR_OUT){ + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } + else { + dcd_transmit_packet(xfer,epnum); + } + return true; } // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_STALLRQS; + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_STALLRQS; } // clear stall, data toggle is also reset to DATA0 void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_HSTPIPIER_RSTDTS; + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_HSTPIPIER_RSTDTS; } #endif -- cgit v1.3.1 From 1dafcd1132deb10c824a0587b333e646b102e8aa Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 5 Mar 2021 17:15:02 +0100 Subject: - Add Full Speed switch - Add DMA support - Add Dual bank support Signed-off-by: HiFiPhile --- src/portable/microchip/same70/dcd_same70.c | 145 ++++++++++++++++++++++------- 1 file changed, 111 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c index 98fe61360..89ef63660 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/same70/dcd_same70.c @@ -34,7 +34,6 @@ #include "device/dcd.h" #include "sam.h" - //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ @@ -42,17 +41,29 @@ // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) // We disable SOF for now until needed later on #ifndef USE_SOF -# define USE_SOF 0 +# define USE_SOF 0 #endif -#ifndef USBHS_RAM_ADDR -# define USBHS_RAM_ADDR 0xA0100000u +// Dual bank can imporve performance, but need 2 times bigger packet buffer +// As SAME70 has only 4KB packet buffer, use with caution ! +// Enable in FS mode as packets are smaller +#ifndef USE_DUAL_BANK +# if TUD_OPT_HIGH_SPEED +# define USE_DUAL_BANK 0 +# else +# define USE_DUAL_BANK 1 +# endif #endif -#define get_ep_fifo_ptr(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) - #define EP_MAX 10 +#define USBHS_RAM_ADDR 0xA0100000u + +#define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) + +// Errata: The DMA feature is not available for Pipe/Endpoint 7 +#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) + typedef struct { uint8_t * buffer; uint16_t total_len; @@ -82,9 +93,12 @@ void dcd_init (uint8_t rhport) PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); // Wait until USB UTMI stabilize while (!(PMC->PMC_SR & PMC_SR_LOCKU)); +#if !TUD_OPT_HIGH_SPEED // Enable USB FS clk + PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2; PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); PMC->PMC_SCER = PMC_SCER_USBCLK; +#endif dcd_connect(rhport); } @@ -128,10 +142,12 @@ void dcd_connect(uint8_t rhport) PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); // Enable the USB controller in device mode USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE; - // Wait to unfreeze clock - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Attach the device - USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); +#if TUD_OPT_HIGH_SPEED + USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_SPDCONF_Msk; +#else + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_SPDCONF_LOW_POWER; +#endif // Enable the End Of Reset, Suspend & Wakeup interrupts USBHS->USBHS_DEVIER = (USBHS_DEVIER_EORSTES | USBHS_DEVIER_SUSPES | USBHS_DEVIER_WAKEUPES); #if USE_SOF @@ -143,6 +159,8 @@ void dcd_connect(uint8_t rhport) USBHS->USBHS_DEVIFR |= USBHS_DEVIFR_SUSPS; // Ack the Wakeup Interrupt USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Attach the device + USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; // Freeze USB clock USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; __set_PRIMASK(irq_state); @@ -158,7 +176,6 @@ void dcd_disconnect(uint8_t rhport) USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - // Wait to unfreeze clock while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); // Clear all the pending interrupts USBHS->USBHS_DEVICR = USBHS_DEVICR_Msk; @@ -195,7 +212,7 @@ static void dcd_ep_handler(uint8_t ep_ix) // Setup packet should always be 8 bytes. If not, ignore it, and try again. if (count == 8) { - uint8_t *ptr = get_ep_fifo_ptr(0,8); + uint8_t *ptr = EP_GET_FIFO_PTR(0,8); dcd_event_setup_received(0, ptr, true); } // Acknowledge the interrupt @@ -204,7 +221,7 @@ static void dcd_ep_handler(uint8_t ep_ix) if (int_status & USBHS_DEVEPTISR_RXOUTI) { xfer_ctl_t *xfer = &xfer_status[0]; if (count) { - uint8_t *ptr = get_ep_fifo_ptr(0,8); + uint8_t *ptr = EP_GET_FIFO_PTR(0,8); for (int i = 0; i < count; i++) { xfer->buffer[xfer->queued_len + i] = ptr[i]; } @@ -230,7 +247,7 @@ static void dcd_ep_handler(uint8_t ep_ix) } else { // TX complete - dcd_event_xfer_complete(0, (uint8_t)(0x80 + 0), xfer->total_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); } } } @@ -238,7 +255,7 @@ static void dcd_ep_handler(uint8_t ep_ix) if (int_status & USBHS_DEVEPTISR_RXOUTI) { xfer_ctl_t *xfer = &xfer_status[ep_ix]; if (count) { - uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); + uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); memcpy(xfer->buffer + xfer->queued_len, ptr, count); xfer->queued_len = (uint16_t)(xfer->queued_len + count); } @@ -264,12 +281,34 @@ static void dcd_ep_handler(uint8_t ep_ix) } else { // TX complete - dcd_event_xfer_complete(0, (uint8_t)(0x80 + ep_ix), xfer->total_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; } } } } +static void dcd_dma_handler(uint8_t ep_ix) +{ + uint32_t status = USBHS->UsbhsDevdma[ep_ix - 1].USBHS_DEVDMASTATUS; + if (status & USBHS_DEVDMASTATUS_CHANN_ENB) { + return; // Ignore EOT_STA interrupt + } + // Disable DMA interrupt + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_DMA_1 << (ep_ix - 1); + + xfer_ctl_t *xfer = &xfer_status[ep_ix]; + uint16_t count = xfer->total_len - ((status & USBHS_DEVDMASTATUS_BUFF_COUNT_Msk) >> USBHS_DEVDMASTATUS_BUFF_COUNT_Pos); + if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) + { + dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); + } + else + { + dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); + } +} + void dcd_int_handler(uint8_t rhport) { (void) rhport; @@ -337,10 +376,18 @@ void dcd_int_handler(uint8_t rhport) #endif // Endpoints interrupt for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { - if (int_status & (1 << (USBHS_DEVISR_PEP_0_Pos + ep_ix))) { + if (int_status & (USBHS_DEVISR_PEP_0 << ep_ix)) { dcd_ep_handler(ep_ix); } } + // Endpoints DMA interrupt + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { + if (EP_DMA_SUPPORT(ep_ix)) { + if (int_status & (USBHS_DEVISR_DMA_1 << (ep_ix - 1))) { + dcd_dma_handler(ep_ix); + } + } + } } //--------------------------------------------------------------------+ @@ -415,26 +462,27 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); // Set up the maxpacket size, fifo start address fifosize // and enable the interrupt. CLear the data toggle. + // AUTOSW is needed for DMA ack ! USBHS->USBHS_DEVEPTCFG[epnum] = ( USBHS_DEVEPTCFG_EPSIZE(fifoSize) | USBHS_DEVEPTCFG_EPTYPE(eptype) | USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | + USBHS_DEVEPTCFG_AUTOSW | ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) ); - if (eptype == TUSB_XFER_ISOCHRONOUS){ - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1) | USBHS_DEVEPTCFG_EPBK_2_BANK; + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); } +#if USE_DUAL_BANK + if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK){ + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_EPBK_2_BANK; + } +#endif USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) { - // Endpoint configuration is successful. Enable Endpoint Interrupts - if (dir == TUSB_DIR_IN) { - USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_TXINIC; - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_TXINES; - } USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); return true; } @@ -453,28 +501,26 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) len = xfer->max_packet_size; } - uint8_t *ptr = get_ep_fifo_ptr(ep_ix,8); + uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); memcpy(ptr, xfer->buffer + xfer->queued_len, len); xfer->queued_len = (uint16_t)(xfer->queued_len + len); if (ep_ix == 0U) { - // Control endpoint: clear the interrupt flag to send the data, - // and re-enable the interrupts to trigger an interrupt at the - // end of the transfer. + // Control endpoint: clear the interrupt flag to send the data USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_TXINES; + } else { - // Other endpoint types: clear the FIFO control flag to send the data. + // Other endpoint types: clear the FIFO control flag to send the data USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; } + USBHS->USBHS_DEVEPTIER[ep_ix] = USBHS_DEVEPTIER_TXINES; } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -486,11 +532,42 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->total_len = total_bytes; xfer->queued_len = 0; - if (dir == TUSB_DIR_OUT){ - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + if(EP_DMA_SUPPORT(epnum) && total_bytes != 0) { + uint32_t udd_dma_ctrl = 0; + udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); + if (dir == TUSB_DIR_OUT){ + udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; + } + else { + udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_B_EN; + } + // Start USB DMA to fill or read fifo of the selected endpoint + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)buffer; + udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_BUFFIT | USBHS_DEVDMACONTROL_CHANN_ENB; + // Disable IRQs to have a short sequence + // between read of EOT_STA and DMA enable + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) { + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl; + USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); + __set_PRIMASK(irq_state); + return true; + } + __set_PRIMASK(irq_state); + + // Here a ZLP has been recieved + // and the DMA transfer must be not started. + // It is the end of transfer + return false; } else { - dcd_transmit_packet(xfer,epnum); + if (dir == TUSB_DIR_OUT){ + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } + else { + dcd_transmit_packet(xfer,epnum); + } } return true; } -- cgit v1.3.1 From 24de9d39af9c7f015dc00295a1d9f8c5bf428d34 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 11 Mar 2021 20:47:53 +0100 Subject: Format. --- src/portable/microchip/same70/dcd_same70.c | 155 ++++++++++++++++++----------- 1 file changed, 95 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c index 89ef63660..72d91e466 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/same70/dcd_same70.c @@ -25,8 +25,6 @@ * This file is part of the TinyUSB stack. */ - - #include "tusb_option.h" #if CFG_TUSB_MCU == OPT_MCU_SAME70 @@ -207,8 +205,10 @@ static void dcd_ep_handler(uint8_t ep_ix) int_status &= USBHS->USBHS_DEVEPTIMR[ep_ix]; uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; - if (ep_ix == 0U) { - if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) { + if (ep_ix == 0U) + { + if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) + { // Setup packet should always be 8 bytes. If not, ignore it, and try again. if (count == 8) { @@ -218,18 +218,22 @@ static void dcd_ep_handler(uint8_t ep_ix) // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXSTPIC; } - if (int_status & USBHS_DEVEPTISR_RXOUTI) { + if (int_status & USBHS_DEVEPTISR_RXOUTI) + { xfer_ctl_t *xfer = &xfer_status[0]; - if (count) { + if (count) + { uint8_t *ptr = EP_GET_FIFO_PTR(0,8); - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { xfer->buffer[xfer->queued_len + i] = ptr[i]; } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) + { // RX COMPLETE dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt @@ -237,24 +241,28 @@ static void dcd_ep_handler(uint8_t ep_ix) // Though the host could still send, we don't know. } } - if (int_status & USBHS_DEVEPTISR_TXINI) { + if (int_status & USBHS_DEVEPTISR_TXINI) + { // Disable the interrupt USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; xfer_ctl_t * xfer = &xfer_status[EP_MAX]; - if ((xfer->total_len != xfer->queued_len)) { + if ((xfer->total_len != xfer->queued_len)) + { // TX not complete dcd_transmit_packet(xfer, 0); - } - else { + } else + { // TX complete dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); } } - } - else { - if (int_status & USBHS_DEVEPTISR_RXOUTI) { + } else + { + if (int_status & USBHS_DEVEPTISR_RXOUTI) + { xfer_ctl_t *xfer = &xfer_status[ep_ix]; - if (count) { + if (count) + { uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); memcpy(xfer->buffer + xfer->queued_len, ptr, count); xfer->queued_len = (uint16_t)(xfer->queued_len + count); @@ -263,7 +271,8 @@ static void dcd_ep_handler(uint8_t ep_ix) USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; // Clear the FIFO control flag to receive more data. USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) + { // RX COMPLETE dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt @@ -271,15 +280,17 @@ static void dcd_ep_handler(uint8_t ep_ix) // Though the host could still send, we don't know. } } - if (int_status & USBHS_DEVEPTISR_TXINI) { + if (int_status & USBHS_DEVEPTISR_TXINI) + { // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; xfer_ctl_t * xfer = &xfer_status[ep_ix];; - if ((xfer->total_len != xfer->queued_len)) { + if ((xfer->total_len != xfer->queued_len)) + { // TX not complete dcd_transmit_packet(xfer, ep_ix); - } - else { + } else + { // TX complete dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; @@ -291,7 +302,8 @@ static void dcd_ep_handler(uint8_t ep_ix) static void dcd_dma_handler(uint8_t ep_ix) { uint32_t status = USBHS->UsbhsDevdma[ep_ix - 1].USBHS_DEVDMASTATUS; - if (status & USBHS_DEVDMASTATUS_CHANN_ENB) { + if (status & USBHS_DEVDMASTATUS_CHANN_ENB) + { return; // Ignore EOT_STA interrupt } // Disable DMA interrupt @@ -302,8 +314,7 @@ static void dcd_dma_handler(uint8_t ep_ix) if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) { dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); - } - else + } else { dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); } @@ -314,12 +325,14 @@ void dcd_int_handler(uint8_t rhport) (void) rhport; uint32_t int_status = USBHS->USBHS_DEVISR; // End of reset interrupt - if (int_status & USBHS_DEVISR_EORST) { + if (int_status & USBHS_DEVISR_EORST) + { // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); // Reset all endpoints - for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) { + for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) + { USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix); USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix)); } @@ -336,7 +349,8 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_reset(rhport, get_speed(), true); } // End of Wakeup interrupt - if (int_status & USBHS_DEVISR_WAKEUP) { + if (int_status & USBHS_DEVISR_WAKEUP) + { // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; // Wait to unfreeze clock @@ -351,7 +365,8 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } // Suspend interrupt - if (int_status & USBHS_DEVISR_SUSP) { + if (int_status & USBHS_DEVISR_SUSP) + { // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; // Wait to unfreeze clock @@ -368,22 +383,28 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } #if USE_SOF - if(int_status & USBHS_DEVISR_SOF) { + if(int_status & USBHS_DEVISR_SOF) + { USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } #endif // Endpoints interrupt - for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { - if (int_status & (USBHS_DEVISR_PEP_0 << ep_ix)) { + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) + { + if (int_status & (USBHS_DEVISR_PEP_0 << ep_ix)) + { dcd_ep_handler(ep_ix); } } // Endpoints DMA interrupt - for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { - if (EP_DMA_SUPPORT(ep_ix)) { - if (int_status & (USBHS_DEVISR_DMA_1 << (ep_ix - 1))) { + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) + { + if (EP_DMA_SUPPORT(ep_ix)) + { + if (int_status & (USBHS_DEVISR_DMA_1 << (ep_ix - 1))) + { dcd_dma_handler(ep_ix); } } @@ -420,8 +441,10 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) uint8_t fifoSize = 0; // FIFO size uint16_t defaultEndpointSize = 8; // Default size of Endpoint // Find upper 2 power number of epMaxPktSize - if (epMaxPktSize) { - while (defaultEndpointSize < epMaxPktSize) { + if (epMaxPktSize) + { + while (defaultEndpointSize < epMaxPktSize) + { fifoSize++; defaultEndpointSize <<= 1; } @@ -431,7 +454,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + epnum); USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + epnum)); - if (epnum == 0) { + if (epnum == 0) + { xfer_status[EP_MAX].max_packet_size = epMaxPktSize; // Enable the control endpoint - Endpoint 0 USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; @@ -445,19 +469,20 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) ); USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_STALLRQC; - if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) { + if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) + { // Endpoint configuration is successful USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXSTPES; // Enable Endpoint 0 Interrupts USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; return true; - } - else { + } else + { // Endpoint configuration is not successful return false; } - } - else { + } else + { // Enable the endpoint USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); // Set up the maxpacket size, fifo start address fifosize @@ -471,22 +496,25 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS_DEVEPTCFG_AUTOSW | ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) ); - if (eptype == TUSB_XFER_ISOCHRONOUS){ + if (eptype == TUSB_XFER_ISOCHRONOUS) + { USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); } #if USE_DUAL_BANK - if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK){ + if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK) + { USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_EPBK_2_BANK; } #endif USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; - if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) { + if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) + { USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); return true; - } - else { + } else + { // Endpoint configuration is not successful return false; } @@ -497,7 +525,8 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - if (len > xfer->max_packet_size) { + if (len > xfer->max_packet_size) + { len = xfer->max_packet_size; } @@ -506,11 +535,13 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) xfer->queued_len = (uint16_t)(xfer->queued_len + len); - if (ep_ix == 0U) { + if (ep_ix == 0U) + { // Control endpoint: clear the interrupt flag to send the data USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - } else { + } else + { // Other endpoint types: clear the FIFO control flag to send the data USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; } @@ -532,13 +563,15 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->total_len = total_bytes; xfer->queued_len = 0; - if(EP_DMA_SUPPORT(epnum) && total_bytes != 0) { + if(EP_DMA_SUPPORT(epnum) && total_bytes != 0) + { uint32_t udd_dma_ctrl = 0; udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); - if (dir == TUSB_DIR_OUT){ + if (dir == TUSB_DIR_OUT) + { udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; - } - else { + } else + { udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_B_EN; } // Start USB DMA to fill or read fifo of the selected endpoint @@ -548,7 +581,8 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // between read of EOT_STA and DMA enable uint32_t irq_state = __get_PRIMASK(); __disable_irq(); - if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) { + if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) + { USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl; USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); __set_PRIMASK(irq_state); @@ -560,12 +594,13 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // and the DMA transfer must be not started. // It is the end of transfer return false; - } - else { - if (dir == TUSB_DIR_OUT){ + } else + { + if (dir == TUSB_DIR_OUT) + { USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } - else { + } else + { dcd_transmit_packet(xfer,epnum); } } -- cgit v1.3.1 From c291deccfac7725a4e1f26357e133f32887e65aa Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Fri, 11 Jun 2021 12:14:14 +0200 Subject: Add fifo & DMA linked list mode support. --- examples/device/cdc_msc/src/tusb_config.h | 2 +- examples/device/cdc_msc/src/usb_descriptors.c | 4 +- src/portable/microchip/same70/dcd_same70.c | 177 +++++++++++++++++++------- 3 files changed, 132 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index 9a0262d30..f9e98b0f7 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -48,7 +48,7 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_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) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAME70) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index fa4342165..46b57f7e2 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -94,8 +94,8 @@ enum #define EPNUM_MSC_OUT 0x05 #define EPNUM_MSC_IN 0x85 -#elif CFG_TUSB_MCU == OPT_MCU_SAMG - // SAMG doesn't support a same endpoint number with different direction IN and OUT +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAME70 + // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_CDC_NOTIF 0x81 #define EPNUM_CDC_OUT 0x02 diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c index 72d91e466..eb716182d 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/same70/dcd_same70.c @@ -62,14 +62,33 @@ // Errata: The DMA feature is not available for Pipe/Endpoint 7 #define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) +// DMA Channel Transfer Descriptor +typedef struct { + volatile uint32_t next_desc; + volatile uint32_t buff_addr; + volatile uint32_t chnl_ctrl; + uint32_t padding; +} dma_desc_t; + +// Transfer control context typedef struct { uint8_t * buffer; uint16_t total_len; uint16_t queued_len; uint16_t max_packet_size; uint8_t interval; + tu_fifo_t * fifo; } xfer_ctl_t; +static tusb_speed_t get_speed(void); +static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); + +// DMA descriptors shouldn't be placed in ITCM +#if defined(USB_DMA_DESC_SECTION) +TU_ATTR_SECTION(TU_XSTRING(USB_DMA_DESC_SECTION)) +#endif +dma_desc_t dma_desc[6]; + xfer_ctl_t xfer_status[EP_MAX+1]; static const tusb_desc_endpoint_t ep0_desc = @@ -78,8 +97,6 @@ static const tusb_desc_endpoint_t ep0_desc = .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, }; -static tusb_speed_t get_speed(void); -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); //------------------------------------------------------------------ // Device API //------------------------------------------------------------------ @@ -224,9 +241,11 @@ static void dcd_ep_handler(uint8_t ep_ix) if (count) { uint8_t *ptr = EP_GET_FIFO_PTR(0,8); - for (int i = 0; i < count; i++) + if (xfer->buffer) { - xfer->buffer[xfer->queued_len + i] = ptr[i]; + memcpy(xfer->buffer + xfer->queued_len, ptr, count); + } else { + tu_fifo_write_n(xfer->fifo, ptr, count); } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } @@ -250,21 +269,24 @@ static void dcd_ep_handler(uint8_t ep_ix) { // TX not complete dcd_transmit_packet(xfer, 0); - } else - { + } else { // TX complete dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); } } - } else - { + } else { if (int_status & USBHS_DEVEPTISR_RXOUTI) { xfer_ctl_t *xfer = &xfer_status[ep_ix]; if (count) { uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); - memcpy(xfer->buffer + xfer->queued_len, ptr, count); + if (xfer->buffer) + { + memcpy(xfer->buffer + xfer->queued_len, ptr, count); + } else { + tu_fifo_write_n(xfer->fifo, ptr, count); + } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } // Acknowledge the interrupt @@ -289,8 +311,7 @@ static void dcd_ep_handler(uint8_t ep_ix) { // TX not complete dcd_transmit_packet(xfer, ep_ix); - } else - { + } else { // TX complete dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; @@ -314,8 +335,7 @@ static void dcd_dma_handler(uint8_t ep_ix) if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) { dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); - } else - { + } else { dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); } } @@ -337,13 +357,9 @@ void dcd_int_handler(uint8_t rhport) USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix)); } dcd_edpt_open (0, &ep0_desc); - // Acknowledge the End of Reset interrupt USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC; - // Acknowledge the Wakeup interrupt USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - // Acknowledge the suspend interrupt USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; - // Enable Suspend Interrupt USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; dcd_event_bus_reset(rhport, get_speed(), true); @@ -351,15 +367,10 @@ void dcd_int_handler(uint8_t rhport) // End of Wakeup interrupt if (int_status & USBHS_DEVISR_WAKEUP) { - // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - // Wait to unfreeze clock while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Acknowledge the Wakeup interrupt USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - // Disable Wakeup Interrupt USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; - // Enable Suspend Interrupt USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); @@ -369,15 +380,10 @@ void dcd_int_handler(uint8_t rhport) { // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - // Wait to unfreeze clock while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Acknowledge the suspend interrupt USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; - // Disable Suspend Interrupt USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; - // Enable Wakeup Interrupt USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; - // Freeze USB clock USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); @@ -476,13 +482,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) // Enable Endpoint 0 Interrupts USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; return true; - } else - { + } else { // Endpoint configuration is not successful return false; } - } else - { + } else { // Enable the endpoint USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); // Set up the maxpacket size, fifo start address fifosize @@ -513,8 +517,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); return true; - } else - { + } else { // Endpoint configuration is not successful return false; } @@ -524,24 +527,25 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - if (len > xfer->max_packet_size) { len = xfer->max_packet_size; } - uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); - memcpy(ptr, xfer->buffer + xfer->queued_len, len); - + if(xfer->buffer) + { + memcpy(ptr, xfer->buffer + xfer->queued_len, len); + } + else { + tu_fifo_read_n(xfer->fifo, ptr, len); + } xfer->queued_len = (uint16_t)(xfer->queued_len + len); - if (ep_ix == 0U) { // Control endpoint: clear the interrupt flag to send the data USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - } else - { + } else { // Other endpoint types: clear the FIFO control flag to send the data USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; } @@ -562,19 +566,17 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->buffer = buffer; xfer->total_len = total_bytes; xfer->queued_len = 0; + xfer->fifo = NULL; if(EP_DMA_SUPPORT(epnum) && total_bytes != 0) { - uint32_t udd_dma_ctrl = 0; - udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); + uint32_t udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); if (dir == TUSB_DIR_OUT) { udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; - } else - { + } else { udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_B_EN; } - // Start USB DMA to fill or read fifo of the selected endpoint USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)buffer; udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_BUFFIT | USBHS_DEVDMACONTROL_CHANN_ENB; // Disable IRQs to have a short sequence @@ -594,13 +596,92 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // and the DMA transfer must be not started. // It is the end of transfer return false; - } else - { + } else { if (dir == TUSB_DIR_OUT) { USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } else + } else { + dcd_transmit_packet(xfer,epnum); + } + } + return true; +} + +// The number of bytes has to be given explicitly to allow more flexible control of how many +// bytes should be written and second to keep the return value free to give back a boolean +// success message. If total_bytes is too big, the FIFO will copy only what is available +// into the USB buffer! +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = &xfer_status[epnum]; + if(epnum == 0x80) + xfer = &xfer_status[EP_MAX]; + + xfer->buffer = NULL; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->fifo = ff; + + if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) + { + tu_fifo_buffer_info_t info; + uint32_t udd_dma_ctrl_lin = USBHS_DEVDMACONTROL_CHANN_ENB; + uint32_t udd_dma_ctrl_wrap = USBHS_DEVDMACONTROL_CHANN_ENB | USBHS_DEVDMACONTROL_END_BUFFIT; + if (dir == TUSB_DIR_OUT) + { + tu_fifo_get_write_info(ff, &info); + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; + udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; + } else { + tu_fifo_get_read_info(ff, &info); + if(info.len_wrap == 0) + { + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_B_EN; + } + udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_B_EN; + } + + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)info.ptr_lin; + if (info.len_wrap) + { + dma_desc[epnum - 1].next_desc = 0; + dma_desc[epnum - 1].buff_addr = (uint32_t)info.ptr_wrap; + dma_desc[epnum - 1].chnl_ctrl = + udd_dma_ctrl_wrap | USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_wrap); + udd_dma_ctrl_lin |= USBHS_DEVDMASTATUS_DESC_LDST; + __DSB(); + __ISB(); + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMANXTDSC = (uint32_t)&dma_desc[epnum - 1]; + } else { + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_BUFFIT; + } + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_lin); + // Disable IRQs to have a short sequence + // between read of EOT_STA and DMA enable + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) + { + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl_lin; + USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); + __set_PRIMASK(irq_state); + return true; + } + __set_PRIMASK(irq_state); + + // Here a ZLP has been recieved + // and the DMA transfer must be not started. + // It is the end of transfer + return false; + } else { + if (dir == TUSB_DIR_OUT) { + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } else { dcd_transmit_packet(xfer,epnum); } } -- cgit v1.3.1 From 5d6e381ef640fce9f590abe0ce304bf4c9474605 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Jun 2021 17:34:51 +0700 Subject: refactor rp2040 usb - make _hw_endpoint_xfer_sync and _hw_endpoint_start_next_buffer private - drop prefix _ from _hw_endpoint_xfer_continue and _hw_endpoint_reset_transfer --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 4 +- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 65 +-------------------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 85 ++++++++++++++-------------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 6 +- 4 files changed, 48 insertions(+), 112 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index ccdbb9c01..c755c2e6f 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -201,7 +201,7 @@ static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t b static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); - _hw_endpoint_xfer_start(ep, buffer, total_bytes); + hw_endpoint_xfer_start(ep, buffer, total_bytes); } static void hw_handle_buff_status(void) @@ -221,7 +221,7 @@ static void hw_handle_buff_status(void) // IN transfer for even i, OUT transfer for odd i struct hw_endpoint *ep = hw_endpoint_get_by_num(i >> 1u, !(i & 1u)); // Continue xfer - bool done = _hw_endpoint_xfer_continue(ep); + bool done = hw_endpoint_xfer_continue(ep); if (done) { // Notify diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 561656a10..1ba9725fe 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -123,7 +123,7 @@ static void hw_xfer_complete(struct hw_endpoint *ep, xfer_result_t xfer_result) static void _handle_buff_status_bit(uint bit, struct hw_endpoint *ep) { usb_hw_clear->buf_status = bit; - bool done = _hw_endpoint_xfer_continue(ep); + bool done = hw_endpoint_xfer_continue(ep); if (done) { hw_xfer_complete(ep, XFER_RESULT_SUCCESS); @@ -485,65 +485,6 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } -// return true if double buffered -static bool xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len) -{ - // Fill in info now that we're kicking off the hw - ep->total_len = total_len; - ep->len = 0; - - // Limit by packet size - ep->user_buf = buffer; - - // Buffer 0 - ep->transfer_size = tu_min16(total_len, ep->wMaxPacketSize); - total_len -= ep->transfer_size; - - // Buffer 1 - ep->buf_1_len = tu_min16(total_len, ep->wMaxPacketSize); - total_len -= ep->buf_1_len; - - ep->active = true; - - // Write buffer control - - // Buffer 0 - uint32_t bufctrl = ep->transfer_size | USB_BUF_CTRL_AVAIL; - - // Copy data to DPB if tx - if (!ep->rx) - { - // Copy data from user buffer to hw buffer - memcpy(ep->hw_data_buf, ep->user_buf, ep->transfer_size + ep->buf_1_len); - - // Mark as full - bufctrl |= USB_BUF_CTRL_FULL | (ep->buf_1_len ? (USB_BUF_CTRL_FULL << 16) : 0); - } - - // PID - bufctrl |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; - ep->next_pid ^= 1u; - - if (ep->buf_1_len) - { - bufctrl |= (ep->buf_1_len | USB_BUF_CTRL_AVAIL) << 16; - bufctrl |= (ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID) << 16; - ep->next_pid ^= 1u; - } - - // determine which buffer is last - if (total_len == 0) - { - bufctrl |= USB_BUF_CTRL_LAST << (ep->buf_1_len ? 16 : 0); - } - - print_bufctrl32(bufctrl); - - _hw_endpoint_buffer_control_set_value32(ep, bufctrl); - - return ep->buf_1_len > 0; -} - bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { (void) rhport; @@ -567,7 +508,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * // sie ctrl registers. Otherwise interrupt ep registers should // already be configured if (ep == &epx) { - _hw_endpoint_xfer_start(ep, buffer, buflen); + hw_endpoint_xfer_start(ep, buffer, buflen); // That has set up buffer control, endpoint control etc // for host we have to initiate the transfer @@ -581,7 +522,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * usb_hw->sie_ctrl = flags; }else { - _hw_endpoint_xfer_start(ep, buffer, buflen); + hw_endpoint_xfer_start(ep, buffer, buflen); } return true; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 5f61f90c5..293325b8b 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -50,6 +50,13 @@ static inline void _hw_endpoint_update_last_buf(struct hw_endpoint *ep) } #endif +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +void _hw_endpoint_xfer_sync(struct hw_endpoint *ep); +void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep); + void rp2040_usb_init(void) { // Reset usb controller @@ -180,8 +187,7 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) _hw_endpoint_buffer_control_set_value32(ep, buf_ctrl); } - -void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len) +void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len) { _hw_endpoint_lock_update(ep, 1); pico_trace("Start transfer of total len %d on ep %d %s\n", total_len, tu_edpt_number(ep->ep_addr), @@ -205,58 +211,34 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t _hw_endpoint_lock_update(ep, -1); } -void _hw_endpoint_xfer_sync (struct hw_endpoint *ep) +static void ep_sync_buf(struct hw_endpoint *ep, uint8_t buf_id) { - // Update hw endpoint struct with info from hardware - // after a buff status interrupt - - uint32_t const buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); - print_bufctrl32(buf_ctrl); - - // Transferred bytes for each buffer - uint16_t xferred_bytes[2]; + uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); + if (buf_id) buf_ctrl = buf_ctrl >> 16; - xferred_bytes[0] = buf_ctrl & USB_BUF_CTRL_LEN_MASK; + uint16_t xferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; - // double buffered: take buffer1 into account as well - if ( (*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS ) - { - xferred_bytes[1] = (buf_ctrl >> 16) & USB_BUF_CTRL_LEN_MASK; - }else - { - xferred_bytes[1] = 0; - } - - TU_LOG_INT(2, xferred_bytes[0]); - TU_LOG_INT(2, xferred_bytes[1]); - - // We are continuing a transfer here. If we are TX, we have successfully - // sent some data can increase the length we have sent if ( !ep->rx ) { + // We are continuing a transfer here. If we are TX, we have successfully + // sent some data can increase the length we have sent assert(!(buf_ctrl & USB_BUF_CTRL_FULL)); - ep->len += xferred_bytes[0] + xferred_bytes[1]; - } - else + + ep->len += xferred_bytes; + }else { - // If we are OUT we have recieved some data, so can increase the length - // we have recieved AFTER we have copied it to the user buffer at the appropriate offset + // If we have received some data, so can increase the length + // we have received AFTER we have copied it to the user buffer at the appropriate offset assert(buf_ctrl & USB_BUF_CTRL_FULL); - memcpy(&ep->user_buf[ep->len], ep->hw_data_buf, xferred_bytes[0]); - ep->len += xferred_bytes[0]; - - if (xferred_bytes[1]) - { - memcpy(&ep->user_buf[ep->len], ep->hw_data_buf+64, xferred_bytes[1]); - ep->len += xferred_bytes[1]; - } + memcpy(&ep->user_buf[ep->len], ep->hw_data_buf + buf_id*64, xferred_bytes); + ep->len += xferred_bytes; } - // Sometimes the host will send less data than we expect... - // If this is a short out transfer update the total length of the transfer - // to be the current length - if ( (ep->rx) && ((xferred_bytes[0] < ep->wMaxPacketSize) || (xferred_bytes[1] && (xferred_bytes[1] < ep->wMaxPacketSize))) ) + // Short packet + // TODO what if we prepare double buffered but receive short packet on buffer 0 !!! + // would the buffer status or trans complete interrupt is triggered + if (xferred_bytes < ep->wMaxPacketSize) { pico_trace("Short rx transfer\n"); // Reduce total length as this is last packet @@ -264,8 +246,23 @@ void _hw_endpoint_xfer_sync (struct hw_endpoint *ep) } } +void _hw_endpoint_xfer_sync (struct hw_endpoint *ep) +{ + // Update hw endpoint struct with info from hardware + // after a buff status interrupt + + // always sync buffer 0 + ep_sync_buf(ep, 0); + + // sync buffer 1 if double buffered + if ( (*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS ) + { + ep_sync_buf(ep, 1); + } +} + // Returns true if transfer is complete -bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) +bool hw_endpoint_xfer_continue(struct hw_endpoint *ep) { _hw_endpoint_lock_update(ep, 1); // Part way through a transfer diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index d27f4157a..b3fcb9417 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -94,11 +94,9 @@ struct hw_endpoint void rp2040_usb_init(void); +void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len); +bool hw_endpoint_xfer_continue(struct hw_endpoint *ep); void hw_endpoint_reset_transfer(struct hw_endpoint *ep); -void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep); -void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len); -void _hw_endpoint_xfer_sync(struct hw_endpoint *ep); -bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep); void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask); static inline uint32_t _hw_endpoint_buffer_control_get_value32(struct hw_endpoint *ep) { -- cgit v1.3.1 From 1d48320d8aa85ebeae617be35614cd80011c37f4 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Jun 2021 17:58:29 +0700 Subject: rename hw endpoint - total_len to remaining_len - len to xferred_len --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 2 +- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 4 +- src/portable/raspberrypi/rp2040/rp2040_usb.c | 78 ++++++++++++---------------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 6 ++- 4 files changed, 41 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index c755c2e6f..3f2bf7810 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -225,7 +225,7 @@ static void hw_handle_buff_status(void) if (done) { // Notify - dcd_event_xfer_complete(0, ep->ep_addr, ep->len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(0, ep->ep_addr, ep->xferred_len, XFER_RESULT_SUCCESS, true); hw_endpoint_reset_transfer(ep); } remaining_buffers &= ~bit; diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 1ba9725fe..6a1d7cff2 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -115,7 +115,7 @@ static void hw_xfer_complete(struct hw_endpoint *ep, xfer_result_t xfer_result) // Mark transfer as done before we tell the tinyusb stack uint8_t dev_addr = ep->dev_addr; uint8_t ep_addr = ep->ep_addr; - uint xferred_len = ep->len; + uint xferred_len = ep->xferred_len; hw_endpoint_reset_transfer(ep); hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, xfer_result, true); } @@ -542,7 +542,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet _hw_endpoint_init(ep, dev_addr, 0x00, ep->wMaxPacketSize, 0, 0); assert(ep->configured); - ep->total_len = 8; + ep->remaining_len = 8; ep->transfer_size = 8; ep->active = true; ep->sent_setup = true; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 293325b8b..037b24247 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -43,20 +43,13 @@ static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) { // sense to have worker and IRQ on same core, however I think using critsec is about equivalent. } -#if TUSB_OPT_HOST_ENABLED -static inline void _hw_endpoint_update_last_buf(struct hw_endpoint *ep) -{ - ep->last_buf = (ep->len + ep->transfer_size == ep->total_len); -} -#endif +void _hw_endpoint_xfer_sync(struct hw_endpoint *ep); +void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep); //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ -void _hw_endpoint_xfer_sync(struct hw_endpoint *ep); -void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep); - void rp2040_usb_init(void) { // Reset usb controller @@ -82,8 +75,8 @@ void hw_endpoint_reset_transfer(struct hw_endpoint *ep) #if TUSB_OPT_HOST_ENABLED ep->sent_setup = false; #endif - ep->total_len = 0; - ep->len = 0; + ep->remaining_len = 0; + ep->xferred_len = 0; ep->transfer_size = 0; ep->user_buf = 0; } @@ -118,22 +111,29 @@ void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_m *ep->buffer_control = value; } +//static void prepare_ep_buf(struct hw_endpoint *ep, uint8_t buf_id) +//{ +// uint16_t buflen = tu_min16(ep->remaining_len, ep->wMaxPacketSize); +// +// +//} + // Prepare buffer control register value void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) { - uint16_t remaining = ep->total_len - ep->len; uint32_t ep_ctrl = *ep->endpoint_control; uint32_t buf_ctrl; // Buffer 0 - ep->transfer_size = tu_min16(remaining, ep->wMaxPacketSize); - remaining -= ep->transfer_size; + ep->transfer_size = tu_min16(ep->remaining_len, ep->wMaxPacketSize); + ep->remaining_len -= ep->transfer_size; buf_ctrl = ep->transfer_size | USB_BUF_CTRL_AVAIL; if ( !ep->rx ) { // Copy data from user buffer to hw buffer - memcpy(ep->hw_data_buf, ep->user_buf+ep->len, ep->transfer_size); + memcpy(ep->hw_data_buf, ep->user_buf, ep->transfer_size); + ep->user_buf += ep->transfer_size; // Mark as full buf_ctrl |= USB_BUF_CTRL_FULL; @@ -144,8 +144,8 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) ep->next_pid ^= 1u; // Buffer 1 - ep->buf_1_len = tu_min16(remaining, ep->wMaxPacketSize); - remaining -= ep->buf_1_len; + ep->buf_1_len = tu_min16(ep->remaining_len, ep->wMaxPacketSize); + ep->remaining_len -= ep->buf_1_len; if (ep->buf_1_len) { @@ -156,7 +156,8 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) if ( !ep->rx ) { // Copy data from user buffer to hw buffer - memcpy(ep->hw_data_buf+64, ep->user_buf+ep->len+ep->transfer_size, ep->buf_1_len); + memcpy(ep->hw_data_buf+64, ep->user_buf, ep->buf_1_len); + ep->user_buf += ep->buf_1_len; } // Set endpoint control double buffered bit if needed @@ -174,7 +175,7 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) // Is this the last buffer? Only really matters for host mode. Will trigger // the trans complete irq but also stop it polling. We only really care about // trans complete for setup packets being sent - if (remaining == 0) + if (ep->remaining_len == 0) { buf_ctrl |= USB_BUF_CTRL_LAST << (ep->buf_1_len ? 16 : 0); } @@ -202,16 +203,16 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t to } // Fill in info now that we're kicking off the hw - ep->total_len = total_len; - ep->len = 0; - ep->active = true; - ep->user_buf = buffer; + ep->remaining_len = total_len; + ep->xferred_len = 0; + ep->active = true; + ep->user_buf = buffer; _hw_endpoint_start_next_buffer(ep); _hw_endpoint_lock_update(ep, -1); } -static void ep_sync_buf(struct hw_endpoint *ep, uint8_t buf_id) +static void sync_ep_buf(struct hw_endpoint *ep, uint8_t buf_id) { uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); if (buf_id) buf_ctrl = buf_ctrl >> 16; @@ -224,15 +225,16 @@ static void ep_sync_buf(struct hw_endpoint *ep, uint8_t buf_id) // sent some data can increase the length we have sent assert(!(buf_ctrl & USB_BUF_CTRL_FULL)); - ep->len += xferred_bytes; + ep->xferred_len += xferred_bytes; }else { // If we have received some data, so can increase the length // we have received AFTER we have copied it to the user buffer at the appropriate offset assert(buf_ctrl & USB_BUF_CTRL_FULL); - memcpy(&ep->user_buf[ep->len], ep->hw_data_buf + buf_id*64, xferred_bytes); - ep->len += xferred_bytes; + memcpy(ep->user_buf, ep->hw_data_buf + buf_id*64, xferred_bytes); + ep->xferred_len += xferred_bytes; + ep->user_buf += xferred_bytes; } // Short packet @@ -242,7 +244,7 @@ static void ep_sync_buf(struct hw_endpoint *ep, uint8_t buf_id) { pico_trace("Short rx transfer\n"); // Reduce total length as this is last packet - ep->total_len = ep->len; + ep->remaining_len = 0; } } @@ -252,12 +254,12 @@ void _hw_endpoint_xfer_sync (struct hw_endpoint *ep) // after a buff status interrupt // always sync buffer 0 - ep_sync_buf(ep, 0); + sync_ep_buf(ep, 0); // sync buffer 1 if double buffered if ( (*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS ) { - ep_sync_buf(ep, 1); + sync_ep_buf(ep, 1); } } @@ -275,23 +277,11 @@ bool hw_endpoint_xfer_continue(struct hw_endpoint *ep) _hw_endpoint_xfer_sync(ep); // Now we have synced our state with the hardware. Is there more data to transfer? - // Limit by packet size - uint16_t remaining_bytes = ep->total_len - ep->len; - ep->transfer_size = tu_min16(remaining_bytes, ep->wMaxPacketSize); - - TU_LOG_INT(2, ep->transfer_size); - - // Can happen because of programmer error so check for it - if (ep->len > ep->total_len) - { - panic("Transferred more data than expected"); - } - // If we are done then notify tinyusb - if (ep->len == ep->total_len) + if (ep->remaining_len == 0) { pico_trace("Completed transfer of %d bytes on ep %d %s\n", - ep->len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); + ep->xferred_len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); // Notify caller we are done so it can notify the tinyusb stack _hw_endpoint_lock_update(ep, -1); return true; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index b3fcb9417..d61a5a57f 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -62,10 +62,12 @@ struct hw_endpoint // Current transfer information bool active; - uint16_t total_len; - uint16_t len; + uint16_t remaining_len; + uint16_t xferred_len; // Amount of data with the hardware + uint16_t buflen[2]; + uint16_t transfer_size; // buf0_len; uint16_t buf_1_len; -- cgit v1.3.1 From 93cb2ff4cf5c9b95ed423be6b8dae498868ab435 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Jun 2021 18:14:11 +0700 Subject: more refactor double buffered rp2040 --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 167 +++++++++++++-------------- 1 file changed, 80 insertions(+), 87 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 037b24247..38a59d83a 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -52,33 +52,33 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep); void rp2040_usb_init(void) { - // Reset usb controller - reset_block(RESETS_RESET_USBCTRL_BITS); - unreset_block_wait(RESETS_RESET_USBCTRL_BITS); + // Reset usb controller + reset_block(RESETS_RESET_USBCTRL_BITS); + unreset_block_wait(RESETS_RESET_USBCTRL_BITS); - // Clear any previous state just in case - memset(usb_hw, 0, sizeof(*usb_hw)); - memset(usb_dpram, 0, sizeof(*usb_dpram)); + // Clear any previous state just in case + memset(usb_hw, 0, sizeof(*usb_hw)); + memset(usb_dpram, 0, sizeof(*usb_dpram)); - // Mux the controller to the onboard usb phy - usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; + // Mux the controller to the onboard usb phy + usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; - // Force VBUS detect so the device thinks it is plugged into a host - // TODO support VBUs detect - usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; + // Force VBUS detect so the device thinks it is plugged into a host + // TODO support VBUs detect + usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; } void hw_endpoint_reset_transfer(struct hw_endpoint *ep) { - ep->stalled = false; - ep->active = false; + ep->stalled = false; + ep->active = false; #if TUSB_OPT_HOST_ENABLED - ep->sent_setup = false; + ep->sent_setup = false; #endif - ep->remaining_len = 0; - ep->xferred_len = 0; - ep->transfer_size = 0; - ep->user_buf = 0; + ep->remaining_len = 0; + ep->xferred_len = 0; + ep->transfer_size = 0; + ep->user_buf = 0; } void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask) { @@ -111,76 +111,69 @@ void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_m *ep->buffer_control = value; } -//static void prepare_ep_buf(struct hw_endpoint *ep, uint8_t buf_id) -//{ -// uint16_t buflen = tu_min16(ep->remaining_len, ep->wMaxPacketSize); -// -// -//} - -// Prepare buffer control register value -void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) +static uint32_t compute_ep_buf(struct hw_endpoint *ep, uint8_t buf_id) { - uint32_t ep_ctrl = *ep->endpoint_control; - uint32_t buf_ctrl; + uint16_t const buflen = tu_min16(ep->remaining_len, ep->wMaxPacketSize); + ep->remaining_len -= buflen; - // Buffer 0 - ep->transfer_size = tu_min16(ep->remaining_len, ep->wMaxPacketSize); - ep->remaining_len -= ep->transfer_size; + uint32_t buf_ctrl = buflen | USB_BUF_CTRL_AVAIL; + + // PID + buf_ctrl |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; + ep->next_pid ^= 1u; - buf_ctrl = ep->transfer_size | USB_BUF_CTRL_AVAIL; if ( !ep->rx ) { // Copy data from user buffer to hw buffer - memcpy(ep->hw_data_buf, ep->user_buf, ep->transfer_size); - ep->user_buf += ep->transfer_size; + memcpy(ep->hw_data_buf, ep->user_buf, buflen); + ep->user_buf += buflen; // Mark as full buf_ctrl |= USB_BUF_CTRL_FULL; } - // PID - buf_ctrl |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; - ep->next_pid ^= 1u; +#if TUSB_OPT_HOST_ENABLED + // Is this the last buffer? Only really matters for host mode. Will trigger + // the trans complete irq but also stop it polling. We only really care about + // trans complete for setup packets being sent + if (ep->remaining_len == 0) + { + buf_ctrl |= USB_BUF_CTRL_LAST; + } +#endif + + if (buf_id) buf_ctrl = buf_ctrl << 16; + + return buf_ctrl; +} + +// Prepare buffer control register value +void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) +{ + uint32_t ep_ctrl = *ep->endpoint_control; - // Buffer 1 - ep->buf_1_len = tu_min16(ep->remaining_len, ep->wMaxPacketSize); - ep->remaining_len -= ep->buf_1_len; + // always compute buffer 0 + uint32_t buf_ctrl = compute_ep_buf(ep, 0); - if (ep->buf_1_len) + if(ep->remaining_len) { - buf_ctrl |= (ep->buf_1_len | USB_BUF_CTRL_AVAIL) << 16; - buf_ctrl |= (ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID) << 16; - ep->next_pid ^= 1u; - - if ( !ep->rx ) - { - // Copy data from user buffer to hw buffer - memcpy(ep->hw_data_buf+64, ep->user_buf, ep->buf_1_len); - ep->user_buf += ep->buf_1_len; - } + // Use buffer 1 (double buffered) if there is still data + // TODO: Isochronous for buffer1 bit-field is different than CBI (control bulk, interrupt) + + buf_ctrl |= compute_ep_buf(ep, 1); // Set endpoint control double buffered bit if needed ep_ctrl &= ~EP_CTRL_INTERRUPT_PER_BUFFER; ep_ctrl |= EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER; }else { + // Single buffered since 1 is enough ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER); ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER; } *ep->endpoint_control = ep_ctrl; -#if TUSB_OPT_HOST_ENABLED - // Is this the last buffer? Only really matters for host mode. Will trigger - // the trans complete irq but also stop it polling. We only really care about - // trans complete for setup packets being sent - if (ep->remaining_len == 0) - { - buf_ctrl |= USB_BUF_CTRL_LAST << (ep->buf_1_len ? 16 : 0); - } -#endif - print_bufctrl32(buf_ctrl); // Finally, write to buffer_control which will trigger the transfer @@ -266,34 +259,34 @@ void _hw_endpoint_xfer_sync (struct hw_endpoint *ep) // Returns true if transfer is complete bool hw_endpoint_xfer_continue(struct hw_endpoint *ep) { - _hw_endpoint_lock_update(ep, 1); - // Part way through a transfer - if (!ep->active) - { - panic("Can't continue xfer on inactive ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string); - } + _hw_endpoint_lock_update(ep, 1); + // Part way through a transfer + if (!ep->active) + { + panic("Can't continue xfer on inactive ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string); + } - // Update EP struct from hardware state - _hw_endpoint_xfer_sync(ep); - - // Now we have synced our state with the hardware. Is there more data to transfer? - // If we are done then notify tinyusb - if (ep->remaining_len == 0) - { - pico_trace("Completed transfer of %d bytes on ep %d %s\n", - ep->xferred_len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); - // Notify caller we are done so it can notify the tinyusb stack - _hw_endpoint_lock_update(ep, -1); - return true; - } - else - { - _hw_endpoint_start_next_buffer(ep); - } + // Update EP struct from hardware state + _hw_endpoint_xfer_sync(ep); + // Now we have synced our state with the hardware. Is there more data to transfer? + // If we are done then notify tinyusb + if (ep->remaining_len == 0) + { + pico_trace("Completed transfer of %d bytes on ep %d %s\n", + ep->xferred_len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); + // Notify caller we are done so it can notify the tinyusb stack _hw_endpoint_lock_update(ep, -1); - // More work to do - return false; + return true; + } + else + { + _hw_endpoint_start_next_buffer(ep); + } + + _hw_endpoint_lock_update(ep, -1); + // More work to do + return false; } #endif -- cgit v1.3.1 From 66c8a13f137d54a2c140d04310cd4b7adba50401 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Jun 2021 18:26:41 +0700 Subject: remove unused variable in hw endpoint last_buf, buf_sel, transfer_size --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 18 +++++++++--------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 22 +++++++++++----------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 12 ------------ 3 files changed, 20 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 6a1d7cff2..0bbd7e7c2 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * Copyright (c) 2021 Ha Thach (tinyusb.org) for Double Buffered * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -220,6 +221,14 @@ static void hcd_rp2040_irq(void) usb_hw_clear->sie_status = USB_SIE_STATUS_SPEED_BITS; } + if (status & USB_INTS_BUFF_STATUS_BITS) + { + handled |= USB_INTS_BUFF_STATUS_BITS; + TU_LOG(2, "Buffer complete\n"); + // print_bufctrl32(*epx.buffer_control); + hw_handle_buff_status(); + } + if (status & USB_INTS_TRANS_COMPLETE_BITS) { handled |= USB_INTS_TRANS_COMPLETE_BITS; @@ -228,14 +237,6 @@ static void hcd_rp2040_irq(void) hw_trans_complete(); } - if (status & USB_INTS_BUFF_STATUS_BITS) - { - handled |= USB_INTS_BUFF_STATUS_BITS; - TU_LOG(2, "Buffer complete\n"); - print_bufctrl32(*epx.buffer_control); - hw_handle_buff_status(); - } - if (status & USB_INTS_STALL_BITS) { // We have rx'd a stall from the device @@ -543,7 +544,6 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet assert(ep->configured); ep->remaining_len = 8; - ep->transfer_size = 8; ep->active = true; ep->sent_setup = true; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 38a59d83a..26c6e8b13 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * Copyright (c) 2021 Ha Thach (tinyusb.org) for Double Buffered * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -43,8 +44,8 @@ static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) { // sense to have worker and IRQ on same core, however I think using critsec is about equivalent. } -void _hw_endpoint_xfer_sync(struct hw_endpoint *ep); -void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep); +static void _hw_endpoint_xfer_sync(struct hw_endpoint *ep); +static void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep); //--------------------------------------------------------------------+ // @@ -77,7 +78,6 @@ void hw_endpoint_reset_transfer(struct hw_endpoint *ep) #endif ep->remaining_len = 0; ep->xferred_len = 0; - ep->transfer_size = 0; ep->user_buf = 0; } @@ -111,7 +111,7 @@ void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_m *ep->buffer_control = value; } -static uint32_t compute_ep_buf(struct hw_endpoint *ep, uint8_t buf_id) +static uint32_t compute_buffer_control(struct hw_endpoint *ep, uint8_t buf_id) { uint16_t const buflen = tu_min16(ep->remaining_len, ep->wMaxPacketSize); ep->remaining_len -= buflen; @@ -148,19 +148,19 @@ static uint32_t compute_ep_buf(struct hw_endpoint *ep, uint8_t buf_id) } // Prepare buffer control register value -void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) +static void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) { uint32_t ep_ctrl = *ep->endpoint_control; // always compute buffer 0 - uint32_t buf_ctrl = compute_ep_buf(ep, 0); + uint32_t buf_ctrl = compute_buffer_control(ep, 0); if(ep->remaining_len) { // Use buffer 1 (double buffered) if there is still data // TODO: Isochronous for buffer1 bit-field is different than CBI (control bulk, interrupt) - buf_ctrl |= compute_ep_buf(ep, 1); + buf_ctrl |= compute_buffer_control(ep, 1); // Set endpoint control double buffered bit if needed ep_ctrl &= ~EP_CTRL_INTERRUPT_PER_BUFFER; @@ -205,7 +205,7 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t to _hw_endpoint_lock_update(ep, -1); } -static void sync_ep_buf(struct hw_endpoint *ep, uint8_t buf_id) +static void sync_ep_buffer(struct hw_endpoint *ep, uint8_t buf_id) { uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); if (buf_id) buf_ctrl = buf_ctrl >> 16; @@ -241,18 +241,18 @@ static void sync_ep_buf(struct hw_endpoint *ep, uint8_t buf_id) } } -void _hw_endpoint_xfer_sync (struct hw_endpoint *ep) +static void _hw_endpoint_xfer_sync (struct hw_endpoint *ep) { // Update hw endpoint struct with info from hardware // after a buff status interrupt // always sync buffer 0 - sync_ep_buf(ep, 0); + sync_ep_buffer(ep, 0); // sync buffer 1 if double buffered if ( (*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS ) { - sync_ep_buf(ep, 1); + sync_ep_buffer(ep, 1); } } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index d61a5a57f..ada1dd750 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -65,12 +65,6 @@ struct hw_endpoint uint16_t remaining_len; uint16_t xferred_len; - // Amount of data with the hardware - uint16_t buflen[2]; - - uint16_t transfer_size; // buf0_len; - uint16_t buf_1_len; - // User buffer in main memory uint8_t *user_buf; @@ -80,12 +74,6 @@ struct hw_endpoint uint8_t transfer_type; #if TUSB_OPT_HOST_ENABLED - // Only needed for host mode - bool last_buf; - - // RP2040-E4: HOST BUG. Host will incorrect write status to top half of buffer - // control register when doing transfers > 1 packet - uint8_t buf_sel; // Only needed for host uint8_t dev_addr; bool sent_setup; -- cgit v1.3.1 From a6d22f5a6879388e657987378cecea827794ad1e Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Jun 2021 18:39:28 +0700 Subject: replace pico_warn by log level 1 --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 2 +- src/portable/raspberrypi/rp2040/rp2040_usb.h | 24 +++++++++++++----------- 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 26c6e8b13..cb46ad1b9 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -189,7 +189,7 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t to if ( ep->active ) { // TODO: Is this acceptable for interrupt packets? - pico_warn("WARN: starting new transfer on already active ep %d %s\n", tu_edpt_number(ep->ep_addr), + TU_LOG(1, "WARN: starting new transfer on already active ep %d %s\n", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]); hw_endpoint_reset_transfer(ep); diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index ada1dd750..278ba59ec 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -29,12 +29,6 @@ #define pico_info(format,...) ((void)0) #endif -#if false && !defined(NDEBUG) -#define pico_warn(format,args...) printf(format, ## args) -#else -#define pico_warn(format,...) ((void)0) -#endif - // Hardware information per endpoint struct hw_endpoint { @@ -127,13 +121,14 @@ typedef union TU_ATTR_PACKED TU_VERIFY_STATIC(sizeof(rp2040_buffer_control_t) == 2, "size is not correct"); -static inline void print_bufctrl16(uint32_t __unused u16) +#if CFG_TUSB_DEBUG >= 3 +static inline void print_bufctrl16(uint32_t u16) { - rp2040_buffer_control_t __unused bufctrl = { + rp2040_buffer_control_t bufctrl = { .u16 = u16 }; - TU_LOG(2, "len = %u, available = %u, stall = %u, reset = %u, toggle = %u, last = %u, full = %u\r\n", + TU_LOG(3, "len = %u, available = %u, stall = %u, reset = %u, toggle = %u, last = %u, full = %u\r\n", bufctrl.xfer_len, bufctrl.available, bufctrl.stall, bufctrl.reset_bufsel, bufctrl.data_toggle, bufctrl.last_buf, bufctrl.full); } @@ -142,12 +137,19 @@ static inline void print_bufctrl32(uint32_t u32) uint16_t u16; u16 = u32 >> 16; - TU_LOG(2, " Buffer Control 1 0x%x: ", u16); + TU_LOG(3, " Buffer Control 1 0x%x: ", u16); print_bufctrl16(u16); u16 = u32 & 0x0000ffff; - TU_LOG(2, " Buffer Control 0 0x%x: ", u16); + TU_LOG(3, " Buffer Control 0 0x%x: ", u16); print_bufctrl16(u16); } +#else + +#define print_bufctrl16(u16) +#define print_bufctrl32(u32) + +#endif + #endif -- cgit v1.3.1 From b39faa15effec35dceb95655b0db75c3fe564f3d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Jun 2021 18:44:08 +0700 Subject: map pico_info to log2, pico_trace to log3 --- src/portable/raspberrypi/rp2040/rp2040_usb.h | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 278ba59ec..4c24b8dbe 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -17,17 +17,8 @@ #endif -#if true || false && !defined(NDEBUG) -#define pico_trace(format,args...) printf(format, ## args) -#else -#define pico_trace(format,...) ((void)0) -#endif - -#if false && !defined(NDEBUG) -#define pico_info(format,args...) printf(format, ## args) -#else -#define pico_info(format,...) ((void)0) -#endif +#define pico_info(...) TU_LOG(2, __VA_ARGS__) +#define pico_trace(...) TU_LOG(3, __VA_ARGS__) // Hardware information per endpoint struct hw_endpoint -- cgit v1.3.1 From dfe5a727c6b236c1b05b5447cdf0535545a6d32e Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Jun 2021 18:53:56 +0700 Subject: log clean up --- src/class/hid/hid_host.c | 6 +++--- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 8 +++----- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index a227c2a86..7444c10fe 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -442,9 +442,9 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t const data8 = desc_report[0]; - TU_LOG2("tag = %d, type = %d, size = %d, data = ", tag, type, size); - for(uint32_t i=0; iendpoint_control; if (ep_ctrl & EP_CTRL_DOUBLE_BUFFERED_BITS) { - TU_LOG(2, "Double Buffered "); + TU_LOG(3, "Double Buffered: "); }else { - TU_LOG(2, "Single Buffered "); + TU_LOG(3, "Single Buffered: "); } - if (ep_ctrl & EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER) TU_LOG(2, "Interrupt per double "); - if (ep_ctrl & EP_CTRL_INTERRUPT_PER_BUFFER) TU_LOG(2, "Interrupt per single "); - TU_LOG_HEX(2, ep_ctrl); + TU_LOG_HEX(3, ep_ctrl); _handle_buff_status_bit(bit, ep); } -- cgit v1.3.1 From 910e11a8aba7328a3cb61ecf8ac5a10f8a525377 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Jun 2021 19:04:16 +0700 Subject: fix ci build --- src/host/usbh.c | 7 ++++--- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index 81b9e84af..203f9fd54 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -990,13 +990,14 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura // parse each interfaces while( p_desc < _usbh_ctrl_buf + desc_cfg->wTotalLength ) { - tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL; + // TODO Do we need to use IAD + // 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) ) { - desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc; - p_desc = tu_desc_next(p_desc); // next to Interface + // desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc; + p_desc = tu_desc_next(p_desc); } TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index c145082f2..ab8639861 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -151,7 +151,6 @@ static void hw_handle_buff_status(void) { TU_LOG(3, "Single Buffered: "); } - TU_LOG_HEX(3, ep_ctrl); _handle_buff_status_bit(bit, ep); -- cgit v1.3.1 From 9a03ab9dfadb4f5a93df02b76a84c44edc6fc9f4 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Fri, 11 Jun 2021 20:52:22 +0100 Subject: dcd: same70: change cmsis deprecated macros Signed-off-by: Rafael Silva --- src/portable/microchip/same70/dcd_same70.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c index eb716182d..284010e53 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/same70/dcd_same70.c @@ -233,7 +233,7 @@ static void dcd_ep_handler(uint8_t ep_ix) dcd_event_setup_received(0, ptr, true); } // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXSTPIC; + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_CTRL_RXSTPIC; } if (int_status & USBHS_DEVEPTISR_RXOUTI) { @@ -474,11 +474,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS_DEVEPTCFG_ALLOC ); USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_STALLRQC; + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_CTRL_STALLRQC; if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) { // Endpoint configuration is successful - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXSTPES; + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; // Enable Endpoint 0 Interrupts USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; return true; @@ -512,7 +512,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) #endif USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_CTRL_STALLRQC; if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) { USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); @@ -693,7 +693,7 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_STALLRQS; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_CTRL_STALLRQS; } // clear stall, data toggle is also reset to DATA0 @@ -701,7 +701,7 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_STALLRQC; + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_CTRL_STALLRQC; USBHS->USBHS_DEVEPTIER[epnum] = USBHS_HSTPIPIER_RSTDTS; } -- cgit v1.3.1 From bcd3e31bd678053918898a29136cf787e72a534b Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Fri, 11 Jun 2021 20:59:48 +0100 Subject: dcd: same70: fix unused variable warning Signed-off-by: Rafael Silva --- src/portable/microchip/same70/dcd_same70.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c index 284010e53..d4430ce99 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/same70/dcd_same70.c @@ -134,6 +134,7 @@ void dcd_int_disable (uint8_t rhport) // Receive Set Address request, mcu port must also include status IN response void dcd_set_address (uint8_t rhport, uint8_t dev_addr) { + (void) dev_addr; // DCD can only set address after status for this request is complete // do it at dcd_edpt0_status_complete() @@ -151,6 +152,7 @@ void dcd_remote_wakeup (uint8_t rhport) // Connect by enabling internal pull-up resistor on D+/D- void dcd_connect(uint8_t rhport) { + (void) rhport; uint32_t irq_state = __get_PRIMASK(); __disable_irq(); // Enable USB clock -- cgit v1.3.1 From 2196991df31f27dcf2bf71cc4bf743774ea395e8 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Fri, 11 Jun 2021 21:03:36 +0100 Subject: dcd: same70: trim trailling spaces Signed-off-by: Rafael Silva --- src/portable/microchip/same70/dcd_same70.c | 108 ++++++++++++++--------------- 1 file changed, 54 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c index d4430ce99..0ad9ad625 100644 --- a/src/portable/microchip/same70/dcd_same70.c +++ b/src/portable/microchip/same70/dcd_same70.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2018, hathach (tinyusb.org) @@ -137,7 +137,7 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) (void) dev_addr; // DCD can only set address after status for this request is complete // do it at dcd_edpt0_status_complete() - + // Response with zlp status dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } @@ -234,7 +234,7 @@ static void dcd_ep_handler(uint8_t ep_ix) uint8_t *ptr = EP_GET_FIFO_PTR(0,8); dcd_event_setup_received(0, ptr, true); } - // Acknowledge the interrupt + // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_CTRL_RXSTPIC; } if (int_status & USBHS_DEVEPTISR_RXOUTI) @@ -251,34 +251,34 @@ static void dcd_ep_handler(uint8_t ep_ix) } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } - // Acknowledge the interrupt + // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { - // RX COMPLETE + // RX COMPLETE dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); - // Disable the interrupt + // Disable the interrupt USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; // Though the host could still send, we don't know. } } if (int_status & USBHS_DEVEPTISR_TXINI) { - // Disable the interrupt + // Disable the interrupt USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; xfer_ctl_t * xfer = &xfer_status[EP_MAX]; if ((xfer->total_len != xfer->queued_len)) { - // TX not complete + // TX not complete dcd_transmit_packet(xfer, 0); } else { - // TX complete + // TX complete dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); } } } else { if (int_status & USBHS_DEVEPTISR_RXOUTI) - { + { xfer_ctl_t *xfer = &xfer_status[ep_ix]; if (count) { @@ -291,27 +291,27 @@ static void dcd_ep_handler(uint8_t ep_ix) } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } - // Acknowledge the interrupt + // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; // Clear the FIFO control flag to receive more data. USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { - // RX COMPLETE + // RX COMPLETE dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); - // Disable the interrupt + // Disable the interrupt USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_RXOUTEC; // Though the host could still send, we don't know. } } if (int_status & USBHS_DEVEPTISR_TXINI) { - // Acknowledge the interrupt + // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; xfer_ctl_t * xfer = &xfer_status[ep_ix];; if ((xfer->total_len != xfer->queued_len)) { - // TX not complete + // TX not complete dcd_transmit_packet(xfer, ep_ix); } else { // TX complete @@ -331,7 +331,7 @@ static void dcd_dma_handler(uint8_t ep_ix) } // Disable DMA interrupt USBHS->USBHS_DEVIDR = USBHS_DEVIDR_DMA_1 << (ep_ix - 1); - + xfer_ctl_t *xfer = &xfer_status[ep_ix]; uint16_t count = xfer->total_len - ((status & USBHS_DEVDMASTATUS_BUFF_COUNT_Msk) >> USBHS_DEVDMASTATUS_BUFF_COUNT_Pos); if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) @@ -346,10 +346,10 @@ void dcd_int_handler(uint8_t rhport) { (void) rhport; uint32_t int_status = USBHS->USBHS_DEVISR; - // End of reset interrupt + // End of reset interrupt if (int_status & USBHS_DEVISR_EORST) { - // Unfreeze USB clock + // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); // Reset all endpoints @@ -363,10 +363,10 @@ void dcd_int_handler(uint8_t rhport) USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; - + dcd_event_bus_reset(rhport, get_speed(), true); } - // End of Wakeup interrupt + // End of Wakeup interrupt if (int_status & USBHS_DEVISR_WAKEUP) { USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; @@ -374,31 +374,31 @@ void dcd_int_handler(uint8_t rhport) USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; - + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } - // Suspend interrupt + // Suspend interrupt if (int_status & USBHS_DEVISR_SUSP) { - // Unfreeze USB clock + // Unfreeze USB clock USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; - + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } #if USE_SOF if(int_status & USBHS_DEVISR_SOF) { USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; - + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } -#endif - // Endpoints interrupt +#endif + // Endpoints interrupt for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { if (int_status & (USBHS_DEVISR_PEP_0 << ep_ix)) @@ -406,7 +406,7 @@ void dcd_int_handler(uint8_t rhport) dcd_ep_handler(ep_ix); } } - // Endpoints DMA interrupt + // Endpoints DMA interrupt for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { if (EP_DMA_SUPPORT(ep_ix)) @@ -433,7 +433,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re request->bRequest == TUSB_REQ_SET_ADDRESS ) { uint8_t const dev_addr = (uint8_t) request->wValue; - + USBHS->USBHS_DEVCTRL |= dev_addr | USBHS_DEVCTRL_ADDEN; } } @@ -446,9 +446,9 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); uint16_t const epMaxPktSize = ep_desc->wMaxPacketSize.size; tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; - uint8_t fifoSize = 0; // FIFO size - uint16_t defaultEndpointSize = 8; // Default size of Endpoint - // Find upper 2 power number of epMaxPktSize + uint8_t fifoSize = 0; // FIFO size + uint16_t defaultEndpointSize = 8; // Default size of Endpoint + // Find upper 2 power number of epMaxPktSize if (epMaxPktSize) { while (defaultEndpointSize < epMaxPktSize) @@ -458,16 +458,16 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) } } xfer_status[epnum].max_packet_size = epMaxPktSize; - + USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + epnum); USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + epnum)); - - if (epnum == 0) + + if (epnum == 0) { xfer_status[EP_MAX].max_packet_size = epMaxPktSize; - // Enable the control endpoint - Endpoint 0 + // Enable the control endpoint - Endpoint 0 USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; - // Configure the Endpoint 0 configuration register + // Configure the Endpoint 0 configuration register USBHS->USBHS_DEVEPTCFG[0] = ( USBHS_DEVEPTCFG_EPSIZE(fifoSize) | @@ -479,20 +479,20 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_CTRL_STALLRQC; if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) { - // Endpoint configuration is successful + // Endpoint configuration is successful USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; - // Enable Endpoint 0 Interrupts + // Enable Endpoint 0 Interrupts USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; return true; } else { - // Endpoint configuration is not successful + // Endpoint configuration is not successful return false; } } else { - // Enable the endpoint + // Enable the endpoint USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); // Set up the maxpacket size, fifo start address fifosize - // and enable the interrupt. CLear the data toggle. + // and enable the interrupt. CLear the data toggle. // AUTOSW is needed for DMA ack ! USBHS->USBHS_DEVEPTCFG[epnum] = ( @@ -504,12 +504,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) ); if (eptype == TUSB_XFER_ISOCHRONOUS) { - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); } #if USE_DUAL_BANK if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK) { - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_EPBK_2_BANK; + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_EPBK_2_BANK; } #endif USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; @@ -520,7 +520,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); return true; } else { - // Endpoint configuration is not successful + // Endpoint configuration is not successful return false; } } @@ -546,7 +546,7 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { // Control endpoint: clear the interrupt flag to send the data USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - + } else { // Other endpoint types: clear the FIFO control flag to send the data USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; @@ -560,16 +560,16 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - + xfer_ctl_t * xfer = &xfer_status[epnum]; if(ep_addr == 0x80) xfer = &xfer_status[EP_MAX]; - + xfer->buffer = buffer; xfer->total_len = total_bytes; xfer->queued_len = 0; xfer->fifo = NULL; - + if(EP_DMA_SUPPORT(epnum) && total_bytes != 0) { uint32_t udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); @@ -618,16 +618,16 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - + xfer_ctl_t * xfer = &xfer_status[epnum]; if(epnum == 0x80) xfer = &xfer_status[EP_MAX]; - + xfer->buffer = NULL; xfer->total_len = total_bytes; xfer->queued_len = 0; xfer->fifo = ff; - + if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) { tu_fifo_buffer_info_t info; @@ -646,13 +646,13 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 } udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_B_EN; } - + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)info.ptr_lin; if (info.len_wrap) { dma_desc[epnum - 1].next_desc = 0; dma_desc[epnum - 1].buff_addr = (uint32_t)info.ptr_wrap; - dma_desc[epnum - 1].chnl_ctrl = + dma_desc[epnum - 1].chnl_ctrl = udd_dma_ctrl_wrap | USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_wrap); udd_dma_ctrl_lin |= USBHS_DEVDMASTATUS_DESC_LDST; __DSB(); -- cgit v1.3.1 From 1c23462b43f47685cf0051568f4bfea5de37d563 Mon Sep 17 00:00:00 2001 From: Wini-Buh Date: Fri, 11 Jun 2021 22:25:36 +0200 Subject: weak atrribute work around removed from CCRX_Port --- src/class/cdc/cdc.h | 54 ++++++++++++----------------- src/class/cdc/cdc_device.c | 23 ++++--------- src/class/cdc/cdc_device.h | 57 ------------------------------- src/common/tusb_compiler.h | 39 --------------------- src/common/tusb_types.h | 42 ++++++----------------- src/device/dcd.h | 30 ---------------- src/device/usbd.c | 61 +++++++++++++-------------------- src/device/usbd.h | 66 ------------------------------------ src/device/usbd_control.c | 6 +--- src/device/usbd_pvt.h | 12 ------- src/portable/renesas/usba/dcd_usba.c | 33 ++++++------------ 11 files changed, 74 insertions(+), 349 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index e5af9fc0c..f59690835 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -215,8 +215,9 @@ typedef enum // Class Specific Functional Descriptor (Communication Interface) //--------------------------------------------------------------------+ +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + /// Header Functional Descriptor (Communication Interface) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -224,10 +225,8 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUNC_DESC_ uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal }cdc_desc_func_header_t; -TU_PACK_STRUCT_END /// Union Functional Descriptor (Communication Interface) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -236,7 +235,8 @@ typedef struct TU_ATTR_PACKED uint8_t bControlInterface ; ///< Interface number of Communication Interface uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface }cdc_desc_func_union_t; -TU_PACK_STRUCT_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) #define cdc_desc_func_union_n_t(no_slave)\ TU_PACK_STRUCT_BEGIN \ @@ -249,8 +249,10 @@ TU_PACK_STRUCT_END } \ TU_PACK_STRUCT_END + +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + /// Country Selection Functional Descriptor (Communication Interface) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -259,7 +261,8 @@ typedef struct TU_ATTR_PACKED uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes. uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. }cdc_desc_func_country_selection_t; -TU_PACK_STRUCT_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) #define cdc_desc_func_country_selection_n_t(no_country) \ TU_PACK_STRUCT_BEGIN \ @@ -276,29 +279,28 @@ TU_PACK_STRUCT_END // PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS //--------------------------------------------------------------------+ +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + /// \brief Call Management Functional Descriptor /// \details This functional descriptor describes the processing of calls for the Communications Class interface. -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface. uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself. uint8_t TU_RESERVED : 6; } bmCapabilities; - TU_BIT_FIELD_ORDER_END uint8_t bDataInterface; }cdc_desc_func_call_management_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_BEGIN TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { @@ -309,13 +311,11 @@ typedef struct TU_ATTR_PACKED uint8_t TU_RESERVED : 4; }cdc_acm_capability_t; TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); /// \brief Abstract Control Management Functional Descriptor /// \details This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -323,31 +323,27 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ cdc_acm_capability_t bmCapabilities ; }cdc_desc_func_acm_t; -TU_PACK_STRUCT_END /// \brief Direct Line Management Functional Descriptor /// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit. uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State. uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time. uint8_t TU_RESERVED : 5; } bmCapabilities; - TU_BIT_FIELD_ORDER_END }cdc_desc_func_direct_line_management_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END /// \brief Telephone Ringer Functional Descriptor /// \details The Telephone Ringer functional descriptor describes the ringer capabilities supported by the Communications Class interface, /// with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -356,38 +352,34 @@ typedef struct TU_ATTR_PACKED uint8_t bRingerVolSteps ; uint8_t bNumRingerPatterns ; }cdc_desc_func_telephone_ringer_t; -TU_PACK_STRUCT_END /// \brief Telephone Operational Modes Functional Descriptor /// \details The Telephone Operational Modes functional descriptor describes the operational modes supported by /// the Communications Class interface, with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - TU_BIT_FIELD_ORDER_BEGIN struct { uint8_t simple_mode : 1; uint8_t standalone_mode : 1; uint8_t computer_centric_mode : 1; uint8_t TU_RESERVED : 5; } bmCapabilities; - TU_BIT_FIELD_ORDER_END }cdc_desc_func_telephone_operational_modes_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END /// \brief Telephone Call and Line State Reporting Capabilities Descriptor /// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a /// telephone device to report optional call and line states. -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ - TU_BIT_FIELD_ORDER_BEGIN struct { uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states. @@ -397,9 +389,8 @@ typedef struct TU_ATTR_PACKED uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification uint32_t TU_RESERVED : 26; } bmCapabilities; - TU_BIT_FIELD_ORDER_END }cdc_desc_func_telephone_call_state_reporting_capabilities_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) { @@ -409,7 +400,6 @@ static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) //--------------------------------------------------------------------+ // Requests //--------------------------------------------------------------------+ -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint32_t bit_rate; @@ -417,11 +407,9 @@ typedef struct TU_ATTR_PACKED uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16 } cdc_line_coding_t; -TU_PACK_STRUCT_END TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); -TU_PACK_STRUCT_BEGIN TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { @@ -430,7 +418,9 @@ typedef struct TU_ATTR_PACKED uint16_t : 14; } cdc_line_control_state_t; TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) + TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 57bb804a8..cac811c45 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -33,15 +33,6 @@ #include "cdc_device.h" -#if defined(TU_HAS_NO_ATTR_WEAK) -static void (*const MAKE_WEAK_FUNC(tud_cdc_rx_cb))(uint8_t) = TUD_CDC_RX_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb))(uint8_t, char) = TUD_CDC_RX_WANTED_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb))(uint8_t) = TUD_CDC_TX_COMPLETE_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_line_state_cb))(uint8_t, bool, bool) = TUD_CDC_LINE_STATE_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_line_coding_cb))(uint8_t, cdc_line_coding_t const*) = TUD_CDC_LINE_CODING_CB; -static void (*const MAKE_WEAK_FUNC(tud_cdc_send_break_cb))(uint8_t, uint16_t) = TUD_CDC_SEND_BREAK_CB; -#endif - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -370,7 +361,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t } else if ( stage == CONTROL_STAGE_ACK) { - if ( MAKE_WEAK_FUNC(tud_cdc_line_coding_cb) ) MAKE_WEAK_FUNC(tud_cdc_line_coding_cb)(itf, &p_cdc->line_coding); + if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); } break; @@ -405,7 +396,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); // Invoke callback - if ( MAKE_WEAK_FUNC(tud_cdc_line_state_cb) ) MAKE_WEAK_FUNC(tud_cdc_line_state_cb)(itf, dtr, rts); + if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); } break; case CDC_REQUEST_SEND_BREAK: @@ -416,7 +407,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t else if (stage == CONTROL_STAGE_ACK) { TU_LOG2(" Send Break\r\n"); - if ( MAKE_WEAK_FUNC(tud_cdc_send_break_cb) ) MAKE_WEAK_FUNC(tud_cdc_send_break_cb)(itf, request->wValue); + if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); } break; @@ -447,19 +438,19 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes); // Check for wanted char and invoke callback if needed - if ( MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb) && (((signed char) p_cdc->wanted_char) != -1) ) + if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) ) { for ( uint32_t i = 0; i < xferred_bytes; i++ ) { if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) ) { - MAKE_WEAK_FUNC(tud_cdc_rx_wanted_cb)(itf, p_cdc->wanted_char); + tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); } } } // invoke receive callback (if there is still data) - if (MAKE_WEAK_FUNC(tud_cdc_rx_cb) && !tu_fifo_empty(&p_cdc->rx_ff) ) MAKE_WEAK_FUNC(tud_cdc_rx_cb)(itf); + if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); // prepare for OUT transaction _prep_out_transaction(p_cdc); @@ -471,7 +462,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if ( ep_addr == p_cdc->ep_in ) { // invoke transmit callback to possibly refill tx fifo - if ( MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb) ) MAKE_WEAK_FUNC(tud_cdc_tx_complete_cb)(itf); + if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); if ( 0 == tud_cdc_n_write_flush(itf) ) { diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 389516883..7ff757add 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -129,7 +129,6 @@ static inline bool tud_cdc_write_clear (void); // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when received new data TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); @@ -148,62 +147,6 @@ TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p // Invoked when received send break TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); -#else - #if ADD_WEAK_FUNC_TUD_CDC_RX_CB - #define TUD_CDC_RX_CB tud_cdc_rx_cb - #endif - #ifndef TUD_CDC_RX_CB - #define TUD_CDC_RX_CB NULL - #else - extern void TUD_CDC_RX_CB(uint8_t itf); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_RX_WANTED_CB - #define TUD_CDC_RX_WANTED_CB tud_cdc_rx_wanted_cb - #endif - #ifndef TUD_CDC_RX_WANTED_CB - #define TUD_CDC_RX_WANTED_CB NULL - #else - extern void TUD_CDC_RX_WANTED_CB(uint8_t itf, char wanted_char); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_TX_COMPLETE_CB - #define TUD_CDC_TX_COMPLETE_CB tud_cdc_tx_complete_cb - #endif - #ifndef TUD_CDC_TX_COMPLETE_CB - #define TUD_CDC_TX_COMPLETE_CB NULL - #else - extern void TUD_CDC_TX_COMPLETE_CB(uint8_t itf); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_LINE_STATE_CB - #define TUD_CDC_LINE_STATE_CB tud_cdc_line_state_cb - #endif - #ifndef TUD_CDC_LINE_STATE_CB - #define TUD_CDC_LINE_STATE_CB NULL - #else - extern void TUD_CDC_LINE_STATE_CB(uint8_t itf, bool dtr, bool rts); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_LINE_CODING_CB - #define TUD_CDC_LINE_CODING_CB tud_cdc_line_coding_cb - #endif - #ifndef TUD_CDC_LINE_CODING_CB - #define TUD_CDC_LINE_CODING_CB NULL - #else - extern void TUD_CDC_LINE_CODING_CB(uint8_t itf, cdc_line_coding_t const* p_line_coding); - #endif - - #if ADD_WEAK_FUNC_TUD_CDC_SEND_BREAK_CB - #define TUD_CDC_SEND_BREAK_CB tud_cdc_send_break_cb - #endif - #ifndef TUD_CDC_SEND_BREAK_CB - #define TUD_CDC_SEND_BREAK_CB NULL - #else - extern void TUD_CDC_SEND_BREAK_CB(uint8_t itf, uint16_t duration_ms); - #endif -#endif - //--------------------------------------------------------------------+ // Inline Functions //--------------------------------------------------------------------+ diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 508bb126e..f77cf94ee 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -64,9 +64,6 @@ // Compiler porting with Attribute and Endian //--------------------------------------------------------------------+ -// define the standard definition of this macro to construct a "weak" function name -#define MAKE_WEAK_FUNC(func_name) func_name - // TODO refactor since __attribute__ is supported across many compiler #if defined(__GNUC__) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) @@ -171,42 +168,6 @@ the aligned attribute (or something similar yet) */ #define TU_HAS_NO_ATTR_ALIGNED - /* activate the "weak" function emulation, because this toolchain does not - know the weak attribute (or something similar yet) */ - #define TU_HAS_NO_ATTR_WEAK - - // make sure to define away the standard definition of this macro - #undef MAKE_WEAK_FUNC - // Helper macro to construct a "weak" function name - #define MAKE_WEAK_FUNC(func_name) weak_ ## func_name - - #if defined(TU_HAS_NO_ATTR_WEAK) - // "Weak function" emulation defined in cdc_device.h - #define ADD_WEAK_FUNC_TUD_CDC_RX_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_RX_WANTED_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_TX_COMPLETE_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_LINE_STATE_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_LINE_CODING_CB 0 - #define ADD_WEAK_FUNC_TUD_CDC_SEND_BREAK_CB 0 - - // "Weak function" emulation defined in usbd_pvt.h - #define ADD_WEAK_FUNC_USBD_APP_DRIVER_GET_CB 0 - - // "Weak function" emulation defined in usbd.h - #define ADD_WEAK_FUNC_TUD_DESCRIPTOR_BOS_CB 0 - #define ADD_WEAK_FUNC_TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB 0 - #define ADD_WEAK_FUNC_TUD_MOUNT_CB 0 - #define ADD_WEAK_FUNC_TUD_UMOUNT_CB 0 - #define ADD_WEAK_FUNC_TUD_SUSPEND_CB 0 - #define ADD_WEAK_FUNC_TUD_RESUME_CB 0 - #define ADD_WEAK_FUNC_TUD_VENDOR_CONTROL_XFER_CB 0 - - // "Weak function" emulation defined in dcd.h - #define ADD_WEAK_FUNC_DCD_EDPT0_STATUS_COMPLETE 0 - #define ADD_WEAK_FUNC_DCD_EDPT_CLOSE 0 - #define ADD_WEAK_FUNC_DCD_EDPT_XFER_FIFO 0 - #endif - #else #error "Compiler attribute porting is required" #endif diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index b20ea2974..a8a4d21e5 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -262,8 +262,9 @@ enum // USB Descriptors //--------------------------------------------------------------------+ +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + /// USB Device Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -284,12 +285,10 @@ typedef struct TU_ATTR_PACKED uint8_t bNumConfigurations ; ///< Number of possible configurations. } tusb_desc_device_t; -TU_PACK_STRUCT_END TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); // USB Binary Device Object Store (BOS) Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -297,10 +296,8 @@ typedef struct TU_ATTR_PACKED uint16_t wTotalLength ; ///< Total length of data returned for this descriptor uint8_t bNumDeviceCaps ; ///< Number of device capability descriptors in the BOS } tusb_desc_bos_t; -TU_PACK_STRUCT_END /// USB Configuration Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -313,10 +310,8 @@ typedef struct TU_ATTR_PACKED uint8_t bmAttributes ; ///< Configuration characteristics \n D7: Reserved (set to one)\n D6: Self-powered \n D5: Remote Wakeup \n D4...0: Reserved (reset to zero) \n D7 is reserved and must be set to one for historical reasons. \n A device configuration that uses power from the bus and a local source reports a non-zero value in bMaxPower to indicate the amount of bus power required and sets D6. The actual power source at runtime may be determined using the GetStatus(DEVICE) request (see USB 2.0 spec Section 9.4.5). \n If a device configuration supports remote wakeup, D5 is set to one. uint8_t bMaxPower ; ///< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. Expressed in 2 mA units (i.e., 50 = 100 mA). } tusb_desc_configuration_t; -TU_PACK_STRUCT_END /// USB Interface Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -330,10 +325,9 @@ typedef struct TU_ATTR_PACKED uint8_t bInterfaceProtocol ; ///< Protocol code (assigned by the USB). \n These codes are qualified by the value of the bInterfaceClass and the bInterfaceSubClass fields. If an interface supports class-specific requests, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use a class-specific protocol on this interface. \li If this field is set to FFH, the device uses a vendor-specific protocol for this interface. uint8_t iInterface ; ///< Index of string descriptor describing this interface } tusb_desc_interface_t; -TU_PACK_STRUCT_END /// USB Endpoint Descriptor -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -341,14 +335,12 @@ typedef struct TU_ATTR_PACKED uint8_t bEndpointAddress ; ///< The address of the endpoint on the USB device described by this descriptor. The address is encoded as follows: \n Bit 3...0: The endpoint number \n Bit 6...4: Reserved, reset to zero \n Bit 7: Direction, ignored for control endpoints 0 = OUT endpoint 1 = IN endpoint. - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t xfer : 2; uint8_t sync : 2; uint8_t usage : 2; uint8_t : 2; } bmAttributes ; ///< This field describes the endpoint's attributes when it is configured using the bConfigurationValue. \n Bits 1..0: Transfer Type \n- 00 = Control \n- 01 = Isochronous \n- 10 = Bulk \n- 11 = Interrupt \n If not an isochronous endpoint, bits 5..2 are reserved and must be set to zero. If isochronous, they are defined as follows: \n Bits 3..2: Synchronization Type \n- 00 = No Synchronization \n- 01 = Asynchronous \n- 10 = Adaptive \n- 11 = Synchronous \n Bits 5..4: Usage Type \n- 00 = Data endpoint \n- 01 = Feedback endpoint \n- 10 = Implicit feedback Data endpoint \n- 11 = Reserved \n Refer to Chapter 5 of USB 2.0 specification for more information. \n All other bits are reserved and must be reset to zero. Reserved bits must be ignored by the host. - TU_BIT_FIELD_ORDER_END struct TU_ATTR_PACKED { #if defined(__CCRX__) @@ -363,10 +355,9 @@ typedef struct TU_ATTR_PACKED uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. } tusb_desc_endpoint_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END /// USB Other Speed Configuration Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -379,10 +370,8 @@ typedef struct TU_ATTR_PACKED uint8_t bmAttributes ; ///< Same as Configuration descriptor uint8_t bMaxPower ; ///< Same as Configuration descriptor } tusb_desc_other_speed_t; -TU_PACK_STRUCT_END /// USB Device Qualifier Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -396,10 +385,8 @@ typedef struct TU_ATTR_PACKED uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations uint8_t bReserved ; ///< Reserved for future use, must be zero } tusb_desc_device_qualifier_t; -TU_PACK_STRUCT_END /// USB Interface Association Descriptor (IAD ECN) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor @@ -414,20 +401,16 @@ typedef struct TU_ATTR_PACKED uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. } tusb_desc_interface_assoc_t; -TU_PACK_STRUCT_END // USB String Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< Descriptor Type uint16_t unicode_string[]; } tusb_desc_string_t; -TU_PACK_STRUCT_END // USB Binary Device Object Store (BOS) -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -437,10 +420,8 @@ typedef struct TU_ATTR_PACKED uint8_t PlatformCapabilityUUID[16]; uint8_t CapabilityData[]; } tusb_desc_bos_platform_t; -TU_PACK_STRUCT_END // USB WebuSB URL Descriptor -TU_PACK_STRUCT_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -448,17 +429,15 @@ typedef struct TU_ATTR_PACKED uint8_t bScheme; char url[]; } tusb_desc_webusb_url_t; -TU_PACK_STRUCT_END // DFU Functional Descriptor -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; union { - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t bitCanDnload : 1; uint8_t bitCanUpload : 1; @@ -466,7 +445,6 @@ typedef struct TU_ATTR_PACKED uint8_t bitWillDetach : 1; uint8_t reserved : 4; } bmAttributes; - TU_BIT_FIELD_ORDER_END uint8_t bAttributes; }; @@ -475,21 +453,19 @@ typedef struct TU_ATTR_PACKED uint16_t wTransferSize; uint16_t bcdDFUVersion; } tusb_desc_dfu_functional_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ -TU_PACK_STRUCT_BEGIN +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED{ union { - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. uint8_t type : 2; ///< Request type tusb_request_type_t. uint8_t direction : 1; ///< Direction type. tusb_dir_t } bmRequestType_bit; - TU_BIT_FIELD_ORDER_END uint8_t bmRequestType; }; @@ -499,7 +475,9 @@ typedef struct TU_ATTR_PACKED{ uint16_t wIndex; uint16_t wLength; } tusb_control_request_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); diff --git a/src/device/dcd.h b/src/device/dcd.h index d68f9baa7..25cfafc4b 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -117,7 +117,6 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; // Endpoint API //--------------------------------------------------------------------+ -#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK; @@ -130,35 +129,6 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // This API is optional, may be useful for register-based for transferring data. bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK; -#else - #if ADD_WEAK_FUNC_DCD_EDPT0_STATUS_COMPLETE - #define DCD_EDPT0_STATUS_COMPLETE dcd_edpt0_status_complete - #endif - #ifndef DCD_EDPT0_STATUS_COMPLETE - #define DCD_EDPT0_STATUS_COMPLETE NULL - #else - extern void DCD_EDPT0_STATUS_COMPLETE(uint8_t rhport, tusb_control_request_t const * request); - #endif - - #if ADD_WEAK_FUNC_DCD_EDPT_CLOSE - #define DCD_EDPT_CLOSE dcd_edpt_close - #endif - #ifndef DCD_EDPT_CLOSE - #define DCD_EDPT_CLOSE NULL - #else - extern void DCD_EDPT_CLOSE(uint8_t rhport, uint8_t ep_addr); - #endif - - #if ADD_WEAK_FUNC_DCD_EDPT_XFER_FIFO - #define DCD_EDPT_XFER_FIFO dcd_edpt_xfer_fifo - #endif - #ifndef DCD_EDPT_XFER_FIFO - #define DCD_EDPT_XFER_FIFO NULL - #else - extern void DCD_EDPT_XFER_FIFO(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); - #endif -#endif - // Configure endpoint's registers according to descriptor bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); diff --git a/src/device/usbd.c b/src/device/usbd.c index 389ba4a4e..49c9279bf 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -33,19 +33,6 @@ #include "device/usbd_pvt.h" #include "device/dcd.h" -#if defined(TU_HAS_NO_ATTR_WEAK) -static uint8_t const* (*const MAKE_WEAK_FUNC(tud_descriptor_bos_cb))(void) = TUD_DESCRIPTOR_BOS_CB; -static uint8_t const* (*const MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb))(void) = TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB; -static void (*const MAKE_WEAK_FUNC(tud_mount_cb))(void) = TUD_MOUNT_CB; -static void (*const MAKE_WEAK_FUNC(tud_umount_cb))(void) = TUD_UMOUNT_CB; -static void (*const MAKE_WEAK_FUNC(tud_suspend_cb))(_Bool) = TUD_SUSPEND_CB; -static void (*const MAKE_WEAK_FUNC(tud_resume_cb))(void) = TUD_RESUME_CB; -static _Bool (*const MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb))(uint8_t, uint8_t, tusb_control_request_t const *) = TUD_RESUME_CB; -static usbd_class_driver_t const* (*const MAKE_WEAK_FUNC(usbd_app_driver_get_cb))(uint8_t*) = USBD_APP_DRIVER_GET_CB; -static bool (*const MAKE_WEAK_FUNC(dcd_edpt_xfer_fifo))(uint8_t, uint8_t, tu_fifo_t *, uint16_t) = DCD_EDPT_XFER_FIFO; -static void (*const MAKE_WEAK_FUNC(dcd_edpt_close))(uint8_t, uint8_t) = DCD_EDPT_CLOSE; -#endif - #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif @@ -61,10 +48,11 @@ static void (*const MAKE_WEAK_FUNC(dcd_edpt_close))(uint8_t, uint8_t) = DCD_EDPT // Invalid driver ID in itf2drv[] ep2drv[][] mapping enum { DRVID_INVALID = 0xFFu }; +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + +TU_BIT_FIELD_ORDER_BEGIN typedef struct { - TU_PACK_STRUCT_BEGIN - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { volatile uint8_t connected : 1; @@ -75,8 +63,6 @@ typedef struct uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute uint8_t self_powered : 1; // configuration descriptor's attribute }; - TU_BIT_FIELD_ORDER_END - TU_PACK_STRUCT_END volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) uint8_t speed; @@ -84,8 +70,6 @@ typedef struct uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUD_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) - TU_PACK_STRUCT_BEGIN - TU_BIT_FIELD_ORDER_BEGIN struct TU_ATTR_PACKED { volatile bool busy : 1; @@ -94,10 +78,11 @@ typedef struct // TODO merge ep2drv here, 4-bit should be sufficient }ep_status[CFG_TUD_EP_MAX][2]; - TU_BIT_FIELD_ORDER_END - TU_PACK_STRUCT_END }usbd_device_t; +TU_BIT_FIELD_ORDER_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) static usbd_device_t _usbd_dev; @@ -257,7 +242,7 @@ static uint8_t _app_driver_count = 0; static inline usbd_class_driver_t const * get_driver(uint8_t drvid) { // Application drivers - if ( MAKE_WEAK_FUNC(usbd_app_driver_get_cb) ) + if ( usbd_app_driver_get_cb ) { if ( drvid < _app_driver_count ) return &_app_driver[drvid]; drvid -= _app_driver_count; @@ -429,9 +414,9 @@ bool tud_init (uint8_t rhport) TU_ASSERT(_usbd_q); // Get application driver if available - if ( MAKE_WEAK_FUNC(usbd_app_driver_get_cb) ) + if ( usbd_app_driver_get_cb ) { - _app_driver = MAKE_WEAK_FUNC(usbd_app_driver_get_cb)(&_app_driver_count); + _app_driver = usbd_app_driver_get_cb(&_app_driver_count); } // Init class drivers @@ -522,7 +507,7 @@ void tud_task (void) usbd_reset(event.rhport); // invoke callback - if (MAKE_WEAK_FUNC(tud_umount_cb)) MAKE_WEAK_FUNC(tud_umount_cb)(); + if (tud_umount_cb) tud_umount_cb(); break; case DCD_EVENT_SETUP_RECEIVED: @@ -578,12 +563,12 @@ void tud_task (void) case DCD_EVENT_SUSPEND: TU_LOG2("\r\n"); - if (MAKE_WEAK_FUNC(tud_suspend_cb)) MAKE_WEAK_FUNC(tud_suspend_cb)(_usbd_dev.remote_wakeup_en); + if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); break; case DCD_EVENT_RESUME: TU_LOG2("\r\n"); - if (MAKE_WEAK_FUNC(tud_resume_cb)) MAKE_WEAK_FUNC(tud_resume_cb)(); + if (tud_resume_cb) tud_resume_cb(); break; case DCD_EVENT_SOF: @@ -630,10 +615,10 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { - TU_VERIFY(MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)); + TU_VERIFY(tud_vendor_control_xfer_cb); - usbd_control_set_complete_callback(MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)); - return MAKE_WEAK_FUNC(tud_vendor_control_xfer_cb)(rhport, CONTROL_STAGE_SETUP, p_request); + usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); + return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); } #if CFG_TUSB_DEBUG >= 2 @@ -913,7 +898,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } // invoke callback - if (MAKE_WEAK_FUNC(tud_mount_cb)) MAKE_WEAK_FUNC(tud_mount_cb)(); + if (tud_mount_cb) tud_mount_cb(); return true; } @@ -970,9 +955,9 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const TU_LOG2(" BOS\r\n"); // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) - if (!MAKE_WEAK_FUNC(tud_descriptor_bos_cb)) return false; + if (!tud_descriptor_bos_cb) return false; - tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*)MAKE_WEAK_FUNC(tud_descriptor_bos_cb)(); + tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*)tud_descriptor_bos_cb(); uint16_t total_len; // Use offsetof to avoid pointer to the odd/misaligned address @@ -1016,9 +1001,9 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // Host sends this request to ask why our device with USB BCD from 2.0 // but is running at Full/Low Speed. If not highspeed capable stall this request, // otherwise return the descriptor that could work in highspeed mode - if (MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb)) + if (tud_descriptor_device_qualifier_cb) { - uint8_t const* desc_qualifier = MAKE_WEAK_FUNC(tud_descriptor_device_qualifier_cb)(); + uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); TU_ASSERT(desc_qualifier); // first byte of descriptor is its size @@ -1306,7 +1291,7 @@ bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = true; - if (MAKE_WEAK_FUNC(dcd_edpt_xfer_fifo)(rhport, ep_addr, ff, total_bytes)) + if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) { TU_LOG2("OK\r\n"); return true; @@ -1369,10 +1354,10 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) */ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - TU_ASSERT(MAKE_WEAK_FUNC(dcd_edpt_close), /**/); + TU_ASSERT(dcd_edpt_close, /**/); TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr); - MAKE_WEAK_FUNC(dcd_edpt_close(rhport, ep_addr)); + dcd_edpt_close(rhport, ep_addr); return; } diff --git a/src/device/usbd.h b/src/device/usbd.h index 67f1e2913..57c80fed1 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -111,7 +111,6 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index); // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); -#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when received GET BOS DESCRIPTOR request // Application return pointer to descriptor TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); @@ -136,71 +135,6 @@ TU_ATTR_WEAK void tud_resume_cb(void); // Invoked when received control request with VENDOR TYPE TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -#else - #if ADD_WEAK_FUNC_TUD_DESCRIPTOR_BOS_CB - #define TUD_DESCRIPTOR_BOS_CB tud_descriptor_bos_cb - #endif - #ifndef TUD_DESCRIPTOR_BOS_CB - #define TUD_DESCRIPTOR_BOS_CB NULL - #else - extern uint8_t const* TUD_DESCRIPTOR_BOS_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB - #define TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB tud_descriptor_device_qualifier_cb - #endif - #ifndef TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB - #define TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB NULL - #else - extern uint8_t const* TUD_DESCRIPTOR_DEVICE_QUALIFIER_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_MOUNT_CB - #define TUD_MOUNT_CB tud_mount_cb - #endif - #ifndef TUD_MOUNT_CB - #define TUD_MOUNT_CB NULL - #else - extern void TUD_MOUNT_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_UMOUNT_CB - #define TUD_UMOUNT_CB tud_umount_cb - #endif - #ifndef TUD_UMOUNT_CB - #define TUD_UMOUNT_CB NULL - #else - extern void TUD_UMOUNT_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_SUSPEND_CB - #define TUD_SUSPEND_CB tud_suspend_cb - #endif - #ifndef TUD_SUSPEND_CB - #define TUD_SUSPEND_CB NULL - #else - extern void TUD_SUSPEND_CB(bool remote_wakeup_en); - #endif - - #if ADD_WEAK_FUNC_TUD_RESUME_CB - #define TUD_RESUME_CB tud_resume_cb - #endif - #ifndef TUD_RESUME_CB - #define TUD_RESUME_CB NULL - #else - extern void TUD_RESUME_CB(void); - #endif - - #if ADD_WEAK_FUNC_TUD_VENDOR_CONTROL_XFER_CB - #define TUD_VENDOR_CONTROL_XFER_CB tud_vendor_control_xfer_cb - #endif - #ifndef TUD_VENDOR_CONTROL_XFER_CB - #define TUD_VENDOR_CONTROL_XFER_CB NULL - #else - extern bool TUD_VENDOR_CONTROL_XFER_CB(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); - #endif -#endif - //--------------------------------------------------------------------+ // Binary Device Object Store (BOS) Descriptor Templates //--------------------------------------------------------------------+ diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 76f999f86..b3bab2e32 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -36,10 +36,6 @@ extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif -#if defined(TU_HAS_NO_ATTR_WEAK) -static void (*const MAKE_WEAK_FUNC(dcd_edpt0_status_complete))(uint8_t, tusb_control_request_t const *) = DCD_EDPT0_STATUS_COMPLETE; -#endif - enum { EDPT_CTRL_OUT = 0x00, @@ -184,7 +180,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result TU_ASSERT(0 == xferred_bytes); // invoke optional dcd hook if available - if (MAKE_WEAK_FUNC(dcd_edpt0_status_complete)) MAKE_WEAK_FUNC(dcd_edpt0_status_complete)(rhport, &_ctrl_xfer.request); + if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); if (_ctrl_xfer.complete_cb) { diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index c814353ae..bb2267d40 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -51,22 +51,10 @@ typedef struct void (* sof ) (uint8_t rhport); /* optional */ } usbd_class_driver_t; -#if !defined(TU_HAS_NO_ATTR_WEAK) // Invoked when initializing device stack to get additional class drivers. // Can optionally implemented by application to extend/overwrite class driver support. // Note: The drivers array must be accessible at all time when stack is active usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK; -#else - #if ADD_WEAK_FUNC_USBD_APP_DRIVER_GET_CB - #define USBD_APP_DRIVER_GET_CB usbd_app_driver_get_cb - #endif - #ifndef USBD_APP_DRIVER_GET_CB - #define USBD_APP_DRIVER_GET_CB NULL - #else - extern usbd_class_driver_t const* USBD_APP_DRIVER_GET_CB(uint8_t* driver_count); - #endif -#endif - typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 0e7881383..13fc50ae5 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -90,45 +90,47 @@ #define FIFO_REQ_CLR (1u) #define FIFO_COMPLETE (1u<<1) +TU_BIT_FIELD_ORDER_BEGIN typedef struct { union { - TU_BIT_FIELD_ORDER_BEGIN struct { uint16_t : 8; uint16_t TRCLR: 1; uint16_t TRENB: 1; uint16_t : 0; }; - TU_BIT_FIELD_ORDER_END uint16_t TRE; }; uint16_t TRN; } reg_pipetre_t; +TU_BIT_FIELD_ORDER_END +TU_BIT_FIELD_ORDER_BEGIN typedef union { - TU_BIT_FIELD_ORDER_BEGIN struct { volatile uint16_t u8: 8; volatile uint16_t : 0; }; - TU_BIT_FIELD_ORDER_END volatile uint16_t u16; } hw_fifo_t; +TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_BEGIN +TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) + +TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uintptr_t addr; /* the start address of a transfer data buffer */ uint16_t length; /* the number of bytes in the buffer */ uint16_t remaining; /* the number of bytes remaining in the buffer */ - TU_BIT_FIELD_ORDER_BEGIN struct { uint32_t ep : 8; /* an assigned endpoint address */ uint32_t : 0; }; - TU_BIT_FIELD_ORDER_END } pipe_state_t; -TU_PACK_STRUCT_END +TU_BIT_FIELD_ORDER_END + +TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) typedef struct { @@ -259,12 +261,6 @@ static int fifo_write(volatile void *fifo, pipe_state_t* pipe, unsigned mps) hw_fifo_t *reg = (hw_fifo_t*)fifo; uintptr_t addr = pipe->addr + pipe->length - rem; - if (addr & 1u) { - /* addr is not 2-byte aligned */ - reg->u8 = *(const uint8_t *)addr; - ++addr; - --len; - } while (len >= 2) { reg->u16 = *(const uint16_t *)addr; addr += 2; @@ -306,17 +302,10 @@ static void process_setup_packet(uint8_t rhport) uint16_t setup_packet[4]; if (0 == (USB0.INTSTS0.WORD & USB_IS0_VALID)) return; USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; - setup_packet[0] = USB0.USBREQ.WORD; + setup_packet[0] = tu_le16toh(USB0.USBREQ.WORD); setup_packet[1] = USB0.USBVAL; setup_packet[2] = USB0.USBINDX; setup_packet[3] = USB0.USBLENG; -#if TU_BYTE_ORDER==TU_BIG_ENDIAN - #if defined(__CCRX__) - setup_packet[0] = tu_le16toh(setup_packet[0]); - #else - //FIXME needs to implemented for other tool chains - #endif -#endif USB0.INTSTS0.WORD = ~USB_IS0_VALID; dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet[0], true); } -- cgit v1.3.1 From 776a7709474a0736ed21218c2ff84208745c58cc Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Fri, 11 Jun 2021 22:50:00 +0100 Subject: dcd: sam7x: rename family dcd to include the whole family Signed-off-by: Rafael Silva --- examples/device/cdc_dual_ports/src/tusb_config.h | 2 +- .../device/cdc_dual_ports/src/usb_descriptors.c | 2 +- examples/device/cdc_msc/src/tusb_config.h | 2 +- examples/device/cdc_msc/src/usb_descriptors.c | 2 +- hw/bsp/same70_xplained/board.mk | 4 +- src/portable/microchip/sam7x/dcd_sam7x.c | 710 +++++++++++++++++++++ src/portable/microchip/same70/dcd_same70.c | 710 --------------------- src/tusb_option.h | 3 +- 8 files changed, 718 insertions(+), 717 deletions(-) create mode 100644 src/portable/microchip/sam7x/dcd_sam7x.c delete mode 100644 src/portable/microchip/same70/dcd_same70.c (limited to 'src') diff --git a/examples/device/cdc_dual_ports/src/tusb_config.h b/examples/device/cdc_dual_ports/src/tusb_config.h index 45167da8e..19b6925bc 100644 --- a/examples/device/cdc_dual_ports/src/tusb_config.h +++ b/examples/device/cdc_dual_ports/src/tusb_config.h @@ -48,7 +48,7 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_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 || CFG_TUSB_MCU == OPT_MCU_SAME70) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAM7X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index e39c140cc..f1f71a778 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -94,7 +94,7 @@ enum #define EPNUM_CDC_1_OUT 0x05 #define EPNUM_CDC_1_IN 0x85 -#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAME70 +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAM7X // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_CDC_0_NOTIF 0x81 diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index f9e98b0f7..950f3c421 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -48,7 +48,7 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_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 || CFG_TUSB_MCU == OPT_MCU_SAME70) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAM7X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 46b57f7e2..6ac34e859 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -94,7 +94,7 @@ enum #define EPNUM_MSC_OUT 0x05 #define EPNUM_MSC_IN 0x85 -#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAME70 +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAM7X // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_CDC_NOTIF 0x81 diff --git a/hw/bsp/same70_xplained/board.mk b/hw/bsp/same70_xplained/board.mk index 13c552f98..031b536b2 100644 --- a/hw/bsp/same70_xplained/board.mk +++ b/hw/bsp/same70_xplained/board.mk @@ -8,7 +8,7 @@ CFLAGS += \ -mfpu=fpv4-sp-d16 \ -nostdlib -nostartfiles \ -D__SAME70Q21B__ \ - -DCFG_TUSB_MCU=OPT_MCU_SAME70 + -DCFG_TUSB_MCU=OPT_MCU_SAM7X # suppress following warnings from mcu driver CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align @@ -19,7 +19,7 @@ ASF_DIR = hw/mcu/microchip/same70 LD_FILE = $(ASF_DIR)/same70b/gcc/gcc/same70q21b_flash.ld SRC_C += \ - src/portable/microchip/same70/dcd_same70.c \ + src/portable/microchip/sam7x/dcd_sam7x.c \ $(ASF_DIR)/same70b/gcc/gcc/startup_same70q21b.c \ $(ASF_DIR)/same70b/gcc/system_same70q21b.c \ $(ASF_DIR)/hpl/core/hpl_init.c \ diff --git a/src/portable/microchip/sam7x/dcd_sam7x.c b/src/portable/microchip/sam7x/dcd_sam7x.c new file mode 100644 index 000000000..53ea796b4 --- /dev/null +++ b/src/portable/microchip/sam7x/dcd_sam7x.c @@ -0,0 +1,710 @@ +/* +* The MIT License (MIT) +* +* Copyright (c) 2018, hathach (tinyusb.org) +* Copyright (c) 2021, HiFiPhile +* +* 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. +* +* This file is part of the TinyUSB stack. +*/ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAM7X + +#include "device/dcd.h" + +#include "sam.h" +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#ifndef USE_SOF +# define USE_SOF 0 +#endif + +// Dual bank can imporve performance, but need 2 times bigger packet buffer +// As SAM7x has only 4KB packet buffer, use with caution ! +// Enable in FS mode as packets are smaller +#ifndef USE_DUAL_BANK +# if TUD_OPT_HIGH_SPEED +# define USE_DUAL_BANK 0 +# else +# define USE_DUAL_BANK 1 +# endif +#endif + +#define EP_MAX 10 + +#define USBHS_RAM_ADDR 0xA0100000u + +#define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) + +// Errata: The DMA feature is not available for Pipe/Endpoint 7 +#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) + +// DMA Channel Transfer Descriptor +typedef struct { + volatile uint32_t next_desc; + volatile uint32_t buff_addr; + volatile uint32_t chnl_ctrl; + uint32_t padding; +} dma_desc_t; + +// Transfer control context +typedef struct { + uint8_t * buffer; + uint16_t total_len; + uint16_t queued_len; + uint16_t max_packet_size; + uint8_t interval; + tu_fifo_t * fifo; +} xfer_ctl_t; + +static tusb_speed_t get_speed(void); +static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); + +// DMA descriptors shouldn't be placed in ITCM +#if defined(USB_DMA_DESC_SECTION) +TU_ATTR_SECTION(TU_XSTRING(USB_DMA_DESC_SECTION)) +#endif +dma_desc_t dma_desc[6]; + +xfer_ctl_t xfer_status[EP_MAX+1]; + +static const tusb_desc_endpoint_t ep0_desc = +{ + .bEndpointAddress = 0x00, + .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, +}; + +//------------------------------------------------------------------ +// Device API +//------------------------------------------------------------------ + +// Initialize controller to device mode +void dcd_init (uint8_t rhport) +{ + // Enable USBPLL + PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); + // Wait until USB UTMI stabilize + while (!(PMC->PMC_SR & PMC_SR_LOCKU)); +#if !TUD_OPT_HIGH_SPEED + // Enable USB FS clk + PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2; + PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); + PMC->PMC_SCER = PMC_SCER_USBCLK; +#endif + dcd_connect(rhport); +} + +// Enable device interrupt +void dcd_int_enable (uint8_t rhport) +{ + (void) rhport; + NVIC_EnableIRQ((IRQn_Type) ID_USBHS); +} + +// Disable device interrupt +void dcd_int_disable (uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ((IRQn_Type) ID_USBHS); +} + +// Receive Set Address request, mcu port must also include status IN response +void dcd_set_address (uint8_t rhport, uint8_t dev_addr) +{ + (void) dev_addr; + // DCD can only set address after status for this request is complete + // do it at dcd_edpt0_status_complete() + + // Response with zlp status + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} + +// Wake up host +void dcd_remote_wakeup (uint8_t rhport) +{ + (void) rhport; + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_RMWKUP; +} + +// Connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + // Enable USB clock + PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); + // Enable the USB controller in device mode + USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE; + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); +#if TUD_OPT_HIGH_SPEED + USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_SPDCONF_Msk; +#else + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_SPDCONF_LOW_POWER; +#endif + // Enable the End Of Reset, Suspend & Wakeup interrupts + USBHS->USBHS_DEVIER = (USBHS_DEVIER_EORSTES | USBHS_DEVIER_SUSPES | USBHS_DEVIER_WAKEUPES); +#if USE_SOF + USBHS->USBHS_DEVIER = USBHS_DEVIER_SOFES; +#endif + // Clear the End Of Reset, SOF & Wakeup interrupts + USBHS->USBHS_DEVICR = (USBHS_DEVICR_EORSTC | USBHS_DEVICR_SOFC | USBHS_DEVICR_WAKEUPC); + // Manually set the Suspend Interrupt + USBHS->USBHS_DEVIFR |= USBHS_DEVIFR_SUSPS; + // Ack the Wakeup Interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Attach the device + USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; + // Freeze USB clock + USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; + __set_PRIMASK(irq_state); +} + +// Disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + // Disable all endpoints + USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Clear all the pending interrupts + USBHS->USBHS_DEVICR = USBHS_DEVICR_Msk; + // Disable all interrupts + USBHS->USBHS_DEVIDR = USBHS_DEVCTRL_UADD_Msk; + // Detach the device + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH; + // Disable the device address + USBHS->USBHS_DEVCTRL &=~(USBHS_DEVCTRL_ADDEN | USBHS_DEVCTRL_UADD_Msk); + __set_PRIMASK(irq_state); +} + +static tusb_speed_t get_speed(void) +{ + switch ((USBHS->USBHS_SR & USBHS_SR_SPEED_Msk) >> USBHS_SR_SPEED_Pos) { + case USBHS_SR_SPEED_FULL_SPEED_Val: + default: + return TUSB_SPEED_FULL; + case USBHS_SR_SPEED_HIGH_SPEED_Val: + return TUSB_SPEED_HIGH; + case USBHS_SR_SPEED_LOW_SPEED_Val: + return TUSB_SPEED_LOW; + } +} + +static void dcd_ep_handler(uint8_t ep_ix) +{ + uint32_t int_status = USBHS->USBHS_DEVEPTISR[ep_ix]; + int_status &= USBHS->USBHS_DEVEPTIMR[ep_ix]; + uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & + USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; + if (ep_ix == 0U) + { + if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) + { + // Setup packet should always be 8 bytes. If not, ignore it, and try again. + if (count == 8) + { + uint8_t *ptr = EP_GET_FIFO_PTR(0,8); + dcd_event_setup_received(0, ptr, true); + } + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_CTRL_RXSTPIC; + } + if (int_status & USBHS_DEVEPTISR_RXOUTI) + { + xfer_ctl_t *xfer = &xfer_status[0]; + if (count) + { + uint8_t *ptr = EP_GET_FIFO_PTR(0,8); + if (xfer->buffer) + { + memcpy(xfer->buffer + xfer->queued_len, ptr, count); + } else { + tu_fifo_write_n(xfer->fifo, ptr, count); + } + xfer->queued_len = (uint16_t)(xfer->queued_len + count); + } + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) + { + // RX COMPLETE + dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; + // Though the host could still send, we don't know. + } + } + if (int_status & USBHS_DEVEPTISR_TXINI) + { + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; + xfer_ctl_t * xfer = &xfer_status[EP_MAX]; + if ((xfer->total_len != xfer->queued_len)) + { + // TX not complete + dcd_transmit_packet(xfer, 0); + } else { + // TX complete + dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + } else { + if (int_status & USBHS_DEVEPTISR_RXOUTI) + { + xfer_ctl_t *xfer = &xfer_status[ep_ix]; + if (count) + { + uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); + if (xfer->buffer) + { + memcpy(xfer->buffer + xfer->queued_len, ptr, count); + } else { + tu_fifo_write_n(xfer->fifo, ptr, count); + } + xfer->queued_len = (uint16_t)(xfer->queued_len + count); + } + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; + // Clear the FIFO control flag to receive more data. + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) + { + // RX COMPLETE + dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_RXOUTEC; + // Though the host could still send, we don't know. + } + } + if (int_status & USBHS_DEVEPTISR_TXINI) + { + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; + xfer_ctl_t * xfer = &xfer_status[ep_ix];; + if ((xfer->total_len != xfer->queued_len)) + { + // TX not complete + dcd_transmit_packet(xfer, ep_ix); + } else { + // TX complete + dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; + } + } + } +} + +static void dcd_dma_handler(uint8_t ep_ix) +{ + uint32_t status = USBHS->UsbhsDevdma[ep_ix - 1].USBHS_DEVDMASTATUS; + if (status & USBHS_DEVDMASTATUS_CHANN_ENB) + { + return; // Ignore EOT_STA interrupt + } + // Disable DMA interrupt + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_DMA_1 << (ep_ix - 1); + + xfer_ctl_t *xfer = &xfer_status[ep_ix]; + uint16_t count = xfer->total_len - ((status & USBHS_DEVDMASTATUS_BUFF_COUNT_Msk) >> USBHS_DEVDMASTATUS_BUFF_COUNT_Pos); + if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) + { + dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); + } else { + dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); + } +} + +void dcd_int_handler(uint8_t rhport) +{ + (void) rhport; + uint32_t int_status = USBHS->USBHS_DEVISR; + // End of reset interrupt + if (int_status & USBHS_DEVISR_EORST) + { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Reset all endpoints + for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) + { + USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix); + USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix)); + } + dcd_edpt_open (0, &ep0_desc); + USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC; + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; + USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; + + dcd_event_bus_reset(rhport, get_speed(), true); + } + // End of Wakeup interrupt + if (int_status & USBHS_DEVISR_WAKEUP) + { + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; + USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; + + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + // Suspend interrupt + if (int_status & USBHS_DEVISR_SUSP) + { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; + USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; + USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; + + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + } +#if USE_SOF + if(int_status & USBHS_DEVISR_SOF) + { + USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; + + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); + } +#endif + // Endpoints interrupt + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) + { + if (int_status & (USBHS_DEVISR_PEP_0 << ep_ix)) + { + dcd_ep_handler(ep_ix); + } + } + // Endpoints DMA interrupt + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) + { + if (EP_DMA_SUPPORT(ep_ix)) + { + if (int_status & (USBHS_DEVISR_DMA_1 << (ep_ix - 1))) + { + dcd_dma_handler(ep_ix); + } + } + } +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void) rhport; + + if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && + request->bRequest == TUSB_REQ_SET_ADDRESS ) + { + uint8_t const dev_addr = (uint8_t) request->wValue; + + USBHS->USBHS_DEVCTRL |= dev_addr | USBHS_DEVCTRL_ADDEN; + } +} + +// Configure endpoint's registers according to descriptor +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_desc->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); + uint16_t const epMaxPktSize = ep_desc->wMaxPacketSize.size; + tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; + uint8_t fifoSize = 0; // FIFO size + uint16_t defaultEndpointSize = 8; // Default size of Endpoint + // Find upper 2 power number of epMaxPktSize + if (epMaxPktSize) + { + while (defaultEndpointSize < epMaxPktSize) + { + fifoSize++; + defaultEndpointSize <<= 1; + } + } + xfer_status[epnum].max_packet_size = epMaxPktSize; + + USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + epnum); + USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + epnum)); + + if (epnum == 0) + { + xfer_status[EP_MAX].max_packet_size = epMaxPktSize; + // Enable the control endpoint - Endpoint 0 + USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; + // Configure the Endpoint 0 configuration register + USBHS->USBHS_DEVEPTCFG[0] = + ( + USBHS_DEVEPTCFG_EPSIZE(fifoSize) | + USBHS_DEVEPTCFG_EPTYPE(TUSB_XFER_CONTROL) | + USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | + USBHS_DEVEPTCFG_ALLOC + ); + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_CTRL_STALLRQC; + if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) + { + // Endpoint configuration is successful + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; + // Enable Endpoint 0 Interrupts + USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; + return true; + } else { + // Endpoint configuration is not successful + return false; + } + } else { + // Enable the endpoint + USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); + // Set up the maxpacket size, fifo start address fifosize + // and enable the interrupt. CLear the data toggle. + // AUTOSW is needed for DMA ack ! + USBHS->USBHS_DEVEPTCFG[epnum] = + ( + USBHS_DEVEPTCFG_EPSIZE(fifoSize) | + USBHS_DEVEPTCFG_EPTYPE(eptype) | + USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | + USBHS_DEVEPTCFG_AUTOSW | + ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) + ); + if (eptype == TUSB_XFER_ISOCHRONOUS) + { + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); + } +#if USE_DUAL_BANK + if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK) + { + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_EPBK_2_BANK; + } +#endif + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_CTRL_STALLRQC; + if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) + { + USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); + return true; + } else { + // Endpoint configuration is not successful + return false; + } + } +} + +static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) +{ + uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); + if (len > xfer->max_packet_size) + { + len = xfer->max_packet_size; + } + uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); + if(xfer->buffer) + { + memcpy(ptr, xfer->buffer + xfer->queued_len, len); + } + else { + tu_fifo_read_n(xfer->fifo, ptr, len); + } + xfer->queued_len = (uint16_t)(xfer->queued_len + len); + if (ep_ix == 0U) + { + // Control endpoint: clear the interrupt flag to send the data + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; + + } else { + // Other endpoint types: clear the FIFO control flag to send the data + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + } + USBHS->USBHS_DEVEPTIER[ep_ix] = USBHS_DEVEPTIER_TXINES; +} + +// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = &xfer_status[epnum]; + if(ep_addr == 0x80) + xfer = &xfer_status[EP_MAX]; + + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->fifo = NULL; + + if(EP_DMA_SUPPORT(epnum) && total_bytes != 0) + { + uint32_t udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); + if (dir == TUSB_DIR_OUT) + { + udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; + } else { + udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_B_EN; + } + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)buffer; + udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_BUFFIT | USBHS_DEVDMACONTROL_CHANN_ENB; + // Disable IRQs to have a short sequence + // between read of EOT_STA and DMA enable + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) + { + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl; + USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); + __set_PRIMASK(irq_state); + return true; + } + __set_PRIMASK(irq_state); + + // Here a ZLP has been recieved + // and the DMA transfer must be not started. + // It is the end of transfer + return false; + } else { + if (dir == TUSB_DIR_OUT) + { + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } else { + dcd_transmit_packet(xfer,epnum); + } + } + return true; +} + +// The number of bytes has to be given explicitly to allow more flexible control of how many +// bytes should be written and second to keep the return value free to give back a boolean +// success message. If total_bytes is too big, the FIFO will copy only what is available +// into the USB buffer! +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = &xfer_status[epnum]; + if(epnum == 0x80) + xfer = &xfer_status[EP_MAX]; + + xfer->buffer = NULL; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->fifo = ff; + + if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) + { + tu_fifo_buffer_info_t info; + uint32_t udd_dma_ctrl_lin = USBHS_DEVDMACONTROL_CHANN_ENB; + uint32_t udd_dma_ctrl_wrap = USBHS_DEVDMACONTROL_CHANN_ENB | USBHS_DEVDMACONTROL_END_BUFFIT; + if (dir == TUSB_DIR_OUT) + { + tu_fifo_get_write_info(ff, &info); + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; + udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; + } else { + tu_fifo_get_read_info(ff, &info); + if(info.len_wrap == 0) + { + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_B_EN; + } + udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_B_EN; + } + + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)info.ptr_lin; + if (info.len_wrap) + { + dma_desc[epnum - 1].next_desc = 0; + dma_desc[epnum - 1].buff_addr = (uint32_t)info.ptr_wrap; + dma_desc[epnum - 1].chnl_ctrl = + udd_dma_ctrl_wrap | USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_wrap); + udd_dma_ctrl_lin |= USBHS_DEVDMASTATUS_DESC_LDST; + __DSB(); + __ISB(); + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMANXTDSC = (uint32_t)&dma_desc[epnum - 1]; + } else { + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_BUFFIT; + } + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_lin); + // Disable IRQs to have a short sequence + // between read of EOT_STA and DMA enable + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) + { + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl_lin; + USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); + __set_PRIMASK(irq_state); + return true; + } + __set_PRIMASK(irq_state); + + // Here a ZLP has been recieved + // and the DMA transfer must be not started. + // It is the end of transfer + return false; + } else { + if (dir == TUSB_DIR_OUT) + { + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } else { + dcd_transmit_packet(xfer,epnum); + } + } + return true; +} + +// Stall endpoint +void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_CTRL_STALLRQS; +} + +// clear stall, data toggle is also reset to DATA0 +void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_CTRL_STALLRQC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_HSTPIPIER_RSTDTS; +} + +#endif diff --git a/src/portable/microchip/same70/dcd_same70.c b/src/portable/microchip/same70/dcd_same70.c deleted file mode 100644 index 0ad9ad625..000000000 --- a/src/portable/microchip/same70/dcd_same70.c +++ /dev/null @@ -1,710 +0,0 @@ -/* -* The MIT License (MIT) -* -* Copyright (c) 2018, hathach (tinyusb.org) -* Copyright (c) 2021, HiFiPhile -* -* 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. -* -* This file is part of the TinyUSB stack. -*/ - -#include "tusb_option.h" - -#if CFG_TUSB_MCU == OPT_MCU_SAME70 - -#include "device/dcd.h" - -#include "sam.h" -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) -// We disable SOF for now until needed later on -#ifndef USE_SOF -# define USE_SOF 0 -#endif - -// Dual bank can imporve performance, but need 2 times bigger packet buffer -// As SAME70 has only 4KB packet buffer, use with caution ! -// Enable in FS mode as packets are smaller -#ifndef USE_DUAL_BANK -# if TUD_OPT_HIGH_SPEED -# define USE_DUAL_BANK 0 -# else -# define USE_DUAL_BANK 1 -# endif -#endif - -#define EP_MAX 10 - -#define USBHS_RAM_ADDR 0xA0100000u - -#define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) - -// Errata: The DMA feature is not available for Pipe/Endpoint 7 -#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) - -// DMA Channel Transfer Descriptor -typedef struct { - volatile uint32_t next_desc; - volatile uint32_t buff_addr; - volatile uint32_t chnl_ctrl; - uint32_t padding; -} dma_desc_t; - -// Transfer control context -typedef struct { - uint8_t * buffer; - uint16_t total_len; - uint16_t queued_len; - uint16_t max_packet_size; - uint8_t interval; - tu_fifo_t * fifo; -} xfer_ctl_t; - -static tusb_speed_t get_speed(void); -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); - -// DMA descriptors shouldn't be placed in ITCM -#if defined(USB_DMA_DESC_SECTION) -TU_ATTR_SECTION(TU_XSTRING(USB_DMA_DESC_SECTION)) -#endif -dma_desc_t dma_desc[6]; - -xfer_ctl_t xfer_status[EP_MAX+1]; - -static const tusb_desc_endpoint_t ep0_desc = -{ - .bEndpointAddress = 0x00, - .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, -}; - -//------------------------------------------------------------------ -// Device API -//------------------------------------------------------------------ - -// Initialize controller to device mode -void dcd_init (uint8_t rhport) -{ - // Enable USBPLL - PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); - // Wait until USB UTMI stabilize - while (!(PMC->PMC_SR & PMC_SR_LOCKU)); -#if !TUD_OPT_HIGH_SPEED - // Enable USB FS clk - PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2; - PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); - PMC->PMC_SCER = PMC_SCER_USBCLK; -#endif - dcd_connect(rhport); -} - -// Enable device interrupt -void dcd_int_enable (uint8_t rhport) -{ - (void) rhport; - NVIC_EnableIRQ((IRQn_Type) ID_USBHS); -} - -// Disable device interrupt -void dcd_int_disable (uint8_t rhport) -{ - (void) rhport; - NVIC_DisableIRQ((IRQn_Type) ID_USBHS); -} - -// Receive Set Address request, mcu port must also include status IN response -void dcd_set_address (uint8_t rhport, uint8_t dev_addr) -{ - (void) dev_addr; - // DCD can only set address after status for this request is complete - // do it at dcd_edpt0_status_complete() - - // Response with zlp status - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); -} - -// Wake up host -void dcd_remote_wakeup (uint8_t rhport) -{ - (void) rhport; - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_RMWKUP; -} - -// Connect by enabling internal pull-up resistor on D+/D- -void dcd_connect(uint8_t rhport) -{ - (void) rhport; - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - // Enable USB clock - PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); - // Enable the USB controller in device mode - USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE; - while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); -#if TUD_OPT_HIGH_SPEED - USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_SPDCONF_Msk; -#else - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_SPDCONF_LOW_POWER; -#endif - // Enable the End Of Reset, Suspend & Wakeup interrupts - USBHS->USBHS_DEVIER = (USBHS_DEVIER_EORSTES | USBHS_DEVIER_SUSPES | USBHS_DEVIER_WAKEUPES); -#if USE_SOF - USBHS->USBHS_DEVIER = USBHS_DEVIER_SOFES; -#endif - // Clear the End Of Reset, SOF & Wakeup interrupts - USBHS->USBHS_DEVICR = (USBHS_DEVICR_EORSTC | USBHS_DEVICR_SOFC | USBHS_DEVICR_WAKEUPC); - // Manually set the Suspend Interrupt - USBHS->USBHS_DEVIFR |= USBHS_DEVIFR_SUSPS; - // Ack the Wakeup Interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - // Attach the device - USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; - // Freeze USB clock - USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; - __set_PRIMASK(irq_state); -} - -// Disconnect by disabling internal pull-up resistor on D+/D- -void dcd_disconnect(uint8_t rhport) -{ - (void) rhport; - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - // Disable all endpoints - USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); - // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Clear all the pending interrupts - USBHS->USBHS_DEVICR = USBHS_DEVICR_Msk; - // Disable all interrupts - USBHS->USBHS_DEVIDR = USBHS_DEVCTRL_UADD_Msk; - // Detach the device - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH; - // Disable the device address - USBHS->USBHS_DEVCTRL &=~(USBHS_DEVCTRL_ADDEN | USBHS_DEVCTRL_UADD_Msk); - __set_PRIMASK(irq_state); -} - -static tusb_speed_t get_speed(void) -{ - switch ((USBHS->USBHS_SR & USBHS_SR_SPEED_Msk) >> USBHS_SR_SPEED_Pos) { - case USBHS_SR_SPEED_FULL_SPEED_Val: - default: - return TUSB_SPEED_FULL; - case USBHS_SR_SPEED_HIGH_SPEED_Val: - return TUSB_SPEED_HIGH; - case USBHS_SR_SPEED_LOW_SPEED_Val: - return TUSB_SPEED_LOW; - } -} - -static void dcd_ep_handler(uint8_t ep_ix) -{ - uint32_t int_status = USBHS->USBHS_DEVEPTISR[ep_ix]; - int_status &= USBHS->USBHS_DEVEPTIMR[ep_ix]; - uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & - USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; - if (ep_ix == 0U) - { - if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) - { - // Setup packet should always be 8 bytes. If not, ignore it, and try again. - if (count == 8) - { - uint8_t *ptr = EP_GET_FIFO_PTR(0,8); - dcd_event_setup_received(0, ptr, true); - } - // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_CTRL_RXSTPIC; - } - if (int_status & USBHS_DEVEPTISR_RXOUTI) - { - xfer_ctl_t *xfer = &xfer_status[0]; - if (count) - { - uint8_t *ptr = EP_GET_FIFO_PTR(0,8); - if (xfer->buffer) - { - memcpy(xfer->buffer + xfer->queued_len, ptr, count); - } else { - tu_fifo_write_n(xfer->fifo, ptr, count); - } - xfer->queued_len = (uint16_t)(xfer->queued_len + count); - } - // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { - // RX COMPLETE - dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); - // Disable the interrupt - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; - // Though the host could still send, we don't know. - } - } - if (int_status & USBHS_DEVEPTISR_TXINI) - { - // Disable the interrupt - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; - xfer_ctl_t * xfer = &xfer_status[EP_MAX]; - if ((xfer->total_len != xfer->queued_len)) - { - // TX not complete - dcd_transmit_packet(xfer, 0); - } else { - // TX complete - dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - } - } else { - if (int_status & USBHS_DEVEPTISR_RXOUTI) - { - xfer_ctl_t *xfer = &xfer_status[ep_ix]; - if (count) - { - uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); - if (xfer->buffer) - { - memcpy(xfer->buffer + xfer->queued_len, ptr, count); - } else { - tu_fifo_write_n(xfer->fifo, ptr, count); - } - xfer->queued_len = (uint16_t)(xfer->queued_len + count); - } - // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; - // Clear the FIFO control flag to receive more data. - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { - // RX COMPLETE - dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); - // Disable the interrupt - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_RXOUTEC; - // Though the host could still send, we don't know. - } - } - if (int_status & USBHS_DEVEPTISR_TXINI) - { - // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; - xfer_ctl_t * xfer = &xfer_status[ep_ix];; - if ((xfer->total_len != xfer->queued_len)) - { - // TX not complete - dcd_transmit_packet(xfer, ep_ix); - } else { - // TX complete - dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; - } - } - } -} - -static void dcd_dma_handler(uint8_t ep_ix) -{ - uint32_t status = USBHS->UsbhsDevdma[ep_ix - 1].USBHS_DEVDMASTATUS; - if (status & USBHS_DEVDMASTATUS_CHANN_ENB) - { - return; // Ignore EOT_STA interrupt - } - // Disable DMA interrupt - USBHS->USBHS_DEVIDR = USBHS_DEVIDR_DMA_1 << (ep_ix - 1); - - xfer_ctl_t *xfer = &xfer_status[ep_ix]; - uint16_t count = xfer->total_len - ((status & USBHS_DEVDMASTATUS_BUFF_COUNT_Msk) >> USBHS_DEVDMASTATUS_BUFF_COUNT_Pos); - if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) - { - dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); - } else { - dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); - } -} - -void dcd_int_handler(uint8_t rhport) -{ - (void) rhport; - uint32_t int_status = USBHS->USBHS_DEVISR; - // End of reset interrupt - if (int_status & USBHS_DEVISR_EORST) - { - // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Reset all endpoints - for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) - { - USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix); - USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix)); - } - dcd_edpt_open (0, &ep0_desc); - USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC; - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; - USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; - - dcd_event_bus_reset(rhport, get_speed(), true); - } - // End of Wakeup interrupt - if (int_status & USBHS_DEVISR_WAKEUP) - { - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; - USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; - - dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); - } - // Suspend interrupt - if (int_status & USBHS_DEVISR_SUSP) - { - // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; - USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; - USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; - USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; - - dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); - } -#if USE_SOF - if(int_status & USBHS_DEVISR_SOF) - { - USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; - - dcd_event_bus_signal(0, DCD_EVENT_SOF, true); - } -#endif - // Endpoints interrupt - for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) - { - if (int_status & (USBHS_DEVISR_PEP_0 << ep_ix)) - { - dcd_ep_handler(ep_ix); - } - } - // Endpoints DMA interrupt - for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) - { - if (EP_DMA_SUPPORT(ep_ix)) - { - if (int_status & (USBHS_DEVISR_DMA_1 << (ep_ix - 1))) - { - dcd_dma_handler(ep_ix); - } - } - } -} - -//--------------------------------------------------------------------+ -// Endpoint API -//--------------------------------------------------------------------+ -// Invoked when a control transfer's status stage is complete. -// May help DCD to prepare for next control transfer, this API is optional. -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - - if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && - request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && - request->bRequest == TUSB_REQ_SET_ADDRESS ) - { - uint8_t const dev_addr = (uint8_t) request->wValue; - - USBHS->USBHS_DEVCTRL |= dev_addr | USBHS_DEVCTRL_ADDEN; - } -} - -// Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_desc->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); - uint16_t const epMaxPktSize = ep_desc->wMaxPacketSize.size; - tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; - uint8_t fifoSize = 0; // FIFO size - uint16_t defaultEndpointSize = 8; // Default size of Endpoint - // Find upper 2 power number of epMaxPktSize - if (epMaxPktSize) - { - while (defaultEndpointSize < epMaxPktSize) - { - fifoSize++; - defaultEndpointSize <<= 1; - } - } - xfer_status[epnum].max_packet_size = epMaxPktSize; - - USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + epnum); - USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + epnum)); - - if (epnum == 0) - { - xfer_status[EP_MAX].max_packet_size = epMaxPktSize; - // Enable the control endpoint - Endpoint 0 - USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; - // Configure the Endpoint 0 configuration register - USBHS->USBHS_DEVEPTCFG[0] = - ( - USBHS_DEVEPTCFG_EPSIZE(fifoSize) | - USBHS_DEVEPTCFG_EPTYPE(TUSB_XFER_CONTROL) | - USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | - USBHS_DEVEPTCFG_ALLOC - ); - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_CTRL_STALLRQC; - if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) - { - // Endpoint configuration is successful - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; - // Enable Endpoint 0 Interrupts - USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; - return true; - } else { - // Endpoint configuration is not successful - return false; - } - } else { - // Enable the endpoint - USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); - // Set up the maxpacket size, fifo start address fifosize - // and enable the interrupt. CLear the data toggle. - // AUTOSW is needed for DMA ack ! - USBHS->USBHS_DEVEPTCFG[epnum] = - ( - USBHS_DEVEPTCFG_EPSIZE(fifoSize) | - USBHS_DEVEPTCFG_EPTYPE(eptype) | - USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | - USBHS_DEVEPTCFG_AUTOSW | - ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) - ); - if (eptype == TUSB_XFER_ISOCHRONOUS) - { - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); - } -#if USE_DUAL_BANK - if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK) - { - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_EPBK_2_BANK; - } -#endif - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_CTRL_STALLRQC; - if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) - { - USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); - return true; - } else { - // Endpoint configuration is not successful - return false; - } - } -} - -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) -{ - uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - if (len > xfer->max_packet_size) - { - len = xfer->max_packet_size; - } - uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); - if(xfer->buffer) - { - memcpy(ptr, xfer->buffer + xfer->queued_len, len); - } - else { - tu_fifo_read_n(xfer->fifo, ptr, len); - } - xfer->queued_len = (uint16_t)(xfer->queued_len + len); - if (ep_ix == 0U) - { - // Control endpoint: clear the interrupt flag to send the data - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - - } else { - // Other endpoint types: clear the FIFO control flag to send the data - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; - } - USBHS->USBHS_DEVEPTIER[ep_ix] = USBHS_DEVEPTIER_TXINES; -} - -// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t * xfer = &xfer_status[epnum]; - if(ep_addr == 0x80) - xfer = &xfer_status[EP_MAX]; - - xfer->buffer = buffer; - xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->fifo = NULL; - - if(EP_DMA_SUPPORT(epnum) && total_bytes != 0) - { - uint32_t udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); - if (dir == TUSB_DIR_OUT) - { - udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; - } else { - udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_B_EN; - } - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)buffer; - udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_BUFFIT | USBHS_DEVDMACONTROL_CHANN_ENB; - // Disable IRQs to have a short sequence - // between read of EOT_STA and DMA enable - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) - { - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl; - USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); - __set_PRIMASK(irq_state); - return true; - } - __set_PRIMASK(irq_state); - - // Here a ZLP has been recieved - // and the DMA transfer must be not started. - // It is the end of transfer - return false; - } else { - if (dir == TUSB_DIR_OUT) - { - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } else { - dcd_transmit_packet(xfer,epnum); - } - } - return true; -} - -// The number of bytes has to be given explicitly to allow more flexible control of how many -// bytes should be written and second to keep the return value free to give back a boolean -// success message. If total_bytes is too big, the FIFO will copy only what is available -// into the USB buffer! -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t * xfer = &xfer_status[epnum]; - if(epnum == 0x80) - xfer = &xfer_status[EP_MAX]; - - xfer->buffer = NULL; - xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->fifo = ff; - - if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) - { - tu_fifo_buffer_info_t info; - uint32_t udd_dma_ctrl_lin = USBHS_DEVDMACONTROL_CHANN_ENB; - uint32_t udd_dma_ctrl_wrap = USBHS_DEVDMACONTROL_CHANN_ENB | USBHS_DEVDMACONTROL_END_BUFFIT; - if (dir == TUSB_DIR_OUT) - { - tu_fifo_get_write_info(ff, &info); - udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; - udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; - } else { - tu_fifo_get_read_info(ff, &info); - if(info.len_wrap == 0) - { - udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_B_EN; - } - udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_B_EN; - } - - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)info.ptr_lin; - if (info.len_wrap) - { - dma_desc[epnum - 1].next_desc = 0; - dma_desc[epnum - 1].buff_addr = (uint32_t)info.ptr_wrap; - dma_desc[epnum - 1].chnl_ctrl = - udd_dma_ctrl_wrap | USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_wrap); - udd_dma_ctrl_lin |= USBHS_DEVDMASTATUS_DESC_LDST; - __DSB(); - __ISB(); - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMANXTDSC = (uint32_t)&dma_desc[epnum - 1]; - } else { - udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_BUFFIT; - } - udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_lin); - // Disable IRQs to have a short sequence - // between read of EOT_STA and DMA enable - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) - { - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl_lin; - USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); - __set_PRIMASK(irq_state); - return true; - } - __set_PRIMASK(irq_state); - - // Here a ZLP has been recieved - // and the DMA transfer must be not started. - // It is the end of transfer - return false; - } else { - if (dir == TUSB_DIR_OUT) - { - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } else { - dcd_transmit_packet(xfer,epnum); - } - } - return true; -} - -// Stall endpoint -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_CTRL_STALLRQS; -} - -// clear stall, data toggle is also reset to DATA0 -void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_CTRL_STALLRQC; - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_HSTPIPIER_RSTDTS; -} - -#endif diff --git a/src/tusb_option.h b/src/tusb_option.h index fb86d7f9c..2e1678ccf 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -61,7 +61,8 @@ #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 #define OPT_MCU_SAML22 205 ///< MicroChip SAML22 -#define OPT_MCU_SAME70 206 ///< MicroChip SAME70 series +#define OPT_MCU_SAM7X 206 ///< MicroChip SAME70, S70, V70, V71 family + // STM32 #define OPT_MCU_STM32F0 300 ///< ST STM32F0 -- cgit v1.3.1 From a4ad064e638679a7c8759a2c30ed555bd93e524b Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 12 Jun 2021 14:20:09 +0700 Subject: increase example CFG_TUH_HID from 2 to 4 --- examples/host/cdc_msc_hid/src/tusb_config.h | 2 +- src/common/tusb_verify.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 8253964c0..531bb2c30 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -76,7 +76,7 @@ #define CFG_TUH_HUB 1 #define CFG_TUH_CDC 1 -#define CFG_TUH_HID 2 +#define CFG_TUH_HID 4 #define CFG_TUH_MSC 1 #define CFG_TUH_VENDOR 0 diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 542809899..56ba8bcd1 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -75,7 +75,7 @@ #if CFG_TUSB_DEBUG #include #define _MESS_ERR(_err) tu_printf("%s %d: failed, error = %s\r\n", __func__, __LINE__, tusb_strerr[_err]) - #define _MESS_FAILED() tu_printf("%s %d: assert failed\r\n", __func__, __LINE__) + #define _MESS_FAILED() tu_printf("%s %d: ASSERT FAILED\r\n", __func__, __LINE__) #else #define _MESS_ERR(_err) do {} while (0) #define _MESS_FAILED() do {} while (0) -- cgit v1.3.1 From f039607afcf7473ea3869f2e2e7cd763d13f8de0 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 12 Jun 2021 11:19:08 +0200 Subject: Fix indent. Signed-off-by: MasterPhi --- src/portable/microchip/sam7x/dcd_sam7x.c | 62 ++++++++++++++++---------------- 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/sam7x/dcd_sam7x.c b/src/portable/microchip/sam7x/dcd_sam7x.c index 53ea796b4..6463973bd 100644 --- a/src/portable/microchip/sam7x/dcd_sam7x.c +++ b/src/portable/microchip/sam7x/dcd_sam7x.c @@ -430,7 +430,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && - request->bRequest == TUSB_REQ_SET_ADDRESS ) + request->bRequest == TUSB_REQ_SET_ADDRESS ) { uint8_t const dev_addr = (uint8_t) request->wValue; @@ -474,7 +474,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS_DEVEPTCFG_EPTYPE(TUSB_XFER_CONTROL) | USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | USBHS_DEVEPTCFG_ALLOC - ); + ); USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_CTRL_STALLRQC; if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) @@ -501,7 +501,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | USBHS_DEVEPTCFG_AUTOSW | ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) - ); + ); if (eptype == TUSB_XFER_ISOCHRONOUS) { USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); @@ -570,7 +570,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->queued_len = 0; xfer->fifo = NULL; - if(EP_DMA_SUPPORT(epnum) && total_bytes != 0) + if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) { uint32_t udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); if (dir == TUSB_DIR_OUT) @@ -579,24 +579,24 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } else { udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_B_EN; } - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)buffer; - udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_BUFFIT | USBHS_DEVDMACONTROL_CHANN_ENB; + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)buffer; + udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_BUFFIT | USBHS_DEVDMACONTROL_CHANN_ENB; // Disable IRQs to have a short sequence - // between read of EOT_STA and DMA enable - uint32_t irq_state = __get_PRIMASK(); + // between read of EOT_STA and DMA enable + uint32_t irq_state = __get_PRIMASK(); __disable_irq(); - if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) + if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) { USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl; - USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); - __set_PRIMASK(irq_state); - return true; - } - __set_PRIMASK(irq_state); - - // Here a ZLP has been recieved - // and the DMA transfer must be not started. - // It is the end of transfer + USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); + __set_PRIMASK(irq_state); + return true; + } + __set_PRIMASK(irq_state); + + // Here a ZLP has been recieved + // and the DMA transfer must be not started. + // It is the end of transfer return false; } else { if (dir == TUSB_DIR_OUT) @@ -661,23 +661,23 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 } else { udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_BUFFIT; } - udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_lin); + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_lin); // Disable IRQs to have a short sequence - // between read of EOT_STA and DMA enable - uint32_t irq_state = __get_PRIMASK(); + // between read of EOT_STA and DMA enable + uint32_t irq_state = __get_PRIMASK(); __disable_irq(); - if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) + if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) { USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl_lin; - USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); - __set_PRIMASK(irq_state); - return true; - } - __set_PRIMASK(irq_state); - - // Here a ZLP has been recieved - // and the DMA transfer must be not started. - // It is the end of transfer + USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); + __set_PRIMASK(irq_state); + return true; + } + __set_PRIMASK(irq_state); + + // Here a ZLP has been recieved + // and the DMA transfer must be not started. + // It is the end of transfer return false; } else { if (dir == TUSB_DIR_OUT) -- cgit v1.3.1 From 85fc42356977cac4d893c33eff80937e6ff9b45a Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 12 Jun 2021 12:28:28 +0200 Subject: Rename SAM7X to SAMX7X Signed-off-by: MasterPhi --- examples/device/cdc_dual_ports/src/tusb_config.h | 2 +- .../device/cdc_dual_ports/src/usb_descriptors.c | 2 +- examples/device/cdc_msc/src/msc_disk.c | 2 +- examples/device/cdc_msc/src/tusb_config.h | 2 +- examples/device/cdc_msc/src/usb_descriptors.c | 2 +- examples/device/cdc_msc_freertos/.skip.MCU_SAM7X | 0 examples/device/cdc_msc_freertos/.skip.MCU_SAMX7X | 0 .../device/hid_composite_freertos/.skip.MCU_SAM7X | 0 .../device/hid_composite_freertos/.skip.MCU_SAMX7X | 0 hw/bsp/same70_xplained/board.mk | 4 +- src/portable/microchip/sam7x/dcd_sam7x.c | 710 --------------------- src/portable/microchip/samx7x/dcd_samx7x.c | 710 +++++++++++++++++++++ src/tusb_option.h | 2 +- 13 files changed, 718 insertions(+), 718 deletions(-) delete mode 100644 examples/device/cdc_msc_freertos/.skip.MCU_SAM7X create mode 100644 examples/device/cdc_msc_freertos/.skip.MCU_SAMX7X delete mode 100644 examples/device/hid_composite_freertos/.skip.MCU_SAM7X create mode 100644 examples/device/hid_composite_freertos/.skip.MCU_SAMX7X delete mode 100644 src/portable/microchip/sam7x/dcd_sam7x.c create mode 100644 src/portable/microchip/samx7x/dcd_samx7x.c (limited to 'src') diff --git a/examples/device/cdc_dual_ports/src/tusb_config.h b/examples/device/cdc_dual_ports/src/tusb_config.h index 19b6925bc..ff8535d1a 100644 --- a/examples/device/cdc_dual_ports/src/tusb_config.h +++ b/examples/device/cdc_dual_ports/src/tusb_config.h @@ -48,7 +48,7 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_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 || CFG_TUSB_MCU == OPT_MCU_SAM7X) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index f1f71a778..b935b672f 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -94,7 +94,7 @@ enum #define EPNUM_CDC_1_OUT 0x05 #define EPNUM_CDC_1_IN 0x85 -#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAM7X +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_CDC_0_NOTIF 0x81 diff --git a/examples/device/cdc_msc/src/msc_disk.c b/examples/device/cdc_msc/src/msc_disk.c index 503baace9..3caf3fd42 100644 --- a/examples/device/cdc_msc/src/msc_disk.c +++ b/examples/device/cdc_msc/src/msc_disk.c @@ -23,7 +23,7 @@ * */ -#include "bsp/board.h" +//#include "bsp/board.h" #include "tusb.h" #if CFG_TUD_MSC diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index 950f3c421..bf6af06bc 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -48,7 +48,7 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_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 || CFG_TUSB_MCU == OPT_MCU_SAM7X) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 6ac34e859..1a89ce561 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -94,7 +94,7 @@ enum #define EPNUM_MSC_OUT 0x05 #define EPNUM_MSC_IN 0x85 -#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAM7X +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_CDC_NOTIF 0x81 diff --git a/examples/device/cdc_msc_freertos/.skip.MCU_SAM7X b/examples/device/cdc_msc_freertos/.skip.MCU_SAM7X deleted file mode 100644 index e69de29bb..000000000 diff --git a/examples/device/cdc_msc_freertos/.skip.MCU_SAMX7X b/examples/device/cdc_msc_freertos/.skip.MCU_SAMX7X new file mode 100644 index 000000000..e69de29bb diff --git a/examples/device/hid_composite_freertos/.skip.MCU_SAM7X b/examples/device/hid_composite_freertos/.skip.MCU_SAM7X deleted file mode 100644 index e69de29bb..000000000 diff --git a/examples/device/hid_composite_freertos/.skip.MCU_SAMX7X b/examples/device/hid_composite_freertos/.skip.MCU_SAMX7X new file mode 100644 index 000000000..e69de29bb diff --git a/hw/bsp/same70_xplained/board.mk b/hw/bsp/same70_xplained/board.mk index 031b536b2..94b0bed98 100644 --- a/hw/bsp/same70_xplained/board.mk +++ b/hw/bsp/same70_xplained/board.mk @@ -8,7 +8,7 @@ CFLAGS += \ -mfpu=fpv4-sp-d16 \ -nostdlib -nostartfiles \ -D__SAME70Q21B__ \ - -DCFG_TUSB_MCU=OPT_MCU_SAM7X + -DCFG_TUSB_MCU=OPT_MCU_SAMX7X # suppress following warnings from mcu driver CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align @@ -19,7 +19,7 @@ ASF_DIR = hw/mcu/microchip/same70 LD_FILE = $(ASF_DIR)/same70b/gcc/gcc/same70q21b_flash.ld SRC_C += \ - src/portable/microchip/sam7x/dcd_sam7x.c \ + src/portable/microchip/samx7x/dcd_samx7x.c \ $(ASF_DIR)/same70b/gcc/gcc/startup_same70q21b.c \ $(ASF_DIR)/same70b/gcc/system_same70q21b.c \ $(ASF_DIR)/hpl/core/hpl_init.c \ diff --git a/src/portable/microchip/sam7x/dcd_sam7x.c b/src/portable/microchip/sam7x/dcd_sam7x.c deleted file mode 100644 index 6463973bd..000000000 --- a/src/portable/microchip/sam7x/dcd_sam7x.c +++ /dev/null @@ -1,710 +0,0 @@ -/* -* The MIT License (MIT) -* -* Copyright (c) 2018, hathach (tinyusb.org) -* Copyright (c) 2021, HiFiPhile -* -* 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. -* -* This file is part of the TinyUSB stack. -*/ - -#include "tusb_option.h" - -#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAM7X - -#include "device/dcd.h" - -#include "sam.h" -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) -// We disable SOF for now until needed later on -#ifndef USE_SOF -# define USE_SOF 0 -#endif - -// Dual bank can imporve performance, but need 2 times bigger packet buffer -// As SAM7x has only 4KB packet buffer, use with caution ! -// Enable in FS mode as packets are smaller -#ifndef USE_DUAL_BANK -# if TUD_OPT_HIGH_SPEED -# define USE_DUAL_BANK 0 -# else -# define USE_DUAL_BANK 1 -# endif -#endif - -#define EP_MAX 10 - -#define USBHS_RAM_ADDR 0xA0100000u - -#define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) - -// Errata: The DMA feature is not available for Pipe/Endpoint 7 -#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) - -// DMA Channel Transfer Descriptor -typedef struct { - volatile uint32_t next_desc; - volatile uint32_t buff_addr; - volatile uint32_t chnl_ctrl; - uint32_t padding; -} dma_desc_t; - -// Transfer control context -typedef struct { - uint8_t * buffer; - uint16_t total_len; - uint16_t queued_len; - uint16_t max_packet_size; - uint8_t interval; - tu_fifo_t * fifo; -} xfer_ctl_t; - -static tusb_speed_t get_speed(void); -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); - -// DMA descriptors shouldn't be placed in ITCM -#if defined(USB_DMA_DESC_SECTION) -TU_ATTR_SECTION(TU_XSTRING(USB_DMA_DESC_SECTION)) -#endif -dma_desc_t dma_desc[6]; - -xfer_ctl_t xfer_status[EP_MAX+1]; - -static const tusb_desc_endpoint_t ep0_desc = -{ - .bEndpointAddress = 0x00, - .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, -}; - -//------------------------------------------------------------------ -// Device API -//------------------------------------------------------------------ - -// Initialize controller to device mode -void dcd_init (uint8_t rhport) -{ - // Enable USBPLL - PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); - // Wait until USB UTMI stabilize - while (!(PMC->PMC_SR & PMC_SR_LOCKU)); -#if !TUD_OPT_HIGH_SPEED - // Enable USB FS clk - PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2; - PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); - PMC->PMC_SCER = PMC_SCER_USBCLK; -#endif - dcd_connect(rhport); -} - -// Enable device interrupt -void dcd_int_enable (uint8_t rhport) -{ - (void) rhport; - NVIC_EnableIRQ((IRQn_Type) ID_USBHS); -} - -// Disable device interrupt -void dcd_int_disable (uint8_t rhport) -{ - (void) rhport; - NVIC_DisableIRQ((IRQn_Type) ID_USBHS); -} - -// Receive Set Address request, mcu port must also include status IN response -void dcd_set_address (uint8_t rhport, uint8_t dev_addr) -{ - (void) dev_addr; - // DCD can only set address after status for this request is complete - // do it at dcd_edpt0_status_complete() - - // Response with zlp status - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); -} - -// Wake up host -void dcd_remote_wakeup (uint8_t rhport) -{ - (void) rhport; - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_RMWKUP; -} - -// Connect by enabling internal pull-up resistor on D+/D- -void dcd_connect(uint8_t rhport) -{ - (void) rhport; - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - // Enable USB clock - PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); - // Enable the USB controller in device mode - USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE; - while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); -#if TUD_OPT_HIGH_SPEED - USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_SPDCONF_Msk; -#else - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_SPDCONF_LOW_POWER; -#endif - // Enable the End Of Reset, Suspend & Wakeup interrupts - USBHS->USBHS_DEVIER = (USBHS_DEVIER_EORSTES | USBHS_DEVIER_SUSPES | USBHS_DEVIER_WAKEUPES); -#if USE_SOF - USBHS->USBHS_DEVIER = USBHS_DEVIER_SOFES; -#endif - // Clear the End Of Reset, SOF & Wakeup interrupts - USBHS->USBHS_DEVICR = (USBHS_DEVICR_EORSTC | USBHS_DEVICR_SOFC | USBHS_DEVICR_WAKEUPC); - // Manually set the Suspend Interrupt - USBHS->USBHS_DEVIFR |= USBHS_DEVIFR_SUSPS; - // Ack the Wakeup Interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - // Attach the device - USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; - // Freeze USB clock - USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; - __set_PRIMASK(irq_state); -} - -// Disconnect by disabling internal pull-up resistor on D+/D- -void dcd_disconnect(uint8_t rhport) -{ - (void) rhport; - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - // Disable all endpoints - USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); - // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Clear all the pending interrupts - USBHS->USBHS_DEVICR = USBHS_DEVICR_Msk; - // Disable all interrupts - USBHS->USBHS_DEVIDR = USBHS_DEVCTRL_UADD_Msk; - // Detach the device - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH; - // Disable the device address - USBHS->USBHS_DEVCTRL &=~(USBHS_DEVCTRL_ADDEN | USBHS_DEVCTRL_UADD_Msk); - __set_PRIMASK(irq_state); -} - -static tusb_speed_t get_speed(void) -{ - switch ((USBHS->USBHS_SR & USBHS_SR_SPEED_Msk) >> USBHS_SR_SPEED_Pos) { - case USBHS_SR_SPEED_FULL_SPEED_Val: - default: - return TUSB_SPEED_FULL; - case USBHS_SR_SPEED_HIGH_SPEED_Val: - return TUSB_SPEED_HIGH; - case USBHS_SR_SPEED_LOW_SPEED_Val: - return TUSB_SPEED_LOW; - } -} - -static void dcd_ep_handler(uint8_t ep_ix) -{ - uint32_t int_status = USBHS->USBHS_DEVEPTISR[ep_ix]; - int_status &= USBHS->USBHS_DEVEPTIMR[ep_ix]; - uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & - USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; - if (ep_ix == 0U) - { - if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) - { - // Setup packet should always be 8 bytes. If not, ignore it, and try again. - if (count == 8) - { - uint8_t *ptr = EP_GET_FIFO_PTR(0,8); - dcd_event_setup_received(0, ptr, true); - } - // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_CTRL_RXSTPIC; - } - if (int_status & USBHS_DEVEPTISR_RXOUTI) - { - xfer_ctl_t *xfer = &xfer_status[0]; - if (count) - { - uint8_t *ptr = EP_GET_FIFO_PTR(0,8); - if (xfer->buffer) - { - memcpy(xfer->buffer + xfer->queued_len, ptr, count); - } else { - tu_fifo_write_n(xfer->fifo, ptr, count); - } - xfer->queued_len = (uint16_t)(xfer->queued_len + count); - } - // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { - // RX COMPLETE - dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); - // Disable the interrupt - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; - // Though the host could still send, we don't know. - } - } - if (int_status & USBHS_DEVEPTISR_TXINI) - { - // Disable the interrupt - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; - xfer_ctl_t * xfer = &xfer_status[EP_MAX]; - if ((xfer->total_len != xfer->queued_len)) - { - // TX not complete - dcd_transmit_packet(xfer, 0); - } else { - // TX complete - dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - } - } else { - if (int_status & USBHS_DEVEPTISR_RXOUTI) - { - xfer_ctl_t *xfer = &xfer_status[ep_ix]; - if (count) - { - uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); - if (xfer->buffer) - { - memcpy(xfer->buffer + xfer->queued_len, ptr, count); - } else { - tu_fifo_write_n(xfer->fifo, ptr, count); - } - xfer->queued_len = (uint16_t)(xfer->queued_len + count); - } - // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; - // Clear the FIFO control flag to receive more data. - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { - // RX COMPLETE - dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); - // Disable the interrupt - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_RXOUTEC; - // Though the host could still send, we don't know. - } - } - if (int_status & USBHS_DEVEPTISR_TXINI) - { - // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; - xfer_ctl_t * xfer = &xfer_status[ep_ix];; - if ((xfer->total_len != xfer->queued_len)) - { - // TX not complete - dcd_transmit_packet(xfer, ep_ix); - } else { - // TX complete - dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; - } - } - } -} - -static void dcd_dma_handler(uint8_t ep_ix) -{ - uint32_t status = USBHS->UsbhsDevdma[ep_ix - 1].USBHS_DEVDMASTATUS; - if (status & USBHS_DEVDMASTATUS_CHANN_ENB) - { - return; // Ignore EOT_STA interrupt - } - // Disable DMA interrupt - USBHS->USBHS_DEVIDR = USBHS_DEVIDR_DMA_1 << (ep_ix - 1); - - xfer_ctl_t *xfer = &xfer_status[ep_ix]; - uint16_t count = xfer->total_len - ((status & USBHS_DEVDMASTATUS_BUFF_COUNT_Msk) >> USBHS_DEVDMASTATUS_BUFF_COUNT_Pos); - if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) - { - dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); - } else { - dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); - } -} - -void dcd_int_handler(uint8_t rhport) -{ - (void) rhport; - uint32_t int_status = USBHS->USBHS_DEVISR; - // End of reset interrupt - if (int_status & USBHS_DEVISR_EORST) - { - // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - // Reset all endpoints - for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) - { - USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix); - USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix)); - } - dcd_edpt_open (0, &ep0_desc); - USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC; - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; - USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; - - dcd_event_bus_reset(rhport, get_speed(), true); - } - // End of Wakeup interrupt - if (int_status & USBHS_DEVISR_WAKEUP) - { - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; - USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; - - dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); - } - // Suspend interrupt - if (int_status & USBHS_DEVISR_SUSP) - { - // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; - USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; - USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; - USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; - - dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); - } -#if USE_SOF - if(int_status & USBHS_DEVISR_SOF) - { - USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; - - dcd_event_bus_signal(0, DCD_EVENT_SOF, true); - } -#endif - // Endpoints interrupt - for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) - { - if (int_status & (USBHS_DEVISR_PEP_0 << ep_ix)) - { - dcd_ep_handler(ep_ix); - } - } - // Endpoints DMA interrupt - for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) - { - if (EP_DMA_SUPPORT(ep_ix)) - { - if (int_status & (USBHS_DEVISR_DMA_1 << (ep_ix - 1))) - { - dcd_dma_handler(ep_ix); - } - } - } -} - -//--------------------------------------------------------------------+ -// Endpoint API -//--------------------------------------------------------------------+ -// Invoked when a control transfer's status stage is complete. -// May help DCD to prepare for next control transfer, this API is optional. -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - - if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && - request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && - request->bRequest == TUSB_REQ_SET_ADDRESS ) - { - uint8_t const dev_addr = (uint8_t) request->wValue; - - USBHS->USBHS_DEVCTRL |= dev_addr | USBHS_DEVCTRL_ADDEN; - } -} - -// Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_desc->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); - uint16_t const epMaxPktSize = ep_desc->wMaxPacketSize.size; - tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; - uint8_t fifoSize = 0; // FIFO size - uint16_t defaultEndpointSize = 8; // Default size of Endpoint - // Find upper 2 power number of epMaxPktSize - if (epMaxPktSize) - { - while (defaultEndpointSize < epMaxPktSize) - { - fifoSize++; - defaultEndpointSize <<= 1; - } - } - xfer_status[epnum].max_packet_size = epMaxPktSize; - - USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + epnum); - USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + epnum)); - - if (epnum == 0) - { - xfer_status[EP_MAX].max_packet_size = epMaxPktSize; - // Enable the control endpoint - Endpoint 0 - USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; - // Configure the Endpoint 0 configuration register - USBHS->USBHS_DEVEPTCFG[0] = - ( - USBHS_DEVEPTCFG_EPSIZE(fifoSize) | - USBHS_DEVEPTCFG_EPTYPE(TUSB_XFER_CONTROL) | - USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | - USBHS_DEVEPTCFG_ALLOC - ); - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_CTRL_STALLRQC; - if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) - { - // Endpoint configuration is successful - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; - // Enable Endpoint 0 Interrupts - USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; - return true; - } else { - // Endpoint configuration is not successful - return false; - } - } else { - // Enable the endpoint - USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); - // Set up the maxpacket size, fifo start address fifosize - // and enable the interrupt. CLear the data toggle. - // AUTOSW is needed for DMA ack ! - USBHS->USBHS_DEVEPTCFG[epnum] = - ( - USBHS_DEVEPTCFG_EPSIZE(fifoSize) | - USBHS_DEVEPTCFG_EPTYPE(eptype) | - USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | - USBHS_DEVEPTCFG_AUTOSW | - ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) - ); - if (eptype == TUSB_XFER_ISOCHRONOUS) - { - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); - } -#if USE_DUAL_BANK - if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK) - { - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_EPBK_2_BANK; - } -#endif - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_CTRL_STALLRQC; - if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) - { - USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); - return true; - } else { - // Endpoint configuration is not successful - return false; - } - } -} - -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) -{ - uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - if (len > xfer->max_packet_size) - { - len = xfer->max_packet_size; - } - uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); - if(xfer->buffer) - { - memcpy(ptr, xfer->buffer + xfer->queued_len, len); - } - else { - tu_fifo_read_n(xfer->fifo, ptr, len); - } - xfer->queued_len = (uint16_t)(xfer->queued_len + len); - if (ep_ix == 0U) - { - // Control endpoint: clear the interrupt flag to send the data - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - - } else { - // Other endpoint types: clear the FIFO control flag to send the data - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; - } - USBHS->USBHS_DEVEPTIER[ep_ix] = USBHS_DEVEPTIER_TXINES; -} - -// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t * xfer = &xfer_status[epnum]; - if(ep_addr == 0x80) - xfer = &xfer_status[EP_MAX]; - - xfer->buffer = buffer; - xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->fifo = NULL; - - if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) - { - uint32_t udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); - if (dir == TUSB_DIR_OUT) - { - udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; - } else { - udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_B_EN; - } - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)buffer; - udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_BUFFIT | USBHS_DEVDMACONTROL_CHANN_ENB; - // Disable IRQs to have a short sequence - // between read of EOT_STA and DMA enable - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) - { - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl; - USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); - __set_PRIMASK(irq_state); - return true; - } - __set_PRIMASK(irq_state); - - // Here a ZLP has been recieved - // and the DMA transfer must be not started. - // It is the end of transfer - return false; - } else { - if (dir == TUSB_DIR_OUT) - { - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } else { - dcd_transmit_packet(xfer,epnum); - } - } - return true; -} - -// The number of bytes has to be given explicitly to allow more flexible control of how many -// bytes should be written and second to keep the return value free to give back a boolean -// success message. If total_bytes is too big, the FIFO will copy only what is available -// into the USB buffer! -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t * xfer = &xfer_status[epnum]; - if(epnum == 0x80) - xfer = &xfer_status[EP_MAX]; - - xfer->buffer = NULL; - xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->fifo = ff; - - if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) - { - tu_fifo_buffer_info_t info; - uint32_t udd_dma_ctrl_lin = USBHS_DEVDMACONTROL_CHANN_ENB; - uint32_t udd_dma_ctrl_wrap = USBHS_DEVDMACONTROL_CHANN_ENB | USBHS_DEVDMACONTROL_END_BUFFIT; - if (dir == TUSB_DIR_OUT) - { - tu_fifo_get_write_info(ff, &info); - udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; - udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; - } else { - tu_fifo_get_read_info(ff, &info); - if(info.len_wrap == 0) - { - udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_B_EN; - } - udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_B_EN; - } - - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)info.ptr_lin; - if (info.len_wrap) - { - dma_desc[epnum - 1].next_desc = 0; - dma_desc[epnum - 1].buff_addr = (uint32_t)info.ptr_wrap; - dma_desc[epnum - 1].chnl_ctrl = - udd_dma_ctrl_wrap | USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_wrap); - udd_dma_ctrl_lin |= USBHS_DEVDMASTATUS_DESC_LDST; - __DSB(); - __ISB(); - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMANXTDSC = (uint32_t)&dma_desc[epnum - 1]; - } else { - udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_BUFFIT; - } - udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_lin); - // Disable IRQs to have a short sequence - // between read of EOT_STA and DMA enable - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) - { - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl_lin; - USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); - __set_PRIMASK(irq_state); - return true; - } - __set_PRIMASK(irq_state); - - // Here a ZLP has been recieved - // and the DMA transfer must be not started. - // It is the end of transfer - return false; - } else { - if (dir == TUSB_DIR_OUT) - { - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } else { - dcd_transmit_packet(xfer,epnum); - } - } - return true; -} - -// Stall endpoint -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_CTRL_STALLRQS; -} - -// clear stall, data toggle is also reset to DATA0 -void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_CTRL_STALLRQC; - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_HSTPIPIER_RSTDTS; -} - -#endif diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c new file mode 100644 index 000000000..a864fda5b --- /dev/null +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -0,0 +1,710 @@ +/* +* The MIT License (MIT) +* +* Copyright (c) 2018, hathach (tinyusb.org) +* Copyright (c) 2021, HiFiPhile +* +* 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. +* +* This file is part of the TinyUSB stack. +*/ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAMX7X + +#include "device/dcd.h" + +#include "sam.h" +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#ifndef USE_SOF +# define USE_SOF 0 +#endif + +// Dual bank can imporve performance, but need 2 times bigger packet buffer +// As SAM7x has only 4KB packet buffer, use with caution ! +// Enable in FS mode as packets are smaller +#ifndef USE_DUAL_BANK +# if TUD_OPT_HIGH_SPEED +# define USE_DUAL_BANK 0 +# else +# define USE_DUAL_BANK 1 +# endif +#endif + +#define EP_MAX 10 + +#define USBHS_RAM_ADDR 0xA0100000u + +#define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) + +// Errata: The DMA feature is not available for Pipe/Endpoint 7 +#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) + +// DMA Channel Transfer Descriptor +typedef struct { + volatile uint32_t next_desc; + volatile uint32_t buff_addr; + volatile uint32_t chnl_ctrl; + uint32_t padding; +} dma_desc_t; + +// Transfer control context +typedef struct { + uint8_t * buffer; + uint16_t total_len; + uint16_t queued_len; + uint16_t max_packet_size; + uint8_t interval; + tu_fifo_t * fifo; +} xfer_ctl_t; + +static tusb_speed_t get_speed(void); +static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); + +// DMA descriptors shouldn't be placed in ITCM +#if defined(USB_DMA_DESC_SECTION) +TU_ATTR_SECTION(TU_XSTRING(USB_DMA_DESC_SECTION)) +#endif +dma_desc_t dma_desc[6]; + +xfer_ctl_t xfer_status[EP_MAX+1]; + +static const tusb_desc_endpoint_t ep0_desc = +{ + .bEndpointAddress = 0x00, + .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, +}; + +//------------------------------------------------------------------ +// Device API +//------------------------------------------------------------------ + +// Initialize controller to device mode +void dcd_init (uint8_t rhport) +{ + // Enable USBPLL + PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); + // Wait until USB UTMI stabilize + while (!(PMC->PMC_SR & PMC_SR_LOCKU)); +#if !TUD_OPT_HIGH_SPEED + // Enable USB FS clk + PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2; + PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); + PMC->PMC_SCER = PMC_SCER_USBCLK; +#endif + dcd_connect(rhport); +} + +// Enable device interrupt +void dcd_int_enable (uint8_t rhport) +{ + (void) rhport; + NVIC_EnableIRQ((IRQn_Type) ID_USBHS); +} + +// Disable device interrupt +void dcd_int_disable (uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ((IRQn_Type) ID_USBHS); +} + +// Receive Set Address request, mcu port must also include status IN response +void dcd_set_address (uint8_t rhport, uint8_t dev_addr) +{ + (void) dev_addr; + // DCD can only set address after status for this request is complete + // do it at dcd_edpt0_status_complete() + + // Response with zlp status + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} + +// Wake up host +void dcd_remote_wakeup (uint8_t rhport) +{ + (void) rhport; + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_RMWKUP; +} + +// Connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + // Enable USB clock + PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); + // Enable the USB controller in device mode + USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE; + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); +#if TUD_OPT_HIGH_SPEED + USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_SPDCONF_Msk; +#else + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_SPDCONF_LOW_POWER; +#endif + // Enable the End Of Reset, Suspend & Wakeup interrupts + USBHS->USBHS_DEVIER = (USBHS_DEVIER_EORSTES | USBHS_DEVIER_SUSPES | USBHS_DEVIER_WAKEUPES); +#if USE_SOF + USBHS->USBHS_DEVIER = USBHS_DEVIER_SOFES; +#endif + // Clear the End Of Reset, SOF & Wakeup interrupts + USBHS->USBHS_DEVICR = (USBHS_DEVICR_EORSTC | USBHS_DEVICR_SOFC | USBHS_DEVICR_WAKEUPC); + // Manually set the Suspend Interrupt + USBHS->USBHS_DEVIFR |= USBHS_DEVIFR_SUSPS; + // Ack the Wakeup Interrupt + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + // Attach the device + USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; + // Freeze USB clock + USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; + __set_PRIMASK(irq_state); +} + +// Disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + // Disable all endpoints + USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Clear all the pending interrupts + USBHS->USBHS_DEVICR = USBHS_DEVICR_Msk; + // Disable all interrupts + USBHS->USBHS_DEVIDR = USBHS_DEVCTRL_UADD_Msk; + // Detach the device + USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH; + // Disable the device address + USBHS->USBHS_DEVCTRL &=~(USBHS_DEVCTRL_ADDEN | USBHS_DEVCTRL_UADD_Msk); + __set_PRIMASK(irq_state); +} + +static tusb_speed_t get_speed(void) +{ + switch ((USBHS->USBHS_SR & USBHS_SR_SPEED_Msk) >> USBHS_SR_SPEED_Pos) { + case USBHS_SR_SPEED_FULL_SPEED_Val: + default: + return TUSB_SPEED_FULL; + case USBHS_SR_SPEED_HIGH_SPEED_Val: + return TUSB_SPEED_HIGH; + case USBHS_SR_SPEED_LOW_SPEED_Val: + return TUSB_SPEED_LOW; + } +} + +static void dcd_ep_handler(uint8_t ep_ix) +{ + uint32_t int_status = USBHS->USBHS_DEVEPTISR[ep_ix]; + int_status &= USBHS->USBHS_DEVEPTIMR[ep_ix]; + uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & + USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; + if (ep_ix == 0U) + { + if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) + { + // Setup packet should always be 8 bytes. If not, ignore it, and try again. + if (count == 8) + { + uint8_t *ptr = EP_GET_FIFO_PTR(0,8); + dcd_event_setup_received(0, ptr, true); + } + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_CTRL_RXSTPIC; + } + if (int_status & USBHS_DEVEPTISR_RXOUTI) + { + xfer_ctl_t *xfer = &xfer_status[0]; + if (count) + { + uint8_t *ptr = EP_GET_FIFO_PTR(0,8); + if (xfer->buffer) + { + memcpy(xfer->buffer + xfer->queued_len, ptr, count); + } else { + tu_fifo_write_n(xfer->fifo, ptr, count); + } + xfer->queued_len = (uint16_t)(xfer->queued_len + count); + } + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) + { + // RX COMPLETE + dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; + // Though the host could still send, we don't know. + } + } + if (int_status & USBHS_DEVEPTISR_TXINI) + { + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; + xfer_ctl_t * xfer = &xfer_status[EP_MAX]; + if ((xfer->total_len != xfer->queued_len)) + { + // TX not complete + dcd_transmit_packet(xfer, 0); + } else { + // TX complete + dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + } else { + if (int_status & USBHS_DEVEPTISR_RXOUTI) + { + xfer_ctl_t *xfer = &xfer_status[ep_ix]; + if (count) + { + uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); + if (xfer->buffer) + { + memcpy(xfer->buffer + xfer->queued_len, ptr, count); + } else { + tu_fifo_write_n(xfer->fifo, ptr, count); + } + xfer->queued_len = (uint16_t)(xfer->queued_len + count); + } + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; + // Clear the FIFO control flag to receive more data. + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) + { + // RX COMPLETE + dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_RXOUTEC; + // Though the host could still send, we don't know. + } + } + if (int_status & USBHS_DEVEPTISR_TXINI) + { + // Acknowledge the interrupt + USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; + xfer_ctl_t * xfer = &xfer_status[ep_ix];; + if ((xfer->total_len != xfer->queued_len)) + { + // TX not complete + dcd_transmit_packet(xfer, ep_ix); + } else { + // TX complete + dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; + } + } + } +} + +static void dcd_dma_handler(uint8_t ep_ix) +{ + uint32_t status = USBHS->UsbhsDevdma[ep_ix - 1].USBHS_DEVDMASTATUS; + if (status & USBHS_DEVDMASTATUS_CHANN_ENB) + { + return; // Ignore EOT_STA interrupt + } + // Disable DMA interrupt + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_DMA_1 << (ep_ix - 1); + + xfer_ctl_t *xfer = &xfer_status[ep_ix]; + uint16_t count = xfer->total_len - ((status & USBHS_DEVDMASTATUS_BUFF_COUNT_Msk) >> USBHS_DEVDMASTATUS_BUFF_COUNT_Pos); + if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) + { + dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); + } else { + dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); + } +} + +void dcd_int_handler(uint8_t rhport) +{ + (void) rhport; + uint32_t int_status = USBHS->USBHS_DEVISR; + // End of reset interrupt + if (int_status & USBHS_DEVISR_EORST) + { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + // Reset all endpoints + for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) + { + USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix); + USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix)); + } + dcd_edpt_open (0, &ep0_desc); + USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC; + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; + USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; + + dcd_event_bus_reset(rhport, get_speed(), true); + } + // End of Wakeup interrupt + if (int_status & USBHS_DEVISR_WAKEUP) + { + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; + USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; + + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + // Suspend interrupt + if (int_status & USBHS_DEVISR_SUSP) + { + // Unfreeze USB clock + USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; + while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; + USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; + USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; + USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; + + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + } +#if USE_SOF + if(int_status & USBHS_DEVISR_SOF) + { + USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; + + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); + } +#endif + // Endpoints interrupt + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) + { + if (int_status & (USBHS_DEVISR_PEP_0 << ep_ix)) + { + dcd_ep_handler(ep_ix); + } + } + // Endpoints DMA interrupt + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) + { + if (EP_DMA_SUPPORT(ep_ix)) + { + if (int_status & (USBHS_DEVISR_DMA_1 << (ep_ix - 1))) + { + dcd_dma_handler(ep_ix); + } + } + } +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void) rhport; + + if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && + request->bRequest == TUSB_REQ_SET_ADDRESS ) + { + uint8_t const dev_addr = (uint8_t) request->wValue; + + USBHS->USBHS_DEVCTRL |= dev_addr | USBHS_DEVCTRL_ADDEN; + } +} + +// Configure endpoint's registers according to descriptor +bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_desc->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); + uint16_t const epMaxPktSize = ep_desc->wMaxPacketSize.size; + tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; + uint8_t fifoSize = 0; // FIFO size + uint16_t defaultEndpointSize = 8; // Default size of Endpoint + // Find upper 2 power number of epMaxPktSize + if (epMaxPktSize) + { + while (defaultEndpointSize < epMaxPktSize) + { + fifoSize++; + defaultEndpointSize <<= 1; + } + } + xfer_status[epnum].max_packet_size = epMaxPktSize; + + USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + epnum); + USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + epnum)); + + if (epnum == 0) + { + xfer_status[EP_MAX].max_packet_size = epMaxPktSize; + // Enable the control endpoint - Endpoint 0 + USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; + // Configure the Endpoint 0 configuration register + USBHS->USBHS_DEVEPTCFG[0] = + ( + USBHS_DEVEPTCFG_EPSIZE(fifoSize) | + USBHS_DEVEPTCFG_EPTYPE(TUSB_XFER_CONTROL) | + USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | + USBHS_DEVEPTCFG_ALLOC + ); + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_CTRL_STALLRQC; + if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) + { + // Endpoint configuration is successful + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; + // Enable Endpoint 0 Interrupts + USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; + return true; + } else { + // Endpoint configuration is not successful + return false; + } + } else { + // Enable the endpoint + USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); + // Set up the maxpacket size, fifo start address fifosize + // and enable the interrupt. CLear the data toggle. + // AUTOSW is needed for DMA ack ! + USBHS->USBHS_DEVEPTCFG[epnum] = + ( + USBHS_DEVEPTCFG_EPSIZE(fifoSize) | + USBHS_DEVEPTCFG_EPTYPE(eptype) | + USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | + USBHS_DEVEPTCFG_AUTOSW | + ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) + ); + if (eptype == TUSB_XFER_ISOCHRONOUS) + { + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); + } +#if USE_DUAL_BANK + if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK) + { + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_EPBK_2_BANK; + } +#endif + USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_CTRL_STALLRQC; + if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) + { + USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); + return true; + } else { + // Endpoint configuration is not successful + return false; + } + } +} + +static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) +{ + uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); + if (len > xfer->max_packet_size) + { + len = xfer->max_packet_size; + } + uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); + if(xfer->buffer) + { + memcpy(ptr, xfer->buffer + xfer->queued_len, len); + } + else { + tu_fifo_read_n(xfer->fifo, ptr, len); + } + xfer->queued_len = (uint16_t)(xfer->queued_len + len); + if (ep_ix == 0U) + { + // Control endpoint: clear the interrupt flag to send the data + USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; + + } else { + // Other endpoint types: clear the FIFO control flag to send the data + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + } + USBHS->USBHS_DEVEPTIER[ep_ix] = USBHS_DEVEPTIER_TXINES; +} + +// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = &xfer_status[epnum]; + if(ep_addr == 0x80) + xfer = &xfer_status[EP_MAX]; + + xfer->buffer = buffer; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->fifo = NULL; + + if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) + { + uint32_t udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); + if (dir == TUSB_DIR_OUT) + { + udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; + } else { + udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_B_EN; + } + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)buffer; + udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_BUFFIT | USBHS_DEVDMACONTROL_CHANN_ENB; + // Disable IRQs to have a short sequence + // between read of EOT_STA and DMA enable + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) + { + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl; + USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); + __set_PRIMASK(irq_state); + return true; + } + __set_PRIMASK(irq_state); + + // Here a ZLP has been recieved + // and the DMA transfer must be not started. + // It is the end of transfer + return false; + } else { + if (dir == TUSB_DIR_OUT) + { + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } else { + dcd_transmit_packet(xfer,epnum); + } + } + return true; +} + +// The number of bytes has to be given explicitly to allow more flexible control of how many +// bytes should be written and second to keep the return value free to give back a boolean +// success message. If total_bytes is too big, the FIFO will copy only what is available +// into the USB buffer! +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = &xfer_status[epnum]; + if(epnum == 0x80) + xfer = &xfer_status[EP_MAX]; + + xfer->buffer = NULL; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->fifo = ff; + + if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) + { + tu_fifo_buffer_info_t info; + uint32_t udd_dma_ctrl_lin = USBHS_DEVDMACONTROL_CHANN_ENB; + uint32_t udd_dma_ctrl_wrap = USBHS_DEVDMACONTROL_CHANN_ENB | USBHS_DEVDMACONTROL_END_BUFFIT; + if (dir == TUSB_DIR_OUT) + { + tu_fifo_get_write_info(ff, &info); + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; + udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; + } else { + tu_fifo_get_read_info(ff, &info); + if(info.len_wrap == 0) + { + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_B_EN; + } + udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_B_EN; + } + + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)info.ptr_lin; + if (info.len_wrap) + { + dma_desc[epnum - 1].next_desc = 0; + dma_desc[epnum - 1].buff_addr = (uint32_t)info.ptr_wrap; + dma_desc[epnum - 1].chnl_ctrl = + udd_dma_ctrl_wrap | USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_wrap); + udd_dma_ctrl_lin |= USBHS_DEVDMASTATUS_DESC_LDST; + __DSB(); + __ISB(); + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMANXTDSC = (uint32_t)&dma_desc[epnum - 1]; + } else { + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_BUFFIT; + } + udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_lin); + // Disable IRQs to have a short sequence + // between read of EOT_STA and DMA enable + uint32_t irq_state = __get_PRIMASK(); + __disable_irq(); + if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) + { + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl_lin; + USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); + __set_PRIMASK(irq_state); + return true; + } + __set_PRIMASK(irq_state); + + // Here a ZLP has been recieved + // and the DMA transfer must be not started. + // It is the end of transfer + return false; + } else { + if (dir == TUSB_DIR_OUT) + { + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } else { + dcd_transmit_packet(xfer,epnum); + } + } + return true; +} + +// Stall endpoint +void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_CTRL_STALLRQS; +} + +// clear stall, data toggle is also reset to DATA0 +void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + uint8_t const epnum = tu_edpt_number(ep_addr); + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_CTRL_STALLRQC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_HSTPIPIER_RSTDTS; +} + +#endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 2e1678ccf..3f5710362 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -61,7 +61,7 @@ #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 #define OPT_MCU_SAML22 205 ///< MicroChip SAML22 -#define OPT_MCU_SAM7X 206 ///< MicroChip SAME70, S70, V70, V71 family +#define OPT_MCU_SAMX7X 206 ///< MicroChip SAME70, S70, V70, V71 family // STM32 -- cgit v1.3.1 From 289ccf3c938c8f2be0edf2a2c8a18c68e39880c0 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 13 Jun 2021 13:18:32 +0700 Subject: remove dev_ep_map --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 49 ++++++++-------------------- 1 file changed, 13 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index ab8639861..42d0839f6 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -59,44 +59,24 @@ static struct hw_endpoint ep_pool[1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS]; #define usb_hw_set hw_set_alias(usb_hw) #define usb_hw_clear hw_clear_alias(usb_hw) -// todo still a bit wasteful -// top bit set if valid -uint8_t dev_ep_map[CFG_TUSB_HOST_DEVICE_MAX][1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS][2]; - // Flags we set by default in sie_ctrl (we add other bits on top) enum { - sie_ctrl_base = USB_SIE_CTRL_SOF_EN_BITS | - USB_SIE_CTRL_KEEP_ALIVE_EN_BITS | - USB_SIE_CTRL_PULLDOWN_EN_BITS | - USB_SIE_CTRL_EP0_INT_1BUF_BITS + SIE_CTRL_BASE = USB_SIE_CTRL_SOF_EN_BITS | USB_SIE_CTRL_KEEP_ALIVE_EN_BITS | + USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS }; static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr) { - uint8_t num = tu_edpt_number(ep_addr); - if (num == 0) { - return &epx; - } - uint8_t in = (ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0; - uint mapping = dev_ep_map[dev_addr-1][num][in]; - pico_trace("Get dev addr %d ep %d = %d\n", dev_addr, ep_addr, mapping); - return mapping >= 128 ? ep_pool + (mapping & 0x7fu) : NULL; -} - -static void set_dev_ep(uint8_t dev_addr, uint8_t ep_addr, struct hw_endpoint *ep) -{ - uint8_t num = tu_edpt_number(ep_addr); - uint8_t in = (uint8_t) tu_edpt_dir(ep_addr); - - uint32_t index = ep - ep_pool; - hard_assert(index < TU_ARRAY_SIZE(ep_pool)); + uint8_t num = tu_edpt_number(ep_addr); + if ( num == 0 ) return &epx; - // todo revisit why dev_addr can be 0 here - if (dev_addr) { - dev_ep_map[dev_addr-1][num][in] = 128u | index; - } + for ( uint32_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++ ) + { + struct hw_endpoint *ep = &ep_pool[i]; + if ( ep->configured && (ep->dev_addr == dev_addr) && (ep->ep_addr == ep_addr) ) return ep; + } - pico_trace("Set dev addr %d ep %d = %d\n", dev_addr, ep_addr, index); + return NULL; } static inline uint8_t dev_speed(void) @@ -387,7 +367,7 @@ bool hcd_init(uint8_t rhport) // Enable in host mode with SOF / Keep alive on usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS | USB_MAIN_CTRL_HOST_NDEVICE_BITS; - usb_hw->sie_ctrl = sie_ctrl_base; + usb_hw->sie_ctrl = SIE_CTRL_BASE; usb_hw->inte = USB_INTE_BUFF_STATUS_BITS | USB_INTE_HOST_CONN_DIS_BITS | USB_INTE_HOST_RESUME_BITS | @@ -477,9 +457,6 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const ep_desc->bmAttributes.xfer, ep_desc->bInterval); - // Map this struct to ep@device address - set_dev_ep(dev_addr, ep_desc->bEndpointAddress, ep); - return true; } @@ -512,7 +489,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * // for host we have to initiate the transfer usb_hw->dev_addr_ctrl = dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB); - uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | sie_ctrl_base | + uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | SIE_CTRL_BASE | (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS); // Set pre if we are a low speed device on full speed hub flags |= need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0; @@ -548,7 +525,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet usb_hw->dev_addr_ctrl = dev_addr; // Set pre if we are a low speed device on full speed hub - uint32_t const flags = sie_ctrl_base | USB_SIE_CTRL_SEND_SETUP_BITS | USB_SIE_CTRL_START_TRANS_BITS | + uint32_t const flags = SIE_CTRL_BASE | USB_SIE_CTRL_SEND_SETUP_BITS | USB_SIE_CTRL_START_TRANS_BITS | (need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0); usb_hw->sie_ctrl = flags; -- cgit v1.3.1 From 1af64f9729f743f4fc9d8686af239c65f689630f Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 13 Jun 2021 15:27:20 +0700 Subject: remove sent_setup from hw endpoint --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 34 +++++++++++++++------------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 3 --- src/portable/raspberrypi/rp2040/rp2040_usb.h | 3 ++- 3 files changed, 20 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 42d0839f6..40a0805c6 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -161,19 +161,19 @@ static void hw_handle_buff_status(void) static void hw_trans_complete(void) { - struct hw_endpoint *ep = &epx; - assert(ep->active); + struct hw_endpoint *ep = &epx; + assert(ep->active); - if (ep->sent_setup) - { - pico_trace("Sent setup packet\n"); - hw_xfer_complete(ep, XFER_RESULT_SUCCESS); - } - else - { - // Don't care. Will handle this in buff status - return; - } + if (usb_hw->sie_ctrl & USB_SIE_CTRL_SEND_SETUP_BITS) + { + pico_trace("Sent setup packet\n"); + hw_xfer_complete(ep, XFER_RESULT_SUCCESS); + } + else + { + // Don't care. Will handle this in buff status + return; + } } static void hcd_rp2040_irq(void) @@ -473,10 +473,13 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr); assert(ep); - if (ep_addr != ep->ep_addr) + // Control endpoint can change direction 0x00 <-> 0x80 + if ( ep_addr != ep->ep_addr ) { - // Direction has flipped on endpoint control so re init it but with same properties - _hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, ep->transfer_type, 0); + assert(ep_num == 0); + + // Direction has flipped on endpoint control so re init it but with same properties + _hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, ep->transfer_type, 0); } // If a normal transfer (non-interrupt) then initiate using @@ -519,7 +522,6 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet ep->remaining_len = 8; ep->active = true; - ep->sent_setup = true; // Set device address usb_hw->dev_addr_ctrl = dev_addr; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index cb46ad1b9..7430881e0 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -73,9 +73,6 @@ void hw_endpoint_reset_transfer(struct hw_endpoint *ep) { ep->stalled = false; ep->active = false; -#if TUSB_OPT_HOST_ENABLED - ep->sent_setup = false; -#endif ep->remaining_len = 0; ep->xferred_len = 0; ep->user_buf = 0; diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 4c24b8dbe..4c787f496 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -55,13 +55,14 @@ struct hw_endpoint // Data needed from EP descriptor uint16_t wMaxPacketSize; + // Interrupt, bulk, etc uint8_t transfer_type; #if TUSB_OPT_HOST_ENABLED // Only needed for host uint8_t dev_addr; - bool sent_setup; + // If interrupt endpoint uint8_t interrupt_num; #endif -- cgit v1.3.1 From bd039c8d37d7df05da992eb8afdcb31f782e1f23 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 13 Jun 2021 16:16:25 +0700 Subject: fix build with log for device --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 35 +++++++--------------------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 2 +- 2 files changed, 10 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 3f2bf7810..63e129e53 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -69,6 +69,7 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep) // Assumes single buffered for now ep->hw_data_buf = next_buffer_ptr; next_buffer_ptr += size; + // Bits 0-5 are ignored by the controller so make sure these are 0 if ((uintptr_t)next_buffer_ptr & 0b111111u) { @@ -87,8 +88,8 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep) size, dpram_offset, ep->hw_data_buf, - ep->num, - ep_dir_string[ep->in]); + tu_edpt_number(ep->ep_addr), + ep_dir_string[tu_edpt_dir(ep->ep_addr)]); // Fill in endpoint control register with buffer offset uint32_t reg = EP_CTRL_ENABLE_BITS @@ -103,28 +104,15 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t { const uint8_t num = tu_edpt_number(ep_addr); const tusb_dir_t dir = tu_edpt_dir(ep_addr); + ep->ep_addr = ep_addr; + // For device, IN is a tx transfer and OUT is an rx transfer ep->rx = (dir == TUSB_DIR_OUT); + // Response to a setup packet on EP0 starts with pid of 1 ep->next_pid = num == 0 ? 1u : 0u; - // Add some checks around the max packet size - if (transfer_type == TUSB_XFER_ISOCHRONOUS) - { - if (wMaxPacketSize > USB_MAX_ISO_PACKET_SIZE) - { - panic("Isochronous wMaxPacketSize %d too large", wMaxPacketSize); - } - } - else - { - if (wMaxPacketSize > USB_MAX_PACKET_SIZE) - { - panic("Isochronous wMaxPacketSize %d too large", wMaxPacketSize); - } - } - ep->wMaxPacketSize = wMaxPacketSize; ep->transfer_type = transfer_type; @@ -339,10 +327,7 @@ static void dcd_rp2040_irq(void) #if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX // Only run enumeration walk-around if pull up is enabled - if ( usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS ) - { - rp2040_usb_device_enumeration_fix(); - } + if ( usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS ) rp2040_usb_device_enumeration_fix(); #endif } @@ -402,9 +387,9 @@ void dcd_init (uint8_t rhport) // EP0 always exists so init it now // EP0 OUT - hw_endpoint_init(0x0, 64, 0); + hw_endpoint_init(0x0, 64, TUSB_XFER_CONTROL); // EP0 IN - hw_endpoint_init(0x80, 64, 0); + hw_endpoint_init(0x80, 64, TUSB_XFER_CONTROL); // Initializes the USB peripheral for device mode and enables it. // Don't need to enable the pull up here. Force VBUS @@ -495,7 +480,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { assert(rhport == 0); - // True means start new xfer hw_endpoint_xfer(ep_addr, buffer, total_bytes); return true; } @@ -519,7 +503,6 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) { // usbd.c says: In progress transfers on this EP may be delivered after this call pico_trace("dcd_edpt_close %d %02x\n", rhport, ep_addr); - } void dcd_int_handler(uint8_t rhport) diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 7430881e0..de3a83be9 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -194,7 +194,7 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t to // Fill in info now that we're kicking off the hw ep->remaining_len = total_len; - ep->xferred_len = 0; + ep->xferred_len = 0; ep->active = true; ep->user_buf = buffer; -- cgit v1.3.1 From f38c460433abc0c557f2035c7205b4f36bcbc677 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 13 Jun 2021 17:19:14 +0700 Subject: fix ep tx with double buffered --- src/common/tusb_common.h | 2 +- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 54 ++++++++++++---------------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 11 +++--- 3 files changed, 28 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index fe5bf5f41..8490daad7 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -123,7 +123,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align4k (uint32_t value) { retur TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); } //------------- Mathematics -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_abs(int32_t value) { return (uint32_t)((value < 0) ? (-value) : value); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_div_ceil(uint32_t v, uint32_t d) { return (v + d -1)/d; } /// inclusive range checking TODO remove TU_ATTR_ALWAYS_INLINE static inline bool tu_within(uint32_t lower, uint32_t value, uint32_t upper) diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 63e129e53..4f70d60cc 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -64,40 +64,30 @@ static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr) static void _hw_endpoint_alloc(struct hw_endpoint *ep) { - uint16_t size = tu_min16(64, ep->wMaxPacketSize); + // size must be multiple of 64 + uint16_t size = tu_div_ceil(ep->wMaxPacketSize, 64) * 64u; - // Assumes single buffered for now - ep->hw_data_buf = next_buffer_ptr; - next_buffer_ptr += size; + // double buffered for non-ISO endpoint + if ( ep->transfer_type != TUSB_XFER_ISOCHRONOUS ) size *= 2u; - // Bits 0-5 are ignored by the controller so make sure these are 0 - if ((uintptr_t)next_buffer_ptr & 0b111111u) - { - // Round up to the next 64 - uint32_t fixptr = (uintptr_t)next_buffer_ptr; - fixptr &= ~0b111111u; - fixptr += 64; - pico_info("Rounding non 64 byte boundary buffer up from %x to %x\n", (uintptr_t)next_buffer_ptr, fixptr); - next_buffer_ptr = (uint8_t*)fixptr; - } - assert(((uintptr_t)next_buffer_ptr & 0b111111u) == 0); - uint dpram_offset = hw_data_offset(ep->hw_data_buf); - assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX); - - pico_info("Alloced %d bytes at offset 0x%x (0x%p) for ep %d %s\n", - size, - dpram_offset, - ep->hw_data_buf, - tu_edpt_number(ep->ep_addr), - ep_dir_string[tu_edpt_dir(ep->ep_addr)]); - - // Fill in endpoint control register with buffer offset - uint32_t reg = EP_CTRL_ENABLE_BITS - | EP_CTRL_INTERRUPT_PER_BUFFER - | (ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) - | dpram_offset; - - *ep->endpoint_control = reg; + ep->hw_data_buf = next_buffer_ptr; + next_buffer_ptr += size; + + assert(((uintptr_t )next_buffer_ptr & 0b111111u) == 0); + uint dpram_offset = hw_data_offset(ep->hw_data_buf); + assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX); + + pico_info("Alloced %d bytes at offset 0x%x (0x%p) for ep %d %s\n", + size, + dpram_offset, + ep->hw_data_buf, + tu_edpt_number(ep->ep_addr), + ep_dir_string[tu_edpt_dir(ep->ep_addr)]); + + // Fill in endpoint control register with buffer offset + uint32_t const reg = EP_CTRL_ENABLE_BITS | (ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; + + *ep->endpoint_control = reg; } static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index de3a83be9..f8d36e5eb 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -108,7 +108,8 @@ void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_m *ep->buffer_control = value; } -static uint32_t compute_buffer_control(struct hw_endpoint *ep, uint8_t buf_id) +// prepare buffer, return buffer control +static uint32_t prepare_ep_buffer(struct hw_endpoint *ep, uint8_t buf_id) { uint16_t const buflen = tu_min16(ep->remaining_len, ep->wMaxPacketSize); ep->remaining_len -= buflen; @@ -122,14 +123,13 @@ static uint32_t compute_buffer_control(struct hw_endpoint *ep, uint8_t buf_id) if ( !ep->rx ) { // Copy data from user buffer to hw buffer - memcpy(ep->hw_data_buf, ep->user_buf, buflen); + memcpy(ep->hw_data_buf + buf_id*64, ep->user_buf, buflen); ep->user_buf += buflen; // Mark as full buf_ctrl |= USB_BUF_CTRL_FULL; } -#if TUSB_OPT_HOST_ENABLED // Is this the last buffer? Only really matters for host mode. Will trigger // the trans complete irq but also stop it polling. We only really care about // trans complete for setup packets being sent @@ -137,7 +137,6 @@ static uint32_t compute_buffer_control(struct hw_endpoint *ep, uint8_t buf_id) { buf_ctrl |= USB_BUF_CTRL_LAST; } -#endif if (buf_id) buf_ctrl = buf_ctrl << 16; @@ -150,14 +149,14 @@ static void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) uint32_t ep_ctrl = *ep->endpoint_control; // always compute buffer 0 - uint32_t buf_ctrl = compute_buffer_control(ep, 0); + uint32_t buf_ctrl = prepare_ep_buffer(ep, 0); if(ep->remaining_len) { // Use buffer 1 (double buffered) if there is still data // TODO: Isochronous for buffer1 bit-field is different than CBI (control bulk, interrupt) - buf_ctrl |= compute_buffer_control(ep, 1); + buf_ctrl |= prepare_ep_buffer(ep, 1); // Set endpoint control double buffered bit if needed ep_ctrl &= ~EP_CTRL_INTERRUPT_PER_BUFFER; -- cgit v1.3.1 From 5c567129ea34ea78833cee2bf38e4e09cbdee389 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 13 Jun 2021 18:30:26 +0700 Subject: fix calculating xferred bytes with double buffer with short packet on buffer0 --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 26 ++++++++++++++------------ src/portable/raspberrypi/rp2040/rp2040_usb.c | 20 +++++++++++++------- 2 files changed, 27 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 4f70d60cc..b87951421 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -67,8 +67,11 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep) // size must be multiple of 64 uint16_t size = tu_div_ceil(ep->wMaxPacketSize, 64) * 64u; - // double buffered for non-ISO endpoint - if ( ep->transfer_type != TUSB_XFER_ISOCHRONOUS ) size *= 2u; + // double buffered for Control and Bulk endpoint + if ( ep->transfer_type == TUSB_XFER_CONTROL || ep->transfer_type == TUSB_XFER_BULK) + { + size *= 2u; + } ep->hw_data_buf = next_buffer_ptr; next_buffer_ptr += size; @@ -445,18 +448,17 @@ void dcd_connect(uint8_t rhport) void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) { - pico_trace("dcd_edpt0_status_complete %d\n", rhport); - assert(rhport == 0); + (void) rhport; - if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && - request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && - request->bRequest == TUSB_REQ_SET_ADDRESS) - { - pico_trace("Set HW address %d\n", request->wValue); - usb_hw->dev_addr_ctrl = (uint8_t) request->wValue; - } + if ( request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && + request->bRequest == TUSB_REQ_SET_ADDRESS ) + { + pico_trace("Set HW address %d\n", request->wValue); + usb_hw->dev_addr_ctrl = (uint8_t) request->wValue; + } - reset_ep0(); + reset_ep0(); } bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index f8d36e5eb..5b2a5f5a0 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -170,6 +170,7 @@ static void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) *ep->endpoint_control = ep_ctrl; + TU_LOG(3, "Prepare Buffer Control:\r\n"); print_bufctrl32(buf_ctrl); // Finally, write to buffer_control which will trigger the transfer @@ -201,7 +202,8 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t to _hw_endpoint_lock_update(ep, -1); } -static void sync_ep_buffer(struct hw_endpoint *ep, uint8_t buf_id) +// sync endpoint buffer and return transferred bytes +static uint16_t sync_ep_buffer(struct hw_endpoint *ep, uint8_t buf_id) { uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); if (buf_id) buf_ctrl = buf_ctrl >> 16; @@ -227,14 +229,14 @@ static void sync_ep_buffer(struct hw_endpoint *ep, uint8_t buf_id) } // Short packet - // TODO what if we prepare double buffered but receive short packet on buffer 0 !!! - // would the buffer status or trans complete interrupt is triggered if (xferred_bytes < ep->wMaxPacketSize) { - pico_trace("Short rx transfer\n"); + pico_trace("Short rx transfer on buffer %d with %u bytes\n", buf_id, xferred_bytes); // Reduce total length as this is last packet ep->remaining_len = 0; } + + return xferred_bytes; } static void _hw_endpoint_xfer_sync (struct hw_endpoint *ep) @@ -242,11 +244,15 @@ static void _hw_endpoint_xfer_sync (struct hw_endpoint *ep) // Update hw endpoint struct with info from hardware // after a buff status interrupt + uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep); + TU_LOG(3, "_hw_endpoint_xfer_sync:\r\n"); + print_bufctrl32(buf_ctrl); + // always sync buffer 0 - sync_ep_buffer(ep, 0); + uint16_t buf0_bytes = sync_ep_buffer(ep, 0); - // sync buffer 1 if double buffered - if ( (*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS ) + // sync buffer 1 if double buffered and buffer 0 is not short packet + if ( ((*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS) && (buf0_bytes == ep->wMaxPacketSize) ) { sync_ep_buffer(ep, 1); } -- cgit v1.3.1 From 7bed7d70f06e291bf4ba4f5d6cfcc238b11c563b Mon Sep 17 00:00:00 2001 From: sabas1080 Date: Tue, 15 Jun 2021 00:01:28 -0500 Subject: add support SAML21 --- hw/bsp/board_mcu.h | 2 +- hw/bsp/saml21/boards/atsaml21_xpro/board.h | 50 +++++++ hw/bsp/saml21/boards/atsaml21_xpro/board.mk | 10 ++ .../boards/atsaml21_xpro/saml21j18b_flash.ld | 152 +++++++++++++++++++ hw/bsp/saml21/family.c | 163 +++++++++++++++++++++ hw/bsp/saml21/family.mk | 50 +++++++ src/portable/microchip/samd/dcd_samd.c | 4 +- src/tusb_option.h | 1 + 8 files changed, 429 insertions(+), 3 deletions(-) create mode 100644 hw/bsp/saml21/boards/atsaml21_xpro/board.h create mode 100644 hw/bsp/saml21/boards/atsaml21_xpro/board.mk create mode 100644 hw/bsp/saml21/boards/atsaml21_xpro/saml21j18b_flash.ld create mode 100644 hw/bsp/saml21/family.c create mode 100644 hw/bsp/saml21/family.mk (limited to 'src') diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index 1a659c410..f8e89ad04 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -54,7 +54,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \ - CFG_TUSB_MCU == OPT_MCU_SAML22 + CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21 #include "sam.h" #elif CFG_TUSB_MCU == OPT_MCU_SAMG diff --git a/hw/bsp/saml21/boards/atsaml21_xpro/board.h b/hw/bsp/saml21/boards/atsaml21_xpro/board.h new file mode 100644 index 000000000..a3e03997c --- /dev/null +++ b/hw/bsp/saml21/boards/atsaml21_xpro/board.h @@ -0,0 +1,50 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PIN (32 + 30) // PB30 +#define LED_STATE_ON 0 + +// Button +#define BUTTON_PIN (0 + 15) // PA15 +#define BUTTON_STATE_ACTIVE 0 + +// UART +#define UART_RX_PIN 4 +#define UART_TX_PIN 5 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/saml21/boards/atsaml21_xpro/board.mk b/hw/bsp/saml21/boards/atsaml21_xpro/board.mk new file mode 100644 index 000000000..aa77d4a21 --- /dev/null +++ b/hw/bsp/saml21/boards/atsaml21_xpro/board.mk @@ -0,0 +1,10 @@ +CFLAGS += -D__SAML21J18B__ + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/saml21j18b_flash.ld + +# For flash-jlink target +JLINK_DEVICE = ATSAML21J18 + +# flash using jlink +flash: flash-jlink diff --git a/hw/bsp/saml21/boards/atsaml21_xpro/saml21j18b_flash.ld b/hw/bsp/saml21/boards/atsaml21_xpro/saml21j18b_flash.ld new file mode 100644 index 000000000..42f1de8d4 --- /dev/null +++ b/hw/bsp/saml21/boards/atsaml21_xpro/saml21j18b_flash.ld @@ -0,0 +1,152 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAML21J18B + * + * Copyright (c) 2016 Atmel Corporation, + * a wholly owned subsidiary of Microchip Technology Inc. + * + * \asf_license_start + * + * \page License + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the Licence at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 + lpram (rwx) : ORIGIN = 0x30000000, LENGTH = 0x00002000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x2000; + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + .lpram (NOLOAD): + { + . = ALIGN(8); + _slpram = .; + *(.lpram .lpram.*); + . = ALIGN(8); + _elpram = .; + } > lpram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/hw/bsp/saml21/family.c b/hw/bsp/saml21/family.c new file mode 100644 index 000000000..d2d25ecac --- /dev/null +++ b/hw/bsp/saml21/family.c @@ -0,0 +1,163 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "sam.h" +#include "bsp/board.h" +#include "board.h" + +#include "hal/include/hal_gpio.h" +#include "hal/include/hal_init.h" +#include "hpl/gclk/hpl_gclk_base.h" +#include "hpl_mclk_config.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_Handler(void) +{ + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +/* Referenced GCLKs (out of 0~4), should be initialized firstly */ +#define _GCLK_INIT_1ST 0x00000000 +/* Not referenced GCLKs, initialized last */ +#define _GCLK_INIT_LAST 0x0000001F + +void board_init(void) +{ + // Clock init ( follow hpl_init.c ) + hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, CONF_NVM_WAIT_STATE); + + _set_performance_level(2); + + _osc32kctrl_init_sources(); + _oscctrl_init_sources(); + _mclk_init(); +#if _GCLK_INIT_1ST + _gclk_init_generators_by_fref(_GCLK_INIT_1ST); +#endif + _oscctrl_init_referenced_generators(); + _gclk_init_generators_by_fref(_GCLK_INIT_LAST); + +#if (CONF_PORT_EVCTRL_PORT_0 | CONF_PORT_EVCTRL_PORT_1 | CONF_PORT_EVCTRL_PORT_2 | CONF_PORT_EVCTRL_PORT_3) + hri_port_set_EVCTRL_reg(PORT, 0, CONF_PORTA_EVCTRL); + hri_port_set_EVCTRL_reg(PORT, 1, CONF_PORTB_EVCTRL); +#endif + + // Update SystemCoreClock since it is hard coded with asf4 and not correct + // Init 1ms tick timer (samd SystemCoreClock may not correct) + SystemCoreClock = CONF_CPU_FREQUENCY; + SysTick_Config(CONF_CPU_FREQUENCY / 1000); + + // Led init + gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_level(LED_PIN, !LED_STATE_ON); + + // Button init + gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULL_DOWN : GPIO_PULL_UP); + +#if CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); +#endif + + /* USB Clock init + * The USB module requires a GCLK_USB of 48 MHz ~ 0.25% clock + * for low speed and full speed operation. */ + hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); + hri_mclk_set_AHBMASK_USB_bit(MCLK); + hri_mclk_set_APBBMASK_USB_bit(MCLK); + + // USB Pin Init + gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PIN_PA24, false); + gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF); + gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PIN_PA25, false); + gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF); + + gpio_set_pin_function(PIN_PA24, PINMUX_PA24G_USB_DM); + gpio_set_pin_function(PIN_PA25, PINMUX_PA25G_USB_DP); + + // Output 500hz PWM on PB23 (TCC0 WO[3]) so we can validate the GCLK1 clock speed + hri_mclk_set_APBCMASK_TCC0_bit(MCLK); + TCC0->PER.bit.PER = 48000000 / 1000; + TCC0->CC[3].bit.CC = 48000000 / 2000; + TCC0->CTRLA.bit.ENABLE = true; + + gpio_set_pin_function(PIN_PA19, PINMUX_PA19F_TCC0_WO3); + hri_gclk_write_PCHCTRL_reg(GCLK, TCC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + gpio_set_pin_level(LED_PIN, state); +} + +uint32_t board_button_read(void) +{ + // button is active low + return gpio_get_pin_level(BUTTON_PIN) ? 0 : 1; +} + +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +int board_uart_write(void const * buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; + +void SysTick_Handler (void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif +void _init(void) +{ + +} \ No newline at end of file diff --git a/hw/bsp/saml21/family.mk b/hw/bsp/saml21/family.mk new file mode 100644 index 000000000..a6611d5f4 --- /dev/null +++ b/hw/bsp/saml21/family.mk @@ -0,0 +1,50 @@ +UF2_FAMILY_ID = 0x68ed2b88 +DEPS_SUBMODULES += hw/mcu/microchip + +include $(TOP)/$(BOARD_PATH)/board.mk + +CFLAGS += \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m0plus \ + -nostdlib -nostartfiles \ + -DCONF_OSC32K_CALIB_ENABLE=0 \ + -DCFG_TUSB_MCU=OPT_MCU_SAML21 + +SRC_C += \ + src/portable/microchip/samd/dcd_samd.c \ + hw/mcu/microchip/saml21/gcc/gcc/startup_saml21.c \ + hw/mcu/microchip/saml21/gcc/system_saml21.c \ + hw/mcu/microchip/saml21/hpl/gclk/hpl_gclk.c \ + hw/mcu/microchip/saml21/hpl/mclk/hpl_mclk.c \ + hw/mcu/microchip/saml21/hpl/pm/hpl_pm.c \ + hw/mcu/microchip/saml21/hpl/osc32kctrl/hpl_osc32kctrl.c \ + hw/mcu/microchip/saml21/hpl/oscctrl/hpl_oscctrl.c \ + hw/mcu/microchip/saml21/hal/src/hal_atomic.c + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/hw/mcu/microchip/saml21/ \ + $(TOP)/hw/mcu/microchip/saml21/config \ + $(TOP)/hw/mcu/microchip/saml21/include \ + $(TOP)/hw/mcu/microchip/saml21/hal/include \ + $(TOP)/hw/mcu/microchip/saml21/hal/utils/include \ + $(TOP)/hw/mcu/microchip/saml21/hpl/port \ + $(TOP)/hw/mcu/microchip/saml21/hri \ + $(TOP)/hw/mcu/microchip/saml21/CMSIS/Include + +# For TinyUSB port source +VENDOR = microchip +CHIP_FAMILY = samd + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM0 + +# flash using bossac at least version 1.8 +# can be found in arduino15/packages/arduino/tools/bossac/ +# Add it to your PATH or change BOSSAC variable to match your installation +BOSSAC = bossac + +flash-bossac: $(BUILD)/$(PROJECT).bin + @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) + $(BOSSAC) --port=$(SERIAL) -U -i --offset=0x2000 -e -w $^ -R diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 13e56453d..577bd0e05 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -29,7 +29,7 @@ #if TUSB_OPT_DEVICE_ENABLED && \ (CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \ - CFG_TUSB_MCU == OPT_MCU_SAML22) + CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21) #include "sam.h" #include "device/dcd.h" @@ -125,7 +125,7 @@ void dcd_int_disable(uint8_t rhport) } #elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ - CFG_TUSB_MCU == OPT_MCU_SAML22 + CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21 void dcd_int_enable(uint8_t rhport) { diff --git a/src/tusb_option.h b/src/tusb_option.h index 5cfcc08e2..d5776c029 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -61,6 +61,7 @@ #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 #define OPT_MCU_SAML22 205 ///< MicroChip SAML22 +#define OPT_MCU_SAML21 206 ///< MicroChip SAML21 // STM32 #define OPT_MCU_STM32F0 300 ///< ST STM32F0 -- cgit v1.3.1 From ca8e8041ef05ba06d7d01bf1567106a76a793cab Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 15 Jun 2021 17:53:09 +0200 Subject: Fix resume, always init FS clock. Signed-off-by: MasterPhi --- examples/device/hid_composite/src/tusb_config.h | 4 ++-- src/portable/microchip/samx7x/dcd_samx7x.c | 5 ++--- src/tusb_option.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index 3e608ed37..31dea4ee9 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -48,7 +48,7 @@ // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed #ifndef BOARD_DEVICE_RHPORT_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) + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X) #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED #else #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED @@ -69,7 +69,7 @@ #endif // CFG_TUSB_DEBUG is defined by compiler in DEBUG build -// #define CFG_TUSB_DEBUG 0 +#define CFG_TUSB_DEBUG 0 /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. * Tinyusb use follows macros to declare transferring memory so that they can be put diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index a864fda5b..f486e0eed 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -49,7 +49,7 @@ # if TUD_OPT_HIGH_SPEED # define USE_DUAL_BANK 0 # else -# define USE_DUAL_BANK 1 +# define USE_DUAL_BANK 0 # endif #endif @@ -108,12 +108,10 @@ void dcd_init (uint8_t rhport) PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); // Wait until USB UTMI stabilize while (!(PMC->PMC_SR & PMC_SR_LOCKU)); -#if !TUD_OPT_HIGH_SPEED // Enable USB FS clk PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2; PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); PMC->PMC_SCER = PMC_SCER_USBCLK; -#endif dcd_connect(rhport); } @@ -346,6 +344,7 @@ void dcd_int_handler(uint8_t rhport) { (void) rhport; uint32_t int_status = USBHS->USBHS_DEVISR; + int_status &= USBHS->USBHS_DEVIMR; // End of reset interrupt if (int_status & USBHS_DEVISR_EORST) { diff --git a/src/tusb_option.h b/src/tusb_option.h index 3f5710362..69c5fb0bd 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -61,7 +61,7 @@ #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 #define OPT_MCU_SAML22 205 ///< MicroChip SAML22 -#define OPT_MCU_SAMX7X 206 ///< MicroChip SAME70, S70, V70, V71 family +#define OPT_MCU_SAMX7X 206 ///< MicroChip SAME70, S70, V70, V71 family // STM32 -- cgit v1.3.1 From 54dc694be4430e51d153405afa3b80d949479558 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 15 Jun 2021 19:11:53 +0200 Subject: Use byte copy. --- src/portable/microchip/samx7x/dcd_samx7x.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index f486e0eed..a46fa2cf1 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -243,7 +243,9 @@ static void dcd_ep_handler(uint8_t ep_ix) uint8_t *ptr = EP_GET_FIFO_PTR(0,8); if (xfer->buffer) { - memcpy(xfer->buffer + xfer->queued_len, ptr, count); + //memcpy(xfer->buffer + xfer->queued_len, ptr, count); + for(int i = 0; i < count; i++) + xfer->buffer[i + xfer->queued_len] = ptr[i]; } else { tu_fifo_write_n(xfer->fifo, ptr, count); } @@ -283,7 +285,9 @@ static void dcd_ep_handler(uint8_t ep_ix) uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); if (xfer->buffer) { - memcpy(xfer->buffer + xfer->queued_len, ptr, count); + //memcpy(xfer->buffer + xfer->queued_len, ptr, count); + for(int i = 0; i < count; i++) + xfer->buffer[i + xfer->queued_len] = ptr[i]; } else { tu_fifo_write_n(xfer->fifo, ptr, count); } @@ -535,7 +539,9 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); if(xfer->buffer) { - memcpy(ptr, xfer->buffer + xfer->queued_len, len); + //memcpy(ptr, xfer->buffer + xfer->queued_len, len); + for(int i = 0; i < len; i++) + ptr[i] = xfer->buffer[i + xfer->queued_len]; } else { tu_fifo_read_n(xfer->fifo, ptr, len); @@ -569,6 +575,11 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->queued_len = 0; xfer->fifo = NULL; + TU_LOG3("Xfer: "); + for(int i = 0; i < total_bytes; i++) + TU_LOG3("%02X ", buffer[i]); + TU_LOG3("\r\n"); + if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) { uint32_t udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); -- cgit v1.3.1 From 6cc702e9ece9bbf32ac9ad4283407b4937c671a9 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 15 Jun 2021 21:16:51 +0200 Subject: Prevent buffer overflow. Signed-off-by: MasterPhi --- src/portable/microchip/samx7x/dcd_samx7x.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index a46fa2cf1..848febc66 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -238,8 +238,13 @@ static void dcd_ep_handler(uint8_t ep_ix) if (int_status & USBHS_DEVEPTISR_RXOUTI) { xfer_ctl_t *xfer = &xfer_status[0]; - if (count) + if (count && xfer->total_len) { + uint16_t remain = xfer->total_len - xfer->queued_len; + if (count > remain) + { + count = remain; + } uint8_t *ptr = EP_GET_FIFO_PTR(0,8); if (xfer->buffer) { @@ -256,7 +261,7 @@ static void dcd_ep_handler(uint8_t ep_ix) if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { // RX COMPLETE - dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(0, 0, xfer->total_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; // Though the host could still send, we don't know. @@ -280,8 +285,13 @@ static void dcd_ep_handler(uint8_t ep_ix) if (int_status & USBHS_DEVEPTISR_RXOUTI) { xfer_ctl_t *xfer = &xfer_status[ep_ix]; - if (count) + if (count && xfer->total_len) { + uint16_t remain = xfer->total_len - xfer->queued_len; + if (count > remain) + { + count = remain; + } uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); if (xfer->buffer) { -- cgit v1.3.1 From 67a6560ec9f379418cccc312ee09bb021e464716 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 15 Jun 2021 21:34:42 +0200 Subject: Default use dual bank for FS, use dcd irq switch. --- src/portable/microchip/samx7x/dcd_samx7x.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 848febc66..a9e125b7c 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -49,7 +49,7 @@ # if TUD_OPT_HIGH_SPEED # define USE_DUAL_BANK 0 # else -# define USE_DUAL_BANK 0 +# define USE_DUAL_BANK 1 # endif #endif @@ -151,8 +151,7 @@ void dcd_remote_wakeup (uint8_t rhport) void dcd_connect(uint8_t rhport) { (void) rhport; - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); + dcd_int_disable(rhport); // Enable USB clock PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); // Enable the USB controller in device mode @@ -178,15 +177,13 @@ void dcd_connect(uint8_t rhport) USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; // Freeze USB clock USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; - __set_PRIMASK(irq_state); } // Disconnect by disabling internal pull-up resistor on D+/D- void dcd_disconnect(uint8_t rhport) { (void) rhport; - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); + dcd_int_disable(rhport); // Disable all endpoints USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); // Unfreeze USB clock @@ -200,7 +197,6 @@ void dcd_disconnect(uint8_t rhport) USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH; // Disable the device address USBHS->USBHS_DEVCTRL &=~(USBHS_DEVCTRL_ADDEN | USBHS_DEVCTRL_UADD_Msk); - __set_PRIMASK(irq_state); } static tusb_speed_t get_speed(void) @@ -584,11 +580,6 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer->total_len = total_bytes; xfer->queued_len = 0; xfer->fifo = NULL; - - TU_LOG3("Xfer: "); - for(int i = 0; i < total_bytes; i++) - TU_LOG3("%02X ", buffer[i]); - TU_LOG3("\r\n"); if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) { -- cgit v1.3.1 From 30fff56aa4b3e75dd14b95cf21484e7342088997 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Wed, 16 Jun 2021 00:18:38 +0200 Subject: Revert "Use byte copy.", add barrier after buffer write. Signed-off-by: MasterPhi --- src/portable/microchip/samx7x/dcd_samx7x.c | 38 ++++++++++++++---------------- 1 file changed, 18 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index a9e125b7c..0299d12b9 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -244,9 +244,7 @@ static void dcd_ep_handler(uint8_t ep_ix) uint8_t *ptr = EP_GET_FIFO_PTR(0,8); if (xfer->buffer) { - //memcpy(xfer->buffer + xfer->queued_len, ptr, count); - for(int i = 0; i < count; i++) - xfer->buffer[i + xfer->queued_len] = ptr[i]; + memcpy(xfer->buffer + xfer->queued_len, ptr, count); } else { tu_fifo_write_n(xfer->fifo, ptr, count); } @@ -291,9 +289,7 @@ static void dcd_ep_handler(uint8_t ep_ix) uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); if (xfer->buffer) { - //memcpy(xfer->buffer + xfer->queued_len, ptr, count); - for(int i = 0; i < count; i++) - xfer->buffer[i + xfer->queued_len] = ptr[i]; + memcpy(xfer->buffer + xfer->queued_len, ptr, count); } else { tu_fifo_write_n(xfer->fifo, ptr, count); } @@ -538,26 +534,28 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - if (len > xfer->max_packet_size) + if (len) { - len = xfer->max_packet_size; - } - uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); - if(xfer->buffer) - { - //memcpy(ptr, xfer->buffer + xfer->queued_len, len); - for(int i = 0; i < len; i++) - ptr[i] = xfer->buffer[i + xfer->queued_len]; - } - else { - tu_fifo_read_n(xfer->fifo, ptr, len); + if (len > xfer->max_packet_size) + { + len = xfer->max_packet_size; + } + uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); + if(xfer->buffer) + { + memcpy(ptr, xfer->buffer + xfer->queued_len, len); + } + else { + tu_fifo_read_n(xfer->fifo, ptr, len); + } + __DSB(); + __ISB(); + xfer->queued_len = (uint16_t)(xfer->queued_len + len); } - xfer->queued_len = (uint16_t)(xfer->queued_len + len); if (ep_ix == 0U) { // Control endpoint: clear the interrupt flag to send the data USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - } else { // Other endpoint types: clear the FIFO control flag to send the data USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; -- cgit v1.3.1 From 832d22d7addf9b1e4b88556c544f60bd9fa32dd6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Jun 2021 01:55:35 +0700 Subject: force single buffered for device mode, out endpoint --- src/device/usbd.c | 3 +- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 15 ++++---- src/portable/raspberrypi/rp2040/rp2040_usb.c | 52 +++++++++++++++++++++++----- src/portable/raspberrypi/rp2040/rp2040_usb.h | 4 +-- 4 files changed, 55 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 2935defd0..587d487dc 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1254,14 +1254,13 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ) { - TU_LOG2("OK\r\n"); return true; }else { // DCD error, mark endpoint as ready to allow next transfer _usbd_dev.ep_status[epnum][dir].busy = false; _usbd_dev.ep_status[epnum][dir].claimed = 0; - TU_LOG2("failed\r\n"); + TU_LOG2("FAILED\r\n"); TU_BREAKPOINT(); return false; } diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index b87951421..f78a932f1 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -145,6 +145,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t // Now if it hasn't already been done //alloc a buffer and fill in endpoint control register + // TODO device may change configuration (dynamic), should clear and reallocate if(!(ep->configured)) { _hw_endpoint_alloc(ep); @@ -194,9 +195,6 @@ static void hw_handle_buff_status(void) { if (remaining_buffers & bit) { - uint __unused which = (usb_hw->buf_cpu_should_handle & bit) ? 1 : 0; - // Should be single buffered - assert(which == 0); // clear this in advance usb_hw_clear->buf_status = bit; // IN transfer for even i, OUT transfer for odd i @@ -463,7 +461,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { - pico_info("dcd_edpt_open %d %02x\n", rhport, desc_edpt->bEndpointAddress); + pico_info("dcd_edpt_open %02x\n", desc_edpt->bEndpointAddress); assert(rhport == 0); hw_endpoint_init(desc_edpt->bEndpointAddress, desc_edpt->wMaxPacketSize.size, desc_edpt->bmAttributes.xfer); return true; @@ -478,14 +476,14 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { - pico_trace("dcd_edpt_stall %d %02x\n", rhport, ep_addr); + pico_trace("dcd_edpt_stall %02x\n", ep_addr); assert(rhport == 0); hw_endpoint_stall(ep_addr); } void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { - pico_trace("dcd_edpt_clear_stall %d %02x\n", rhport, ep_addr); + pico_trace("dcd_edpt_clear_stall %02x\n", ep_addr); assert(rhport == 0); hw_endpoint_clear_stall(ep_addr); } @@ -493,8 +491,11 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) { + (void) rhport; + (void) ep_addr; + // usbd.c says: In progress transfers on this EP may be delivered after this call - pico_trace("dcd_edpt_close %d %02x\n", rhport, ep_addr); + pico_trace("dcd_edpt_close %02x\n", ep_addr); } void dcd_int_handler(uint8_t rhport) diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 5b2a5f5a0..dc12e6d82 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -148,10 +148,15 @@ static void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) { uint32_t ep_ctrl = *ep->endpoint_control; - // always compute buffer 0 - uint32_t buf_ctrl = prepare_ep_buffer(ep, 0); + // always compute and start with buffer 0 + uint32_t buf_ctrl = prepare_ep_buffer(ep, 0) | USB_BUF_CTRL_SEL; - if(ep->remaining_len) + // For now: skip double buffered for Device mode, OUT endpoint since + // host could send < 64 bytes and cause short packet on buffer0 + // NOTE this could happen to Host mode IN endpoint + bool const force_single = !(usb_hw->main_ctrl & USB_MAIN_CTRL_HOST_NDEVICE_BITS) && !tu_edpt_dir(ep->ep_addr); + + if(ep->remaining_len && !force_single) { // Use buffer 1 (double buffered) if there is still data // TODO: Isochronous for buffer1 bit-field is different than CBI (control bulk, interrupt) @@ -181,8 +186,7 @@ static void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len) { _hw_endpoint_lock_update(ep, 1); - pico_trace("Start transfer of total len %d on ep %d %s\n", total_len, tu_edpt_number(ep->ep_addr), - ep_dir_string[tu_edpt_dir(ep->ep_addr)]); + if ( ep->active ) { // TODO: Is this acceptable for interrupt packets? @@ -251,10 +255,42 @@ static void _hw_endpoint_xfer_sync (struct hw_endpoint *ep) // always sync buffer 0 uint16_t buf0_bytes = sync_ep_buffer(ep, 0); - // sync buffer 1 if double buffered and buffer 0 is not short packet - if ( ((*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS) && (buf0_bytes == ep->wMaxPacketSize) ) + // sync buffer 1 if double buffered + if ( (*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS ) { - sync_ep_buffer(ep, 1); + if (buf0_bytes == ep->wMaxPacketSize) + { + // sync buffer 1 if not short packet + sync_ep_buffer(ep, 1); + }else + { + // short packet on buffer 0 + // TODO couldn't figure out how to handle this case which happen with net_lwip_webserver example + // At this time (currently trigger per 2 buffer), the buffer1 is probably filled with data from + // the next transfer (not current one). For now we disable double buffered for device OUT + // NOTE this could happen to Host IN +#if 0 + uint8_t const ep_num = tu_edpt_number(ep->ep_addr); + uint8_t const dir = (uint8_t) tu_edpt_dir(ep->ep_addr); + uint8_t const ep_id = 2*ep_num + (dir ? 0 : 1); + + // abort queued transfer on buffer 1 + usb_hw->abort |= TU_BIT(ep_id); + + while ( !(usb_hw->abort_done & TU_BIT(ep_id)) ) {} + + uint32_t ep_ctrl = *ep->endpoint_control; + ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER); + ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER; + + _hw_endpoint_buffer_control_set_value32(ep, 0); + + usb_hw->abort &= ~TU_BIT(ep_id); + + TU_LOG(3, "----SHORT PACKET buffer0 on EP %02X:\r\n", ep->ep_addr); + print_bufctrl32(buf_ctrl); +#endif + } } } diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 4c787f496..514152cd9 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -120,8 +120,8 @@ static inline void print_bufctrl16(uint32_t u16) .u16 = u16 }; - TU_LOG(3, "len = %u, available = %u, stall = %u, reset = %u, toggle = %u, last = %u, full = %u\r\n", - bufctrl.xfer_len, bufctrl.available, bufctrl.stall, bufctrl.reset_bufsel, bufctrl.data_toggle, bufctrl.last_buf, bufctrl.full); + TU_LOG(3, "len = %u, available = %u, full = %u, last = %u, stall = %u, reset = %u, toggle = %u\r\n", + bufctrl.xfer_len, bufctrl.available, bufctrl.full, bufctrl.last_buf, bufctrl.stall, bufctrl.reset_bufsel, bufctrl.data_toggle); } static inline void print_bufctrl32(uint32_t u32) -- cgit v1.3.1 From 6b621baeb33c08ac92e8e94950250c0923da975e Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 19 Jun 2021 01:58:27 +0700 Subject: fix race condition with control since TASKS_EP0RCVOUT also require EasyDMA --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 59 ++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 977ec6cdb..b3b2dec2d 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -108,13 +108,21 @@ static inline uint32_t NVIC_GetEnableIRQ(IRQn_Type IRQn) } #endif +// check if we are in ISR +TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void) +{ + return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) ? true : false; +} + // helper to start DMA +// TODO use Cortex M4 LDREX and STREX command (atomic) to have better mutex access to EasyDMA +// since current implementation does not 100% guarded against race condition static void edpt_dma_start(volatile uint32_t* reg_startep) { // Only one dma can be active if ( _dcd.dma_pending ) { - if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) + if (is_in_isr()) { // Called within ISR, use usbd task to defer later usbd_defer_func( (osal_task_func_t) edpt_dma_start, (void*) reg_startep, true ); @@ -159,6 +167,17 @@ static void edpt_dma_end(void) _dcd.dma_pending = 0; } +// helper to set TASKS_EP0STATUS / TASKS_EP0RCVOUT since they also need EasyDMA +// However TASKS_EP0STATUS doesn't trigger any DMA transfer and got ENDED event subsequently +// Therefore dma_running state will be corrected right away +void start_ep0_task(volatile uint32_t* reg_task) +{ + edpt_dma_start(reg_task); + + // correct the dma_running++ in dma start + if (_dcd.dma_pending) _dcd.dma_pending--; +} + // helper getting td static inline xfer_td_t* get_td(uint8_t epnum, uint8_t dir) { @@ -407,21 +426,18 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t if ( control_status ) { - // Status Phase also requires Easy DMA has to be available as well !!!! - // However TASKS_EP0STATUS doesn't trigger any DMA transfer and got ENDED event subsequently - // Therefore dma_running state will be corrected right away - edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS); - if (_dcd.dma_pending) _dcd.dma_pending--; // correct the dma_running++ in dma start + // Status Phase also requires EasyDMA has to be available as well !!!! + start_ep0_task(&NRF_USBD->TASKS_EP0STATUS); // The nRF doesn't interrupt on status transmit so we queue up a success response. - dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, false); + dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, is_in_isr()); } else if ( dir == TUSB_DIR_OUT ) { if ( epnum == 0 ) { - // Accept next Control Out packet - NRF_USBD->TASKS_EP0RCVOUT = 1; + // Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA + start_ep0_task(&NRF_USBD->TASKS_EP0RCVOUT); }else { if ( xfer->data_received ) @@ -581,12 +597,6 @@ void dcd_int_handler(uint8_t rhport) } } - if ( int_status & EDPT_END_ALL_MASK ) - { - // DMA complete move data from SRAM -> Endpoint - edpt_dma_end(); - } - // Setup tokens are specific to the Control endpoint. if ( int_status & USBD_INTEN_EP0SETUP_Msk ) { @@ -607,6 +617,12 @@ void dcd_int_handler(uint8_t rhport) } } + if ( int_status & EDPT_END_ALL_MASK ) + { + // DMA complete move data from SRAM -> Endpoint + edpt_dma_end(); + } + //--------------------------------------------------------------------+ /* Control/Bulk/Interrupt (CBI) Transfer * @@ -655,8 +671,15 @@ void dcd_int_handler(uint8_t rhport) { if ( epnum == 0 ) { - // Accept next Control Out packet - NRF_USBD->TASKS_EP0RCVOUT = 1; + // Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA + if ( _dcd.dma_pending ) + { + // use usbd task to defer later + usbd_defer_func( (osal_task_func_t) start_ep0_task, (void*) &NRF_USBD->TASKS_EP0RCVOUT, true ); + }else + { + start_ep0_task(&NRF_USBD->TASKS_EP0RCVOUT); + } }else { // nRF auto accept next Bulk/Interrupt OUT packet @@ -973,7 +996,7 @@ void tusb_hal_nrf_power_event (uint32_t event) hfclk_disable(); - dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) ? true : false); + dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, is_in_isr()); } break; -- cgit v1.3.1 From 76336a67a05ee4b6676a438578819a48cb0f0420 Mon Sep 17 00:00:00 2001 From: Ned Konz Date: Fri, 18 Jun 2021 14:50:55 -0700 Subject: Changed order of struct initializer to avoid compiler error --- src/common/tusb_fifo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index cf299269d..de2ae163d 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -86,8 +86,8 @@ typedef struct .depth = _depth, \ .item_size = sizeof(_type), \ .overwritable = _overwritable, \ - .max_pointer_idx = 2*(_depth)-1, \ .non_used_index_space = UINT16_MAX - (2*(_depth)-1), \ + .max_pointer_idx = 2*(_depth)-1, \ } #define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ -- cgit v1.3.1 From fbda7d58370663e57bde8e011c7045fa85beb397 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 20 Jun 2021 15:04:39 +0700 Subject: adding rx65n --- hw/bsp/rx63n/boards/gr_citrus/board.mk | 8 - hw/bsp/rx63n/boards/rx65n_cloud_kit/board.mk | 52 +++++ hw/bsp/rx63n/boards/rx65n_cloud_kit/r5f565ne.ld | 158 ++++++++++++++ .../rx63n/boards/rx65n_cloud_kit/rx65n_cloud_kit.c | 243 +++++++++++++++++++++ hw/bsp/rx63n/family.mk | 18 +- src/tusb_option.h | 1 + 6 files changed, 471 insertions(+), 9 deletions(-) create mode 100644 hw/bsp/rx63n/boards/rx65n_cloud_kit/board.mk create mode 100644 hw/bsp/rx63n/boards/rx65n_cloud_kit/r5f565ne.ld create mode 100644 hw/bsp/rx63n/boards/rx65n_cloud_kit/rx65n_cloud_kit.c (limited to 'src') diff --git a/hw/bsp/rx63n/boards/gr_citrus/board.mk b/hw/bsp/rx63n/boards/gr_citrus/board.mk index feab5b5e6..6edd588bc 100644 --- a/hw/bsp/rx63n/boards/gr_citrus/board.mk +++ b/hw/bsp/rx63n/boards/gr_citrus/board.mk @@ -1,18 +1,10 @@ DEPS_SUBMODULES += hw/mcu/renesas/rx CFLAGS += \ - -nostartfiles \ - -ffunction-sections \ - -fdata-sections \ - -fshort-enums \ -mcpu=rx610 \ -misa=v1 \ - -mlittle-endian-data \ -DCFG_TUSB_MCU=OPT_MCU_RX63X -# Cross Compiler for RX -CROSS_COMPILE = rx-elf- - RX_NEWLIB ?= 1 ifeq ($(CMDEXE),1) diff --git a/hw/bsp/rx63n/boards/rx65n_cloud_kit/board.mk b/hw/bsp/rx63n/boards/rx65n_cloud_kit/board.mk new file mode 100644 index 000000000..87cbd74a8 --- /dev/null +++ b/hw/bsp/rx63n/boards/rx65n_cloud_kit/board.mk @@ -0,0 +1,52 @@ +CFLAGS += \ + -mcpu=rx64m \ + -misa=v2 \ + -DCFG_TUSB_MCU=OPT_MCU_RX65X + +RX_NEWLIB ?= 1 + +ifeq ($(CMDEXE),1) +OPTLIBINC="$(shell for /F "usebackq delims=" %%i in (`where rx-elf-gcc`) do echo %%~dpi..\rx-elf\optlibinc)" +else +OPTLIBINC=$(shell dirname `which rx-elf-gcc`)../rx-elf/optlibinc +endif + +ifeq ($(RX_NEWLIB),1) +CFLAGS += -DSSIZE_MAX=__INT_MAX__ +else +# setup for optlib +CFLAGS += -nostdinc \ + -isystem $(OPTLIBINC) \ + -DLWIP_NO_INTTYPES_H + +LIBS += -loptc -loptm +endif + +MCU_DIR = hw/mcu/renesas/rx/rx65n + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/r5f565ne.ld + +SRC_C += \ + src/portable/renesas/usba/dcd_usba.c \ + $(MCU_DIR)/vects.c + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/$(MCU_DIR) + +SRC_S += $(MCU_DIR)/start.S + +# For freeRTOS port source +FREERTOS_PORT = RX600 + +# For flash-jlink target +JLINK_DEVICE = R5F565NE +JLINK_IF = JTAG + +# For flash-pyocd target +PYOCD_TARGET = + +# flash using rfp-cli +flash: $(BUILD)/$(PROJECT).mot + rfp-cli -device rx65x -tool e2l -auto $^ diff --git a/hw/bsp/rx63n/boards/rx65n_cloud_kit/r5f565ne.ld b/hw/bsp/rx63n/boards/rx65n_cloud_kit/r5f565ne.ld new file mode 100644 index 000000000..8d4806f09 --- /dev/null +++ b/hw/bsp/rx63n/boards/rx65n_cloud_kit/r5f565ne.ld @@ -0,0 +1,158 @@ +MEMORY +{ + RAM : ORIGIN = 0x0, LENGTH = 262144 + RAM2 : ORIGIN = 0x00800000, LENGTH = 393216 + ROM : ORIGIN = 0xFFE00000, LENGTH = 2097152 + OFS : ORIGIN = 0xFE7F5D00, LENGTH = 128 +} +SECTIONS +{ + .exvectors 0xFFFFFF80: AT(0xFFFFFF80) + { + KEEP(*(.exvectors)) + } > ROM + .fvectors 0xFFFFFFFC: AT(0xFFFFFFFC) + { + KEEP(*(.fvectors)) + } > ROM + .text 0xFFE00000: AT(0xFFE00000) + { + *(.text) + *(.text.*) + *(P) + etext = .; + } > ROM + .rvectors ALIGN(4): + { + _rvectors_start = .; + KEEP(*(.rvectors)) + _rvectors_end = .; + } > ROM + .init : + { + KEEP(*(.init)) + __preinit_array_start = .; + KEEP(*(.preinit_array)) + __preinit_array_end = .; + __init_array_start = (. + 3) & ~ 3; + KEEP(*(.init_array)) + KEEP(*(SORT(.init_array.*))) + __init_array_end = .; + __fini_array_start = .; + KEEP(*(.fini_array)) + KEEP(*(SORT(.fini_array.*))) + __fini_array_end = .; + } > ROM + .fini : + { + KEEP(*(.fini)) + } > ROM + .got : + { + *(.got) + *(.got.plt) + } > ROM + .rodata : + { + *(.rodata) + *(.rodata.*) + *(C_1) + *(C_2) + *(C) + _erodata = .; + } > ROM + .eh_frame_hdr : + { + *(.eh_frame_hdr) + } > ROM + .eh_frame : + { + *(.eh_frame) + } > ROM + .jcr : + { + *(.jcr) + } > ROM + .tors : + { + __CTOR_LIST__ = .; + . = ALIGN(2); + ___ctors = .; + *(.ctors) + ___ctors_end = .; + __CTOR_END__ = .; + __DTOR_LIST__ = .; + ___dtors = .; + *(.dtors) + ___dtors_end = .; + __DTOR_END__ = .; + . = ALIGN(2); + _mdata = .; + } > ROM + .ustack 0x200: AT(0x200) + { + _ustack = .; + } > RAM + .istack 0x100: AT(0x100) + { + _istack = .; + } > RAM + .data 0x204: AT(_mdata) + { + _data = .; + *(.data) + *(.data.*) + *(D) + *(D_1) + *(D_2) + _edata = .; + } > RAM + .gcc_exc : + { + *(.gcc_exc) + } > RAM + .bss : + { + _bss = .; + *(.bss) + *(.bss.**) + *(COMMON) + *(B) + *(B_1) + *(B_2) + _ebss = .; + _end = .; + } > RAM + .ofs1 0xFE7F5D00: AT(0xFE7F5D00) + { + KEEP(*(.ofs1)) + } > OFS + .ofs2 0xFE7F5D10: AT(0xFE7F5D10) + { + KEEP(*(.ofs2)) + } > OFS + .ofs3 0xFE7F5D20: AT(0xFE7F5D20) + { + KEEP(*(.ofs3)) + } > OFS + .ofs4 0xFE7F5D40: AT(0xFE7F5D40) + { + KEEP(*(.ofs4)) + } > OFS + .ofs5 0xFE7F5D48: AT(0xFE7F5D48) + { + KEEP(*(.ofs5)) + } > OFS + .ofs6 0xFE7F5D50: AT(0xFE7F5D50) + { + KEEP(*(.ofs6)) + } > OFS + .ofs7 0xFE7F5D64: AT(0xFE7F5D64) + { + KEEP(*(.ofs7)) + } > OFS + .ofs8 0xFE7F5D70: AT(0xFE7F5D70) + { + KEEP(*(.ofs8)) + } > OFS +} diff --git a/hw/bsp/rx63n/boards/rx65n_cloud_kit/rx65n_cloud_kit.c b/hw/bsp/rx63n/boards/rx65n_cloud_kit/rx65n_cloud_kit.c new file mode 100644 index 000000000..0853763c8 --- /dev/null +++ b/hw/bsp/rx63n/boards/rx65n_cloud_kit/rx65n_cloud_kit.c @@ -0,0 +1,243 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, Koji Kitayama + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "bsp/board.h" +#include "iodefine.h" +#include "interrupt_handlers.h" + +#define IRQ_PRIORITY_CMT0 5 +#define IRQ_PRIORITY_USBI0 6 +#define IRQ_PRIORITY_SCI0 5 + +#define SYSTEM_PRCR_PRC1 (1<<1) +#define SYSTEM_PRCR_PRKEY (0xA5u<<8) + +#define CMT_PCLK 48000000 +#define CMT_CMCR_CKS_DIV_128 2 +#define CMT_CMCR_CMIE (1<<6) +#define MPC_PFS_ISEL (1<<6) + +#define SCI_PCLK 48000000 +#define SCI_SSR_FER (1<<4) +#define SCI_SSR_ORER (1<<5) + +#define SCI_SCR_TEIE (1u<<2) +#define SCI_SCR_RE (1u<<4) +#define SCI_SCR_TE (1u<<5) +#define SCI_SCR_RIE (1u<<6) +#define SCI_SCR_TIE (1u<<7) + +void HardwareSetup(void) +{ +/* + BSC.CS0MOD.WORD = 0x1234; + BSC.CS7CNT.WORD = 0x5678; + + SCI0.SCR.BIT.TE = 0; + SCI0.SCR.BIT.RE = 0; + SCI0.SCR.BIT.TE = 1; + SCI2.SSR.BIT.PER = 0; + + TMR0.TCR.BYTE = 0x12; + TMR1.TCR.BYTE = 0x12; + TMR2.TCR.BYTE = 0x12; + + P0.DDR.BYTE = 0x12; + P1.DDR.BYTE = 0x12; +*/ +} + +//--------------------------------------------------------------------+ +// SCI0 handling +//--------------------------------------------------------------------+ +typedef struct { + uint8_t *buf; + uint32_t cnt; +} sci_buf_t; +static volatile sci_buf_t sci0_buf[2]; + +void INT_Excep_SCI0_TXI0(void) +{ + uint8_t *buf = sci0_buf[0].buf; + uint32_t cnt = sci0_buf[0].cnt; + + if (!buf || !cnt) { + SCI0.SCR.BYTE &= ~(SCI_SCR_TEIE | SCI_SCR_TE | SCI_SCR_TIE); + return; + } + SCI0.TDR = *buf; + if (--cnt) { + ++buf; + } else { + buf = NULL; + SCI0.SCR.BIT.TIE = 0; + SCI0.SCR.BIT.TEIE = 1; + } + sci0_buf[0].buf = buf; + sci0_buf[0].cnt = cnt; +} + +void INT_Excep_SCI0_TEI0(void) +{ + SCI0.SCR.BYTE &= ~(SCI_SCR_TEIE | SCI_SCR_TE | SCI_SCR_TIE); +} + +void INT_Excep_SCI0_RXI0(void) +{ + uint8_t *buf = sci0_buf[1].buf; + uint32_t cnt = sci0_buf[1].cnt; + + if (!buf || !cnt || + (SCI0.SSR.BYTE & (SCI_SSR_FER | SCI_SSR_ORER))) { + sci0_buf[1].buf = NULL; + SCI0.SSR.BYTE = 0; + SCI0.SCR.BYTE &= ~(SCI_SCR_RE | SCI_SCR_RIE); + return; + } + *buf = SCI0.RDR; + if (--cnt) { + ++buf; + } else { + buf = NULL; + SCI0.SCR.BYTE &= ~(SCI_SCR_RE | SCI_SCR_RIE); + } + sci0_buf[1].buf = buf; + sci0_buf[1].cnt = cnt; +} + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void INT_Excep_USB0_USBI0(void) +{ + tud_int_handler(0); +} + +void board_init(void) +{ +#if CFG_TUSB_OS == OPT_OS_NONE + /* Enable CMT0 */ + SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY | SYSTEM_PRCR_PRC1; + MSTP(CMT0) = 0; + SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY; + /* Setup 1ms tick timer */ + CMT0.CMCNT = 0; + CMT0.CMCOR = CMT_PCLK / 1000 / 128; + CMT0.CMCR.WORD = CMT_CMCR_CMIE | CMT_CMCR_CKS_DIV_128; + IR(CMT0, CMI0) = 0; + IPR(CMT0, CMI0) = IRQ_PRIORITY_CMT0; + IEN(CMT0, CMI0) = 1; + CMT.CMSTR0.BIT.STR0 = 1; +#endif + + /* Unlock MPC registers */ + MPC.PWPR.BIT.B0WI = 0; + MPC.PWPR.BIT.PFSWE = 1; + /* LED PA0 */ + PORTA.PMR.BIT.B0 = 0U; + PORTA.PODR.BIT.B0 = 0U; + PORTA.PDR.BIT.B0 = 1U; + /* UART TXD0 => P20, RXD0 => P21 */ + PORT2.PMR.BIT.B0 = 1U; + PORT2.PCR.BIT.B0 = 1U; + MPC.P20PFS.BYTE = 0b01010; + PORT2.PMR.BIT.B1 = 1U; + MPC.P21PFS.BYTE = 0b01010; + /* USB VBUS -> P16 DPUPE -> P14 */ + PORT1.PMR.BIT.B4 = 1U; + PORT1.PMR.BIT.B6 = 1U; + MPC.P14PFS.BYTE = 0b10001; + MPC.P16PFS.BYTE = MPC_PFS_ISEL | 0b10001; +// MPC.PFUSB0.BIT.PUPHZS = 1; + /* Lock MPC registers */ + MPC.PWPR.BIT.PFSWE = 0; + MPC.PWPR.BIT.B0WI = 1; + +// IR(USB0, USBI0) = 0; +// IPR(USB0, USBI0) = IRQ_PRIORITY_USBI0; + + /* Enable SCI0 */ + SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY | SYSTEM_PRCR_PRC1; + MSTP(SCI0) = 0; + SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY; + SCI0.BRR = (SCI_PCLK / (32 * 115200)) - 1; +// IR(SCI0, RXI0) = 0; +// IR(SCI0, TXI0) = 0; +// IR(SCI0, TEI0) = 0; +// IPR(SCI0, RXI0) = IRQ_PRIORITY_SCI0; +// IPR(SCI0, TXI0) = IRQ_PRIORITY_SCI0; +// IPR(SCI0, TEI0) = IRQ_PRIORITY_SCI0; +// IEN(SCI0, RXI0) = 1; +// IEN(SCI0, TXI0) = 1; +// IEN(SCI0, TEI0) = 1; +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + PORTA.PODR.BIT.B0 = state ? 1 : 0; +} + +uint32_t board_button_read(void) +{ + return 0; +} + +int board_uart_read(uint8_t* buf, int len) +{ + sci0_buf[1].buf = buf; + sci0_buf[1].cnt = len; + SCI0.SCR.BYTE |= SCI_SCR_RE | SCI_SCR_RIE; + while (SCI0.SCR.BIT.RE) ; + return len - sci0_buf[1].cnt; +} + +int board_uart_write(void const *buf, int len) +{ + sci0_buf[0].buf = (uint8_t*)buf; + sci0_buf[0].cnt = len; + SCI0.SCR.BYTE |= SCI_SCR_TE | SCI_SCR_TIE; + while (SCI0.SCR.BIT.TE) ; + return len; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void INT_Excep_CMT0_CMI0(void) +{ + ++system_ticks; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#else +uint32_t SystemCoreClock = 96000000; +#endif diff --git a/hw/bsp/rx63n/family.mk b/hw/bsp/rx63n/family.mk index d3c743ed1..a9c74e6b0 100644 --- a/hw/bsp/rx63n/family.mk +++ b/hw/bsp/rx63n/family.mk @@ -1 +1,17 @@ -include $(TOP)/$(BOARD_PATH)/board.mk \ No newline at end of file +DEPS_SUBMODULES += hw/mcu/renesas/rx + +# Cross Compiler for RX +CROSS_COMPILE = rx-elf- + +include $(TOP)/$(BOARD_PATH)/board.mk + +CFLAGS += \ + -nostartfiles \ + -ffunction-sections \ + -fdata-sections \ + -fshort-enums \ + -mlittle-endian-data \ + +$(BUILD)/$(PROJECT).mot: $(BUILD)/$(PROJECT).elf + @echo CREATE $@ + $(OBJCOPY) -O srec -I elf32-rx-be-ns $^ $@ diff --git a/src/tusb_option.h b/src/tusb_option.h index 5cfcc08e2..5571c91d7 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -112,6 +112,7 @@ // Renesas RX #define OPT_MCU_RX63X 1400 ///< Renesas RX63N/631 +#define OPT_MCU_RX65X 1401 ///< Renesas RX65N/RX651 // Mind Motion #define OPT_MCU_MM32F327X 1500 ///< Mind Motion MM32F327 -- cgit v1.3.1 From 8433f638e64ce1b13fead28b4395d9a32c480548 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sun, 20 Jun 2021 15:38:20 +0200 Subject: Add bracket to switch case, fix warning. --- src/class/audio/audio_device.c | 209 +++++++++++++++++++++-------------------- 1 file changed, 107 insertions(+), 102 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8e4420ed0..7ad7edf9e 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -393,12 +393,12 @@ static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); #if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf); -#endif static inline uint8_t tu_desc_subtype(void const* desc) { return ((uint8_t const*) desc)[2]; } +#endif bool tud_audio_n_mounted(uint8_t func_id) { @@ -1658,64 +1658,65 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - if (entityID != 0) + case TUSB_REQ_RCPT_INTERFACE: { - if (tud_audio_set_req_entity_cb) + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + if (entityID != 0) { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + if (tud_audio_set_req_entity_cb) + { + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + // Invoke callback + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + } + else + { + TU_LOG2(" No entity set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } } else { - TU_LOG2(" No entity set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it + if (tud_audio_set_req_itf_cb) + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + + // Invoke callback + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + } + else + { + TU_LOG2(" No interface set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } } } - else + break; + + case TUSB_REQ_RCPT_ENDPOINT: { - if (tud_audio_set_req_itf_cb) + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + if (tud_audio_set_req_ep_cb) { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } else { - TU_LOG2(" No interface set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it + TU_LOG2(" No EP set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it } } - break; - - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - if (tud_audio_set_req_ep_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - - // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No EP set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - // Unknown/Unsupported recipient default: TU_BREAKPOINT(); return false; } @@ -1754,73 +1755,75 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) + case TUSB_REQ_RCPT_INTERFACE: { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) + // Verify if entity is present + if (entityID != 0) { - if (tud_audio_get_req_entity_cb) + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - return tud_audio_get_req_entity_cb(rhport, p_request); + if (tud_audio_get_req_entity_cb) + { + return tud_audio_get_req_entity_cb(rhport, p_request); + } + else + { + TU_LOG2(" No entity get request callback available!\r\n"); + return false; // Stall + } } - else + } + else + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - TU_LOG2(" No entity get request callback available!\r\n"); - return false; // Stall + if (tud_audio_get_req_itf_cb) + { + return tud_audio_get_req_itf_cb(rhport, p_request); + } + else + { + TU_LOG2(" No interface get request callback available!\r\n"); + return false; // Stall + } } } } - else + break; + + case TUSB_REQ_RCPT_ENDPOINT: { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - if (tud_audio_get_req_itf_cb) + if (tud_audio_get_req_ep_cb) { - return tud_audio_get_req_itf_cb(rhport, p_request); + return tud_audio_get_req_ep_cb(rhport, p_request); } else { - TU_LOG2(" No interface get request callback available!\r\n"); - return false; // Stall + TU_LOG2(" No EP get request callback available!\r\n"); + return false; // Stall } } } break; - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else - { - TU_LOG2(" No EP get request callback available!\r\n"); - return false; // Stall - } - } - break; - // Unknown/Unsupported recipient default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; } @@ -1935,29 +1938,31 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) + case TUSB_REQ_RCPT_INTERFACE: { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - } - else - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present + if (entityID != 0) + { + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + } + else + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + } } break; case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + { + uint8_t ep = TU_U16_LOW(p_request->wIndex); - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); + } break; // Unknown/Unsupported recipient -- cgit v1.3.1 From 9323a9d094684a25e65fcae964e7ee91c9746f57 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 21 Jun 2021 00:00:46 +0700 Subject: fix issue when calling midi API when not enumerated yet --- src/class/midi/midi_device.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 953ca26e6..4eac0de48 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -197,9 +197,11 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) { - midid_interface_t* p_midi = &_midid_itf[itf]; - uint32_t num_read = tu_fifo_read_n(&p_midi->rx_ff, packet, 4); - _prep_out_transaction(p_midi); + midid_interface_t* midi = &_midid_itf[itf]; + TU_VERIFY(midi->ep_out); + + uint32_t const num_read = tu_fifo_read_n(&midi->rx_ff, packet, 4); + _prep_out_transaction(midi); return (num_read == 4); } @@ -234,7 +236,7 @@ static uint32_t write_flush(midid_interface_t* midi) uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->itf_num, 0); + TU_VERIFY(midi->ep_in, 0); midid_stream_t* stream = &midi->stream_write; @@ -351,9 +353,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) { midid_interface_t* midi = &_midid_itf[itf]; - if (midi->itf_num == 0) { - return 0; - } + TU_VERIFY(midi->ep_in); if (tu_fifo_remaining(&midi->tx_ff) < 4) return false; @@ -435,6 +435,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint } p_midi->itf_num = desc_midi->bInterfaceNumber; + (void) p_midi->itf_num; // next descriptor drv_len += tu_desc_len(p_desc); -- cgit v1.3.1 From 264dc35b95a2313201845f3612d3e807afad62c3 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Mon, 21 Jun 2021 05:32:43 +0200 Subject: Fix typo in TUH configuration define --- examples/host/cdc_msc_hid/src/tusb_config.h | 2 +- src/class/hid/hid_host.c | 2 +- src/host/usbh.c | 4 ++-- src/host/usbh_control.c | 2 +- src/tusb_option.h | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 8253964c0..cc77b6554 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -72,7 +72,7 @@ //-------------------------------------------------------------------- // Size of buffer to hold descriptors and other data used for enumeration -#define CFG_TUH_ENUMERATION_BUFSZIE 256 +#define CFG_TUH_ENUMERATION_BUFSIZE 256 #define CFG_TUH_HUB 1 #define CFG_TUH_CDC 1 diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index cde5e23a5..761258f1b 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -368,7 +368,7 @@ static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t cons // Get Report Descriptor // using usbh enumeration buffer since report descriptor can be very long - TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSZIE ); + TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSIZE ); TU_LOG2("HID Get Report Descriptor\r\n"); tusb_control_request_t const new_request = diff --git a/src/host/usbh.c b/src/host/usbh.c index 59246a663..8ecc87488 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -130,7 +130,7 @@ CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; OSAL_QUEUE_DEF(OPT_MODE_HOST, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); static osal_queue_t _usbh_q; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSZIE]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; //------------- Helper Function Prototypes -------------// static bool enum_new_device(hcd_event_t* event); @@ -907,7 +907,7 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r // Use offsetof to avoid pointer to the odd/misaligned address memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); - TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSZIE); + TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE); // Get full configuration descriptor TU_LOG2("Get Configuration Descriptor\r\n"); diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 4dbf8592a..53413b6e5 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -50,7 +50,7 @@ typedef struct static usbh_control_xfer_t _ctrl_xfer; //CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN -//static uint8_t _tuh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSZIE]; +//static uint8_t _tuh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE]; //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION diff --git a/src/tusb_option.h b/src/tusb_option.h index d5776c029..815e588de 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -278,8 +278,8 @@ #error there is no benefit enable hub with max device is 1. Please disable hub or increase CFG_TUSB_HOST_DEVICE_MAX #endif - #ifndef CFG_TUH_ENUMERATION_BUFSZIE - #define CFG_TUH_ENUMERATION_BUFSZIE 256 + #ifndef CFG_TUH_ENUMERATION_BUFSIZE + #define CFG_TUH_ENUMERATION_BUFSIZE 256 #endif //------------- CLASS -------------// -- cgit v1.3.1 From 51c6444e1d8be85d5f4c8b4ebf7e48db7f589bc2 Mon Sep 17 00:00:00 2001 From: Wini-Buh Date: Tue, 22 Jun 2021 23:49:24 +0200 Subject: final clean up --- src/common/tusb_compiler.h | 10 ---------- src/device/usbd.c | 4 ++-- src/device/usbd_control.c | 10 +--------- src/osal/osal_freertos.h | 25 ------------------------- src/portable/renesas/usba/dcd_usba.c | 11 +---------- 5 files changed, 4 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index f77cf94ee..538daa171 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -84,8 +84,6 @@ // Endian conversion use well-known host to network (big endian) naming #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define TU_BYTE_ORDER TU_LITTLE_ENDIAN - #define TU_ENDIAN_LITTLE_BEGIN - #define TU_ENDIAN_LITTLE_END #else #define TU_BYTE_ORDER TU_BIG_ENDIAN #endif @@ -153,21 +151,13 @@ // Endian conversion use well-known host to network (big endian) naming #if defined(__LIT) #define TU_BYTE_ORDER TU_LITTLE_ENDIAN - #define TU_ENDIAN_LITTLE_BEGIN - #define TU_ENDIAN_LITTLE_END #else #define TU_BYTE_ORDER TU_BIG_ENDIAN - #define TU_ENDIAN_LITTLE_BEGIN _Pragma("endian little") - #define TU_ENDIAN_LITTLE_END _Pragma("endian") #endif #define TU_BSWAP16(u16) ((unsigned short)_builtin_revw((unsigned long)u16)) #define TU_BSWAP32(u32) (_builtin_revl(u32)) - /* activate the "aligned" emulation, because this toolchain does not know - the aligned attribute (or something similar yet) */ - #define TU_HAS_NO_ATTR_ALIGNED - #else #error "Compiler attribute porting is required" #endif diff --git a/src/device/usbd.c b/src/device/usbd.c index cedca540e..00ec29c9a 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1156,14 +1156,14 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { - TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); + TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, tu_le16toh(desc_ep->wMaxPacketSize.size)); switch (desc_ep->bmAttributes.xfer) { case TUSB_XFER_ISOCHRONOUS: { uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023); - TU_ASSERT(desc_ep->wMaxPacketSize.size <= max_epsize); + TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) <= max_epsize); } break; diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index b3bab2e32..5483406e5 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -55,17 +55,9 @@ typedef struct static usbd_control_xfer_t _ctrl_xfer; -#if defined(TU_HAS_NO_ATTR_ALIGNED) -// Helper union to overcome the lack of the alignment attribute/pragma -static union { - uint16_t : (sizeof(uint16_t) * 8); // Alignment of at least the size of the used type - uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; -} Align_usbd_ctrl_buf_; -static uint8_t *_usbd_ctrl_buf = (uint8_t*)&Align_usbd_ctrl_buf_; -#else CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; -#endif + //--------------------------------------------------------------------+ // Application API diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index ec33b317d..66070c273 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -51,7 +51,6 @@ static inline void osal_task_delay(uint32_t msec) typedef StaticSemaphore_t osal_semaphore_def_t; typedef SemaphoreHandle_t osal_semaphore_t; -#if (configSUPPORT_STATIC_ALLOCATION == 1) //FIXME Only static API supported static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { return xSemaphoreCreateBinaryStatic(semdef); @@ -77,7 +76,6 @@ static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) return res != 0; } } -#endif static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) { @@ -98,12 +96,7 @@ typedef SemaphoreHandle_t osal_mutex_t; static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { -#if (configSUPPORT_STATIC_ALLOCATION == 0) //FIXME Only static API supported - (void)mdef; - return xSemaphoreCreateMutex(); -#else return xSemaphoreCreateMutexStatic(mdef); -#endif } static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) @@ -138,11 +131,7 @@ typedef QueueHandle_t osal_queue_t; static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { -#if defined(__Tx36V5_Maincard__) - return xQueueCreate(qdef->depth, qdef->item_sz); -#else return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq); -#endif } static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) @@ -150,19 +139,6 @@ static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) return xQueueReceive(qhdl, data, portMAX_DELAY); } -#if defined(__Tx36V5_Maincard__) -extern BaseType_t UsbTaskWoken; -static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) -{ - if (!in_isr) { - return(xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER)); - - } else { - BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &UsbTaskWoken); - return(res != 0); - } -} -#else static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) { if ( !in_isr ) @@ -183,7 +159,6 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in return res != 0; } } -#endif static inline bool osal_queue_empty(osal_queue_t qhdl) { diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 13fc50ae5..51729de06 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -518,22 +518,13 @@ static void process_set_address(uint8_t rhport) { const uint32_t addr = USB0.USBADDR.BIT.USBADDR; if (!addr) return; -#if defined(__CCRX__) - tusb_control_request_t setup_packet; - setup_packet.bmRequestType = 0; - setup_packet.bRequest = 5; - setup_packet.wValue = addr; - setup_packet.wIndex = 0; - setup_packet.wLength = 0; -#else const tusb_control_request_t setup_packet = { - .bmRequestType = 0, + .bmRequestType = { 0 }, /* Note: CCRX needs the braces over this struct member */ .bRequest = 5, .wValue = addr, .wIndex = 0, .wLength = 0, }; -#endif dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet, true); } -- cgit v1.3.1 From f5f087b2f85ebf4ff41c84c5f1a70a598d32cb21 Mon Sep 17 00:00:00 2001 From: Jeremiah McCarthy Date: Wed, 23 Jun 2021 10:58:18 -0400 Subject: Add dfu function memory access protection Adds TU_VERIFY to dfu internal buffer access from host. Adds TU_ASSERT to dfu internal buffer access by application. --- src/class/dfu/dfu_device.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 81045ff7b..df731ee50 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -249,6 +249,7 @@ static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * re { TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + TU_ASSERT( retval <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; } @@ -276,6 +277,7 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * // if they wish, there still will be the internal control buffer copy to this buffer // but this mode would provide zero copy from the class driver to the application + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); // setup for data phase tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, request->wLength); } @@ -283,6 +285,7 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { (void) rhport; + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; } -- cgit v1.3.1 From 9d6fd78b632db5b40e84e4c019f00286aae5d1ad Mon Sep 17 00:00:00 2001 From: Mengsk Date: Thu, 24 Jun 2021 11:34:29 +0200 Subject: Add fifo helper function to CDC class for DMA transfer. --- src/class/cdc/cdc_device.c | 14 ++++++++++++++ src/class/cdc/cdc_device.h | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index cac811c45..a926081cc 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -483,4 +483,18 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ return true; } +// Get the Receive FIFO (for DMA transfer) +tu_fifo_t* tud_cdc_n_get_rx_ff (uint8_t itf) +{ + TU_ASSERT(itf < CFG_TUD_CDC); + return &_cdcd_itf[itf].rx_ff; +} + +// Get the transmit FIFO (for DMA transfer) +tu_fifo_t* tud_cdc_n_get_tx_ff (uint8_t itf) +{ + TU_ASSERT(itf < CFG_TUD_CDC); + return &_cdcd_itf[itf].tx_ff; +} + #endif diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 7ff757add..94678a660 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -104,6 +104,12 @@ uint32_t tud_cdc_n_write_available (uint8_t itf); // Clear the transmit FIFO bool tud_cdc_n_write_clear (uint8_t itf); +// Get the Receive FIFO (for DMA transfer) +tu_fifo_t* tud_cdc_n_get_rx_ff (uint8_t itf); + +// Get the transmit FIFO (for DMA transfer) +tu_fifo_t* tud_cdc_n_get_tx_ff (uint8_t itf); + //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ @@ -241,6 +247,18 @@ static inline bool tud_cdc_write_clear(void) return tud_cdc_n_write_clear(0); } +// Get the Receive FIFO +static inline tu_fifo_t* tud_cdc_get_rx_ff (uint8_t itf) +{ + return tud_cdc_n_get_rx_ff(0); +} + +// Get the transmit FIFO +static inline tu_fifo_t* tud_cdc_get_tx_ff (uint8_t itf) +{ + return tud_cdc_n_get_tx_ff(0); +} + /** @} */ /** @} */ -- cgit v1.3.1 From b9e9773d04419032d9e8eb8ca568390f74382690 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Thu, 24 Jun 2021 11:35:05 +0200 Subject: fix warning --- src/class/cdc/cdc_device.h | 4 ++-- src/device/usbd.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 94678a660..f8a2216c1 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -248,13 +248,13 @@ static inline bool tud_cdc_write_clear(void) } // Get the Receive FIFO -static inline tu_fifo_t* tud_cdc_get_rx_ff (uint8_t itf) +static inline tu_fifo_t* tud_cdc_get_rx_ff (void) { return tud_cdc_n_get_rx_ff(0); } // Get the transmit FIFO -static inline tu_fifo_t* tud_cdc_get_tx_ff (uint8_t itf) +static inline tu_fifo_t* tud_cdc_get_tx_ff (void) { return tud_cdc_n_get_tx_ff(0); } diff --git a/src/device/usbd.h b/src/device/usbd.h index 3857295d7..0a0f0bf00 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -236,7 +236,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval #define TUD_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \ /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ /* HID descriptor */\ 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ /* Endpoint In */\ @@ -249,7 +249,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval #define TUD_HID_INOUT_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epout, _epin, _epsize, _ep_interval) \ /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ /* HID descriptor */\ 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ /* Endpoint Out */\ -- cgit v1.3.1 From 393a9120ac0725ba525aa09fcf8e24fd32735391 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Sat, 26 Jun 2021 23:09:18 +0900 Subject: add the entry for RX65N --- src/portable/renesas/usba/dcd_usba.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 06ea1a3f9..de3e0e312 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -26,8 +26,8 @@ #include "tusb_option.h" -#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_RX63X ) - +#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_RX63X || \ + CFG_TUSB_MCU == OPT_MCU_RX65X) #include "device/dcd.h" #include "iodefine.h" -- cgit v1.3.1 From b5ce269675c4d220806126cc76f8c57406da27d2 Mon Sep 17 00:00:00 2001 From: DuMaM Date: Sat, 26 Jun 2021 17:03:46 +0200 Subject: GCC 11 build fix During Adafruit Bootloader compilation, I spotted bellow error which do not allow me build project. ``` c inlined from 'hfclk_running' at lib/tinyusb/src/portable/nordic/nrf5x/dcd_nrf5x.c:785:13: lib/tinyusb/src/portable/nordic/nrf5x/dcd_nrf5x.c:792:31: error: 'is_running' may be used uninitialized [-Werror=maybe-uninitialized] 792 | return (is_running ? true : false); | ~~~~~~~~~~~~~~~~~~~^~~~~~~~ ``` --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index b3b2dec2d..5f4fe08ad 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -787,7 +787,7 @@ static bool hfclk_running(void) #ifdef SOFTDEVICE_PRESENT if ( is_sd_enabled() ) { - uint32_t is_running; + uint32_t is_running = 0; (void) sd_clock_hfclk_is_running(&is_running); return (is_running ? true : false); } -- cgit v1.3.1 From 5811122cfd04b84c8760991e287e29fc424453fd Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Jun 2021 11:58:34 +0700 Subject: change usbh open driver to have max_len and return driver len --- src/class/cdc/cdc_device.c | 10 +++----- src/class/cdc/cdc_host.c | 62 ++++++++++++++++++++++----------------------- src/class/cdc/cdc_host.h | 10 ++++---- src/class/hid/hid_host.c | 20 +++++++++------ src/class/hid/hid_host.h | 10 ++++---- src/class/msc/msc_host.c | 13 ++++++---- src/class/msc/msc_host.h | 20 ++++----------- src/host/hub.c | 31 +++++++++++++---------- src/host/hub.h | 10 ++++---- src/host/usbh.c | 15 ++++++----- src/host/usbh_classdriver.h | 10 ++++---- 11 files changed, 104 insertions(+), 107 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index cac811c45..e622bd616 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -273,9 +273,6 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); - // Note: 0xFF can be used with RNDIS - TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA), 0); - // Find available interface cdcd_interface_t * p_cdc = NULL; for(uint8_t cdc_id=0; cdc_idep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + TU_ASSERT( usbd_edpt_open(rhport, desc_ep), 0 ); + p_cdc->ep_notif = desc_ep->bEndpointAddress; drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 33f1a8ad3..fc7100e81 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -149,29 +149,27 @@ void cdch_init(void) tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX); } -bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) +uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { - // Only support ACM - TU_VERIFY( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass); + (void) max_len; - // Only support AT commands, no protocol and vendor specific commands. - TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || - 0xff == itf_desc->bInterfaceProtocol); + // Only support ACM subclass + // Protocol 0xFF can be RNDIS device for windows XP + TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass && + 0xFF != itf_desc->bInterfaceProtocol, 0); - uint8_t const * p_desc; - cdch_data_t * p_cdc; - - p_desc = tu_desc_next(itf_desc); - p_cdc = get_itf(dev_addr); + cdch_data_t * p_cdc = get_itf(dev_addr); - p_cdc->itf_num = itf_desc->bInterfaceNumber; - p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; // TODO 0xff is consider as rndis candidate, other is virtual Com + p_cdc->itf_num = itf_desc->bInterfaceNumber; + p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; //------------- Communication Interface -------------// - (*p_length) = sizeof(tusb_desc_interface_t); + uint16_t drv_len = tu_desc_len(itf_desc); + uint8_t const * p_desc = tu_desc_next(itf_desc); // Communication Functional Descriptors - while( TUSB_DESC_CS_INTERFACE == p_desc[DESC_OFFSET_TYPE] ) + while( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) { if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) ) { @@ -179,52 +177,52 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; } - (*p_length) += p_desc[DESC_OFFSET_LEN]; + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } - if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { // notification endpoint - tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) p_desc; + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, ep_desc) ); - p_cdc->ep_notif = ep_desc->bEndpointAddress; + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 ); + p_cdc->ep_notif = desc_ep->bEndpointAddress; - (*p_length) += p_desc[DESC_OFFSET_LEN]; + drv_len += 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) ) { - (*p_length) += p_desc[DESC_OFFSET_LEN]; + // next to endpoint descriptor + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); // data endpoints expected to be in pairs for(uint32_t i=0; i<2; i++) { - tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); - TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep), 0); - if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) + if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) { - p_cdc->ep_in = ep_desc->bEndpointAddress; + p_cdc->ep_in = desc_ep->bEndpointAddress; }else { - p_cdc->ep_out = ep_desc->bEndpointAddress; + p_cdc->ep_out = desc_ep->bEndpointAddress; } - (*p_length) += p_desc[DESC_OFFSET_LEN]; + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next( p_desc ); } } - return true; + return drv_len; } bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 6ff392709..edcd258a8 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -121,11 +121,11 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void cdch_init(void); -bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num); -bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void cdch_close(uint8_t dev_addr); +void cdch_init (void); +uint16_t cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); +bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void cdch_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 16d908a5d..81ed6e8b6 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -247,29 +247,33 @@ static bool config_get_protocol (uint8_t dev_addr, tusb_control_requ static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) +uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + (void) max_len; + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); + + uint16_t drv_len = sizeof(tusb_desc_interface_t); uint8_t const *p_desc = (uint8_t const *) desc_itf; //------------- HID descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, 0); // not enough interface, try to increase CFG_TUH_HID // TODO multiple devices hidh_device_t* hid_dev = get_dev(dev_addr); - TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID); + TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID, 0); //------------- Endpoint Descriptor -------------// + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, 0); // TODO also open endpoint OUT - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 ); hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); hid_dev->inst_count++; @@ -285,9 +289,9 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; - *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + drv_len += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - return true; + return drv_len; } bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 2e4cce600..6ae7c6721 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -118,11 +118,11 @@ TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t ins //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hidh_init(void); -bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length); -bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num); -bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void hidh_close(uint8_t dev_addr); +void hidh_init (void); +uint16_t hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); +bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num); +bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void hidh_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 7f98ef9b1..83cbe7c89 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -360,18 +360,22 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) +uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); + // msc driver length is fixed + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + TU_ASSERT(drv_len <= max_len, 0); + msch_interface_t* p_msc = get_itf(dev_addr); tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); for(uint32_t i=0; i<2; i++) { - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer, 0); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc), 0); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { @@ -385,9 +389,8 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de } p_msc->itf_num = desc_itf->bInterfaceNumber; - (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); - return true; + return drv_len; } bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index ce4fe64dc..9e4217ba5 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -41,13 +41,6 @@ #define CFG_TUH_MSC_MAXLUN 4 #endif - -/** \addtogroup ClassDriver_MSC - * @{ - * \defgroup MSC_Host Host - * The interface API includes status checking function, data transferring function and callback functions - * @{ */ - typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); //--------------------------------------------------------------------+ @@ -113,17 +106,14 @@ TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); // Internal Class Driver API //--------------------------------------------------------------------+ -void msch_init(void); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length); -bool msch_set_config(uint8_t dev_addr, uint8_t itf_num); -bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void msch_close(uint8_t dev_addr); +void msch_init (void); +uint16_t msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); +bool msch_set_config (uint8_t dev_addr, uint8_t itf_num); +bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void msch_close (uint8_t dev_addr); #ifdef __cplusplus } #endif #endif /* _TUSB_MSC_HOST_H_ */ - -/// @} -/// @} diff --git a/src/host/hub.c b/src/host/hub.c index b2761184d..2ead5bed1 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -144,29 +144,32 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_con //--------------------------------------------------------------------+ void hub_init(void) { - tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof( hub_interface_t)); + tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof(hub_interface_t)); } -bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) +uint16_t hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { - // not support multiple TT yet - if ( itf_desc->bInterfaceProtocol > 1 ) return false; + // hub driver does not support multiple TT yet + TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass && + 0 == itf_desc->bInterfaceSubClass && + 1 <= itf_desc->bInterfaceProtocol, 0); - //------------- Open Interrupt Status Pipe -------------// - tusb_desc_endpoint_t const *ep_desc; - ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + // msc driver length is fixed + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); + TU_ASSERT(drv_len <= max_len, 0); - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); - TU_ASSERT(TUSB_XFER_INTERRUPT == ep_desc->bmAttributes.xfer); + //------------- Interrupt Status endpoint -------------// + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && + TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep)); hub_data[dev_addr-1].itf_num = itf_desc->bInterfaceNumber; - hub_data[dev_addr-1].ep_in = ep_desc->bEndpointAddress; - - (*p_length) = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); + hub_data[dev_addr-1].ep_in = desc_ep->bEndpointAddress; - return true; + return drv_len; } void hub_close(uint8_t dev_addr) diff --git a/src/host/hub.h b/src/host/hub.h index a5111b8e7..c9ffe4985 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -181,11 +181,11 @@ bool hub_status_pipe_queue(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hub_init(void); -bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -bool hub_set_config(uint8_t dev_addr, uint8_t itf_num); -bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void hub_close(uint8_t dev_addr); +void hub_init (void); +uint16_t hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +bool hub_set_config (uint8_t dev_addr, uint8_t itf_num); +bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hub_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/host/usbh.c b/src/host/usbh.c index bad1aa61a..93621c42a 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -984,11 +984,12 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) { usbh_device_t* dev = &_usbh_devices[dev_addr]; - uint8_t const* p_desc = (uint8_t const*) desc_cfg; - p_desc = tu_desc_next(p_desc); + + uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); + uint8_t const* p_desc = tu_desc_next(desc_cfg); // parse each interfaces - while( p_desc < _usbh_ctrl_buf + desc_cfg->wTotalLength ) + while( p_desc < desc_end ) { // TODO Do we need to use IAD // tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL; @@ -1003,8 +1004,9 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; + uint16_t const remaining_len = desc_end-p_desc; - // Check if class is supported + // Check if class is supported TODO drop class_code uint8_t drv_id; for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) { @@ -1034,9 +1036,8 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura { TU_LOG2("%s open\r\n", driver->name); - uint16_t itf_len = 0; - TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) ); - TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); + uint16_t const itf_len = driver->open(dev->rhport, dev_addr, desc_itf, remaining_len); + TU_ASSERT( sizeof(tusb_desc_interface_t) <= itf_len && itf_len <= remaining_len); p_desc += itf_len; } } diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index 07480fe8e..0736fefa1 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -45,11 +45,11 @@ typedef struct { uint8_t class_code; - void (* const init )(void); - bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen); - bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); - bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* const close )(uint8_t dev_addr); + void (* const init )(void); + uint16_t (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); + bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); + bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + void (* const close )(uint8_t dev_addr); } usbh_class_driver_t; // Call by class driver to tell USBH that it has complete the enumeration -- cgit v1.3.1 From c99b70c08cb9c3b252e015fd455c35674282aa91 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Jun 2021 12:35:51 +0700 Subject: force boot protocol for keyboard/mouse --- src/class/hid/hid_host.c | 27 +++++++++++++++------------ src/class/hid/hid_host.h | 6 +++--- 2 files changed, 18 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 81ed6e8b6..59fbb097e 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -98,7 +98,7 @@ uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) return hid_itf->itf_protocol; } -bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) +uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->protocol_mode; @@ -243,7 +243,7 @@ void hidh_close(uint8_t dev_addr) // Enumeration //--------------------------------------------------------------------+ -static bool config_get_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_set_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -286,7 +286,8 @@ uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const hid_itf->report_desc_type = desc_hid->bReportType; hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); - hid_itf->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode + // Per HID Specs: default is Report protocol, though we will force Boot protocol when set_config + hid_itf->protocol_mode = HID_PROTOCOL_BOOT; if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; drv_len += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); @@ -318,42 +319,44 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) .wLength = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_get_protocol : config_get_report_desc) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_set_protocol : config_get_report_desc) ); return true; } -static bool config_get_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +// Force device to work in BOOT protocol +static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - // Stall is a valid response for SET_IDLE GET_PROTOCOL, therefore we could ignore its result + // Stall is a valid response for SET_PROTOCOL, therefore we could ignore its result (void) result; uint8_t const itf_num = (uint8_t) request->wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - TU_LOG2("HID Get Protocol\r\n"); + TU_LOG2("HID Set Protocol\r\n"); + hid_itf->protocol_mode = HID_PROTOCOL_BOOT; tusb_control_request_t const new_request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN + .direction = TUSB_DIR_OUT }, - .bRequest = HID_REQ_CONTROL_GET_PROTOCOL, - .wValue = 0, + .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, + .wValue = HID_PROTOCOL_BOOT, .wIndex = hid_itf->itf_num, .wLength = 1 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, &hid_itf->protocol_mode, config_get_report_desc) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_get_report_desc) ); return false; } static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - // Stall is a valid response for SET_IDLE GET_PROTOCOL, therefore we could ignore its result + // Stall is a valid response for SET_IDLE, therefore we could ignore its result (void) result; uint8_t const itf_num = (uint8_t) request->wIndex; diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 6ae7c6721..b95f0d9b7 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -66,9 +66,9 @@ bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance); // Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); -// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// Note: as HID spec, device will be initialized in Report mode -bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); +// Get current protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +// Note: device will be initialized in Boot protocol for simplicity. +uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); // Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) -- cgit v1.3.1 From 58d3e8c08b05ac00bd2510c04f7679b5f7503404 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Jun 2021 12:47:48 +0700 Subject: update func comment --- src/class/hid/hid_host.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index b95f0d9b7..ef203123d 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -67,7 +67,8 @@ bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance); uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); // Get current protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// Note: device will be initialized in Boot protocol for simplicity. +// Note: Device will be initialized in Boot protocol for simplicity. +// Application can use set_protocol() to switch back to Report protocol. uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); // Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -- cgit v1.3.1 From 268dcc8d20da15e64ba7198f0412f758f6b8a911 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Jun 2021 13:05:12 +0700 Subject: fix issue with weird msc device with 3 endpoints --- src/class/msc/msc_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 83cbe7c89..2c027deff 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -366,7 +366,7 @@ uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); // msc driver length is fixed - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); TU_ASSERT(drv_len <= max_len, 0); msch_interface_t* p_msc = get_itf(dev_addr); -- cgit v1.3.1 From efc12ae7d4e2c3d6834203aff5dd1178ed601288 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 28 Jun 2021 23:57:57 +0700 Subject: fix SET_PROTOCOl, update hid host behavior for default boot interface --- examples/host/cdc_msc_hid/src/hid_app.c | 166 +++++++++++++++++++------------- src/class/hid/hid_host.c | 12 ++- 2 files changed, 108 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 817646dab..fd00cf653 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -39,11 +39,15 @@ static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; // Each HID instance can has multiple reports -static uint8_t _report_count[CFG_TUH_HID]; -static tuh_hid_report_info_t _report_info_arr[CFG_TUH_HID][MAX_REPORT]; +static struct +{ + uint8_t report_count; + tuh_hid_report_info_t report_info[MAX_REPORT]; +}hid_info[CFG_TUH_HID]; static void process_kbd_report(hid_keyboard_report_t const *report); static void process_mouse_report(hid_mouse_report_t const * report); +static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); void hid_app_task(void) { @@ -61,13 +65,19 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re { printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); - // Interface protocol - const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t - uint8_t const interface_protocol = tuh_hid_interface_protocol(dev_addr, instance); + // Interface protocol (hid_interface_protocol_enum_t) + const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; + uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); + + printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]); - // Parse report descriptor with built-in parser - _report_count[instance] = tuh_hid_parse_report_descriptor(_report_info_arr[instance], MAX_REPORT, desc_report, desc_len); - printf("HID has %u reports and interface protocol = %s\r\n", _report_count[instance], protocol_str[interface_protocol]); + // By default host stack will use activate boot protocol on supported interface. + // Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser) + if ( itf_protocol == HID_ITF_PROTOCOL_NONE ) + { + hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT, desc_report, desc_len); + printf("HID has %u reports \r\n", hid_info[instance].report_count); + } } // Invoked when device with hid interface is un-mounted @@ -79,66 +89,24 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) // Invoked when received report from device via interrupt endpoint void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) { - (void) dev_addr; + uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); - uint8_t const rpt_count = _report_count[instance]; - tuh_hid_report_info_t* rpt_info_arr = _report_info_arr[instance]; - tuh_hid_report_info_t* rpt_info = NULL; - - if ( rpt_count == 1 && rpt_info_arr[0].report_id == 0) - { - // Simple report without report ID as 1st byte - rpt_info = &rpt_info_arr[0]; - }else + switch (itf_protocol) { - // Composite report, 1st byte is report ID, data starts from 2nd byte - uint8_t const rpt_id = report[0]; - - // Find report id in the arrray - for(uint8_t i=0; iusage_page == HID_USAGE_PAGE_DESKTOP ) - { - switch (rpt_info->usage) - { - case HID_USAGE_DESKTOP_KEYBOARD: - TU_LOG1("HID receive keyboard report\r\n"); - // Assume keyboard follow boot report layout - process_kbd_report( (hid_keyboard_report_t const*) report ); - break; - - case HID_USAGE_DESKTOP_MOUSE: - TU_LOG1("HID receive mouse report\r\n"); - // Assume mouse follow boot report layout - process_mouse_report( (hid_mouse_report_t const*) report ); - break; - - default: break; - } + case HID_ITF_PROTOCOL_KEYBOARD: + TU_LOG2("HID receive boot keyboard report\r\n"); + process_kbd_report( (hid_keyboard_report_t const*) report ); + break; + + case HID_ITF_PROTOCOL_MOUSE: + TU_LOG2("HID receive boot mouse report\r\n"); + process_mouse_report( (hid_mouse_report_t const*) report ); + break; + + default: + // Generic report requires matching ReportID and contents with previous parsed report info + process_generic_report(dev_addr, instance, report, len); + break; } } @@ -243,3 +211,69 @@ static void process_mouse_report(hid_mouse_report_t const * report) //------------- cursor movement -------------// cursor_movement(report->x, report->y, report->wheel); } + +//--------------------------------------------------------------------+ +// Generic Report +//--------------------------------------------------------------------+ +static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) +{ + uint8_t const rpt_count = hid_info[instance].report_count; + tuh_hid_report_info_t* rpt_info_arr = hid_info[instance].report_info; + tuh_hid_report_info_t* rpt_info = NULL; + + if ( rpt_count == 1 && rpt_info_arr[0].report_id == 0) + { + // Simple report without report ID as 1st byte + rpt_info = &rpt_info_arr[0]; + }else + { + // Composite report, 1st byte is report ID, data starts from 2nd byte + uint8_t const rpt_id = report[0]; + + // Find report id in the arrray + for(uint8_t i=0; iusage_page == HID_USAGE_PAGE_DESKTOP ) + { + switch (rpt_info->usage) + { + case HID_USAGE_DESKTOP_KEYBOARD: + TU_LOG1("HID receive keyboard report\r\n"); + // Assume keyboard follow boot report layout + process_kbd_report( (hid_keyboard_report_t const*) report ); + break; + + case HID_USAGE_DESKTOP_MOUSE: + TU_LOG1("HID receive mouse report\r\n"); + // Assume mouse follow boot report layout + process_mouse_report( (hid_mouse_report_t const*) report ); + break; + + default: break; + } + } +} diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 59fbb097e..091c5c1c4 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -327,7 +327,7 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) // Force device to work in BOOT protocol static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - // Stall is a valid response for SET_PROTOCOL, therefore we could ignore its result + // Stall is a valid response for SET_IDLE, therefore we could ignore its result (void) result; uint8_t const itf_num = (uint8_t) request->wIndex; @@ -347,7 +347,7 @@ static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, .wValue = HID_PROTOCOL_BOOT, .wIndex = hid_itf->itf_num, - .wLength = 1 + .wLength = 0 }; TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_get_report_desc) ); @@ -356,8 +356,12 @@ static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - // Stall is a valid response for SET_IDLE, therefore we could ignore its result - (void) result; + // We can be here after SET_IDLE or SET_PROTOCOL (boot device) + // Trigger assert if result is not successful with set protocol + if ( request->bRequest != HID_REQ_CONTROL_SET_IDLE ) + { + TU_ASSERT(result == XFER_RESULT_SUCCESS); + } uint8_t const itf_num = (uint8_t) request->wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); -- cgit v1.3.1 From c172caa288213535ed5c59cea2c13d0e5b4a0597 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 29 Jun 2021 00:03:34 +0700 Subject: clean up --- src/class/hid/hid_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 091c5c1c4..40b6f5631 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -351,7 +351,7 @@ static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * }; TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_get_report_desc) ); - return false; + return true; } static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) -- cgit v1.3.1 From 36ba9608bd2e70513d5ede87c3cefe38d7edf603 Mon Sep 17 00:00:00 2001 From: Wini-Buh Date: Tue, 29 Jun 2021 00:43:41 +0200 Subject: Merge from current master. Fixed a compilation error with the GNUC toolchain --- src/portable/renesas/usba/dcd_usba.c | 13 +++++++------ src/tusb_option.h | 5 +---- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index bb4a08e2b..6f55a7226 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2020 Koji Kitayama + * Portions copyrighted (c) 2021 Roland Winistoerfer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,13 +27,9 @@ #include "tusb_option.h" -<<<<<<< HEAD -#if TUSB_OPT_DEVICE_ENABLED && (( CFG_TUSB_MCU == OPT_MCU_RX63X ) || ( CFG_TUSB_MCU == OPT_MCU_RX72N )) - -======= #if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_RX63X || \ - CFG_TUSB_MCU == OPT_MCU_RX65X) ->>>>>>> origin/master + CFG_TUSB_MCU == OPT_MCU_RX65X || \ + CFG_TUSB_MCU == OPT_MCU_RX72N ) #include "device/dcd.h" #include "iodefine.h" @@ -524,7 +521,11 @@ static void process_set_address(uint8_t rhport) const uint32_t addr = USB0.USBADDR.BIT.USBADDR; if (!addr) return; const tusb_control_request_t setup_packet = { +#if defined(__GNUC__) + .bmRequestType = 0, +#else .bmRequestType = { 0 }, /* Note: CCRX needs the braces over this struct member */ +#endif .bRequest = 5, .wValue = addr, .wIndex = 0, diff --git a/src/tusb_option.h b/src/tusb_option.h index 2a68dcbc1..e9a7ac54a 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -113,11 +113,8 @@ // Renesas RX #define OPT_MCU_RX63X 1400 ///< Renesas RX63N/631 -<<<<<<< HEAD -#define OPT_MCU_RX72N 1401 ///< Renesas RX72N -======= #define OPT_MCU_RX65X 1401 ///< Renesas RX65N/RX651 ->>>>>>> origin/master +#define OPT_MCU_RX72N 1402 ///< Renesas RX72N // Mind Motion #define OPT_MCU_MM32F327X 1500 ///< Mind Motion MM32F327 -- cgit v1.3.1 From 5877f20d4b5d54b2dfe310fedddf1c30fe6dc66c Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 29 Jun 2021 10:57:26 +0200 Subject: Fix IAR compile error on pointer type. Clean up warnings. Signed-off-by: MasterPhi --- src/class/audio/audio_device.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 7ad7edf9e..7263958df 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -885,7 +885,7 @@ range [-1, +1) * */ // Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, void * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) +static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, uint8_t * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) { // Optimize for fast half word copies typedef struct{ @@ -900,15 +900,15 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const switch (nBytesToCopy) { case 1: - while((uint8_t *)src < src_end) + while(src < src_end) { - *dst = *(uint8_t *)src++; + *dst = *src++; dst += n_ff_used; } break; case 2: - while((uint8_t *)src < src_end) + while(src < src_end) { *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; src += 2; @@ -917,23 +917,23 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const break; case 3: - while((uint8_t *)src < src_end) + while(src < src_end) { // memcpy(dst, src, 3); // src = (uint8_t *)src + 3; // dst += 3 * n_ff_used; // TODO: Is there a faster way to copy 3 bytes? - *dst++ = *(uint8_t *)src++; - *dst++ = *(uint8_t *)src++; - *dst++ = *(uint8_t *)src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; dst += 3 * (n_ff_used - 1); } break; case 4: - while((uint8_t *)src < src_end) + while(src < src_end) { *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; src += 4; @@ -993,7 +993,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi if (info.len_lin != 0) { info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length - src_end = info.ptr_lin + info.len_lin; + src_end = (uint8_t *)info.ptr_lin + info.len_lin; dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); // Limit up to desired length @@ -1002,7 +1002,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi // Handle wrapped part of FIFO if (info.len_wrap != 0) { - src_end = info.ptr_wrap + info.len_wrap; + src_end = (uint8_t *)info.ptr_wrap + info.len_wrap; audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used); } @@ -1956,7 +1956,7 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req } break; - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label + case TUSB_REQ_RCPT_ENDPOINT: { uint8_t ep = TU_U16_LOW(p_request->wIndex); @@ -2142,10 +2142,10 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * if (as_itf == audio->ep_in_as_intf_num) { audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; - audio->format_type_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; + audio->format_type_tx = (audio_format_type_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType); #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - audio->format_type_I_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; + audio->format_type_I_tx = (audio_data_format_type_I_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats); #endif } #endif -- cgit v1.3.1 From 3eec011a7c7f7c81954a417b9683eded91ad86e5 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 29 Jun 2021 17:28:35 +0700 Subject: add tud_vendor_control_request_cb() to poisoned list --- src/common/tusb_compiler.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 679060b20..f755e13f4 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -83,6 +83,10 @@ #define TU_BSWAP16(u16) (__builtin_bswap16(u16)) #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) + // List of obsolete callback function that is renamed and should not be defined. + // Put it here since only gcc support this pragma + #pragma GCC poison tud_vendor_control_request_cb + #elif defined(__TI_COMPILER_VERSION__) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) -- cgit v1.3.1 From 4c0cce4b1df707aa1aeb5e861971b5b31e94a416 Mon Sep 17 00:00:00 2001 From: Wini-Buh Date: Tue, 29 Jun 2021 21:45:18 +0200 Subject: Make toolchain dependency more consistent --- src/portable/renesas/usba/dcd_usba.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 6f55a7226..c7a6aef47 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -521,10 +521,10 @@ static void process_set_address(uint8_t rhport) const uint32_t addr = USB0.USBADDR.BIT.USBADDR; if (!addr) return; const tusb_control_request_t setup_packet = { -#if defined(__GNUC__) - .bmRequestType = 0, -#else +#if defined(__CCRX__) .bmRequestType = { 0 }, /* Note: CCRX needs the braces over this struct member */ +#else + .bmRequestType = 0, #endif .bRequest = 5, .wValue = addr, -- cgit v1.3.1 From 2b2549b57316033e544e3261334e3e20224563ce Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 30 Jun 2021 16:50:32 +0200 Subject: Fix fifo overflow correction. --- src/common/tusb_fifo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 1eb886aa1..1229201b8 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -342,7 +342,7 @@ static uint16_t backward_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) // We limit the index space of p such that a correct wrap around happens // Check for a wrap around or if we are in unused index space - This has to be checked first!! // We are exploiting the wrap around to the correct index - if ((p < p - offset) || (p - offset > f->max_pointer_idx)) + if ((p < (uint16_t)(p - offset)) || ((uint16_t)(p - offset) > f->max_pointer_idx)) { p = (p - offset) - f->non_used_index_space; } -- cgit v1.3.1 From 7321972380b7bf74557293ba975e912f2941ae02 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Wed, 30 Jun 2021 20:26:27 +0200 Subject: Force unsigned compare on advance_pointer. --- src/common/tusb_fifo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 1229201b8..73217cf75 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -325,7 +325,7 @@ static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) // We are exploiting the wrap around to the correct index // TODO warning: assuming signed overflow does not occur when assuming that (X + c) < X is always false [-Wstrict-overflow] - if ((p > p + offset) || (p + offset > f->max_pointer_idx)) + if ((p > (uint16_t)(p + offset)) || ((uint16_t)(p + offset) > f->max_pointer_idx)) { p = (p + offset) + f->non_used_index_space; } -- cgit v1.3.1 From ca98996e1f9ac802c60d9da4c28ab0e16ca640d6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 1 Jul 2021 22:46:39 +0700 Subject: better support for hid device set/get protocol add caplock detection for hid_composite --- examples/device/hid_composite/src/main.c | 31 ++++++++++++++--- hw/bsp/board.c | 58 +++++++++++++++++++++++++++++--- hw/bsp/board.h | 9 +++-- src/class/hid/hid_device.c | 28 +++++++++++++-- src/device/usbd.c | 2 +- src/device/usbd_control.c | 1 + 6 files changed, 115 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 512f6f9d9..6ddad5aae 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -255,12 +255,30 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t // received data on OUT endpoint ( Report ID = 0, Type = 0 ) void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { - // TODO set LED based on CAPLOCK, NUMLOCK etc... (void) itf; - (void) report_id; - (void) report_type; - (void) buffer; - (void) bufsize; + + if (report_type == HID_REPORT_TYPE_OUTPUT) + { + // Set keyboard LED e.g Capslock, Numlock etc... + if (report_id == REPORT_ID_KEYBOARD) + { + // bufsize should be (at least) 1 + if ( bufsize < 1 ) return; + + uint8_t const kbd_leds = buffer[0]; + + if (kbd_leds & KEYBOARD_LED_CAPSLOCK) + { + // Capslock On: disable blink, turn led on + blink_interval_ms = 0; + board_led_write(true); + }else + { + // Caplocks Off: back to normal link + blink_interval_ms = BLINK_MOUNTED; + } + } + } } //--------------------------------------------------------------------+ @@ -271,6 +289,9 @@ void led_blinking_task(void) static uint32_t start_ms = 0; static bool led_state = false; + // blink is disabled + if (!blink_interval_ms) return; + // Blink every interval ms if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 383a02ef4..c21c9e976 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -25,6 +25,60 @@ #include "board.h" +#if 0 +#define LED_PHASE_MAX 8 + +static struct +{ + uint32_t phase[LED_PHASE_MAX]; + uint8_t phase_count; + + bool led_state; + uint8_t current_phase; + uint32_t current_ms; +}led_pattern; + +void board_led_pattern(uint32_t const phase_ms[], uint8_t count) +{ + memcpy(led_pattern.phase, phase_ms, 4*count); + led_pattern.phase_count = count; + + // reset with 1st phase is on + led_pattern.current_ms = board_millis(); + led_pattern.current_phase = 0; + led_pattern.led_state = true; + board_led_on(); +} + +void board_led_task(void) +{ + if ( led_pattern.phase_count == 0 ) return; + + uint32_t const duration = led_pattern.phase[led_pattern.current_phase]; + + // return if not enough time + if (board_millis() - led_pattern.current_ms < duration) return; + + led_pattern.led_state = !led_pattern.led_state; + board_led_write(led_pattern.led_state); + + led_pattern.current_ms += duration; + led_pattern.current_phase++; + + if (led_pattern.current_phase == led_pattern.phase_count) + { + led_pattern.current_phase = 0; + led_pattern.led_state = true; + board_led_on(); + } +} + +#endif + +//--------------------------------------------------------------------+ +// newlib read()/write() retarget +//--------------------------------------------------------------------+ + #if defined(__MSP430__) #define sys_write write #define sys_read read @@ -33,10 +87,6 @@ #define sys_read _read #endif -//--------------------------------------------------------------------+ -// newlib read()/write() retarget -//--------------------------------------------------------------------+ - #if defined(LOGGER_RTT) // Logging with RTT diff --git a/hw/bsp/board.h b/hw/bsp/board.h index 7b77def50..782e0939c 100644 --- a/hw/bsp/board.h +++ b/hw/bsp/board.h @@ -54,6 +54,10 @@ void board_init(void); // Turn LED on or off void board_led_write(bool state); +// Control led pattern using phase duration in ms. +// For each phase, LED is toggle then repeated, board_led_task() is required to be called +//void board_led_pattern(uint32_t const phase_ms[], uint8_t count); + // Get the current state of button // a '1' means active (pressed), a '0' means inactive. uint32_t board_button_read(void); @@ -81,11 +85,12 @@ int board_uart_write(void const * buf, int len); } #elif CFG_TUSB_OS == OPT_OS_PICO -#include "pico/time.h" -static inline uint32_t board_millis(void) + #include "pico/time.h" + static inline uint32_t board_millis(void) { return to_ms_since_boot(get_absolute_time()); } + #elif CFG_TUSB_OS == OPT_OS_RTTHREAD static inline uint32_t board_millis(void) { diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index e44f282c4..65c7d1a18 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -280,7 +280,21 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); - uint16_t xferlen = tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); + uint8_t* report_buf = p_hid->epin_buf; + uint16_t req_len = request->wLength; + + uint16_t xferlen = 0; + + // If host request a specific Report ID, add ID to as 1 byte of response + if ( (report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1) ) + { + *report_buf++ = report_id; + req_len--; + + xferlen++; + } + + xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len); TU_ASSERT( xferlen > 0 ); tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); @@ -298,7 +312,17 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); - tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength); + uint8_t const* report_buf = p_hid->epout_buf; + uint16_t report_len = request->wLength; + + // If host request a specific Report ID, extract report ID in buffer before invoking callback + if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == p_hid->epout_buf[0]) ) + { + report_buf++; + report_len--; + } + + tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len); } break; diff --git a/src/device/usbd.c b/src/device/usbd.c index 587d487dc..af4fd58c4 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1243,7 +1243,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + TU_LOG2(" Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes); // Attempt to transfer on a busy endpoint, sound like an race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 724c652e6..7a8244699 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -186,6 +186,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result { TU_VERIFY(_ctrl_xfer.buffer); memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes); + TU_LOG_MEM(2, _usbd_ctrl_buf, xferred_bytes, 2); } _ctrl_xfer.total_xferred += xferred_bytes; -- cgit v1.3.1 From 2b3d547b7bccf46c6a274c75cb1769532611c5bf Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 1 Jul 2021 23:05:21 +0700 Subject: clean up --- src/class/hid/hid_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 65c7d1a18..a10e3a5e3 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -316,7 +316,7 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint16_t report_len = request->wLength; // If host request a specific Report ID, extract report ID in buffer before invoking callback - if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == p_hid->epout_buf[0]) ) + if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0]) ) { report_buf++; report_len--; -- cgit v1.3.1 From 3019c6eb40f5e577a5075a4fccd275c5537c5a34 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Sat, 3 Jul 2021 00:48:49 +0900 Subject: Add SUSPEND/RESUME handling for Renesas RX family. --- src/portable/renesas/usba/dcd_usba.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index de3e0e312..fa584945e 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -63,7 +63,10 @@ #define USB_IS0_CTSQ_SETUP (1u) #define USB_IS0_DVSQ_DEF (1u<<4) #define USB_IS0_DVSQ_ADDR (2u<<4) -#define USB_IS0_DVSQ_SUSP (4u<<4) +#define USB_IS0_DVSQ_SUSP0 (4u<<4) +#define USB_IS0_DVSQ_SUSP1 (5u<<4) +#define USB_IS0_DVSQ_SUSP2 (6u<<4) +#define USB_IS0_DVSQ_SUSP3 (7u<<4) #define USB_PIPECTR_PID_NAK (0u) #define USB_PIPECTR_PID_BUF (1u) @@ -125,6 +128,7 @@ typedef struct { pipe_state_t pipe[9]; uint8_t ep[2][16]; /* a lookup table for a pipe index from an endpoint address */ + uint8_t suspended; } dcd_data_t; //--------------------------------------------------------------------+ @@ -517,7 +521,8 @@ void dcd_init(uint8_t rhport) /* Setup default control pipe */ USB0.DCPMAXP.BIT.MXPS = 64; - USB0.INTENB0.WORD = USB_IS0_VBINT | USB_IS0_BRDY | USB_IS0_BEMP | USB_IS0_DVST | USB_IS0_CTRT; + USB0.INTENB0.WORD = USB_IS0_VBINT | USB_IS0_BRDY | USB_IS0_BEMP | + USB_IS0_DVST | USB_IS0_CTRT | USB_IS0_SOFR | USB_IS0_RESM; USB0.BEMPENB.WORD = 1; USB0.BRDYENB.WORD = 1; @@ -547,7 +552,8 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) void dcd_remote_wakeup(uint8_t rhport) { (void)rhport; - /* TODO */ + USB0.DVSTCTR0.BIT.WKUP = 1; + while (USB0.DVSTCTR0.BIT.WKUP) ; } void dcd_connect(uint8_t rhport) @@ -689,6 +695,17 @@ void dcd_int_handler(uint8_t rhport) dcd_disconnect(rhport); } } + if (is0 & USB_IS0_RESM) { + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); + _dcd.suspended = 0; + } + if (is0 & USB_IS0_SOFR) { + if (_dcd.suspended) { + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); + _dcd.suspended = 0; + } + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); + } if (is0 & USB_IS0_DVST) { switch (is0 & USB_IS0_DVSQ) { case USB_IS0_DVSQ_DEF: @@ -697,6 +714,12 @@ void dcd_int_handler(uint8_t rhport) case USB_IS0_DVSQ_ADDR: process_set_address(rhport); break; + case USB_IS0_DVSQ_SUSP0: + case USB_IS0_DVSQ_SUSP1: + case USB_IS0_DVSQ_SUSP2: + case USB_IS0_DVSQ_SUSP3: + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + _dcd.suspended = 1; default: break; } -- cgit v1.3.1 From 6e9da70c18a0dbabaedb1c9aadcc9fe53a0113a7 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 29 Jun 2021 22:40:21 +0200 Subject: Fix audiod_get_AS_interface_index in audio class. Enhance uac2_headset example with multiple sample rates. Add macro to calculate EP size. --- examples/device/uac2_headset/src/main.c | 69 ++++++++++++++++------ examples/device/uac2_headset/src/tusb_config.h | 13 ++-- examples/device/uac2_headset/src/usb_descriptors.c | 2 +- examples/device/uac2_headset/src/usb_descriptors.h | 8 +-- src/class/audio/audio_device.c | 16 ++--- src/device/usbd.h | 5 ++ 6 files changed, 77 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index 1b6a770a3..e76b081c8 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -34,9 +34,11 @@ // MACRO CONSTANT TYPEDEF PROTOTYPES //--------------------------------------------------------------------+ -#ifndef AUDIO_SAMPLE_RATE -#define AUDIO_SAMPLE_RATE 48000 -#endif +// List of supported sample rates +const uint32_t sample_rates[] = {44100, 48000, 88200, 96000}; +uint32_t current_sample_rate = 44100; + +#define N_SAMPLE_RATES (sizeof(sample_rates) / 4) /* Blink pattern * - 25 ms : streaming data @@ -166,24 +168,30 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t { TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK); - // Example supports only single frequency, same value will be used for current value and range if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) { if (request->bRequest == AUDIO_CS_REQ_CUR) { - TU_LOG2("Clock get current freq %u\r\n", AUDIO_SAMPLE_RATE); + TU_LOG1("Clock get current freq %u\r\n", current_sample_rate); - audio_control_cur_4_t curf = { tu_htole32(AUDIO_SAMPLE_RATE) }; + audio_control_cur_4_t curf = { tu_htole32(current_sample_rate) }; return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &curf, sizeof(curf)); } else if (request->bRequest == AUDIO_CS_REQ_RANGE) { - audio_control_range_4_n_t(1) rangef = + audio_control_range_4_n_t(N_SAMPLE_RATES) rangef = { - .wNumSubRanges = tu_htole16(1), - .subrange[0] = { tu_htole32(AUDIO_SAMPLE_RATE), tu_htole32(AUDIO_SAMPLE_RATE), 0} + .wNumSubRanges = tu_htole16(N_SAMPLE_RATES) }; - TU_LOG2("Clock get freq range (%d, %d, %d)\r\n", (int)rangef.subrange[0].bMin, (int)rangef.subrange[0].bMax, (int)rangef.subrange[0].bRes); + TU_LOG1("Clock get %d freq ranges\r\n", N_SAMPLE_RATES); + for(uint8_t i = 0; i < N_SAMPLE_RATES; i++) + { + rangef.subrange[i].bMin = sample_rates[i]; + rangef.subrange[i].bMax = sample_rates[i]; + rangef.subrange[i].bRes = 0; + TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int)rangef.subrange[i].bMin, (int)rangef.subrange[i].bMax, (int)rangef.subrange[i].bRes); + } + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &rangef, sizeof(rangef)); } } @@ -191,7 +199,7 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t request->bRequest == AUDIO_CS_REQ_CUR) { audio_control_cur_1_t cur_valid = { .bCur = 1 }; - TU_LOG2("Clock get is valid %u\r\n", cur_valid.bCur); + TU_LOG1("Clock get is valid %u\r\n", cur_valid.bCur); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_valid, sizeof(cur_valid)); } TU_LOG1("Clock get request not supported, entity = %u, selector = %u, request = %u\r\n", @@ -199,6 +207,32 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t return false; } +// Helper for clock set requests +static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) +{ + (void)rhport; + + TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT); + TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR); + + if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) + { + TU_VERIFY(request->wLength == sizeof(audio_control_cur_4_t)); + + current_sample_rate = ((audio_control_cur_4_t *)buf)->bCur; + + TU_LOG1("Clock set current freq: %d\r\n", current_sample_rate); + + return true; + } + else + { + TU_LOG1("Clock set request not supported, entity = %u, selector = %u, request = %u\r\n", + request->bEntityID, request->bControlSelector, request->bRequest); + return false; + } +} + // Helper for feature unit get requests static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_request_t const *request) { @@ -207,7 +241,7 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req if (request->bControlSelector == AUDIO_FU_CTRL_MUTE && request->bRequest == AUDIO_CS_REQ_CUR) { audio_control_cur_1_t mute1 = { .bCur = mute[request->bChannelNumber] }; - TU_LOG2("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur); + TU_LOG1("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &mute1, sizeof(mute1)); } else if (UAC2_ENTITY_SPK_FEATURE_UNIT && request->bControlSelector == AUDIO_FU_CTRL_VOLUME) @@ -218,14 +252,14 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req .wNumSubRanges = tu_htole16(1), .subrange[0] = { .bMin = tu_htole16(-VOLUME_CTRL_50_DB), tu_htole16(VOLUME_CTRL_0_DB), tu_htole16(256) } }; - TU_LOG2("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber, + TU_LOG1("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber, range_vol.subrange[0].bMin / 256, range_vol.subrange[0].bMax / 256, range_vol.subrange[0].bRes / 256); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &range_vol, sizeof(range_vol)); } else if (request->bRequest == AUDIO_CS_REQ_CUR) { audio_control_cur_2_t cur_vol = { .bCur = tu_htole16(volume[request->bChannelNumber]) }; - TU_LOG2("Get channel %u volume %u dB\r\n", request->bChannelNumber, cur_vol.bCur); + TU_LOG1("Get channel %u volume %d dB\r\n", request->bChannelNumber, cur_vol.bCur / 256); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_vol, sizeof(cur_vol)); } } @@ -249,7 +283,7 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req mute[request->bChannelNumber] = ((audio_control_cur_1_t *)buf)->bCur; - TU_LOG2("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]); + TU_LOG1("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]); return true; } @@ -259,7 +293,7 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req volume[request->bChannelNumber] = ((audio_control_cur_2_t const *)buf)->bCur; - TU_LOG2("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256); + TU_LOG1("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256); return true; } @@ -299,7 +333,8 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) return tud_audio_feature_unit_set_request(rhport, request, buf); - + if (request->bEntityID == UAC2_ENTITY_CLOCK) + return tud_audio_clock_set_request(rhport, request, buf); TU_LOG1("Set request not handled, entity = %d, selector = %d, request = %d\r\n", request->bEntityID, request->bControlSelector, request->bRequest); diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 88f9efcff..9b7ed337c 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -93,13 +93,12 @@ extern "C" { //-------------------------------------------------------------------- // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUD_AUDIO_IN_PATH (CFG_TUD_AUDIO) -#define CFG_TUD_AUDIO_OUT_PATH (CFG_TUD_AUDIO) //#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN 220 // This equals TUD_AUDIO_HEADSET_STEREO_DESC_LEN, however, including it from usb_descriptors.h is not possible due to some strange include hassle #define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN // Audio format type I specifications +#define CFG_TUD_AUDIO_FUNC_1_N_MAX_SAMPLE_RATE 96000 #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX 2 @@ -108,18 +107,18 @@ extern "C" { // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 -#define CFG_TUD_AUDIO_EP_SZ_IN (CFG_TUD_AUDIO_IN_PATH * (48 + 1) * (CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX) * (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX)) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_N_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) // 48 Samples (48 kHz) x 2 Bytes/Sample x n Channels #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN // Maximum EP IN size for all AS alternate settings used // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 -#define CFG_TUD_AUDIO_EP_OUT_SZ (CFG_TUD_AUDIO_OUT_PATH * ((48 + CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP) * (CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX) * (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX))) // N Samples (N kHz) x 2 Bytes/Sample x n Channels -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ CFG_TUD_AUDIO_EP_OUT_SZ*3 -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX CFG_TUD_AUDIO_EP_OUT_SZ // Maximum EP IN size for all AS alternate settings used +#define CFG_TUD_AUDIO_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_N_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) // N Samples (N kHz) x 2 Bytes/Sample x n Channels +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_OUT*3 +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX CFG_TUD_AUDIO_EP_SZ_OUT // Maximum EP IN size for all AS alternate settings used // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) -#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 2 // Size of control request buffer #define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index cd749eb65..f5d8e461b 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -93,7 +93,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, 2, 16, EPNUM_AUDIO, CFG_TUD_AUDIO_EP_OUT_SZ, EPNUM_AUDIO | 0x80, CFG_TUD_AUDIO_EP_SZ_IN) + TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, 2, 16, EPNUM_AUDIO, CFG_TUD_AUDIO_EP_SZ_OUT, EPNUM_AUDIO | 0x80, CFG_TUD_AUDIO_EP_SZ_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/uac2_headset/src/usb_descriptors.h b/examples/device/uac2_headset/src/usb_descriptors.h index d9c5a63a7..1595d9c5d 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.h +++ b/examples/device/uac2_headset/src/usb_descriptors.h @@ -77,7 +77,7 @@ enum /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_HEADSET, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ 3, /*_ctrl*/ 5, /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \ + TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ 3, /*_ctrl*/ 7, /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \ /* Input Terminal Descriptor(4.7.2.4) */\ TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x02, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ /* Feature Unit Descriptor(4.7.2.8) */\ @@ -99,21 +99,21 @@ enum /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 2, Alternate 0 - default alternate setting with 0 bandwidth */\ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x04),\ /* Standard AS Interface Descriptor(4.9.1) */\ - /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + /* Interface 2, Alternate 1 - alternate interface for data streaming */\ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x04),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epinsize, /*_interval*/ (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 0x04 : 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epinsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000)\ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 7263958df..cb35adb82 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1997,15 +1997,17 @@ static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio while (p_desc < p_desc_end) { // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == 0) { - *idxItf = tmp; - *pp_desc_int = p_desc; - return true; + if (((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + { + *idxItf = tmp; + *pp_desc_int = p_desc; + return true; + } + // Increase index, bytes read, and pointer + tmp++; } - - // Increase index, bytes read, and pointer - tmp++; p_desc = tu_desc_next(p_desc); } } diff --git a/src/device/usbd.h b/src/device/usbd.h index 3857295d7..45aefe53b 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -542,6 +542,11 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\ +// Calculate wMaxPacketSize of Endpoints +#define TUD_AUDIO_EP_SIZE(_maxFrequency, _nBytesPerSample, _nChannels) \ + ((((_maxFrequency + ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 7999 : 999)) / ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 8000 : 1000)) + 1) * _nBytesPerSample * _nChannels) + + //------------- TUD_USBTMC/USB488 -------------// #define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC) #define TUD_USBTMC_APP_SUBCLASS 0x03u -- cgit v1.3.1 From 204f3152cb486b8de3817bf940efd4593c8bfd07 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Thu, 1 Jul 2021 11:38:06 +0200 Subject: audio_device : clear fifo on intf change. --- src/class/audio/audio_device.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index cb35adb82..230b689cd 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1481,6 +1481,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_in_as_intf_num = 0; usbd_edpt_close(rhport, audio->ep_in); + // Clear FIFOs, since data is no longer valid + tu_fifo_clear(&audio->ep_in_ff); + // Invoke callback - can be used to stop data sampling if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); @@ -1502,6 +1505,13 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { audio->ep_out_as_intf_num = 0; usbd_edpt_close(rhport, audio->ep_out); + + // Clear FIFOs, since data is no longer valid + tu_fifo_clear(&audio->ep_out_ff); + + // Invoke callback - can be used to stop data sampling + if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + audio->ep_out = 0; // Necessary? // Clear support FIFOs if used -- cgit v1.3.1 From 5f67e5c1e9b10e40ac6e3a649f45f7719b437dc5 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Thu, 1 Jul 2021 11:45:39 +0200 Subject: Clear FIFO only if enabled... Add buffer align --- examples/device/uac2_headset/src/main.c | 14 +++++++------- examples/device/uac2_headset/src/tusb_config.h | 4 ++-- src/class/audio/audio_device.c | 4 ++++ 3 files changed, 13 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index c9e79a543..f7d20a607 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -78,9 +78,9 @@ int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master chan int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 // Buffer for microphone data -uint8_t mic_buf[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; +int32_t mic_buf[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ / 4]; // Buffer for speaker data -uint8_t spk_buf[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; +int32_t spk_buf[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ / 4]; // Speaker data size received in the last frame int spk_data_size; // Resolution per format @@ -430,14 +430,14 @@ void audio_task(void) } else if (current_resolution == 24) { - int32_t *src = (int32_t*)spk_buf; - int32_t *limit = (int32_t*)spk_buf + spk_data_size / 4; - int32_t *dst = (int32_t*)mic_buf; + int32_t *src = spk_buf; + int32_t *limit = spk_buf + spk_data_size / 4; + int32_t *dst = mic_buf; while (src < limit) { // Combine two channels into one - int32_t left = (*src++); - int32_t right = (*src++); + int32_t left = *src++; + int32_t right = *src++; *dst++ = (int32_t)((left + right) / 2) & 0xffffff00; } tud_audio_write((uint8_t *)mic_buf, spk_data_size / 2); diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 642e52551..d955a746d 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -122,7 +122,7 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) #define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN) +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN)*2 #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN) // Maximum EP IN size for all AS alternate settings used // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) @@ -131,7 +131,7 @@ extern "C" { #define CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) #define CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT)*3 +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT)*2 #define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO_UNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_UNC_1_FORMAT_2_EP_SZ_OUT) // Maximum EP IN size for all AS alternate settings used // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 230b689cd..3e05b3763 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1481,8 +1481,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_in_as_intf_num = 0; usbd_edpt_close(rhport, audio->ep_in); +#if !CFG_TUD_AUDIO_ENABLE_ENCODING // Clear FIFOs, since data is no longer valid tu_fifo_clear(&audio->ep_in_ff); +#endif // Invoke callback - can be used to stop data sampling if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); @@ -1506,8 +1508,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_out_as_intf_num = 0; usbd_edpt_close(rhport, audio->ep_out); +#if !CFG_TUD_AUDIO_ENABLE_ENCODING // Clear FIFOs, since data is no longer valid tu_fifo_clear(&audio->ep_out_ff); +#endif // Invoke callback - can be used to stop data sampling if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); -- cgit v1.3.1 From 449936c0f11ea72dd969c8bb353b0f58814f7bc6 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Fri, 2 Jul 2021 21:51:54 +0200 Subject: more uac fixes, --- src/class/audio/audio.h | 2 +- src/class/audio/audio_device.c | 50 +++++++++++++++++++++--------------------- 2 files changed, 26 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 936f09104..238295d25 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -489,7 +489,7 @@ typedef enum AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000, } audio_data_format_type_I_t; /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 3e05b3763..31b318c3f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -102,19 +102,19 @@ // EP IN software buffers and mutexes #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO #endif #endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO #endif #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO #endif @@ -126,32 +126,32 @@ osal_mutex_def_t ep_in_ff_mutex_wr_3; // - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into #if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) // EP OUT software buffers and mutexes #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO #endif #endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO #endif #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO #endif @@ -163,52 +163,52 @@ osal_mutex_def_t ep_out_ff_mutex_rd_3; // - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into #if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) // Control buffers -CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; #if CFG_TUD_AUDIO > 1 -CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; #endif #if CFG_TUD_AUDIO > 2 -CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; #endif // Active alternate setting of interfaces -CFG_TUSB_MEM_ALIGN uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 -CFG_TUSB_MEM_ALIGN uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 -CFG_TUSB_MEM_ALIGN uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; #endif // Software encoding/decoding support FIFOs #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING #if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO #endif #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO #endif #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO @@ -218,21 +218,21 @@ osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING #if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO #endif #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO #endif #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO @@ -294,7 +294,7 @@ typedef struct // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74) #if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN - CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; + CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; #endif // Decoding parameters - parameters are set when alternate AS interface is set by host -- cgit v1.3.1 From 090859bf424e910002fff7dc9195d38d6c22ae1f Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Fri, 2 Jul 2021 23:44:46 +0200 Subject: Fix speed detection --- src/class/audio/audio_device.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 31b318c3f..cc07d5e19 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -2223,22 +2223,19 @@ bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); // Format the feedback value - if (_audiod_fct[func_id].rhport == 0) - { - uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; - - // For FS format is 10.14 - *(fb++) = (feedback >> 2) & 0xFF; - *(fb++) = (feedback >> 10) & 0xFF; - *(fb++) = (feedback >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - *fb = 0; - } - else - { - // For HS format is 16.16 as originally demanded - _audiod_fct[func_id].fb_val = feedback; - } +#if !TUD_OPT_HIGH_SPEED + uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; + + // For FS format is 10.14 + *(fb++) = (feedback >> 2) & 0xFF; + *(fb++) = (feedback >> 10) & 0xFF; + *(fb++) = (feedback >> 18) & 0xFF; + // 4th byte is needed to work correctly with MS Windows + *fb = 0; +#else + // For HS format is 16.16 as originally demanded + _audiod_fct[func_id].fb_val = feedback; +#endif // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) -- cgit v1.3.1 From 61fd0e2c1cd60921ea3cc6de01534a1e512aff12 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 3 Jul 2021 10:54:20 +0200 Subject: Delay tud_audio_set_itf_cb call with feedback EP. --- src/class/audio/audio_device.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index cc07d5e19..61884f867 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1619,9 +1619,17 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * TU_ASSERT( audio->n_ff_used_rx <= audio->n_rx_supp_ff ); #endif #endif + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // In case of asynchronous EP, call Cb after ep_fb is set + if (((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.sync != 0x01) + { + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + } +#else // Invoke callback if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - +#endif // Prepare for incoming data #if USE_LINEAR_BUFFER_RX TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); -- cgit v1.3.1 From 1c8b685457aee291f8352003c7ca7b852c412982 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sun, 4 Jul 2021 00:19:33 +0200 Subject: Move audio_control_request_t to audio.h --- examples/device/uac2_headset/src/main.c | 26 -------------------------- src/class/audio/audio.h | 27 +++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index b459bc2a8..ba27350b4 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -142,32 +142,6 @@ void tud_resume_cb(void) blink_interval_ms = BLINK_MOUNTED; } -typedef struct TU_ATTR_PACKED -{ - union - { - struct TU_ATTR_PACKED - { - uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. - uint8_t type : 2; ///< Request type tusb_request_type_t. - uint8_t direction : 1; ///< Direction type. tusb_dir_t - } bmRequestType_bit; - - uint8_t bmRequestType; - }; - - uint8_t bRequest; ///< Request type audio_cs_req_t - uint8_t bChannelNumber; - uint8_t bControlSelector; - union - { - uint8_t bInterface; - uint8_t bEndpoint; - }; - uint8_t bEntityID; - uint16_t wLength; -} audio_control_request_t; - // Helper for clock get requests static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t const *request) { diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 238295d25..f99061eae 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -823,6 +823,33 @@ typedef struct TU_ATTR_PACKED uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. } audio_desc_cs_as_iso_data_ep_t; +// 5.2.2 Control Request Layout +typedef struct TU_ATTR_PACKED +{ + union + { + struct TU_ATTR_PACKED + { + uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. + uint8_t type : 2; ///< Request type tusb_request_type_t. + uint8_t direction : 1; ///< Direction type. tusb_dir_t + } bmRequestType_bit; + + uint8_t bmRequestType; + }; + + uint8_t bRequest; ///< Request type audio_cs_req_t + uint8_t bChannelNumber; + uint8_t bControlSelector; + union + { + uint8_t bInterface; + uint8_t bEndpoint; + }; + uint8_t bEntityID; + uint16_t wLength; +} audio_control_request_t; + //// 5.2.3 Control Request Parameter Block Layout // 5.2.3.1 1-byte Control CUR Parameter Block -- cgit v1.3.1 From 98d921c4b3657e473f2231857bb6c82ef567b0e3 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sun, 4 Jul 2021 15:10:45 +0200 Subject: Better handling tud_audio_set_itf_cb with FB. --- src/class/audio/audio_device.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 61884f867..c7b8b8519 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1622,7 +1622,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // In case of asynchronous EP, call Cb after ep_fb is set - if (((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.sync != 0x01) + if (!(((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.sync == 0x01 && audio->ep_fb == 0)) { if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); } @@ -1643,8 +1643,11 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { audio->ep_fb = ep_addr; - // Invoke callback - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + // Invoke callback after ep_out is set + if (audio->ep_out != 0) + { + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + } } #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT @@ -1938,8 +1941,12 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 { if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); - // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, &_audiod_fct[func_id]); + // Schedule a transmit with the new value if EP is not busy + if (!usbd_edpt_busy(rhport, _audiod_fct[func_id].ep_fb)) + { + // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent + return audiod_fb_send(rhport, &_audiod_fct[func_id]); + } } #endif #endif -- cgit v1.3.1 From dfe410ea8beb15b4d85320efeb059f42be647ea6 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 5 Jul 2021 12:38:15 +0700 Subject: fix ci build, address review comment --- src/class/dfu/dfu_device.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index df731ee50..c696d70a2 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -247,9 +247,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) { - TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); - TU_ASSERT( retval <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; } @@ -277,7 +276,7 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * // if they wish, there still will be the internal control buffer copy to this buffer // but this mode would provide zero copy from the class driver to the application - TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); // setup for data phase tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, request->wLength); } @@ -285,7 +284,7 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { (void) rhport; - TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; } -- cgit v1.3.1 From 1ff3b76451c446cfd79fb7728f4e457e4dc0d7cb Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Mon, 5 Jul 2021 21:27:08 +0900 Subject: remove unnecessary blocking operation. add comments why resume event is sent manually. --- src/portable/renesas/usba/dcd_usba.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index fa584945e..338d5b0e6 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -553,7 +553,6 @@ void dcd_remote_wakeup(uint8_t rhport) { (void)rhport; USB0.DVSTCTR0.BIT.WKUP = 1; - while (USB0.DVSTCTR0.BIT.WKUP) ; } void dcd_connect(uint8_t rhport) @@ -701,6 +700,11 @@ void dcd_int_handler(uint8_t rhport) } if (is0 & USB_IS0_SOFR) { if (_dcd.suspended) { + /* When USB host resumes caused by `dcd_remote_wakeup()`, + * RESM interrupt does not rise. + * Therefore we need to manually send resume event. + * Of course, when USB host resumes on its own, + * RESM interrupt rise properly, then this statements are ignored. */ dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); _dcd.suspended = 0; } -- cgit v1.3.1 From c2d8ed3fd1fdb722d67a30a6768720c9ed578779 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Mon, 5 Jul 2021 17:56:21 +0200 Subject: Add alt settings support in DFU class. --- examples/device/dfu/src/main.c | 25 ++++++++--------- examples/device/dfu/src/usb_descriptors.c | 8 ++++-- src/class/dfu/dfu_device.c | 46 ++++++++++++++++++++----------- src/class/dfu/dfu_device.h | 10 ++++--- src/device/usbd.h | 8 +++--- 5 files changed, 56 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 1c09066a8..81532ee90 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -115,25 +115,20 @@ void tud_resume_cb(void) blink_interval_ms = BLINK_MOUNTED; } -// Invoked on DFU_DETACH request to reboot to the bootloader -void tud_dfu_runtime_reboot_to_dfu_cb(void) -{ - blink_interval_ms = BLINK_DFU_MODE; -} - //--------------------------------------------------------------------+ // Class callbacks //--------------------------------------------------------------------+ -bool tud_dfu_firmware_valid_check_cb(void) +bool tud_dfu_firmware_valid_check_cb(uint8_t alt) { + (void) alt; printf(" Firmware check\r\n"); return true; } -void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length) +void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length) { (void) data; - printf(" Received BlockNum %u of length %u\r\n", wBlockNum, length); + printf(" Received Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); #if DFU_VERBOSE for(uint16_t i=0; ibInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && - (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); + uint16_t drv_len = 0; + uint8_t const * p_desc = (uint8_t*)itf_desc; - uint8_t const * p_desc = tu_desc_next( itf_desc ); - uint16_t drv_len = sizeof(tusb_desc_interface_t); - - if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) + while (max_len) { - tusb_desc_dfu_functional_t const *dfu_desc = (tusb_desc_dfu_functional_t const *)p_desc; - _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; - + // Ensure this is DFU Mode + TU_VERIFY((((tusb_desc_interface_t const *)p_desc)->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && + (((tusb_desc_interface_t const *)p_desc)->bInterfaceProtocol == DFU_PROTOCOL_DFU), drv_len); + + p_desc = tu_desc_next( p_desc ); drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } + if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) + { + tusb_desc_dfu_functional_t const *dfu_desc = (tusb_desc_dfu_functional_t const *)p_desc; + _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; + + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + + max_len -= drv_len; + } return drv_len; } @@ -200,6 +208,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && TUSB_REQ_SET_INTERFACE == request->bRequest ) { + // Save Alt interface + _dfu_state_ctx.alt = request->wValue; tud_control_status(rhport, request); return true; } @@ -248,7 +258,11 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) { TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); - uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + uint16_t retval = 0; + if (tud_dfu_req_upload_data_cb) + { + tud_dfu_req_upload_data_cb(_dfu_state_ctx.alt, block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + } tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; } @@ -285,7 +299,7 @@ static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * { (void) rhport; TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); + tud_dfu_req_dnload_data_cb(_dfu_state_ctx.alt, request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; } @@ -426,7 +440,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req _dfu_state_ctx.blk_transfer_in_proc = true; dfu_req_dnload_setup(rhport, request); } else { - if ( tud_dfu_device_data_done_check_cb() ) + if ( tud_dfu_device_data_done_check_cb(_dfu_state_ctx.alt) ) { _dfu_state_ctx.state = DFU_MANIFEST_SYNC; tud_control_status(rhport, request); @@ -481,7 +495,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); } else { - if ( tud_dfu_firmware_valid_check_cb() ) + if ( tud_dfu_firmware_valid_check_cb(_dfu_state_ctx.alt) ) { _dfu_state_ctx.state = DFU_IDLE; } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 9a09a46b1..d5bc88ab2 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -39,13 +39,14 @@ //--------------------------------------------------------------------+ // Invoked during DFU_MANIFEST_SYNC get status request to check if firmware // is valid -bool tud_dfu_firmware_valid_check_cb(void); +bool tud_dfu_firmware_valid_check_cb(uint8_t alt); // Invoked when a DFU_DNLOAD request is received // This callback takes the wBlockNum chunk of length length and provides it // to the application at the data pointer. This data is only valid for this // call, so the app must use it not or copy it. -void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length); +// alt is used as the partition number, in order to multiple partitions like FLASH, EEPROM, etc. +void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); // Must be called when the application is done using the last block of data // provided by tud_dfu_req_dnload_data_cb @@ -56,7 +57,7 @@ void tud_dfu_dnload_complete(void); // Return true if the application agrees there is no more data // Return false if the device disagrees, which will stall the pipe, and the Host // should initiate a recovery procedure -bool tud_dfu_device_data_done_check_cb(void); +bool tud_dfu_device_data_done_check_cb(uint8_t alt); // Invoked when the Host has terminated a download or upload transfer TU_ATTR_WEAK void tud_dfu_abort_cb(void); @@ -64,7 +65,8 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(void); // Invoked when a DFU_UPLOAD request is received // This callback must populate data with up to length bytes // Return the number of bytes to write -uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length); +// alt is used as the partition number, in order to multiple partitions like FLASH, EEPROM, etc. +TU_ATTR_WEAK uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/device/usbd.h b/src/device/usbd.h index 3857295d7..41c78de10 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -603,11 +603,11 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb // Length of template descriptr: 18 bytes #define TUD_DFU_MODE_DESC_LEN (9 + 9) -// DFU runtime descriptor -// Interface number, string index, attributes, detach timeout, transfer size -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \ +// DFU mode descriptor +// Interface number, alt settings, string index, attributes, detach timeout, transfer size +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _alt, _stridx, _attr, _timeout, _xfer_size) \ /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -- cgit v1.3.1 From c2b9ac9dd415505350c40f6830c1d211de67c342 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Mon, 5 Jul 2021 17:57:23 +0200 Subject: Fix ATTR_MANIFESTATION_TOLERANT logic. --- src/class/dfu/dfu_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 0570b5958..9eafca359 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -310,7 +310,7 @@ void tud_dfu_dnload_complete(void) _dfu_state_ctx.state = DFU_DNLOAD_SYNC; } else if (_dfu_state_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -490,7 +490,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0) + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) { _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); -- cgit v1.3.1 From 05a1b854ffcebe8144481a8af9e447d0eac2ae1f Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Mon, 5 Jul 2021 21:00:04 +0200 Subject: ENCODE -> DECODE --- src/class/audio/audio_device.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index c7b8b8519..97a9c495e 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1481,9 +1481,14 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_in_as_intf_num = 0; usbd_edpt_close(rhport, audio->ep_in); -#if !CFG_TUD_AUDIO_ENABLE_ENCODING // Clear FIFOs, since data is no longer valid +#if !CFG_TUD_AUDIO_ENABLE_ENCODING tu_fifo_clear(&audio->ep_in_ff); +#else + for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) + { + tu_fifo_clear(&audio->tx_supp_ff[cnt]); + } #endif // Invoke callback - can be used to stop data sampling @@ -1491,14 +1496,6 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_in = 0; // Necessary? - // Clear support FIFOs if used -#if CFG_TUD_AUDIO_ENABLE_ENCODING - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->tx_supp_ff[cnt]); - } -#endif - } #endif @@ -1508,9 +1505,14 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_out_as_intf_num = 0; usbd_edpt_close(rhport, audio->ep_out); -#if !CFG_TUD_AUDIO_ENABLE_ENCODING // Clear FIFOs, since data is no longer valid +#if !CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_clear(&audio->ep_out_ff); +#else + for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) + { + tu_fifo_clear(&audio->rx_supp_ff[cnt]); + } #endif // Invoke callback - can be used to stop data sampling @@ -1518,14 +1520,6 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_out = 0; // Necessary? - // Clear support FIFOs if used -#if CFG_TUD_AUDIO_ENABLE_DECODING - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) - { - tu_fifo_clear(&audio->rx_supp_ff[cnt]); - } -#endif - // Close corresponding feedback EP #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP usbd_edpt_close(rhport, audio->ep_fb); -- cgit v1.3.1 From 82d355aefe5251f6dd15a7406920efaf516df705 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 6 Jul 2021 00:25:00 +0200 Subject: - Remove alt_setting alignment --- src/class/audio/audio_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 97a9c495e..f6e6e13f4 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -183,12 +183,12 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_ #endif // Active alternate setting of interfaces -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; +uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; +uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; +uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; #endif // Software encoding/decoding support FIFOs -- cgit v1.3.1 From 72f916423e85083a090186ecc05a6a5b8962685a Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 6 Jul 2021 10:56:13 +0200 Subject: Fix copy byte count --- src/class/audio/audio_device.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index f6e6e13f4..404d28817 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -643,7 +643,6 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u // Determine amount of samples uint8_t const n_ff_used = audio->n_ff_used_rx; - uint16_t const nBytesToCopy = audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx; uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used; uint8_t cnt_ff; @@ -662,14 +661,14 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin); src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; dst_end = info.ptr_lin + info.len_lin; - src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); + src = audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_lin, dst_end, src, n_ff_used); // Handle wrapped part of FIFO info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap); if (info.len_wrap != 0) { dst_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_wrap, dst_end, src, n_ff_used); + audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_wrap, dst_end, src, n_ff_used); } tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } @@ -994,7 +993,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi { info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length src_end = (uint8_t *)info.ptr_lin + info.len_lin; - dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); + dst = audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_lin, src_end, dst, n_ff_used); // Limit up to desired length info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap); @@ -1003,7 +1002,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi if (info.len_wrap != 0) { src_end = (uint8_t *)info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used); + audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_wrap, src_end, dst, n_ff_used); } tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); -- cgit v1.3.1 From cf4220a9fb24279b423656257cea39b3ab68aa67 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 6 Jul 2021 18:03:05 +0200 Subject: Update --- examples/device/dfu/src/tusb_config.h | 1 + src/class/dfu/dfu_device.c | 3 +++ src/class/dfu/dfu_device.h | 11 +++++++++-- 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 90e90b2e4..0df46c14e 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -76,6 +76,7 @@ #define CFG_TUD_ENDPOINT0_SIZE 64 #endif +// DFU buffer size, must to be set to the largest buffer size used by an any given storage type #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 //------------- CLASS -------------// diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 9eafca359..a186e9140 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -147,6 +147,7 @@ void dfu_moded_init(void) _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.alt = 0; dfu_debug_print_context(); } @@ -158,6 +159,8 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.blk_transfer_in_proc = false; + _dfu_state_ctx.alt = 0; + dfu_debug_print_context(); } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index d5bc88ab2..c5c1ede28 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -33,6 +33,13 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Class Driver Default Configure & Validation +//--------------------------------------------------------------------+ + +#if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) + #error " CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it have to be set to the largest buffer size used by an any given storage type" +#endif //--------------------------------------------------------------------+ // Application Callback API (weak is optional) @@ -45,7 +52,7 @@ bool tud_dfu_firmware_valid_check_cb(uint8_t alt); // This callback takes the wBlockNum chunk of length length and provides it // to the application at the data pointer. This data is only valid for this // call, so the app must use it not or copy it. -// alt is used as the partition number, in order to multiple partitions like FLASH, EEPROM, etc. +// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); // Must be called when the application is done using the last block of data @@ -65,7 +72,7 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(void); // Invoked when a DFU_UPLOAD request is received // This callback must populate data with up to length bytes // Return the number of bytes to write -// alt is used as the partition number, in order to multiple partitions like FLASH, EEPROM, etc. +// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. TU_ATTR_WEAK uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); //--------------------------------------------------------------------+ -- cgit v1.3.1 From bc49ee7f2fc74932c332520b0fd8eccefbae659a Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 7 Jul 2021 11:55:36 +0200 Subject: Better alt settings support --- src/class/dfu/dfu_device.c | 92 +++++++++++++++++++++++++++++++++------------- src/class/dfu/dfu_device.h | 7 +++- 2 files changed, 72 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index a186e9140..f6fcb1339 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -37,6 +37,8 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +#define DFU_INTF_UNUSED 0xFF + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -44,9 +46,10 @@ typedef struct TU_ATTR_PACKED { dfu_device_status_t status; dfu_state_t state; - uint8_t attrs; + uint8_t attrs[CFG_TUD_DFU_ATL_MAX]; bool blk_transfer_in_proc; uint8_t alt; + uint8_t intf; CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; } dfu_state_ctx_t; @@ -145,9 +148,13 @@ void dfu_moded_init(void) { _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.attrs = 0; + for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) + { + _dfu_state_ctx.attrs[i] = 0; + } _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; + _dfu_state_ctx.intf = DFU_INTF_UNUSED; dfu_debug_print_context(); } @@ -158,8 +165,13 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; + for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) + { + _dfu_state_ctx.attrs[i] = 0; + } _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; + _dfu_state_ctx.intf = DFU_INTF_UNUSED; dfu_debug_print_context(); } @@ -167,32 +179,55 @@ void dfu_moded_reset(uint8_t rhport) uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { (void) rhport; - (void) max_len; - uint16_t drv_len = 0; - uint8_t const * p_desc = (uint8_t*)itf_desc; + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_dfu_functional_t); + + uint8_t const *p_desc = (uint8_t const *)itf_desc; - while (max_len) + uint16_t total_len = 0; + + uint8_t last_alt = 0; + + while(max_len >= drv_len) { // Ensure this is DFU Mode TU_VERIFY((((tusb_desc_interface_t const *)p_desc)->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && - (((tusb_desc_interface_t const *)p_desc)->bInterfaceProtocol == DFU_PROTOCOL_DFU), drv_len); - - p_desc = tu_desc_next( p_desc ); - drv_len += tu_desc_len(p_desc); + (((tusb_desc_interface_t const *)p_desc)->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); - if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) - { - tusb_desc_dfu_functional_t const *dfu_desc = (tusb_desc_dfu_functional_t const *)p_desc; - _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes; + uint8_t const alt = ((tusb_desc_interface_t const *)p_desc)->bAlternateSetting; + uint8_t const intf = ((tusb_desc_interface_t const *)p_desc)->bInterfaceNumber; - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + if (_dfu_state_ctx.intf == DFU_INTF_UNUSED) + { + _dfu_state_ctx.intf = intf; } + else + { + // Only one DFU interface is supported + TU_ASSERT(_dfu_state_ctx.intf == intf); + } + + // CFG_TUD_DFU_ATL_MAX should big enough to hold all alt settings + TU_ASSERT(alt < CFG_TUD_DFU_ATL_MAX); + + // Alt should increse by one every time + TU_ASSERT(alt == last_alt++); + + //------------- DFU descriptor -------------// + p_desc = tu_desc_next(p_desc); + TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); + _dfu_state_ctx.attrs[alt] = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; + + // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the largest buffer size used by all alt settings + TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + + p_desc = tu_desc_next(p_desc); max_len -= drv_len; + total_len += drv_len; } - return drv_len; + + return total_len; } // Invoked when a control transfer occurred on an interface of this class @@ -208,11 +243,16 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque if(stage == CONTROL_STAGE_SETUP) { // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request - if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type && - TUSB_REQ_SET_INTERFACE == request->bRequest ) + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_INTERFACE) { - // Save Alt interface + // Switch Alt interface _dfu_state_ctx.alt = request->wValue; + + // Re-initalise state machine (Necessary ?) + _dfu_state_ctx.state = DFU_IDLE; + _dfu_state_ctx.status = DFU_STATUS_OK; + _dfu_state_ctx.blk_transfer_in_proc = false; + tud_control_status(rhport, request); return true; } @@ -226,7 +266,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case DFU_REQUEST_DNLOAD: { if ( (stage == CONTROL_STAGE_ACK) - && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC)) { dfu_req_dnload_reply(rhport, request); @@ -313,7 +353,7 @@ void tud_dfu_dnload_complete(void) _dfu_state_ctx.state = DFU_DNLOAD_SYNC; } else if (_dfu_state_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -331,7 +371,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -345,7 +385,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req case DFU_REQUEST_UPLOAD: { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) { _dfu_state_ctx.state = DFU_UPLOAD_IDLE; dfu_req_upload(rhport, request, request->wValue, request->wLength); @@ -436,7 +476,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -493,7 +533,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) { _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index c5c1ede28..6f826152f 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -37,8 +37,13 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ +// Maximum alternate settings (used for different partitons) supported +#if !defined(CFG_TUD_DFU_ATL_MAX) + #define CFG_TUD_DFU_ATL_MAX 2 +#endif + #if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) - #error " CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it have to be set to the largest buffer size used by an any given storage type" + #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the largest buffer size used by an any given storage type" #endif //--------------------------------------------------------------------+ -- cgit v1.3.1 From 88478594bc0c5946853567620beb944940f81a1d Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 7 Jul 2021 12:06:41 +0200 Subject: Update comment --- src/class/dfu/dfu_device.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 6f826152f..67d15c3c6 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -49,15 +49,15 @@ //--------------------------------------------------------------------+ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -// Invoked during DFU_MANIFEST_SYNC get status request to check if firmware -// is valid +// Invoked during DFU_MANIFEST_SYNC get status request to check if firmware is valid +// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. bool tud_dfu_firmware_valid_check_cb(uint8_t alt); // Invoked when a DFU_DNLOAD request is received +// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. // This callback takes the wBlockNum chunk of length length and provides it // to the application at the data pointer. This data is only valid for this // call, so the app must use it not or copy it. -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); // Must be called when the application is done using the last block of data @@ -66,6 +66,7 @@ void tud_dfu_dnload_complete(void); // Invoked during the last DFU_DNLOAD request, signifying that the host believes // it is done transmitting data. +// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. // Return true if the application agrees there is no more data // Return false if the device disagrees, which will stall the pipe, and the Host // should initiate a recovery procedure @@ -75,9 +76,9 @@ bool tud_dfu_device_data_done_check_cb(uint8_t alt); TU_ATTR_WEAK void tud_dfu_abort_cb(void); // Invoked when a DFU_UPLOAD request is received +// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. // This callback must populate data with up to length bytes // Return the number of bytes to write -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. TU_ATTR_WEAK uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); //--------------------------------------------------------------------+ -- cgit v1.3.1 From 3949fb9e8c1b9a9646223e3edf7a0df4f010b5be Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 7 Jul 2021 12:07:10 +0200 Subject: Add DFU_DETACH support --- src/class/dfu/dfu_device.c | 7 ++++++- src/class/dfu/dfu_device.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index f6fcb1339..f4edd713a 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -263,6 +263,12 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque switch (request->bRequest) { + case DFU_REQUEST_DETACH: + { + tud_control_status(rhport, request); + if (tud_dfu_reboot_cb) tud_dfu_reboot_cb(); + break; + } case DFU_REQUEST_DNLOAD: { if ( (stage == CONTROL_STAGE_ACK) @@ -273,7 +279,6 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque return true; } } // fallthrough - case DFU_REQUEST_DETACH: case DFU_REQUEST_UPLOAD: case DFU_REQUEST_GETSTATUS: case DFU_REQUEST_CLRSTATUS: diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 67d15c3c6..53be0005e 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -81,6 +81,8 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(void); // Return the number of bytes to write TU_ATTR_WEAK uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); +// Invoked when a DFU_DETACH request is received +TU_ATTR_WEAK void tud_dfu_reboot_cb(void); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -- cgit v1.3.1 From 71c00432610780f07d0e0776eacdda1186481854 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 7 Jul 2021 12:18:25 +0200 Subject: TU_ASSERT return 0. --- src/class/dfu/dfu_device.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index f4edd713a..8bf2e16be 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -204,14 +204,14 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, else { // Only one DFU interface is supported - TU_ASSERT(_dfu_state_ctx.intf == intf); + TU_ASSERT(_dfu_state_ctx.intf == intf, 0); } // CFG_TUD_DFU_ATL_MAX should big enough to hold all alt settings - TU_ASSERT(alt < CFG_TUD_DFU_ATL_MAX); + TU_ASSERT(alt < CFG_TUD_DFU_ATL_MAX, 0); // Alt should increse by one every time - TU_ASSERT(alt == last_alt++); + TU_ASSERT(alt == last_alt++, 0); //------------- DFU descriptor -------------// p_desc = tu_desc_next(p_desc); @@ -220,7 +220,7 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, _dfu_state_ctx.attrs[alt] = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the largest buffer size used by all alt settings - TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); p_desc = tu_desc_next(p_desc); max_len -= drv_len; -- cgit v1.3.1 From 941b02c6a98cd34eb84cf499db9810108871d49b Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 7 Jul 2021 18:02:04 +0200 Subject: Reactor to one functional descriptor. --- examples/device/dfu/src/tusb_config.h | 8 +++-- examples/device/dfu/src/usb_descriptors.c | 7 ++--- src/class/dfu/dfu_device.c | 51 ++++++++++++++----------------- src/class/dfu/dfu_device.h | 7 +---- src/device/usbd.h | 47 +++++++++++++++++++++++----- 5 files changed, 72 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 0df46c14e..55aa19922 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -76,14 +76,16 @@ #define CFG_TUD_ENDPOINT0_SIZE 64 #endif -// DFU buffer size, must to be set to the largest buffer size used by an any given storage type -#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 - //------------- CLASS -------------// #define CFG_TUD_DFU_RUNTIME 0 #define CFG_TUD_DFU_MODE 1 +// Count of all alt settings, typically it's the partition count (Flash, EEPROM, etc.) +#define CFG_TUD_DFU_ALT_COUNT 2 +// DFU buffer size, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR +#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 + #ifdef __cplusplus } #endif diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index 9565da9b2..200817eb4 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -87,7 +87,7 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + 2 * TUD_DFU_MODE_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_MODE_DESC_LEN) #define FUNC_ATTRS (DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK | DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) @@ -96,9 +96,8 @@ 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), - // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 0, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 1, 5, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), + // Interface number, detach timeout, transfer size, string index 0, [string index 1 ... string index n] + TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 0, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 4, 5), }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 8bf2e16be..834648c5a 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -46,7 +46,7 @@ typedef struct TU_ATTR_PACKED { dfu_device_status_t status; dfu_state_t state; - uint8_t attrs[CFG_TUD_DFU_ATL_MAX]; + uint8_t attrs; bool blk_transfer_in_proc; uint8_t alt; uint8_t intf; @@ -148,10 +148,7 @@ void dfu_moded_init(void) { _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; - for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) - { - _dfu_state_ctx.attrs[i] = 0; - } + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; _dfu_state_ctx.intf = DFU_INTF_UNUSED; @@ -165,10 +162,7 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; - for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) - { - _dfu_state_ctx.attrs[i] = 0; - } + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; _dfu_state_ctx.intf = DFU_INTF_UNUSED; @@ -180,15 +174,15 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, { (void) rhport; - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_dfu_functional_t); + uint16_t const drv_len = sizeof(tusb_desc_interface_t); uint8_t const *p_desc = (uint8_t const *)itf_desc; uint16_t total_len = 0; - + uint8_t last_alt = 0; - while(max_len >= drv_len) + while(max_len > drv_len) { // Ensure this is DFU Mode TU_VERIFY((((tusb_desc_interface_t const *)p_desc)->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && @@ -208,25 +202,26 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, } // CFG_TUD_DFU_ATL_MAX should big enough to hold all alt settings - TU_ASSERT(alt < CFG_TUD_DFU_ATL_MAX, 0); + TU_ASSERT(alt < CFG_TUD_DFU_ALT_COUNT, 0); // Alt should increse by one every time TU_ASSERT(alt == last_alt++, 0); - //------------- DFU descriptor -------------// - p_desc = tu_desc_next(p_desc); - TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); - - _dfu_state_ctx.attrs[alt] = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; - - // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the largest buffer size used by all alt settings - TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); - p_desc = tu_desc_next(p_desc); max_len -= drv_len; total_len += drv_len; } + //------------- DFU descriptor -------------// + TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); + + _dfu_state_ctx.attrs = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; + + // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR + TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); + + total_len += sizeof(tusb_desc_dfu_functional_t); + return total_len; } @@ -272,7 +267,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case DFU_REQUEST_DNLOAD: { if ( (stage == CONTROL_STAGE_ACK) - && ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC)) { dfu_req_dnload_reply(rhport, request); @@ -358,7 +353,7 @@ void tud_dfu_dnload_complete(void) _dfu_state_ctx.state = DFU_DNLOAD_SYNC; } else if (_dfu_state_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -376,7 +371,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -390,7 +385,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req case DFU_REQUEST_UPLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) { _dfu_state_ctx.state = DFU_UPLOAD_IDLE; dfu_req_upload(rhport, request, request->wValue, request->wLength); @@ -481,7 +476,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -538,7 +533,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) { _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 53be0005e..f41b4b651 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -37,13 +37,8 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -// Maximum alternate settings (used for different partitons) supported -#if !defined(CFG_TUD_DFU_ATL_MAX) - #define CFG_TUD_DFU_ATL_MAX 2 -#endif - #if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) - #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the largest buffer size used by an any given storage type" + #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR" #endif //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index 41c78de10..fe1863706 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -600,17 +600,50 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -// Length of template descriptr: 18 bytes -#define TUD_DFU_MODE_DESC_LEN (9 + 9) +// Maximum alternate settings (used for different partitons) supported +#ifndef CFG_TUD_DFU_ALT_COUNT +#define CFG_TUD_DFU_ALT_COUNT 1 +#endif -// DFU mode descriptor -// Interface number, alt settings, string index, attributes, detach timeout, transfer size -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _alt, _stridx, _attr, _timeout, _xfer_size) \ - /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ +// Length of template descriptor: 18 bytes + number of alternatives * 9 +#define TUD_DFU_MODE_DESC_LEN (9 + (CFG_TUD_DFU_ALT_COUNT) * 9) + +/* Primary Interface */ +#define TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +#define TUD_DFU_MODE_ALT(_itfnum, _alt, _stridx) \ + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + +#define _TUD_DFU_FIRST(a, ...) a +#define _TUD_DFU_REST(a, ...) __VA_ARGS__ +#define _TUD_DFU_COMBINE(...) __VA_ARGS__ + +#define TUD_DFU_MODE_ALT_1(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 1, _TUD_DFU_FIRST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_2(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 2, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_1(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_3(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 3, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_2(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_4(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 4, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_3(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_5(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 5, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_4(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_6(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 6, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_5(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_7(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 7, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_6(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_8(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 8, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_7(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) + +#define TUD_DFU_MODE_ALTS(_itfnum, ...) \ + TU_XSTRCAT(TUD_DFU_MODE_ALT_, CFG_TUD_DFU_ALT_COUNT)(_itfnum, __VA_ARGS__) + +// Interface number, detach timeout, transfer size, string index 1, [string index 2, string index n] +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _attr, _timeout, _xfer_size, _stridx, ...) \ + TUD_DFU_MODE_ALTS(_itfnum, _TUD_DFU_COMBINE(_stridx, __VA_ARGS__)) \ + TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) //------------- CDC-ECM -------------// -- cgit v1.3.1 From 7e883e0f41a4fdda699bbaf1d64a28d82527b8f9 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 7 Jul 2021 19:01:00 +0200 Subject: Refactor with one DFU functionnal descriptor --- examples/device/dfu/src/tusb_config.h | 8 +++-- examples/device/dfu/src/usb_descriptors.c | 7 ++--- src/class/dfu/dfu_device.c | 51 ++++++++++++++----------------- src/class/dfu/dfu_device.h | 7 +---- src/device/usbd.h | 47 +++++++++++++++++++++++----- 5 files changed, 72 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 0df46c14e..55aa19922 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -76,14 +76,16 @@ #define CFG_TUD_ENDPOINT0_SIZE 64 #endif -// DFU buffer size, must to be set to the largest buffer size used by an any given storage type -#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 - //------------- CLASS -------------// #define CFG_TUD_DFU_RUNTIME 0 #define CFG_TUD_DFU_MODE 1 +// Count of all alt settings, typically it's the partition count (Flash, EEPROM, etc.) +#define CFG_TUD_DFU_ALT_COUNT 2 +// DFU buffer size, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR +#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 + #ifdef __cplusplus } #endif diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index 9565da9b2..8c5eee455 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -87,7 +87,7 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + 2 * TUD_DFU_MODE_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_MODE_DESC_LEN) #define FUNC_ATTRS (DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK | DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) @@ -96,9 +96,8 @@ 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), - // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 0, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, 1, 5, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), + // Interface number, attributes, detach timeout, transfer size, string index 0, [string index 1 ... string index n] + TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 4, 5), }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 8bf2e16be..834648c5a 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -46,7 +46,7 @@ typedef struct TU_ATTR_PACKED { dfu_device_status_t status; dfu_state_t state; - uint8_t attrs[CFG_TUD_DFU_ATL_MAX]; + uint8_t attrs; bool blk_transfer_in_proc; uint8_t alt; uint8_t intf; @@ -148,10 +148,7 @@ void dfu_moded_init(void) { _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; - for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) - { - _dfu_state_ctx.attrs[i] = 0; - } + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; _dfu_state_ctx.intf = DFU_INTF_UNUSED; @@ -165,10 +162,7 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.state = DFU_IDLE; _dfu_state_ctx.status = DFU_STATUS_OK; - for (uint8_t i = 0; i < CFG_TUD_DFU_ATL_MAX; i++) - { - _dfu_state_ctx.attrs[i] = 0; - } + _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; _dfu_state_ctx.intf = DFU_INTF_UNUSED; @@ -180,15 +174,15 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, { (void) rhport; - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_dfu_functional_t); + uint16_t const drv_len = sizeof(tusb_desc_interface_t); uint8_t const *p_desc = (uint8_t const *)itf_desc; uint16_t total_len = 0; - + uint8_t last_alt = 0; - while(max_len >= drv_len) + while(max_len > drv_len) { // Ensure this is DFU Mode TU_VERIFY((((tusb_desc_interface_t const *)p_desc)->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && @@ -208,25 +202,26 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, } // CFG_TUD_DFU_ATL_MAX should big enough to hold all alt settings - TU_ASSERT(alt < CFG_TUD_DFU_ATL_MAX, 0); + TU_ASSERT(alt < CFG_TUD_DFU_ALT_COUNT, 0); // Alt should increse by one every time TU_ASSERT(alt == last_alt++, 0); - //------------- DFU descriptor -------------// - p_desc = tu_desc_next(p_desc); - TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); - - _dfu_state_ctx.attrs[alt] = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; - - // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the largest buffer size used by all alt settings - TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); - p_desc = tu_desc_next(p_desc); max_len -= drv_len; total_len += drv_len; } + //------------- DFU descriptor -------------// + TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); + + _dfu_state_ctx.attrs = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; + + // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR + TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); + + total_len += sizeof(tusb_desc_dfu_functional_t); + return total_len; } @@ -272,7 +267,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case DFU_REQUEST_DNLOAD: { if ( (stage == CONTROL_STAGE_ACK) - && ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC)) { dfu_req_dnload_reply(rhport, request); @@ -358,7 +353,7 @@ void tud_dfu_dnload_complete(void) _dfu_state_ctx.state = DFU_DNLOAD_SYNC; } else if (_dfu_state_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -376,7 +371,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -390,7 +385,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req case DFU_REQUEST_UPLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) { _dfu_state_ctx.state = DFU_UPLOAD_IDLE; dfu_req_upload(rhport, request, request->wValue, request->wLength); @@ -481,7 +476,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { _dfu_state_ctx.state = DFU_DNLOAD_SYNC; @@ -538,7 +533,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs[_dfu_state_ctx.alt] & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) { _dfu_state_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 53be0005e..f41b4b651 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -37,13 +37,8 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -// Maximum alternate settings (used for different partitons) supported -#if !defined(CFG_TUD_DFU_ATL_MAX) - #define CFG_TUD_DFU_ATL_MAX 2 -#endif - #if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) - #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the largest buffer size used by an any given storage type" + #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR" #endif //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index 41c78de10..3d49d4b12 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -600,17 +600,50 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -// Length of template descriptr: 18 bytes -#define TUD_DFU_MODE_DESC_LEN (9 + 9) +// Maximum alternate settings (used for different partitons) supported +#ifndef CFG_TUD_DFU_ALT_COUNT +#define CFG_TUD_DFU_ALT_COUNT 1 +#endif -// DFU mode descriptor -// Interface number, alt settings, string index, attributes, detach timeout, transfer size -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _alt, _stridx, _attr, _timeout, _xfer_size) \ - /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ +// Length of template descriptor: 18 bytes + number of alternatives * 9 +#define TUD_DFU_MODE_DESC_LEN (9 + (CFG_TUD_DFU_ALT_COUNT) * 9) + +/* Primary Interface */ +#define TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) +#define TUD_DFU_MODE_ALT(_itfnum, _alt, _stridx) \ + /* Interface */ \ + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ + +#define _TUD_DFU_FIRST(a, ...) a +#define _TUD_DFU_REST(a, ...) __VA_ARGS__ +#define _TUD_DFU_COMBINE(...) __VA_ARGS__ + +#define TUD_DFU_MODE_ALT_1(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 1, _TUD_DFU_FIRST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_2(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 2, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_1(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_3(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 3, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_2(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_4(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 4, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_3(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_5(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 5, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_4(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_6(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 6, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_5(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_7(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 7, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_6(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) +#define TUD_DFU_MODE_ALT_8(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 8, _TUD_DFU_FIRST(__VA_ARGS__)) \ + TUD_DFU_MODE_ALT_7(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) + +#define TUD_DFU_MODE_ALTS(_itfnum, ...) \ + TU_XSTRCAT(TUD_DFU_MODE_ALT_, CFG_TUD_DFU_ALT_COUNT)(_itfnum, __VA_ARGS__) + +// Interface number, attributes, detach timeout, transfer size, string index 1, [string index 2, string index n] +#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _attr, _timeout, _xfer_size, _stridx, ...) \ + TUD_DFU_MODE_ALTS(_itfnum, _TUD_DFU_COMBINE(_stridx, __VA_ARGS__)) \ + TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) //------------- CDC-ECM -------------// -- cgit v1.3.1 From 2147a31f25e6e848d9ec690d8324a6fa2d1d3127 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Thu, 8 Jul 2021 01:10:02 +0200 Subject: Fix wrong blocknum and length --- src/class/dfu/dfu_device.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 34472bcdd..6e7ad151b 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -50,6 +50,8 @@ typedef struct TU_ATTR_PACKED bool blk_transfer_in_proc; uint8_t alt; uint8_t intf; + uint16_t block; + uint16_t length; CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; } dfu_state_ctx_t; @@ -270,6 +272,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC)) { + _dfu_state_ctx.block = request->wValue; + _dfu_state_ctx.length = request->wLength; return true; } } // fallthrough @@ -349,7 +353,7 @@ static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * { (void) rhport; TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_req_dnload_data_cb(_dfu_state_ctx.alt, request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); + tud_dfu_req_dnload_data_cb(_dfu_state_ctx.alt,_dfu_state_ctx.block, (uint8_t *)_dfu_state_ctx.transfer_buf, _dfu_state_ctx.length); _dfu_state_ctx.blk_transfer_in_proc = false; } -- cgit v1.3.1 From a0691a4fd426f01915a7ce6452b5367aa667fb0b Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 18:48:33 +0700 Subject: update dfu_moded_open --- src/class/dfu/dfu_device.c | 62 ++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 6e7ad151b..04f086e0e 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -49,7 +49,6 @@ typedef struct TU_ATTR_PACKED uint8_t attrs; bool blk_transfer_in_proc; uint8_t alt; - uint8_t intf; uint16_t block; uint16_t length; CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; @@ -153,7 +152,6 @@ void dfu_moded_init(void) _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; - _dfu_state_ctx.intf = DFU_INTF_UNUSED; dfu_debug_print_context(); } @@ -167,7 +165,6 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; _dfu_state_ctx.alt = 0; - _dfu_state_ctx.intf = DFU_INTF_UNUSED; dfu_debug_print_context(); } @@ -176,55 +173,38 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, { (void) rhport; - uint16_t const drv_len = sizeof(tusb_desc_interface_t); + //------------- Interface (with Alt) descriptor -------------// + uint8_t const itf_num = itf_desc->bInterfaceNumber; + uint8_t alt_count = 0; - uint8_t const *p_desc = (uint8_t const *)itf_desc; - - uint16_t total_len = 0; - - uint8_t last_alt = 0; - - while(max_len > drv_len) + uint16_t drv_len = 0; + while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) { - // Ensure this is DFU Mode - TU_VERIFY((((tusb_desc_interface_t const *)p_desc)->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) && - (((tusb_desc_interface_t const *)p_desc)->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0); - - uint8_t const alt = ((tusb_desc_interface_t const *)p_desc)->bAlternateSetting; - uint8_t const intf = ((tusb_desc_interface_t const *)p_desc)->bInterfaceNumber; - - if (_dfu_state_ctx.intf == DFU_INTF_UNUSED) - { - _dfu_state_ctx.intf = intf; - } - else - { - // Only one DFU interface is supported - TU_ASSERT(_dfu_state_ctx.intf == intf, 0); - } + TU_ASSERT(max_len > drv_len, 0); - // CFG_TUD_DFU_ATL_MAX should big enough to hold all alt settings - TU_ASSERT(alt < CFG_TUD_DFU_ALT_COUNT, 0); + // Alternate must have the same interface number + TU_ASSERT(itf_desc->bInterfaceNumber == itf_num, 0); - // Alt should increse by one every time - TU_ASSERT(alt == last_alt++, 0); + // Alt should increase by one every time + TU_ASSERT(itf_desc->bAlternateSetting == alt_count, 0); + alt_count++; - p_desc = tu_desc_next(p_desc); - max_len -= drv_len; - total_len += drv_len; + drv_len += tu_desc_len(itf_desc); + itf_desc = (tusb_desc_interface_t const *) tu_desc_next(itf_desc); } - //------------- DFU descriptor -------------// - TU_ASSERT(tu_desc_type(p_desc) == TUSB_DESC_FUNCTIONAL, 0); + //------------- DFU Functional descriptor -------------// + tusb_desc_dfu_functional_t const *func_desc = (tusb_desc_dfu_functional_t const *) itf_desc; + TU_ASSERT(tu_desc_type(func_desc) == TUSB_DESC_FUNCTIONAL, 0); + drv_len += sizeof(tusb_desc_dfu_functional_t); - _dfu_state_ctx.attrs = ((tusb_desc_dfu_functional_t const *)p_desc)->bAttributes; + _dfu_state_ctx.attrs = func_desc->bAttributes; // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR - TU_ASSERT(((tusb_desc_dfu_functional_t const *)p_desc)->wTransferSize <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); - - total_len += sizeof(tusb_desc_dfu_functional_t); + uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16(&func_desc->wTransferSize) ); + TU_ASSERT(transfer_size <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, drv_len); - return total_len; + return drv_len; } // Invoked when a control transfer occurred on an interface of this class -- cgit v1.3.1 From 134ed995c82635d509621e40568b57309fc26101 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 18:50:19 +0700 Subject: add alt to tud_dfu_abort_cb() --- src/class/dfu/dfu_device.c | 4 ++-- src/class/dfu/dfu_device.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 04f086e0e..933946b7e 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -503,7 +503,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { if ( tud_dfu_abort_cb ) { - tud_dfu_abort_cb(); + tud_dfu_abort_cb(_dfu_state_ctx.alt); } _dfu_state_ctx.state = DFU_IDLE; } @@ -613,7 +613,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { if (tud_dfu_abort_cb) { - tud_dfu_abort_cb(); + tud_dfu_abort_cb(_dfu_state_ctx.alt); } _dfu_state_ctx.state = DFU_IDLE; } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index c09b9a823..73e5055cd 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -73,7 +73,7 @@ void tud_dfu_dnload_complete(void); bool tud_dfu_device_data_done_check_cb(uint8_t alt); // Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_abort_cb(void); +TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); // Invoked when a DFU_UPLOAD request is received // alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -- cgit v1.3.1 From 2916cd45753ca579ee1d0b475b2daf3f715243b6 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 18:51:57 +0700 Subject: rename TUD_DFU_MODE_DESCRIPTOR to TUD_DFU_DESCRIPTOR --- examples/device/dfu/src/tusb_config.h | 2 +- examples/device/dfu/src/usb_descriptors.c | 2 +- src/class/dfu/dfu_device.c | 2 +- src/class/dfu/dfu_device.h | 2 +- src/device/usbd.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 55aa19922..7e10b4321 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -83,7 +83,7 @@ // Count of all alt settings, typically it's the partition count (Flash, EEPROM, etc.) #define CFG_TUD_DFU_ALT_COUNT 2 -// DFU buffer size, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR +// DFU buffer size, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 #ifdef __cplusplus diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index 8c5eee455..870c18a04 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -97,7 +97,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, attributes, detach timeout, transfer size, string index 0, [string index 1 ... string index n] - TUD_DFU_MODE_DESCRIPTOR(ITF_NUM_DFU_MODE, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 4, 5), + TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 4, 5), }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 933946b7e..ae056b441 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -200,7 +200,7 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, _dfu_state_ctx.attrs = func_desc->bAttributes; - // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR + // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16(&func_desc->wTransferSize) ); TU_ASSERT(transfer_size <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, drv_len); diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 73e5055cd..8edb2bae3 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -38,7 +38,7 @@ //--------------------------------------------------------------------+ #if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) - #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_MODE_DESCRIPTOR" + #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" #endif //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index ba415abe8..8c5f0097d 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -646,7 +646,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb TU_XSTRCAT(TUD_DFU_MODE_ALT_, CFG_TUD_DFU_ALT_COUNT)(_itfnum, __VA_ARGS__) // Interface number, attributes, detach timeout, transfer size, string index 0, [string index 1, string index n] -#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _attr, _timeout, _xfer_size, _stridx, ...) \ +#define TUD_DFU_DESCRIPTOR(_itfnum, _attr, _timeout, _xfer_size, _stridx, ...) \ TUD_DFU_MODE_ALTS(_itfnum, _TUD_DFU_COMBINE(_stridx, __VA_ARGS__)) \ TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) -- cgit v1.3.1 From 680b000bd1471d731117ccf4f3fe35579d346cb8 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 20:15:59 +0700 Subject: simplify TUD_DFU_DESCRIPTOR with alternate count remove CFG_TUD_DFU_ALT_COUNT since there is only one DFU functional descriptor --- examples/device/dfu/src/main.c | 3 +- examples/device/dfu/src/tusb_config.h | 2 - examples/device/dfu/src/usb_descriptors.c | 9 ++-- src/device/usbd.h | 79 ++++++++++++++++--------------- 4 files changed, 48 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index f7c27174a..ee201c1c5 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -154,8 +154,9 @@ bool tud_dfu_device_data_done_check_cb(uint8_t alt) return true; } -void tud_dfu_abort_cb(void) +void tud_dfu_abort_cb(uint8_t alt) { + (void) alt; printf(" Host aborted transfer\r\n"); } diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 7e10b4321..77d907ffc 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -81,8 +81,6 @@ #define CFG_TUD_DFU_RUNTIME 0 #define CFG_TUD_DFU_MODE 1 -// Count of all alt settings, typically it's the partition count (Flash, EEPROM, etc.) -#define CFG_TUD_DFU_ALT_COUNT 2 // DFU buffer size, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096 diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index 870c18a04..78e94194e 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -81,13 +81,16 @@ uint8_t const * tud_descriptor_device_cb(void) // Configuration Descriptor //--------------------------------------------------------------------+ +// Number of Alternate Interface (each for 1 flash partition) +#define ALT_COUNT 2 + enum { ITF_NUM_DFU_MODE, ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_MODE_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_DESC_LEN(ALT_COUNT)) #define FUNC_ATTRS (DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK | DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) @@ -96,8 +99,8 @@ 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), - // Interface number, attributes, detach timeout, transfer size, string index 0, [string index 1 ... string index n] - TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 4, 5), + // Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size + TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, ALT_COUNT, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFFER_SIZE), }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/device/usbd.h b/src/device/usbd.h index 8c5f0097d..9697b4497 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -605,50 +605,51 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -// Maximum alternate settings (used for different partitons) supported -#ifndef CFG_TUD_DFU_ALT_COUNT -#define CFG_TUD_DFU_ALT_COUNT 1 -#endif - -// Length of template descriptor: 18 bytes + number of alternatives * 9 -#define TUD_DFU_MODE_DESC_LEN (9 + (CFG_TUD_DFU_ALT_COUNT) * 9) +// Length of template descriptor: 9 bytes + number of alternatives * 9 +#define TUD_DFU_DESC_LEN(_alt_count) (9 + (_alt_count) * 9) -/* Primary Interface */ -#define TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) \ +// Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size +// Note: Alternate count must be numberic or macro, string index is increased by one for each Alt interface +#define TUD_DFU_DESCRIPTOR(_itfnum, _alt_count, _stridx, _attr, _timeout, _xfer_size) \ + TU_XSTRCAT(_TUD_DFU_ALT_,_alt_count)(_itfnum, 0, _stridx), \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -#define TUD_DFU_MODE_ALT(_itfnum, _alt, _stridx) \ +#define _TUD_DFU_ALT(_itfnum, _alt, _stridx) \ /* Interface */ \ - 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \ - -#define _TUD_DFU_FIRST(a, ...) a -#define _TUD_DFU_REST(a, ...) __VA_ARGS__ -#define _TUD_DFU_COMBINE(...) __VA_ARGS__ - -#define TUD_DFU_MODE_ALT_1(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 1, _TUD_DFU_FIRST(__VA_ARGS__)) -#define TUD_DFU_MODE_ALT_2(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 2, _TUD_DFU_FIRST(__VA_ARGS__)) \ - TUD_DFU_MODE_ALT_1(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) -#define TUD_DFU_MODE_ALT_3(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 3, _TUD_DFU_FIRST(__VA_ARGS__)) \ - TUD_DFU_MODE_ALT_2(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) -#define TUD_DFU_MODE_ALT_4(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 4, _TUD_DFU_FIRST(__VA_ARGS__)) \ - TUD_DFU_MODE_ALT_3(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) -#define TUD_DFU_MODE_ALT_5(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 5, _TUD_DFU_FIRST(__VA_ARGS__)) \ - TUD_DFU_MODE_ALT_4(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) -#define TUD_DFU_MODE_ALT_6(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 6, _TUD_DFU_FIRST(__VA_ARGS__)) \ - TUD_DFU_MODE_ALT_5(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) -#define TUD_DFU_MODE_ALT_7(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 7, _TUD_DFU_FIRST(__VA_ARGS__)) \ - TUD_DFU_MODE_ALT_6(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) -#define TUD_DFU_MODE_ALT_8(_itfnum, ...) TUD_DFU_MODE_ALT(_itfnum, (CFG_TUD_DFU_ALT_COUNT) - 8, _TUD_DFU_FIRST(__VA_ARGS__)) \ - TUD_DFU_MODE_ALT_7(_itfnum, _TUD_DFU_REST(__VA_ARGS__)) - -#define TUD_DFU_MODE_ALTS(_itfnum, ...) \ - TU_XSTRCAT(TUD_DFU_MODE_ALT_, CFG_TUD_DFU_ALT_COUNT)(_itfnum, __VA_ARGS__) - -// Interface number, attributes, detach timeout, transfer size, string index 0, [string index 1, string index n] -#define TUD_DFU_DESCRIPTOR(_itfnum, _attr, _timeout, _xfer_size, _stridx, ...) \ - TUD_DFU_MODE_ALTS(_itfnum, _TUD_DFU_COMBINE(_stridx, __VA_ARGS__)) \ - TUD_DFU_MODE_FUNC(_attr, _timeout, _xfer_size) + 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx + +#define _TUD_DFU_ALT_1(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx) + +#define _TUD_DFU_ALT_2(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_1(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_3(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_2(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_4(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_3(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_5(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_4(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_6(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_5(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_7(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_6(_itfnum, _alt_count+1, _stridx+1) + +#define _TUD_DFU_ALT_8(_itfnum, _alt_count, _stridx) \ + _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + _TUD_DFU_ALT_7(_itfnum, _alt_count+1, _stridx+1) + //------------- CDC-ECM -------------// -- cgit v1.3.1 From 389d34067854fcf39dd1839f2643bd8300aafe1d Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 20:17:44 +0700 Subject: clean up --- src/class/dfu/dfu_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index ae056b441..a7a8f578c 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -42,7 +42,7 @@ //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED +typedef struct { dfu_device_status_t status; dfu_state_t state; -- cgit v1.3.1 From 8c48a4a2886bdac96df274311f84bc6c04c56b95 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 20:23:19 +0700 Subject: clean up --- src/class/dfu/dfu_device.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index a7a8f578c..51e6179bc 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -37,8 +37,6 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -#define DFU_INTF_UNUSED 0xFF - //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -- cgit v1.3.1 From 86d511f24452b13c8e5779c7a79bff54a03dafd8 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Jul 2021 21:08:13 +0700 Subject: rename tud_dfu_set_timeout_cb() to tud_dfu_get_status_cb() also add state as argument --- examples/device/dfu/src/main.c | 7 +++++-- src/class/dfu/dfu_device.c | 19 +++++++++---------- src/class/dfu/dfu_device.h | 6 +++--- 3 files changed, 17 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index ee201c1c5..4ec6d477c 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -125,10 +125,13 @@ bool tud_dfu_firmware_valid_check_cb(uint8_t alt) return true; } -uint16_t tud_dfu_set_timeout_cb(uint8_t alt) +uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state) { // For example Alt1 (EEPROM) is slow, add 2000ms timeout - if (alt == 1) return 2000; + if ( state == DFU_DNBUSY ) + { + if (alt == 1) return 2000; + } return 0; } diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 51e6179bc..23669b508 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -293,18 +293,17 @@ static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * re static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) { - dfu_status_req_payload_t resp; - - uint16_t timeout = 0; - resp.bStatus = _dfu_state_ctx.status; - if(_dfu_state_ctx.state == DFU_DNBUSY && tud_dfu_set_timeout_cb) + uint32_t timeout = 0; + if ( tud_dfu_get_status_cb ) { - timeout = tud_dfu_set_timeout_cb(_dfu_state_ctx.alt); - + timeout = tud_dfu_get_status_cb(_dfu_state_ctx.alt, _dfu_state_ctx.state); } - resp.bwPollTimeout[0] = TU_U16_LOW(timeout); - resp.bwPollTimeout[1] = TU_U16_HIGH(timeout); - resp.bwPollTimeout[2] = 0; + + dfu_status_req_payload_t resp; + resp.bStatus = _dfu_state_ctx.status; + resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout); + resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout); + resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout); resp.bState = _dfu_state_ctx.state; resp.iString = 0; diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 8edb2bae3..647fc2c04 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -48,10 +48,10 @@ // alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. bool tud_dfu_firmware_valid_check_cb(uint8_t alt); -// Invoked when a DFU_GETSTATUS request is received in DFU_DNBUSY state -// Used to set the bwPollTimeout value, useful for slow Flash in order to make host wait longer +// Invoked when a DFU_GETSTATUS request is received +// Return the bwPollTimeout value for host's response, useful for slow Flash in order to make host wait longer // alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -TU_ATTR_WEAK uint16_t tud_dfu_set_timeout_cb(uint8_t alt); +TU_ATTR_WEAK uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state); // Invoked when a DFU_DNLOAD request is received // alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -- cgit v1.3.1 From 137dff620bc5890afdf59a61cebe355fc6999f12 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 Jul 2021 20:24:12 +0700 Subject: add option to silent a driver log --- src/class/msc/msc_device.c | 20 ++++++++++++-------- src/common/tusb_common.h | 18 +++++++++++++----- src/common/tusb_compiler.h | 12 ++++++++---- src/common/tusb_fifo.h | 2 +- 4 files changed, 34 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 7f13b4891..014e8b69e 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -37,6 +37,10 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ + +// Can be selectively disabled to reduce logging when troubleshooting other driver +#define MSC_DEBUG 2 + enum { MSC_STAGE_CMD = 0, @@ -99,7 +103,7 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= 2 -static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = +TU_ATTR_UNUSED static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = { { .key = SCSI_CMD_TEST_UNIT_READY , .data = "Test Unit Ready" }, { .key = SCSI_CMD_INQUIRY , .data = "Inquiry" }, @@ -114,7 +118,7 @@ static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = { .key = SCSI_CMD_WRITE_10 , .data = "Write10" } }; -static tu_lookup_table_t const _msc_scsi_cmd_table = +TU_ATTR_UNUSED static tu_lookup_table_t const _msc_scsi_cmd_table = { .count = TU_ARRAY_SIZE(_msc_scsi_cmd_lookup), .items = _msc_scsi_cmd_lookup @@ -232,8 +236,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_ASSERT( event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE ); - TU_LOG2(" SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); - // TU_LOG2_MEM(p_cbw, xferred_bytes, 2); + TU_LOG(MSC_DEBUG, " SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); + // TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2); p_csw->signature = MSC_CSW_SIGNATURE; p_csw->tag = p_cbw->tag; @@ -305,8 +309,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t break; case MSC_STAGE_DATA: - TU_LOG2(" SCSI Data\r\n"); - //TU_LOG2_MEM(_mscd_buf, xferred_bytes, 2); + TU_LOG(MSC_DEBUG, " SCSI Data\r\n"); + //TU_LOG_MEM(MSC_DEBUG, _mscd_buf, xferred_bytes, 2); // OUT transfer, invoke callback if needed if ( !tu_bit_test(p_cbw->dir, 7) ) @@ -402,8 +406,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // Wait for the Status phase to complete if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) ) { - TU_LOG2(" SCSI Status: %u\r\n", p_csw->status); - // TU_LOG2_MEM(p_csw, xferred_bytes, 2); + TU_LOG(MSC_DEBUG, " SCSI Status: %u\r\n", p_csw->status); + // TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2); // Invoke complete callback if defined // Note: There is racing issue with samd51 + qspi flash testing with arduino diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 8490daad7..c8a66a879 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -305,11 +305,11 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize) } // Log with Level -#define TU_LOG(n, ...) TU_LOG##n(__VA_ARGS__) -#define TU_LOG_MEM(n, ...) TU_LOG##n##_MEM(__VA_ARGS__) -#define TU_LOG_VAR(n, ...) TU_LOG##n##_VAR(__VA_ARGS__) -#define TU_LOG_INT(n, ...) TU_LOG##n##_INT(__VA_ARGS__) -#define TU_LOG_HEX(n, ...) TU_LOG##n##_HEX(__VA_ARGS__) +#define TU_LOG(n, ...) TU_XSTRCAT(TU_LOG, n)(__VA_ARGS__) +#define TU_LOG_MEM(n, ...) TU_XSTRCAT3(TU_LOG, n, _MEM)(__VA_ARGS__) +#define TU_LOG_VAR(n, ...) TU_XSTRCAT3(TU_LOG, n, _VAR)(__VA_ARGS__) +#define TU_LOG_INT(n, ...) TU_XSTRCAT3(TU_LOG, n, _INT)(__VA_ARGS__) +#define TU_LOG_HEX(n, ...) TU_XSTRCAT3(TU_LOG, n, _HEX)(__VA_ARGS__) #define TU_LOG_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__) #define TU_LOG_FAILED() tu_printf("%s: %d: Failed\r\n", __PRETTY_FUNCTION__, __LINE__) @@ -373,6 +373,14 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #endif // TODO replace all TU_LOGn with TU_LOG(n) + +#define TU_LOG0(...) +#define TU_LOG0_MEM(...) +#define TU_LOG0_VAR(...) +#define TU_LOG0_INT(...) +#define TU_LOG0_HEX(...) + + #ifndef TU_LOG1 #define TU_LOG1(...) #define TU_LOG1_MEM(...) diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index f755e13f4..0dd9ba016 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -32,10 +32,14 @@ #ifndef _TUSB_COMPILER_H_ #define _TUSB_COMPILER_H_ -#define TU_STRING(x) #x ///< stringify without expand -#define TU_XSTRING(x) TU_STRING(x) ///< expand then stringify -#define TU_STRCAT(a, b) a##b ///< concat without expand -#define TU_XSTRCAT(a, b) TU_STRCAT(a, b) ///< expand then concat +#define TU_STRING(x) #x ///< stringify without expand +#define TU_XSTRING(x) TU_STRING(x) ///< expand then stringify + +#define TU_STRCAT(a, b) a##b ///< concat without expand +#define TU_STRCAT3(a, b, c) a##b##c ///< concat without expand + +#define TU_XSTRCAT(a, b) TU_STRCAT(a, b) ///< expand then concat +#define TU_XSTRCAT3(a, b, c) TU_STRCAT3(a, b, c) ///< expand then concat 3 tokens #if defined __COUNTER__ && __COUNTER__ != __COUNTER__ #define _TU_COUNTER_ __COUNTER__ diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index de2ae163d..18db289a1 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -120,9 +120,9 @@ bool tu_fifo_peek (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_peek_n (tu_fifo_t* f, void * p_buffer, uint16_t n); uint16_t tu_fifo_count (tu_fifo_t* f); +uint16_t tu_fifo_remaining (tu_fifo_t* f); bool tu_fifo_empty (tu_fifo_t* f); bool tu_fifo_full (tu_fifo_t* f); -uint16_t tu_fifo_remaining (tu_fifo_t* f); bool tu_fifo_overflowed (tu_fifo_t* f); void tu_fifo_correct_read_pointer (tu_fifo_t* f); -- cgit v1.3.1 From ebd98e1a18bf1dfbbf45420310c4dee96a3bfd24 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 Jul 2021 21:09:23 +0700 Subject: fix midi stream write return value (off by 1) --- src/class/midi/midi_device.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 4eac0de48..c39e03976 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -240,15 +240,15 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* midid_stream_t* stream = &midi->stream_write; - uint32_t total_written = 0; uint32_t i = 0; - while ( i < bufsize ) + while ( (i < bufsize) && (tu_fifo_remaining(&midi->tx_ff) >= 4) ) { uint8_t const data = buffer[i]; + i++; if ( stream->index == 0 ) { - // new event packet + //------------- New event packet -------------// uint8_t const msg = data >> 4; @@ -310,9 +310,9 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* } else { - // On-going (buffering) packet + //------------- On-going (buffering) packet -------------// - TU_ASSERT(stream->index < 4, total_written); + TU_ASSERT(stream->index < 4, i); stream->buffer[stream->index] = data; stream->index++; @@ -335,19 +335,14 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* // complete current event packet, reset stream stream->index = stream->total = 0; - // fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing - if ( count != 4 ) break; - - // updated written if succeeded - total_written = i; + // FIFO overflown, since we already check fifo remaining. It is probably race condition + TU_ASSERT(count == 4, i); } - - i++; } write_flush(midi); - return total_written; + return i; } bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) -- cgit v1.3.1 From ac8d0abecf93af2498f9d5d1438c2af7b133bedc Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jul 2021 15:04:38 +0700 Subject: rename dfu API - tud_dfu_dnload_complete() -> tud_dfu_download_complete() - tud_dfu_req_dnload_data_cb() -> tud_dfu_download_cb() - tud_dfu_req_upload_data_cb() -> tud_dfu_upload_cb() --- examples/device/dfu/src/main.c | 6 +++--- examples/device/midi_test/src/main.c | 10 +++++++--- src/class/dfu/dfu_device.c | 8 ++++---- src/class/dfu/dfu_device.h | 8 ++++---- 4 files changed, 18 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 4ec6d477c..8e7fa9ee0 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -135,7 +135,7 @@ uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state) return 0; } -void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length) +void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length) { (void) data; printf(" Received Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); @@ -147,7 +147,7 @@ void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, } #endif - tud_dfu_dnload_complete(); + tud_dfu_download_complete(); } bool tud_dfu_device_data_done_check_cb(uint8_t alt) @@ -167,7 +167,7 @@ void tud_dfu_abort_cb(uint8_t alt) const uint8_t upload_test[2][UPLOAD_SIZE] = {"Hello world from TinyUSB DFU! - Partition 0", "Hello world from TinyUSB DFU! - Partition 1"}; -uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length) +uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length) { (void) block_num; (void) length; diff --git a/examples/device/midi_test/src/main.c b/examples/device/midi_test/src/main.c index 9e0e82a10..66b858323 100644 --- a/examples/device/midi_test/src/main.c +++ b/examples/device/midi_test/src/main.c @@ -134,10 +134,13 @@ void midi_task(void) uint8_t packet[4]; while ( tud_midi_available() ) tud_midi_packet_read(packet); - // send note every 1000 ms - if (board_millis() - start_ms < 286) return; // not enough time - start_ms += 286; + // send note periodically + if (board_millis() - start_ms < 1000) return; // not enough time + start_ms += 1000; +#if 1 + +#else // Previous positions in the note sequence. int previous = note_pos - 1; @@ -158,6 +161,7 @@ void midi_task(void) // If we are at the end of the sequence, start over. if (note_pos >= sizeof(note_sequence)) note_pos = 0; +#endif } //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 23669b508..c8c0bcfd4 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -283,9 +283,9 @@ static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * re { TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); uint16_t retval = 0; - if (tud_dfu_req_upload_data_cb) + if (tud_dfu_upload_cb) { - tud_dfu_req_upload_data_cb(_dfu_state_ctx.alt, block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + tud_dfu_upload_cb(_dfu_state_ctx.alt, block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); } tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; @@ -330,11 +330,11 @@ static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * { (void) rhport; TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_req_dnload_data_cb(_dfu_state_ctx.alt,_dfu_state_ctx.block, (uint8_t *)_dfu_state_ctx.transfer_buf, _dfu_state_ctx.length); + tud_dfu_download_cb(_dfu_state_ctx.alt,_dfu_state_ctx.block, (uint8_t *)_dfu_state_ctx.transfer_buf, _dfu_state_ctx.length); _dfu_state_ctx.blk_transfer_in_proc = false; } -void tud_dfu_dnload_complete(void) +void tud_dfu_download_complete(void) { if (_dfu_state_ctx.state == DFU_DNBUSY) { diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 647fc2c04..2a1f5a8e7 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -58,11 +58,11 @@ TU_ATTR_WEAK uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state); // This callback takes the wBlockNum chunk of length length and provides it // to the application at the data pointer. This data is only valid for this // call, so the app must use it not or copy it. -void tud_dfu_req_dnload_data_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); +void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); // Must be called when the application is done using the last block of data -// provided by tud_dfu_req_dnload_data_cb -void tud_dfu_dnload_complete(void); +// provided by tud_dfu_download_cb +void tud_dfu_download_complete(void); // Invoked during the last DFU_DNLOAD request, signifying that the host believes // it is done transmitting data. @@ -79,7 +79,7 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); // alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. // This callback must populate data with up to length bytes // Return the number of bytes to write -TU_ATTR_WEAK uint16_t tud_dfu_req_upload_data_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); +TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); // Invoked when a DFU_DETACH request is received TU_ATTR_WEAK void tud_dfu_reboot_cb(void); -- cgit v1.3.1 From 57d9f696a2c11cf0004ea2eec1204d80c657cb03 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jul 2021 15:24:09 +0700 Subject: clean up --- src/class/dfu/dfu_device.c | 73 ++++++++++------------------------------------ 1 file changed, 16 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index c8c0bcfd4..dcdc34977 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -46,7 +46,7 @@ typedef struct dfu_state_t state; uint8_t attrs; bool blk_transfer_in_proc; - uint8_t alt; + uint8_t alt_num; uint16_t block; uint16_t length; CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE]; @@ -149,7 +149,7 @@ void dfu_moded_init(void) _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.alt = 0; + _dfu_state_ctx.alt_num = 0; dfu_debug_print_context(); } @@ -162,7 +162,7 @@ void dfu_moded_reset(uint8_t rhport) _dfu_state_ctx.status = DFU_STATUS_OK; _dfu_state_ctx.attrs = 0; _dfu_state_ctx.blk_transfer_in_proc = false; - _dfu_state_ctx.alt = 0; + _dfu_state_ctx.alt_num = 0; dfu_debug_print_context(); } @@ -221,7 +221,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_INTERFACE) { // Switch Alt interface - _dfu_state_ctx.alt = request->wValue; + _dfu_state_ctx.alt_num = (uint8_t) request->wValue; // Re-initalise state machine (Necessary ?) _dfu_state_ctx.state = DFU_IDLE; @@ -244,6 +244,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque if (tud_dfu_reboot_cb) tud_dfu_reboot_cb(); break; } + case DFU_REQUEST_DNLOAD: { if ( (stage == CONTROL_STAGE_ACK) @@ -254,7 +255,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque _dfu_state_ctx.length = request->wLength; return true; } - } // fallthrough + } + // fallthrough case DFU_REQUEST_UPLOAD: case DFU_REQUEST_GETSTATUS: case DFU_REQUEST_CLRSTATUS: @@ -285,7 +287,7 @@ static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * re uint16_t retval = 0; if (tud_dfu_upload_cb) { - tud_dfu_upload_cb(_dfu_state_ctx.alt, block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + tud_dfu_upload_cb(_dfu_state_ctx.alt_num, block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); } tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; @@ -296,7 +298,7 @@ static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const uint32_t timeout = 0; if ( tud_dfu_get_status_cb ) { - timeout = tud_dfu_get_status_cb(_dfu_state_ctx.alt, _dfu_state_ctx.state); + timeout = tud_dfu_get_status_cb(_dfu_state_ctx.alt_num, _dfu_state_ctx.state); } dfu_status_req_payload_t resp; @@ -330,7 +332,7 @@ static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * { (void) rhport; TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_download_cb(_dfu_state_ctx.alt,_dfu_state_ctx.block, (uint8_t *)_dfu_state_ctx.transfer_buf, _dfu_state_ctx.length); + tud_dfu_download_cb(_dfu_state_ctx.alt_num,_dfu_state_ctx.block, (uint8_t *)_dfu_state_ctx.transfer_buf, _dfu_state_ctx.length); _dfu_state_ctx.blk_transfer_in_proc = false; } @@ -384,28 +386,20 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATUS: - { dfu_req_getstatus_reply(rhport, request); - } break; case DFU_REQUEST_GETSTATE: - { dfu_req_getstate_reply(rhport, request); - } break; case DFU_REQUEST_ABORT: - { ; // do nothing, but don't stall so continue on - } break; default: - { _dfu_state_ctx.state = DFU_ERROR; return false; // stall on all other requests - } break; } } @@ -430,16 +424,12 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATE: - { dfu_req_getstate_reply(rhport, request); - } break; default: - { _dfu_state_ctx.state = DFU_ERROR; return false; // stall on all other requests - } break; } } @@ -450,10 +440,8 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req switch (request->bRequest) { default: - { _dfu_state_ctx.state = DFU_ERROR; return false; // stall on all other requests - } break; } } @@ -472,7 +460,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req _dfu_state_ctx.blk_transfer_in_proc = true; dfu_req_dnload_setup(rhport, request); } else { - if ( tud_dfu_device_data_done_check_cb(_dfu_state_ctx.alt) ) + if ( tud_dfu_device_data_done_check_cb(_dfu_state_ctx.alt_num) ) { _dfu_state_ctx.state = DFU_MANIFEST_SYNC; tud_control_status(rhport, request); @@ -485,32 +473,24 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATUS: - { dfu_req_getstatus_reply(rhport, request); - } break; case DFU_REQUEST_GETSTATE: - { dfu_req_getstate_reply(rhport, request); - } break; case DFU_REQUEST_ABORT: - { if ( tud_dfu_abort_cb ) { - tud_dfu_abort_cb(_dfu_state_ctx.alt); + tud_dfu_abort_cb(_dfu_state_ctx.alt_num); } _dfu_state_ctx.state = DFU_IDLE; - } break; default: - { _dfu_state_ctx.state = DFU_ERROR; return false; // stall on all other requests - } break; } } @@ -528,7 +508,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstatus_reply(rhport, request); } else { - if ( tud_dfu_firmware_valid_check_cb(_dfu_state_ctx.alt) ) + if ( tud_dfu_firmware_valid_check_cb(_dfu_state_ctx.alt_num) ) { _dfu_state_ctx.state = DFU_IDLE; } @@ -538,16 +518,12 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATE: - { dfu_req_getstate_reply(rhport, request); - } break; default: - { _dfu_state_ctx.state = DFU_ERROR; return false; // stall on all other requests - } break; } } @@ -557,10 +533,9 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { switch (request->bRequest) { + // stall on all other requests default: - { - return false; // stall on all other requests - } + return false; break; } } @@ -573,9 +548,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req switch (request->bRequest) { default: - { return false; // stall on all other requests - } break; } } @@ -595,31 +568,25 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATUS: - { dfu_req_getstatus_reply(rhport, request); - } break; case DFU_REQUEST_GETSTATE: - { dfu_req_getstate_reply(rhport, request); - } break; case DFU_REQUEST_ABORT: { if (tud_dfu_abort_cb) { - tud_dfu_abort_cb(_dfu_state_ctx.alt); + tud_dfu_abort_cb(_dfu_state_ctx.alt_num); } _dfu_state_ctx.state = DFU_IDLE; } break; default: - { return false; // stall on all other requests - } break; } } @@ -630,27 +597,19 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req switch (request->bRequest) { case DFU_REQUEST_GETSTATUS: - { dfu_req_getstatus_reply(rhport, request); - } break; case DFU_REQUEST_CLRSTATUS: - { _dfu_state_ctx.state = DFU_IDLE; - } break; case DFU_REQUEST_GETSTATE: - { dfu_req_getstate_reply(rhport, request); - } break; default: - { return false; // stall on all other requests - } break; } } -- cgit v1.3.1 From 27676f738d54c1edf87449531b3a1fd24fca59d3 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jul 2021 15:31:20 +0700 Subject: rename tud_dfu_reboot_cb() to tud_dfu_detach_cb() --- src/class/dfu/dfu_device.c | 2 +- src/class/dfu/dfu_device.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index dcdc34977..c807004ec 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -241,7 +241,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case DFU_REQUEST_DETACH: { tud_control_status(rhport, request); - if (tud_dfu_reboot_cb) tud_dfu_reboot_cb(); + if (tud_dfu_detach_cb) tud_dfu_detach_cb(); break; } diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 2a1f5a8e7..d5d464f3b 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -82,7 +82,8 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); // Invoked when a DFU_DETACH request is received -TU_ATTR_WEAK void tud_dfu_reboot_cb(void); +TU_ATTR_WEAK void tud_dfu_detach_cb(void); + //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -- cgit v1.3.1 From 5b965a38883efb2d7210d48be6f305c0f31ca8fc Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jul 2021 15:52:38 +0700 Subject: more rename and update --- examples/device/dfu/src/main.c | 14 +-- src/class/dfu/dfu_device.c | 231 +++++++++++++++++++++-------------------- 2 files changed, 128 insertions(+), 117 deletions(-) (limited to 'src') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 8e7fa9ee0..2c114c5a2 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -28,11 +28,13 @@ * * To transfer firmware from host to device: * - * $ dfu-util -D [filename] + * $ dfu-util -d cafe -a 0 -D [filename] + * $ dfu-util -d cafe -a 1 -D [filename] * * To transfer firmware from device to host: * - * $ dfu-util -U [filename] + * $ dfu-util -d cafe -a 0 -U [filename] + * $ dfu-util -d cafe -a 1 -U [filename] * */ @@ -138,12 +140,12 @@ uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state) void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length) { (void) data; - printf(" Received Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); + printf("Received Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); #if DFU_VERBOSE for(uint16_t i=0; ibAttributes; + _dfu_ctx.attrs = func_desc->bAttributes; // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16(&func_desc->wTransferSize) ); @@ -215,67 +215,76 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); - if(stage == CONTROL_STAGE_SETUP) + if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD ) { - // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_INTERFACE) + // Standard request include GET/SET_INTERFACE + switch (request->bRequest ) { - // Switch Alt interface - _dfu_state_ctx.alt_num = (uint8_t) request->wValue; + case TUSB_REQ_SET_INTERFACE: + // Switch Alt interface and Re-initalize state machine + _dfu_ctx.alt_num = (uint8_t) request->wValue; + _dfu_ctx.state = DFU_IDLE; + _dfu_ctx.status = DFU_STATUS_OK; + _dfu_ctx.blk_transfer_in_proc = false; + + return tud_control_status(rhport, request); + break; - // Re-initalise state machine (Necessary ?) - _dfu_state_ctx.state = DFU_IDLE; - _dfu_state_ctx.status = DFU_STATUS_OK; - _dfu_state_ctx.blk_transfer_in_proc = false; + case TUSB_REQ_GET_INTERFACE: + return tud_control_xfer(rhport, request, &_dfu_ctx.alt_num, 1); + break; - tud_control_status(rhport, request); - return true; + // unsupported request + default: return false; } } - - // Handle class request only from here - TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - - switch (request->bRequest) + else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) { - case DFU_REQUEST_DETACH: + // Class request + switch (request->bRequest) { - tud_control_status(rhport, request); - if (tud_dfu_detach_cb) tud_dfu_detach_cb(); - break; - } + case DFU_REQUEST_DETACH: + { + tud_control_status(rhport, request); + if (tud_dfu_detach_cb) tud_dfu_detach_cb(); + break; + } - case DFU_REQUEST_DNLOAD: - { - if ( (stage == CONTROL_STAGE_ACK) - && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC)) + case DFU_REQUEST_DNLOAD: { - _dfu_state_ctx.block = request->wValue; - _dfu_state_ctx.length = request->wLength; - return true; + if ( (stage == CONTROL_STAGE_ACK) + && ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + && (_dfu_ctx.state == DFU_DNLOAD_SYNC)) + { + _dfu_ctx.block = request->wValue; + _dfu_ctx.length = request->wLength; + return true; + } } - } - // fallthrough - case DFU_REQUEST_UPLOAD: - case DFU_REQUEST_GETSTATUS: - case DFU_REQUEST_CLRSTATUS: - case DFU_REQUEST_GETSTATE: - case DFU_REQUEST_ABORT: - { - if(stage == CONTROL_STAGE_SETUP) + // fallthrough + case DFU_REQUEST_UPLOAD: + case DFU_REQUEST_GETSTATUS: + case DFU_REQUEST_CLRSTATUS: + case DFU_REQUEST_GETSTATE: + case DFU_REQUEST_ABORT: { - return dfu_state_machine(rhport, request); + if(stage == CONTROL_STAGE_SETUP) + { + return dfu_state_machine(rhport, request); + } } - } - break; + break; - default: - { - TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); - return false; // stall unsupported request + default: + { + TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); + return false; // stall unsupported request + } + break; } - break; + }else + { + return false; // unsupported request } return true; @@ -287,9 +296,9 @@ static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * re uint16_t retval = 0; if (tud_dfu_upload_cb) { - tud_dfu_upload_cb(_dfu_state_ctx.alt_num, block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); + tud_dfu_upload_cb(_dfu_ctx.alt_num, block_num, (uint8_t *)_dfu_ctx.transfer_buf, wLength); } - tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); + tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, retval); return retval; } @@ -298,15 +307,15 @@ static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const uint32_t timeout = 0; if ( tud_dfu_get_status_cb ) { - timeout = tud_dfu_get_status_cb(_dfu_state_ctx.alt_num, _dfu_state_ctx.state); + timeout = tud_dfu_get_status_cb(_dfu_ctx.alt_num, _dfu_ctx.state); } dfu_status_req_payload_t resp; - resp.bStatus = _dfu_state_ctx.status; + resp.bStatus = _dfu_ctx.status; resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout); resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout); resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout); - resp.bState = _dfu_state_ctx.state; + resp.bState = _dfu_ctx.state; resp.iString = 0; tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); @@ -314,7 +323,7 @@ static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) { - tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1); + tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); } static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) @@ -325,25 +334,25 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); // setup for data phase - tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, request->wLength); + tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); } static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { (void) rhport; TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_download_cb(_dfu_state_ctx.alt_num,_dfu_state_ctx.block, (uint8_t *)_dfu_state_ctx.transfer_buf, _dfu_state_ctx.length); - _dfu_state_ctx.blk_transfer_in_proc = false; + tud_dfu_download_cb(_dfu_ctx.alt_num,_dfu_ctx.block, (uint8_t *)_dfu_ctx.transfer_buf, _dfu_ctx.length); + _dfu_ctx.blk_transfer_in_proc = false; } void tud_dfu_download_complete(void) { - if (_dfu_state_ctx.state == DFU_DNBUSY) + if (_dfu_ctx.state == DFU_DNBUSY) { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - } else if (_dfu_state_ctx.state == DFU_MANIFEST) + _dfu_ctx.state = DFU_DNLOAD_SYNC; + } else if (_dfu_ctx.state == DFU_MANIFEST) { - _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + _dfu_ctx.state = ((_dfu_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; } } @@ -351,9 +360,9 @@ void tud_dfu_download_complete(void) static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) { TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); - TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_state_ctx.state)); + TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state)); - switch (_dfu_state_ctx.state) + switch (_dfu_ctx.state) { case DFU_IDLE: { @@ -361,26 +370,26 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - _dfu_state_ctx.blk_transfer_in_proc = true; + _dfu_ctx.state = DFU_DNLOAD_SYNC; + _dfu_ctx.blk_transfer_in_proc = true; dfu_req_dnload_setup(rhport, request); } else { - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; } } break; case DFU_REQUEST_UPLOAD: { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) + if( ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) { - _dfu_state_ctx.state = DFU_UPLOAD_IDLE; + _dfu_ctx.state = DFU_UPLOAD_IDLE; dfu_req_upload(rhport, request, request->wValue, request->wLength); } else { - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; } } break; @@ -398,7 +407,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; default: - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests break; } @@ -411,13 +420,13 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ( _dfu_state_ctx.blk_transfer_in_proc ) + if ( _dfu_ctx.blk_transfer_in_proc ) { - _dfu_state_ctx.state = DFU_DNBUSY; + _dfu_ctx.state = DFU_DNBUSY; dfu_req_getstatus_reply(rhport, request); dfu_req_dnload_reply(rhport, request); } else { - _dfu_state_ctx.state = DFU_DNLOAD_IDLE; + _dfu_ctx.state = DFU_DNLOAD_IDLE; dfu_req_getstatus_reply(rhport, request); } } @@ -428,7 +437,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; default: - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests break; } @@ -440,7 +449,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req switch (request->bRequest) { default: - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests break; } @@ -453,19 +462,19 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) && (request->wLength > 0) ) { - _dfu_state_ctx.state = DFU_DNLOAD_SYNC; - _dfu_state_ctx.blk_transfer_in_proc = true; + _dfu_ctx.state = DFU_DNLOAD_SYNC; + _dfu_ctx.blk_transfer_in_proc = true; dfu_req_dnload_setup(rhport, request); } else { - if ( tud_dfu_device_data_done_check_cb(_dfu_state_ctx.alt_num) ) + if ( tud_dfu_device_data_done_check_cb(_dfu_ctx.alt_num) ) { - _dfu_state_ctx.state = DFU_MANIFEST_SYNC; + _dfu_ctx.state = DFU_MANIFEST_SYNC; tud_control_status(rhport, request); } else { - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; return false; // stall } } @@ -483,13 +492,13 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req case DFU_REQUEST_ABORT: if ( tud_dfu_abort_cb ) { - tud_dfu_abort_cb(_dfu_state_ctx.alt_num); + tud_dfu_abort_cb(_dfu_ctx.alt_num); } - _dfu_state_ctx.state = DFU_IDLE; + _dfu_ctx.state = DFU_IDLE; break; default: - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests break; } @@ -502,15 +511,15 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) { - _dfu_state_ctx.state = DFU_MANIFEST; + _dfu_ctx.state = DFU_MANIFEST; dfu_req_getstatus_reply(rhport, request); } else { - if ( tud_dfu_firmware_valid_check_cb(_dfu_state_ctx.alt_num) ) + if ( tud_dfu_firmware_valid_check_cb(_dfu_ctx.alt_num) ) { - _dfu_state_ctx.state = DFU_IDLE; + _dfu_ctx.state = DFU_IDLE; } dfu_req_getstatus_reply(rhport, request); } @@ -522,7 +531,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; default: - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests break; } @@ -562,7 +571,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) { - _dfu_state_ctx.state = DFU_IDLE; + _dfu_ctx.state = DFU_IDLE; } } break; @@ -579,9 +588,9 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { if (tud_dfu_abort_cb) { - tud_dfu_abort_cb(_dfu_state_ctx.alt_num); + tud_dfu_abort_cb(_dfu_ctx.alt_num); } - _dfu_state_ctx.state = DFU_IDLE; + _dfu_ctx.state = DFU_IDLE; } break; @@ -601,7 +610,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_CLRSTATUS: - _dfu_state_ctx.state = DFU_IDLE; + _dfu_ctx.state = DFU_IDLE; break; case DFU_REQUEST_GETSTATE: @@ -616,7 +625,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; default: - _dfu_state_ctx.state = DFU_ERROR; + _dfu_ctx.state = DFU_ERROR; TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); return false; // Unexpected state, stall and change to error } -- cgit v1.3.1 From 95ded08e3b96b77bbbb1e11e7f0043fb86b7316f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jul 2021 16:42:12 +0700 Subject: simplify upload request --- src/class/dfu/dfu.h | 8 ++--- src/class/dfu/dfu_device.c | 88 ++++++++++++++++++++-------------------------- src/common/tusb_types.h | 2 +- 3 files changed, 43 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h index 18de3bf99..88f2f3529 100644 --- a/src/class/dfu/dfu.h +++ b/src/class/dfu/dfu.h @@ -95,10 +95,10 @@ typedef enum { DFU_STATUS_ERRSTALLEDPKT = 0x0F, } dfu_device_status_t; -#define DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK (1 << 0) -#define DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK (1 << 1) -#define DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK (1 << 2) -#define DFU_FUNC_ATTR_WILL_DETACH_BITMASK (1 << 3) +#define DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK (1u << 0) +#define DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK (1u << 1) +#define DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK (1u << 2) +#define DFU_FUNC_ATTR_WILL_DETACH_BITMASK (1u << 3) // DFU Status Request Payload typedef struct TU_ATTR_PACKED diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 7b2f920d2..376feb053 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -58,7 +58,6 @@ CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_ctx; static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request); -static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength); static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); @@ -218,37 +217,60 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD ) { // Standard request include GET/SET_INTERFACE - switch (request->bRequest ) + switch ( request->bRequest ) { case TUSB_REQ_SET_INTERFACE: - // Switch Alt interface and Re-initalize state machine - _dfu_ctx.alt_num = (uint8_t) request->wValue; - _dfu_ctx.state = DFU_IDLE; - _dfu_ctx.status = DFU_STATUS_OK; - _dfu_ctx.blk_transfer_in_proc = false; + if ( stage == CONTROL_STAGE_SETUP ) + { + // Switch Alt interface and Re-initalize state machine + _dfu_ctx.alt_num = (uint8_t) request->wValue; + _dfu_ctx.state = DFU_IDLE; + _dfu_ctx.status = DFU_STATUS_OK; + _dfu_ctx.blk_transfer_in_proc = false; - return tud_control_status(rhport, request); + return tud_control_status(rhport, request); + } break; case TUSB_REQ_GET_INTERFACE: - return tud_control_xfer(rhport, request, &_dfu_ctx.alt_num, 1); + if(stage == CONTROL_STAGE_SETUP) + { + return tud_control_xfer(rhport, request, &_dfu_ctx.alt_num, 1); + } break; // unsupported request default: return false; } } - else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) + else if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS ) { // Class request - switch (request->bRequest) + switch ( request->bRequest ) { case DFU_REQUEST_DETACH: - { - tud_control_status(rhport, request); - if (tud_dfu_detach_cb) tud_dfu_detach_cb(); - break; - } + if ( stage == CONTROL_STAGE_SETUP ) + { + tud_control_status(rhport, request); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if (tud_dfu_detach_cb) tud_dfu_detach_cb(); + } + break; + + case DFU_REQUEST_UPLOAD: + if ( stage == CONTROL_STAGE_SETUP ) + { + TU_VERIFY(_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK); + TU_VERIFY(tud_dfu_upload_cb); + TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + + uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt_num, request->wValue, _dfu_ctx.transfer_buf, request->wLength); + + tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len); + } + break; case DFU_REQUEST_DNLOAD: { @@ -262,7 +284,6 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque } } // fallthrough - case DFU_REQUEST_UPLOAD: case DFU_REQUEST_GETSTATUS: case DFU_REQUEST_CLRSTATUS: case DFU_REQUEST_GETSTATE: @@ -290,18 +311,6 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque return true; } -static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) -{ - TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); - uint16_t retval = 0; - if (tud_dfu_upload_cb) - { - tud_dfu_upload_cb(_dfu_ctx.alt_num, block_num, (uint8_t *)_dfu_ctx.transfer_buf, wLength); - } - tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, retval); - return retval; -} - static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) { uint32_t timeout = 0; @@ -382,18 +391,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req } break; - case DFU_REQUEST_UPLOAD: - { - if( ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) ) - { - _dfu_ctx.state = DFU_UPLOAD_IDLE; - dfu_req_upload(rhport, request, request->wValue, request->wLength); - } else { - _dfu_ctx.state = DFU_ERROR; - } - } - break; - case DFU_REQUEST_GETSTATUS: dfu_req_getstatus_reply(rhport, request); break; @@ -567,15 +564,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { switch (request->bRequest) { - case DFU_REQUEST_UPLOAD: - { - if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength) - { - _dfu_ctx.state = DFU_IDLE; - } - } - break; - case DFU_REQUEST_GETSTATUS: dfu_req_getstatus_reply(rhport, request); break; diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ec58a3181..fc1035e2c 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -449,7 +449,7 @@ typedef struct TU_ATTR_PACKED /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ -typedef struct TU_ATTR_PACKED{ +typedef struct TU_ATTR_PACKED TU_ATTR_ALIGNED(4) { union { struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. -- cgit v1.3.1 From 6a68fc699724fb216b745dbf48fdae32305f1d35 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jul 2021 16:51:28 +0700 Subject: update dfu abort --- src/class/dfu/dfu_device.c | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 376feb053..ed36178f1 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -259,6 +259,19 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque } break; + case DFU_REQUEST_ABORT: + if ( stage == CONTROL_STAGE_SETUP ) + { + if (tud_dfu_abort_cb) tud_dfu_abort_cb(_dfu_ctx.alt_num); + + _dfu_ctx.state = DFU_IDLE; + _dfu_ctx.status = DFU_STATUS_OK; + _dfu_ctx.blk_transfer_in_proc = false; + + tud_control_status(rhport, request); + } + break; + case DFU_REQUEST_UPLOAD: if ( stage == CONTROL_STAGE_SETUP ) { @@ -287,7 +300,6 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case DFU_REQUEST_GETSTATUS: case DFU_REQUEST_CLRSTATUS: case DFU_REQUEST_GETSTATE: - case DFU_REQUEST_ABORT: { if(stage == CONTROL_STAGE_SETUP) { @@ -297,10 +309,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque break; default: - { - TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest); return false; // stall unsupported request - } break; } }else @@ -399,10 +408,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstate_reply(rhport, request); break; - case DFU_REQUEST_ABORT: - ; // do nothing, but don't stall so continue on - break; - default: _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests @@ -486,14 +491,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstate_reply(rhport, request); break; - case DFU_REQUEST_ABORT: - if ( tud_dfu_abort_cb ) - { - tud_dfu_abort_cb(_dfu_ctx.alt_num); - } - _dfu_ctx.state = DFU_IDLE; - break; - default: _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests @@ -572,16 +569,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstate_reply(rhport, request); break; - case DFU_REQUEST_ABORT: - { - if (tud_dfu_abort_cb) - { - tud_dfu_abort_cb(_dfu_ctx.alt_num); - } - _dfu_ctx.state = DFU_IDLE; - } - break; - default: return false; // stall on all other requests break; -- cgit v1.3.1 From b4fde90b5518c4e92750af2e27eae598267ad8cf Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jul 2021 17:03:20 +0700 Subject: update clear status and get state --- src/class/dfu/dfu_device.c | 66 +++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index ed36178f1..686d9b023 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -61,6 +61,13 @@ static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t c static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); +static void reset_state(void) +{ + _dfu_ctx.state = DFU_IDLE; + _dfu_ctx.status = DFU_STATUS_OK; + _dfu_ctx.blk_transfer_in_proc = false; +} + //--------------------------------------------------------------------+ // Debug //--------------------------------------------------------------------+ @@ -224,10 +231,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque { // Switch Alt interface and Re-initalize state machine _dfu_ctx.alt_num = (uint8_t) request->wValue; - _dfu_ctx.state = DFU_IDLE; - _dfu_ctx.status = DFU_STATUS_OK; - _dfu_ctx.blk_transfer_in_proc = false; - + reset_state(); return tud_control_status(rhport, request); } break; @@ -264,14 +268,26 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque { if (tud_dfu_abort_cb) tud_dfu_abort_cb(_dfu_ctx.alt_num); - _dfu_ctx.state = DFU_IDLE; - _dfu_ctx.status = DFU_STATUS_OK; - _dfu_ctx.blk_transfer_in_proc = false; + reset_state(); + tud_control_status(rhport, request); + } + break; + case DFU_REQUEST_CLRSTATUS: + if ( stage == CONTROL_STAGE_SETUP ) + { + reset_state(); tud_control_status(rhport, request); } break; + case DFU_REQUEST_GETSTATE: + if ( stage == CONTROL_STAGE_SETUP ) + { + tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); + } + break; + case DFU_REQUEST_UPLOAD: if ( stage == CONTROL_STAGE_SETUP ) { @@ -298,8 +314,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque } // fallthrough case DFU_REQUEST_GETSTATUS: - case DFU_REQUEST_CLRSTATUS: - case DFU_REQUEST_GETSTATE: + { if(stage == CONTROL_STAGE_SETUP) { @@ -339,11 +354,6 @@ static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); } -static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); -} - static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) { // TODO: add "zero" copy mode so the buffer we read into can be provided by the user @@ -404,10 +414,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstatus_reply(rhport, request); break; - case DFU_REQUEST_GETSTATE: - dfu_req_getstate_reply(rhport, request); - break; - default: _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests @@ -434,10 +440,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req } break; - case DFU_REQUEST_GETSTATE: - dfu_req_getstate_reply(rhport, request); - break; - default: _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests @@ -487,10 +489,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstatus_reply(rhport, request); break; - case DFU_REQUEST_GETSTATE: - dfu_req_getstate_reply(rhport, request); - break; - default: _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests @@ -520,10 +518,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req } break; - case DFU_REQUEST_GETSTATE: - dfu_req_getstate_reply(rhport, request); - break; - default: _dfu_ctx.state = DFU_ERROR; return false; // stall on all other requests @@ -565,10 +559,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstatus_reply(rhport, request); break; - case DFU_REQUEST_GETSTATE: - dfu_req_getstate_reply(rhport, request); - break; - default: return false; // stall on all other requests break; @@ -584,14 +574,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req dfu_req_getstatus_reply(rhport, request); break; - case DFU_REQUEST_CLRSTATUS: - _dfu_ctx.state = DFU_IDLE; - break; - - case DFU_REQUEST_GETSTATE: - dfu_req_getstate_reply(rhport, request); - break; - default: return false; // stall on all other requests break; -- cgit v1.3.1 From daca9e520bce0b4eb5882c5692986ec5c513f319 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 Jul 2021 20:47:50 +0700 Subject: wrap up DFU update --- examples/device/dfu/src/main.c | 95 +++++--- examples/device/dfu/src/tusb_config.h | 2 +- examples/device/dfu/src/usb_descriptors.c | 4 +- src/class/dfu/dfu.h | 47 ++-- src/class/dfu/dfu_device.c | 393 +++++++++++++++++++----------- src/class/dfu/dfu_device.h | 68 +++--- src/class/dfu/dfu_rt_device.c | 6 +- src/common/tusb_types.h | 2 +- src/device/usbd.c | 2 +- src/tusb_option.h | 4 - 10 files changed, 368 insertions(+), 255 deletions(-) (limited to 'src') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 2c114c5a2..1621a330b 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -26,7 +26,7 @@ /* * After device is enumerated in dfu mode run the following commands * - * To transfer firmware from host to device: + * To transfer firmware from host to device (best to test with text file) * * $ dfu-util -d cafe -a 0 -D [filename] * $ dfu-util -d cafe -a 1 -D [filename] @@ -45,22 +45,21 @@ #include "bsp/board.h" #include "tusb.h" - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -#ifndef DFU_VERBOSE -#define DFU_VERBOSE 0 -#endif +const char* upload_image[2]= +{ + "Hello world from TinyUSB DFU! - Partition 0", + "Hello world from TinyUSB DFU! - Partition 1" +}; /* Blink pattern - * - 1000 ms : device should reboot * - 250 ms : device not mounted * - 1000 ms : device mounted * - 2500 ms : device is suspended */ enum { - BLINK_DFU_MODE = 100, BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -118,65 +117,87 @@ void tud_resume_cb(void) } //--------------------------------------------------------------------+ -// Class callbacks +// DFU callbacks +// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. //--------------------------------------------------------------------+ -bool tud_dfu_firmware_valid_check_cb(uint8_t alt) -{ - (void) alt; - printf(" Firmware check\r\n"); - return true; -} -uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state) +// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST) +// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation. +// During this period, USB host won't try to communicate with us. +uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state) { - // For example Alt1 (EEPROM) is slow, add 2000ms timeout if ( state == DFU_DNBUSY ) { - if (alt == 1) return 2000; + // For this example + // - Atl0 Flash is fast : 1 ms + // - Alt1 EEPROM is slow: 100 ms + return (alt == 0) ? 1 : 100; } + else if (state == DFU_MANIFEST) + { + // since we don't buffer entire image and do any flashing in manifest stage + return 0; + } + return 0; } -void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length) +// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests +// This callback could be returned before flashing op is complete (async). +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t const* data, uint16_t length) { (void) data; - printf("Received Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); + printf("\r\nReceived Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); -#if DFU_VERBOSE for(uint16_t i=0; ibAttributes; - // CFG_TUD_DFU_TRANSFER_BUFFER_SIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR + // CFG_TUD_DFU_TRANSFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16(&func_desc->wTransferSize) ); - TU_ASSERT(transfer_size <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, drv_len); + TU_ASSERT(transfer_size <= CFG_TUD_DFU_TRANSFER_BUFSIZE, drv_len); return drv_len; } @@ -216,11 +201,10 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, // return false to stall control endpoint (e.g unsupported request) bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - // nothing to do with DATA stage - if ( stage == CONTROL_STAGE_DATA ) return true; - TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); + TU_LOG2(" DFU State : %s, Status: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state), tu_lookup_find(&_dfu_status_table, _dfu_ctx.status)); + if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD ) { // Standard request include GET/SET_INTERFACE @@ -229,8 +213,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case TUSB_REQ_SET_INTERFACE: if ( stage == CONTROL_STAGE_SETUP ) { - // Switch Alt interface and Re-initalize state machine - _dfu_ctx.alt_num = (uint8_t) request->wValue; + // Switch Alt interface and reset state machine + _dfu_ctx.alt = (uint8_t) request->wValue; reset_state(); return tud_control_status(rhport, request); } @@ -239,7 +223,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque case TUSB_REQ_GET_INTERFACE: if(stage == CONTROL_STAGE_SETUP) { - return tud_control_xfer(rhport, request, &_dfu_ctx.alt_num, 1); + return tud_control_xfer(rhport, request, &_dfu_ctx.alt, 1); } break; @@ -249,6 +233,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque } else if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS ) { + TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); + // Class request switch ( request->bRequest ) { @@ -259,73 +245,97 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque } else if ( stage == CONTROL_STAGE_ACK ) { - if (tud_dfu_detach_cb) tud_dfu_detach_cb(); + if ( tud_dfu_detach_cb ) tud_dfu_detach_cb(); } break; - case DFU_REQUEST_ABORT: + case DFU_REQUEST_CLRSTATUS: if ( stage == CONTROL_STAGE_SETUP ) { - if (tud_dfu_abort_cb) tud_dfu_abort_cb(_dfu_ctx.alt_num); - reset_state(); tud_control_status(rhport, request); } break; - case DFU_REQUEST_CLRSTATUS: + case DFU_REQUEST_GETSTATE: if ( stage == CONTROL_STAGE_SETUP ) { - reset_state(); - tud_control_status(rhport, request); + tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); } break; - case DFU_REQUEST_GETSTATE: + case DFU_REQUEST_ABORT: if ( stage == CONTROL_STAGE_SETUP ) { - tud_control_xfer(rhport, request, &_dfu_ctx.state, 1); + reset_state(); + tud_control_status(rhport, request); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if ( tud_dfu_abort_cb ) tud_dfu_abort_cb(_dfu_ctx.alt); } break; case DFU_REQUEST_UPLOAD: if ( stage == CONTROL_STAGE_SETUP ) { - TU_VERIFY(_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK); + TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD); TU_VERIFY(tud_dfu_upload_cb); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE); - uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt_num, request->wValue, _dfu_ctx.transfer_buf, request->wLength); + uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_ctx.transfer_buf, request->wLength); - tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len); + return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len); } break; case DFU_REQUEST_DNLOAD: - { - if ( (stage == CONTROL_STAGE_ACK) - && ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) - && (_dfu_ctx.state == DFU_DNLOAD_SYNC)) + if ( stage == CONTROL_STAGE_SETUP ) { - _dfu_ctx.block = request->wValue; + TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD); + TU_VERIFY(_dfu_ctx.state == DFU_IDLE || _dfu_ctx.state == DFU_DNLOAD_IDLE); + TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE); + + // set to true for both download and manifest + _dfu_ctx.flashing_in_progress = true; + + // save block and length for flashing + _dfu_ctx.block = request->wValue; _dfu_ctx.length = request->wLength; - return true; + + if ( request->wLength ) + { + // Download with payload -> transition to DOWNLOAD SYNC + _dfu_ctx.state = DFU_DNLOAD_SYNC; + return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); + } + else + { + // Download is complete -> transition to MANIFEST SYNC + _dfu_ctx.state = DFU_MANIFEST_SYNC; + return tud_control_status(rhport, request); + } } - } - // fallthrough - case DFU_REQUEST_GETSTATUS: + break; - { - if(stage == CONTROL_STAGE_SETUP) + case DFU_REQUEST_GETSTATUS: + switch ( _dfu_ctx.state ) { - return dfu_state_machine(rhport, request); + case DFU_DNLOAD_SYNC: + return process_download_get_status(rhport, stage, request); + break; + + case DFU_MANIFEST_SYNC: + return process_manifest_get_status(rhport, stage, request); + break; + + default: + if ( stage == CONTROL_STAGE_SETUP ) return reply_getstatus(rhport, request, _dfu_ctx.state, _dfu_ctx.status, 0); + break; } - } break; - default: - return false; // stall unsupported request - break; + default: return false; // stall unsupported request } }else { @@ -335,32 +345,130 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque return true; } -static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request) +void tud_dfu_finish_flashing(uint8_t status) +{ + _dfu_ctx.flashing_in_progress = false; + + if ( status == DFU_STATUS_OK ) + { + if (_dfu_ctx.state == DFU_DNBUSY) + { + _dfu_ctx.state = DFU_DNLOAD_SYNC; + } + else if (_dfu_ctx.state == DFU_MANIFEST) + { + _dfu_ctx.state = (_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT) + ? DFU_MANIFEST_SYNC : DFU_MANIFEST_WAIT_RESET; + } + } + else + { + // failed while flashing, move to dfuError + _dfu_ctx.state = DFU_ERROR; + _dfu_ctx.status = status; + } +} + +static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + if ( stage == CONTROL_STAGE_SETUP ) + { + // only transition to next state on CONTROL_STAGE_ACK + dfu_state_t next_state; + uint32_t timeout; + + if ( _dfu_ctx.flashing_in_progress ) + { + next_state = DFU_DNBUSY; + timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, (uint8_t) next_state); + } + else + { + next_state = DFU_DNLOAD_IDLE; + timeout = 0; + } + + return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if ( _dfu_ctx.flashing_in_progress ) + { + _dfu_ctx.state = DFU_DNBUSY; + tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _dfu_ctx.transfer_buf, _dfu_ctx.length); + }else + { + _dfu_ctx.state = DFU_DNLOAD_IDLE; + } + } + + return true; +} + +static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - uint32_t timeout = 0; - if ( tud_dfu_get_status_cb ) + if ( stage == CONTROL_STAGE_SETUP ) { - timeout = tud_dfu_get_status_cb(_dfu_ctx.alt_num, _dfu_ctx.state); + // only transition to next state on CONTROL_STAGE_ACK + dfu_state_t next_state; + uint32_t timeout; + + if ( _dfu_ctx.flashing_in_progress ) + { + next_state = DFU_MANIFEST; + timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, next_state); + } + else + { + next_state = DFU_IDLE; + timeout = 0; + } + + return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout); + } + else if ( stage == CONTROL_STAGE_ACK ) + { + if ( _dfu_ctx.flashing_in_progress ) + { + _dfu_ctx.state = DFU_MANIFEST; + tud_dfu_manifest_cb(_dfu_ctx.alt); + } + else + { + _dfu_ctx.state = DFU_IDLE; + } } - dfu_status_req_payload_t resp; - resp.bStatus = _dfu_ctx.status; + return true; +} + +static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout) +{ + dfu_status_response_t resp; + resp.bStatus = (uint8_t) status; resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout); resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout); resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout); - resp.bState = _dfu_ctx.state; - resp.iString = 0; + resp.bState = (uint8_t) state; + resp.iString = 0; - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); + return tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); } + +#if 0 + +static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); +static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); +static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); + static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) { // TODO: add "zero" copy mode so the buffer we read into can be provided by the user // if they wish, there still will be the internal control buffer copy to this buffer // but this mode would provide zero copy from the class driver to the application - TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE, ); // setup for data phase tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); } @@ -368,21 +476,9 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { (void) rhport; - TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); - tud_dfu_download_cb(_dfu_ctx.alt_num,_dfu_ctx.block, (uint8_t *)_dfu_ctx.transfer_buf, _dfu_ctx.length); - _dfu_ctx.blk_transfer_in_proc = false; -} - -void tud_dfu_download_complete(void) -{ - if (_dfu_ctx.state == DFU_DNBUSY) - { - _dfu_ctx.state = DFU_DNLOAD_SYNC; - } else if (_dfu_ctx.state == DFU_MANIFEST) - { - _dfu_ctx.state = ((_dfu_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) - ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC; - } + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE, ); + tud_dfu_download_cb(_dfu_ctx.alt,_dfu_ctx.block, (uint8_t *)_dfu_ctx.transfer_buf, _dfu_ctx.length); + _dfu_ctx.flashing_in_progress = false; } static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) @@ -398,11 +494,11 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD) != 0) && (request->wLength > 0) ) { _dfu_ctx.state = DFU_DNLOAD_SYNC; - _dfu_ctx.blk_transfer_in_proc = true; + _dfu_ctx.flashing_in_progress = true; dfu_req_dnload_setup(rhport, request); } else { _dfu_ctx.state = DFU_ERROR; @@ -411,7 +507,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATUS: - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); break; default: @@ -428,14 +524,14 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ( _dfu_ctx.blk_transfer_in_proc ) + if ( _dfu_ctx.flashing_in_progress ) { _dfu_ctx.state = DFU_DNBUSY; - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); dfu_req_dnload_reply(rhport, request); } else { _dfu_ctx.state = DFU_DNLOAD_IDLE; - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); } } break; @@ -466,14 +562,14 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_DNLOAD: { - if( ((_dfu_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0) + if( ((_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD) != 0) && (request->wLength > 0) ) { _dfu_ctx.state = DFU_DNLOAD_SYNC; - _dfu_ctx.blk_transfer_in_proc = true; + _dfu_ctx.flashing_in_progress = true; dfu_req_dnload_setup(rhport, request); } else { - if ( tud_dfu_device_data_done_check_cb(_dfu_ctx.alt_num) ) + if ( tud_dfu_download_complete_cb(_dfu_ctx.alt) ) { _dfu_ctx.state = DFU_MANIFEST_SYNC; tud_control_status(rhport, request); @@ -486,7 +582,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req break; case DFU_REQUEST_GETSTATUS: - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); break; default: @@ -503,17 +599,17 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req { case DFU_REQUEST_GETSTATUS: { - if ((_dfu_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) == 0) + if ((_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT) == 0) { _dfu_ctx.state = DFU_MANIFEST; - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); } else { - if ( tud_dfu_firmware_valid_check_cb(_dfu_ctx.alt_num) ) + if ( tud_dfu_manifest_cb(_dfu_ctx.alt) ) { _dfu_ctx.state = DFU_IDLE; } - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); } } break; @@ -556,7 +652,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req switch (request->bRequest) { case DFU_REQUEST_GETSTATUS: - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); break; default: @@ -571,7 +667,7 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req switch (request->bRequest) { case DFU_REQUEST_GETSTATUS: - dfu_req_getstatus_reply(rhport, request); + reply_getstatus(rhport, request); break; default: @@ -590,5 +686,6 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req return true; } +#endif #endif diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index d5d464f3b..2d398aada 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -37,53 +37,51 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -#if !defined(CFG_TUD_DFU_TRANSFER_BUFFER_SIZE) - #error "CFG_TUD_DFU_TRANSFER_BUFFER_SIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" +#if !defined(CFG_TUD_DFU_TRANSFER_BUFSIZE) + #error "CFG_TUD_DFU_TRANSFER_BUFSIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" #endif +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + +// Must be called when the application is done with flashing started by +// tud_dfu_download_cb() and tud_dfu_manifest_cb(). +// status is DFU_STATUS_OK if successful, any other error status will cause state to enter dfuError +void tud_dfu_finish_flashing(uint8_t status); + //--------------------------------------------------------------------+ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -// Invoked during DFU_MANIFEST_SYNC get status request to check if firmware is valid -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -bool tud_dfu_firmware_valid_check_cb(uint8_t alt); - -// Invoked when a DFU_GETSTATUS request is received -// Return the bwPollTimeout value for host's response, useful for slow Flash in order to make host wait longer -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -TU_ATTR_WEAK uint32_t tud_dfu_get_status_cb(uint8_t alt, uint8_t state); - -// Invoked when a DFU_DNLOAD request is received -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -// This callback takes the wBlockNum chunk of length length and provides it -// to the application at the data pointer. This data is only valid for this -// call, so the app must use it not or copy it. -void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t* data, uint16_t length); - -// Must be called when the application is done using the last block of data -// provided by tud_dfu_download_cb -void tud_dfu_download_complete(void); - -// Invoked during the last DFU_DNLOAD request, signifying that the host believes -// it is done transmitting data. -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -// Return true if the application agrees there is no more data -// Return false if the device disagrees, which will stall the pipe, and the Host -// should initiate a recovery procedure -bool tud_dfu_device_data_done_check_cb(uint8_t alt); -// Invoked when the Host has terminated a download or upload transfer -TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); +// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -// Invoked when a DFU_UPLOAD request is received -// alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -// This callback must populate data with up to length bytes -// Return the number of bytes to write +// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST) +// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation. +// During this period, USB host won't try to communicate with us. +uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state); + +// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests +// This callback could be returned before flashing op is complete (async). +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_download_cb (uint8_t alt, uint16_t block_num, uint8_t const *data, uint16_t length); + +// Invoked when download process is complete, received DFU_DNLOAD (wLength=0) following by DFU_GETSTATUS (state=Manifest) +// Application can do checksum, or actual flashing if buffered entire image previously. +// Once finished flashing, application must call tud_dfu_finish_flashing() +void tud_dfu_manifest_cb(uint8_t alt); + +// Invoked when received DFU_UPLOAD request +// Application must populate data with up to length bytes and +// Return the number of written bytes TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length); // Invoked when a DFU_DETACH request is received TU_ATTR_WEAK void tud_dfu_detach_cb(void); +// Invoked when the Host has terminated a download or upload transfer +TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt); + //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c index 07e6f30f3..afee2aa1f 100644 --- a/src/class/dfu/dfu_rt_device.c +++ b/src/class/dfu/dfu_rt_device.c @@ -108,10 +108,10 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request case DFU_REQUEST_GETSTATUS: { TU_LOG2(" DFU RT Request: GETSTATUS\r\n"); - dfu_status_req_payload_t resp; + dfu_status_response_t resp; // Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0 - memset(&resp, 0x00, sizeof(dfu_status_req_payload_t)); - tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t)); + memset(&resp, 0x00, sizeof(dfu_status_response_t)); + tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); } break; diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index fc1035e2c..eab67ebd5 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -449,7 +449,7 @@ typedef struct TU_ATTR_PACKED /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ -typedef struct TU_ATTR_PACKED TU_ATTR_ALIGNED(4) { +typedef struct TU_ATTR_PACKED { union { struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. diff --git a/src/device/usbd.c b/src/device/usbd.c index af4fd58c4..cf9af783d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -190,7 +190,7 @@ static usbd_class_driver_t const _usbd_driver[] = #if CFG_TUD_DFU_MODE { - DRIVER_NAME("DFU-MODE") + DRIVER_NAME("DFU") .init = dfu_moded_init, .reset = dfu_moded_reset, .open = dfu_moded_open, diff --git a/src/tusb_option.h b/src/tusb_option.h index bf7591dcf..4351d9486 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -253,10 +253,6 @@ #define CFG_TUD_DFU_MODE 0 #endif -#ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE - #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 64 -#endif - #ifndef CFG_TUD_NET #define CFG_TUD_NET 0 #endif -- cgit v1.3.1 From 3960beece0ea3dccf7ca615bd7841daa6b703d56 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 Jul 2021 20:52:58 +0700 Subject: rename CFG_TUD_DFU_MODE to simply CFG_TUD_DFU --- examples/device/dfu/src/main.c | 2 +- examples/device/dfu/src/tusb_config.h | 4 +--- src/class/dfu/dfu_device.c | 2 +- src/device/usbd.c | 2 +- src/tusb.h | 2 +- src/tusb_option.h | 4 ++-- 6 files changed, 7 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 1621a330b..7133d1624 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -148,7 +148,7 @@ uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state) void tud_dfu_download_cb(uint8_t alt, uint16_t wBlockNum, uint8_t const* data, uint16_t length) { (void) data; - printf("\r\nReceived Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); + //printf("\r\nReceived Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); for(uint16_t i=0; i Date: Sat, 17 Jul 2021 12:08:42 +0200 Subject: Change OPT_MCU_SAMX7X value. --- src/tusb_option.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/tusb_option.h b/src/tusb_option.h index 69c5fb0bd..9b0ea4358 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -61,7 +61,8 @@ #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 #define OPT_MCU_SAML22 205 ///< MicroChip SAML22 -#define OPT_MCU_SAMX7X 206 ///< MicroChip SAME70, S70, V70, V71 family +#define OPT_MCU_SAML21 206 ///< MicroChip SAML21 +#define OPT_MCU_SAMX7X 207 ///< MicroChip SAME70, S70, V70, V71 family // STM32 -- cgit v1.3.1 From 7e3e41952fe4c83a182dfe39e5bab89e65120485 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 17 Jul 2021 13:48:21 +0200 Subject: Fix ISO support. --- examples/device/uac2_headset/src/usb_descriptors.c | 16 ++++++++++++---- src/portable/microchip/samx7x/dcd_samx7x.c | 18 +++++++++++++----- 2 files changed, 25 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index 6a01f8938..4a26b0b1e 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -79,12 +79,20 @@ uint8_t const * tud_descriptor_device_cb(void) #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 ... -#define EPNUM_AUDIO 0x03 +#define EPNUM_AUDIO_IN 0x03 +#define EPNUM_AUDIO_OUT 0x03 #elif CFG_TUSB_MCU == OPT_MCU_NRF5X // ISO endpoints for NRF5x are fixed to 0x08 (0x88) -#define EPNUM_AUDIO 0x08 +#define EPNUM_AUDIO_IN 0x08 +#define EPNUM_AUDIO_OUT 0x08 +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X +// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT +// e.g EP1 OUT & EP1 IN cannot exist together +#define EPNUM_AUDIO_IN 0x01 +#define EPNUM_AUDIO_OUT 0x02 #else -#define EPNUM_AUDIO 0x01 +#define EPNUM_AUDIO_IN 0x01 +#define EPNUM_AUDIO_OUT 0x01 #endif uint8_t const desc_configuration[] = @@ -93,7 +101,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO, EPNUM_AUDIO | 0x80) + TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 0299d12b9..2a534b95b 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -83,11 +83,8 @@ typedef struct { static tusb_speed_t get_speed(void); static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); -// DMA descriptors shouldn't be placed in ITCM -#if defined(USB_DMA_DESC_SECTION) -TU_ATTR_SECTION(TU_XSTRING(USB_DMA_DESC_SECTION)) -#endif -dma_desc_t dma_desc[6]; +// DMA descriptors shouldn't be placed in ITCM ! +CFG_TUSB_MEM_SECTION dma_desc_t dma_desc[6]; xfer_ctl_t xfer_status[EP_MAX+1]; @@ -531,6 +528,17 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) } } +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + // Disable endpoint interrupt + USBHS->USBHS_DEVIDR = 1 << (USBHS_DEVIDR_PEP_0_Pos + epnum); + // Disable EP + USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPEN0_Pos + epnum)); +} + static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); -- cgit v1.3.1 From bae0d3b7bbe5145017ebd08f777fe0b8063f44b7 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 17 Jul 2021 14:42:23 +0200 Subject: Fix build error. --- src/portable/microchip/samx7x/dcd_samx7x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 2a534b95b..aa9faa5be 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -531,7 +531,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + (void) ep_addr; // Disable endpoint interrupt USBHS->USBHS_DEVIDR = 1 << (USBHS_DEVIDR_PEP_0_Pos + epnum); -- cgit v1.3.1 From f52e1889c7f4bca23311a97b5869eab70c766094 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 17 Jul 2021 20:41:19 +0200 Subject: Fix merge error. --- examples/device/cdc_msc/src/msc_disk.c | 2 +- examples/device/hid_composite/src/tusb_config.h | 2 +- src/class/cdc/cdc_device.c | 14 -------------- src/class/cdc/cdc_device.h | 18 ------------------ 4 files changed, 2 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/examples/device/cdc_msc/src/msc_disk.c b/examples/device/cdc_msc/src/msc_disk.c index 3caf3fd42..503baace9 100644 --- a/examples/device/cdc_msc/src/msc_disk.c +++ b/examples/device/cdc_msc/src/msc_disk.c @@ -23,7 +23,7 @@ * */ -//#include "bsp/board.h" +#include "bsp/board.h" #include "tusb.h" #if CFG_TUD_MSC diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index 31dea4ee9..868424e6d 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -69,7 +69,7 @@ #endif // CFG_TUSB_DEBUG is defined by compiler in DEBUG build -#define CFG_TUSB_DEBUG 0 +// #define CFG_TUSB_DEBUG 0 /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. * Tinyusb use follows macros to declare transferring memory so that they can be put diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 68080c61d..e622bd616 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -481,18 +481,4 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ return true; } -// Get the Receive FIFO (for DMA transfer) -tu_fifo_t* tud_cdc_n_get_rx_ff (uint8_t itf) -{ - TU_ASSERT(itf < CFG_TUD_CDC); - return &_cdcd_itf[itf].rx_ff; -} - -// Get the transmit FIFO (for DMA transfer) -tu_fifo_t* tud_cdc_n_get_tx_ff (uint8_t itf) -{ - TU_ASSERT(itf < CFG_TUD_CDC); - return &_cdcd_itf[itf].tx_ff; -} - #endif diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index f8a2216c1..7ff757add 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -104,12 +104,6 @@ uint32_t tud_cdc_n_write_available (uint8_t itf); // Clear the transmit FIFO bool tud_cdc_n_write_clear (uint8_t itf); -// Get the Receive FIFO (for DMA transfer) -tu_fifo_t* tud_cdc_n_get_rx_ff (uint8_t itf); - -// Get the transmit FIFO (for DMA transfer) -tu_fifo_t* tud_cdc_n_get_tx_ff (uint8_t itf); - //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ @@ -247,18 +241,6 @@ static inline bool tud_cdc_write_clear(void) return tud_cdc_n_write_clear(0); } -// Get the Receive FIFO -static inline tu_fifo_t* tud_cdc_get_rx_ff (void) -{ - return tud_cdc_n_get_rx_ff(0); -} - -// Get the transmit FIFO -static inline tu_fifo_t* tud_cdc_get_tx_ff (void) -{ - return tud_cdc_n_get_tx_ff(0); -} - /** @} */ /** @} */ -- cgit v1.3.1 From 8cae17bfc87f49c814827b0a31a4b6b6e8314f69 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Mon, 19 Jul 2021 01:07:33 +0200 Subject: Fixing NAKed OUT xfer --- src/portable/microchip/samx7x/dcd_samx7x.c | 53 ++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index aa9faa5be..3134a0597 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -60,7 +60,8 @@ #define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) // Errata: The DMA feature is not available for Pipe/Endpoint 7 -#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) +// #define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) +#define EP_DMA_SUPPORT(epnum) 0 // DMA Channel Transfer Descriptor typedef struct { @@ -294,8 +295,6 @@ static void dcd_ep_handler(uint8_t ep_ix) } // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; - // Clear the FIFO control flag to receive more data. - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { // RX COMPLETE @@ -314,10 +313,10 @@ static void dcd_ep_handler(uint8_t ep_ix) { // TX not complete dcd_transmit_packet(xfer, ep_ix); - } else { + } else + { // TX complete dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; } } } @@ -338,7 +337,8 @@ static void dcd_dma_handler(uint8_t ep_ix) if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) { dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); - } else { + } else + { dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); } } @@ -483,14 +483,17 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { // Endpoint configuration is successful USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXOUTES; // Enable Endpoint 0 Interrupts USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; return true; - } else { + } else + { // Endpoint configuration is not successful return false; } - } else { + } else + { // Enable the endpoint USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); // Set up the maxpacket size, fifo start address fifosize @@ -520,8 +523,17 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) { USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); + if (dir) + { + USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_TXINIC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_TXINES; + } else + { + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + } return true; - } else { + } else + { // Endpoint configuration is not successful return false; } @@ -553,7 +565,8 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { memcpy(ptr, xfer->buffer + xfer->queued_len, len); } - else { + else + { tu_fifo_read_n(xfer->fifo, ptr, len); } __DSB(); @@ -564,11 +577,12 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { // Control endpoint: clear the interrupt flag to send the data USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - } else { + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_TXINES; + } else + { // Other endpoint types: clear the FIFO control flag to send the data USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; } - USBHS->USBHS_DEVEPTIER[ep_ix] = USBHS_DEVEPTIER_TXINES; } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack @@ -615,11 +629,14 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // and the DMA transfer must be not started. // It is the end of transfer return false; - } else { + } else + { if (dir == TUSB_DIR_OUT) { - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } else { + // Clear the FIFO control flag to receive more data. + USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_FIFOCONC; + } else + { dcd_transmit_packet(xfer,epnum); } } @@ -696,11 +713,13 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 // and the DMA transfer must be not started. // It is the end of transfer return false; - } else { + } else + { if (dir == TUSB_DIR_OUT) { USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; - } else { + } else + { dcd_transmit_packet(xfer,epnum); } } -- cgit v1.3.1 From 05f59fb8edc301690042821d447c31631be8d911 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 19 Jul 2021 12:08:01 +0700 Subject: clean up warning --- hw/bsp/same70_xplained/board.mk | 5 ----- hw/bsp/same70_xplained/same70_xplained.c | 4 +--- src/portable/microchip/samx7x/dcd_samx7x.c | 2 +- 3 files changed, 2 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/hw/bsp/same70_xplained/board.mk b/hw/bsp/same70_xplained/board.mk index 94b0bed98..c9bc0cea3 100644 --- a/hw/bsp/same70_xplained/board.mk +++ b/hw/bsp/same70_xplained/board.mk @@ -43,11 +43,6 @@ INC += \ $(TOP)/$(ASF_DIR)/hri \ $(TOP)/$(ASF_DIR)/CMSIS/Core/Include -# For TinyUSB port source -#SRC_C += src/portable/template/dcd_template.c -VENDOR = . -CHIP_FAMILY = template - # For freeRTOS port source FREERTOS_PORT = ARM_CM7 diff --git a/hw/bsp/same70_xplained/same70_xplained.c b/hw/bsp/same70_xplained/same70_xplained.c index f897798e7..ac682a89a 100644 --- a/hw/bsp/same70_xplained/same70_xplained.c +++ b/hw/bsp/same70_xplained/same70_xplained.c @@ -111,9 +111,7 @@ void board_init(void) //--------------------------------------------------------------------+ void USBHS_Handler(void) { - #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE - tud_int_handler(0); - #endif + tud_int_handler(0); } //--------------------------------------------------------------------+ diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 3134a0597..31628583a 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -542,8 +542,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { + (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - (void) ep_addr; // Disable endpoint interrupt USBHS->USBHS_DEVIDR = 1 << (USBHS_DEVIDR_PEP_0_Pos + epnum); -- cgit v1.3.1 From cee980c598ce3ff83f2980280d53c906b7bf1b19 Mon Sep 17 00:00:00 2001 From: Ben Evans Date: Mon, 19 Jul 2021 17:45:12 +1000 Subject: Fix for dcd_synopsys driver integer overflow in HS mode (issue #968). --- src/portable/st/synopsys/dcd_synopsys.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 8a196e061..c15694eba 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -656,7 +656,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } uint16_t num_packets = (total_bytes / xfer->max_size); - uint8_t const short_packet_size = total_bytes % xfer->max_size; + uint16_t const short_packet_size = total_bytes % xfer->max_size; // Zero-size packet is special case. if(short_packet_size > 0 || (total_bytes == 0)) { @@ -687,7 +687,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 xfer->total_len = total_bytes; uint16_t num_packets = (total_bytes / xfer->max_size); - uint8_t const short_packet_size = total_bytes % xfer->max_size; + uint16_t const short_packet_size = total_bytes % xfer->max_size; // Zero-size packet is special case. if(short_packet_size > 0 || (total_bytes == 0)) num_packets++; -- cgit v1.3.1 From 75f61328ea8aaffa0e666c56def4efdafcb63a12 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Mon, 19 Jul 2021 22:03:47 +0200 Subject: Remove clock init. --- src/portable/microchip/samx7x/dcd_samx7x.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 3134a0597..c91702c9f 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -102,14 +102,14 @@ static const tusb_desc_endpoint_t ep0_desc = // Initialize controller to device mode void dcd_init (uint8_t rhport) { - // Enable USBPLL - PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); - // Wait until USB UTMI stabilize - while (!(PMC->PMC_SR & PMC_SR_LOCKU)); - // Enable USB FS clk - PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2; - PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); - PMC->PMC_SCER = PMC_SCER_USBCLK; +// // Enable USBPLL +// PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); +// // Wait until USB UTMI stabilize +// while (!(PMC->PMC_SR & PMC_SR_LOCKU)); +// // Enable USB FS clk +// PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2; +// PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); +// PMC->PMC_SCER = PMC_SCER_USBCLK; dcd_connect(rhport); } -- cgit v1.3.1 From fa9a327a7134a53a0a2b1d7c449083110f9a7d37 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 20 Jul 2021 13:24:39 +0200 Subject: Workaround of EP0 issue, clean up. --- src/portable/microchip/samx7x/dcd_samx7x.c | 35 ++++++++++++++---------------- 1 file changed, 16 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index bb69619d7..b49724901 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -60,8 +60,7 @@ #define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) // Errata: The DMA feature is not available for Pipe/Endpoint 7 -// #define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) -#define EP_DMA_SUPPORT(epnum) 0 +#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) // DMA Channel Transfer Descriptor typedef struct { @@ -102,14 +101,6 @@ static const tusb_desc_endpoint_t ep0_desc = // Initialize controller to device mode void dcd_init (uint8_t rhport) { -// // Enable USBPLL -// PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3fU); -// // Wait until USB UTMI stabilize -// while (!(PMC->PMC_SR & PMC_SR_LOCKU)); -// // Enable USB FS clk -// PMC->PMC_MCKR &= ~PMC_MCKR_UPLLDIV2; -// PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(10 - 1); -// PMC->PMC_SCER = PMC_SCER_USBCLK; dcd_connect(rhport); } @@ -228,9 +219,14 @@ static void dcd_ep_handler(uint8_t ep_ix) } // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_CTRL_RXSTPIC; + // Workaround : + // Clear spurious OUT irq + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; + int_status &=~USBHS_DEVEPTISR_RXOUTI; } if (int_status & USBHS_DEVEPTISR_RXOUTI) { + uint8_t *ptr = EP_GET_FIFO_PTR(0,8); xfer_ctl_t *xfer = &xfer_status[0]; if (count && xfer->total_len) { @@ -239,11 +235,11 @@ static void dcd_ep_handler(uint8_t ep_ix) { count = remain; } - uint8_t *ptr = EP_GET_FIFO_PTR(0,8); if (xfer->buffer) { memcpy(xfer->buffer + xfer->queued_len, ptr, count); - } else { + } else + { tu_fifo_write_n(xfer->fifo, ptr, count); } xfer->queued_len = (uint16_t)(xfer->queued_len + count); @@ -253,7 +249,7 @@ static void dcd_ep_handler(uint8_t ep_ix) if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { // RX COMPLETE - dcd_event_xfer_complete(0, 0, xfer->total_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; // Though the host could still send, we don't know. @@ -268,12 +264,14 @@ static void dcd_ep_handler(uint8_t ep_ix) { // TX not complete dcd_transmit_packet(xfer, 0); - } else { + } else + { // TX complete dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); } } - } else { + } else + { if (int_status & USBHS_DEVEPTISR_RXOUTI) { xfer_ctl_t *xfer = &xfer_status[ep_ix]; @@ -293,6 +291,8 @@ static void dcd_ep_handler(uint8_t ep_ix) } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } + // Clear the FIFO control flag to receive more data. + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) @@ -483,7 +483,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { // Endpoint configuration is successful USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RXOUTES; // Enable Endpoint 0 Interrupts USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; return true; @@ -529,7 +528,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_TXINES; } else { - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; } return true; } else @@ -633,8 +631,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t { if (dir == TUSB_DIR_OUT) { - // Clear the FIFO control flag to receive more data. - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_FIFOCONC; + USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; } else { dcd_transmit_packet(xfer,epnum); -- cgit v1.3.1 From eec927ea959d6d972c62d60fa634df227e196b36 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Wed, 21 Jul 2021 00:14:28 +0200 Subject: Fix EP0 issue (again) --- src/portable/microchip/samx7x/dcd_samx7x.c | 34 ++++++++++++++++++------------ 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index b49724901..de1fd2566 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -86,7 +86,7 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); // DMA descriptors shouldn't be placed in ITCM ! CFG_TUSB_MEM_SECTION dma_desc_t dma_desc[6]; -xfer_ctl_t xfer_status[EP_MAX+1]; +xfer_ctl_t xfer_status[EP_MAX]; static const tusb_desc_endpoint_t ep0_desc = { @@ -205,29 +205,32 @@ static void dcd_ep_handler(uint8_t ep_ix) { uint32_t int_status = USBHS->USBHS_DEVEPTISR[ep_ix]; int_status &= USBHS->USBHS_DEVEPTIMR[ep_ix]; + uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; + xfer_ctl_t *xfer = &xfer_status[ep_ix]; + if (ep_ix == 0U) { + static uint8_t ctrl_dir; + if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) { + ctrl_dir = (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CTRL_CTRLDIR_Msk) >> USBHS_DEVEPTISR_CTRL_CTRLDIR_Pos; // Setup packet should always be 8 bytes. If not, ignore it, and try again. if (count == 8) { uint8_t *ptr = EP_GET_FIFO_PTR(0,8); dcd_event_setup_received(0, ptr, true); } - // Acknowledge the interrupt + // Ack and disable SETUP interrupt USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_CTRL_RXSTPIC; - // Workaround : - // Clear spurious OUT irq - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; - int_status &=~USBHS_DEVEPTISR_RXOUTI; + USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_CTRL_RXSTPEC; } if (int_status & USBHS_DEVEPTISR_RXOUTI) { uint8_t *ptr = EP_GET_FIFO_PTR(0,8); - xfer_ctl_t *xfer = &xfer_status[0]; + if (count && xfer->total_len) { uint16_t remain = xfer->total_len - xfer->queued_len; @@ -252,14 +255,17 @@ static void dcd_ep_handler(uint8_t ep_ix) dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; - // Though the host could still send, we don't know. + // Re-enable SETUP interrupt + if (ctrl_dir == 1) + { + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; + } } } if (int_status & USBHS_DEVEPTISR_TXINI) { // Disable the interrupt USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; - xfer_ctl_t * xfer = &xfer_status[EP_MAX]; if ((xfer->total_len != xfer->queued_len)) { // TX not complete @@ -268,13 +274,17 @@ static void dcd_ep_handler(uint8_t ep_ix) { // TX complete dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); + // Re-enable SETUP interrupt + if (ctrl_dir == 0) + { + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; + } } } } else { if (int_status & USBHS_DEVEPTISR_RXOUTI) { - xfer_ctl_t *xfer = &xfer_status[ep_ix]; if (count && xfer->total_len) { uint16_t remain = xfer->total_len - xfer->queued_len; @@ -308,7 +318,6 @@ static void dcd_ep_handler(uint8_t ep_ix) { // Acknowledge the interrupt USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; - xfer_ctl_t * xfer = &xfer_status[ep_ix];; if ((xfer->total_len != xfer->queued_len)) { // TX not complete @@ -466,7 +475,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) if (epnum == 0) { - xfer_status[EP_MAX].max_packet_size = epMaxPktSize; // Enable the control endpoint - Endpoint 0 USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; // Configure the Endpoint 0 configuration register @@ -591,8 +599,6 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t uint8_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t * xfer = &xfer_status[epnum]; - if(ep_addr == 0x80) - xfer = &xfer_status[EP_MAX]; xfer->buffer = buffer; xfer->total_len = total_bytes; -- cgit v1.3.1 From 9c26c0c01e244310dc0e90573f39be7dc7250ead Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Wed, 21 Jul 2021 09:42:26 +0200 Subject: Remove redundant TX irq. --- src/portable/microchip/samx7x/dcd_samx7x.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index de1fd2566..35d970b99 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -530,13 +530,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) { USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); - if (dir) - { - USBHS->USBHS_DEVEPTICR[epnum] = USBHS_DEVEPTICR_TXINIC; - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_TXINES; - } else - { - } return true; } else { -- cgit v1.3.1 From 5492d9148cbd09d19137b992f9ee51def9bd076f Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Wed, 21 Jul 2021 10:29:47 +0200 Subject: Re-enable SETUP irq on EP0 stall. --- src/portable/microchip/samx7x/dcd_samx7x.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 35d970b99..851978398 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -728,6 +728,11 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_CTRL_STALLRQS; + // Re-enable SETUP interrupt + if (epnum == 0) + { + USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; + } } // clear stall, data toggle is also reset to DATA0 -- cgit v1.3.1 From 8c6cd5396c1276aed12fd3a74825debe136d3ded Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Wed, 21 Jul 2021 10:50:07 +0200 Subject: Fix non-DMA IN irq. --- src/portable/microchip/samx7x/dcd_samx7x.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 851978398..e35cf80a6 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -326,6 +326,8 @@ static void dcd_ep_handler(uint8_t ep_ix) { // TX complete dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); + // Disable the interrupt + USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; } } } @@ -576,12 +578,12 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) { // Control endpoint: clear the interrupt flag to send the data USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_TXINES; } else { // Other endpoint types: clear the FIFO control flag to send the data USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; } + USBHS->USBHS_DEVEPTIER[ep_ix] = USBHS_DEVEPTIER_TXINES; } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -- cgit v1.3.1 From a226dbaa4d1df9e5258e7f4dfacdc76906b08084 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 Jul 2021 13:21:58 +0700 Subject: add dcd_attr for DCD_ATTR_ENDPOINT_MAX could be useful with more dcd specific attribute --- src/device/dcd.h | 2 + src/device/dcd_attr.h | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/device/usbd.c | 19 +++++-- src/device/usbd.h | 3 -- src/tusb_option.h | 34 +++++------- 5 files changed, 175 insertions(+), 29 deletions(-) create mode 100644 src/device/dcd_attr.h (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index 63e97df96..11f8ca5d3 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -31,6 +31,8 @@ #include "osal/osal.h" #include "common/tusb_fifo.h" +#include "dcd_attr.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h new file mode 100644 index 000000000..5deba27b5 --- /dev/null +++ b/src/device/dcd_attr.h @@ -0,0 +1,146 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef TUSB_DCD_ATTR_H_ +#define TUSB_DCD_ATTR_H_ + +#include "tusb_option.h" + +// Attribute includes +// - ENDPOINT_MAX: max (logical) number of endpoint +// - ENDPOINT_EXCLUSIVE_NUMBER: endpoint number with different direction IN and OUT aren't allowed, +// e.g EP1 OUT & EP1 IN cannot exist together + +//------------- NXP -------------// +#if TU_CHECK_MCU(LPC11UXX) || TU_CHECK_MCU(LPC13XX) || TU_CHECK_MCU(LPC15XX) + #define DCD_ATTR_ENDPOINT_MAX 5 + +#elif TU_CHECK_MCU(LPC175X_6X) || TU_CHECK_MCU(LPC177X_8X) || TU_CHECK_MCU(LPC40XX) + #define DCD_ATTR_ENDPOINT_MAX 16 + +#elif TU_CHECK_MCU(LPC18XX) || TU_CHECK_MCU(LPC43XX) + // TODO USB0 has 6, USB1 has 4 + #define DCD_ATTR_ENDPOINT_MAX 6 + +#elif TU_CHECK_MCU(LPC51UXX) + #define DCD_ATTR_ENDPOINT_MAX 5 + +#elif TU_CHECK_MCU(LPC54XXX) || TU_CHECK_MCU(LPC55XX) + // TODO USB0 has 5, USB1 has 6 + #define DCD_ATTR_ENDPOINT_MAX 6 + +#elif TU_CHECK_MCU(MIMXRT10XX) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(MKL25ZXX) + #define DCD_ATTR_ENDPOINT_MAX 16 + +//------------- Nordic -------------// +#elif TU_CHECK_MCU(NRF5X) + // 8 CBI + 1 ISO + #define DCD_ATTR_ENDPOINT_MAX 9 + +//------------- Microchip -------------// +#elif TU_CHECK_MCU(SAMD21) || TU_CHECK_MCU(SAMD51) || TU_CHECK_MCU(SAME5X) || \ + TU_CHECK_MCU(SAMD11) || TU_CHECK_MCU(SAML21) || TU_CHECK_MCU(SAML22) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(SAMG) + #define DCD_ATTR_ENDPOINT_MAX 6 + #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER + +//------------- ST -------------// +#elif TU_CHECK_MCU(STM32F0) || TU_CHECK_MCU(STM32F1) || TU_CHECK_MCU(STM32F3) || \ + TU_CHECK_MCU(STM32L0) || TU_CHECK_MCU(STM32L1) || TU_CHECK_MCU(STM32L4) + // F1: F102, F103 + // L4: L4x2, L4x3 + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(STM32F2) || TU_CHECK_MCU(STM32F4) || TU_CHECK_MCU(STM32F3) + // F1: F105, F107 only has 4 + // L4: L4x5, L4x6 has 6 + // For most mcu, FS has 4, HS has 6 + #define DCD_ATTR_ENDPOINT_MAX 6 + +#elif TU_CHECK_MCU(STM32F7) + // FS has 6, HS has 9 + #define DCD_ATTR_ENDPOINT_MAX 9 + +#elif TU_CHECK_MCU(STM32H7) + #define DCD_ATTR_ENDPOINT_MAX 9 + +//------------- Sony -------------// +#elif TU_CHECK_MCU(CXD56) + #define DCD_ATTR_ENDPOINT_MAX 7 + #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER + +//------------- TI -------------// +#elif TU_CHECK_MCU(MSP430x5xx) + #define DCD_ATTR_ENDPOINT_MAX 8 + +//------------- ValentyUSB -------------// +#elif TU_CHECK_MCU(VALENTYUSB_EPTRI) + #define DCD_ATTR_ENDPOINT_MAX 16 + +//------------- Nuvoton -------------// +#elif TU_CHECK_MCU(NUC121) || TU_CHECK_MCU(NUC126) + #define DCD_ATTR_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(NUC120) + #define DCD_ATTR_ENDPOINT_MAX 6 + +#elif TU_CHECK_MCU(NUC505) + #define DCD_ATTR_ENDPOINT_MAX 12 + +//------------- Espressif -------------// +#elif TU_CHECK_MCU(ESP32S2) || TU_CHECK_MCU(ESP32S3) + #define DCD_ATTR_ENDPOINT_MAX 6 + +//------------- Dialog -------------// +#elif TU_CHECK_MCU(DA1469X) + #define DCD_ATTR_ENDPOINT_MAX 4 + +//------------- Raspberry Pi -------------// +#elif TU_CHECK_MCU(RP2040) + #define DCD_ATTR_ENDPOINT_MAX 16 + +//------------- Silabs -------------// +#elif TU_CHECK_MCU(EFM32GG) + #define DCD_ATTR_ENDPOINT_MAX 7 + +//------------- Renesas -------------// +#elif TU_CHECK_MCU(RX63X) || TU_CHECK_MCU(RX65X) + #define DCD_ATTR_ENDPOINT_MAX 10 + +//#elif TU_CHECK_MCU(MM32F327X) +// #define DCD_ATTR_ENDPOINT_MAX not knwon yet + +#else + #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" + #define DCD_ATTR_ENDPOINT_MAX 8 +#endif + +#endif diff --git a/src/device/usbd.c b/src/device/usbd.c index af4fd58c4..7de3c4377 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -33,12 +33,20 @@ #include "device/usbd_pvt.h" #include "device/dcd.h" +//--------------------------------------------------------------------+ +// USBD Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUD_ENDPOINT0_SIZE + #define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + #ifndef CFG_TUD_TASK_QUEUE_SZ -#define CFG_TUD_TASK_QUEUE_SZ 16 + #define CFG_TUD_TASK_QUEUE_SZ 16 #endif -#ifndef CFG_TUD_EP_MAX -#define CFG_TUD_EP_MAX 9 +#ifndef CFG_TUD_ENDPPOINT_MAX + #define CFG_TUD_ENDPPOINT_MAX DCD_ATTR_ENDPOINT_MAX #endif //--------------------------------------------------------------------+ @@ -65,7 +73,7 @@ typedef struct uint8_t speed; uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[CFG_TUD_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ) struct TU_ATTR_PACKED { @@ -74,7 +82,7 @@ typedef struct volatile bool claimed : 1; // TODO merge ep2drv here, 4-bit should be sufficient - }ep_status[CFG_TUD_EP_MAX][2]; + }ep_status[CFG_TUD_ENDPPOINT_MAX][2]; }usbd_device_t; @@ -1151,6 +1159,7 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); + TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < DCD_ATTR_ENDPOINT_MAX); switch (desc_ep->bmAttributes.xfer) { diff --git a/src/device/usbd.h b/src/device/usbd.h index 2de6a5cfd..e6a4d550b 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -24,9 +24,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_usbd - * @{ */ - #ifndef _TUSB_USBD_H_ #define _TUSB_USBD_H_ diff --git a/src/tusb_option.h b/src/tusb_option.h index 13d11fdfe..e24e5947c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -32,9 +32,11 @@ #define TUSB_VERSION_REVISION 1 #define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION) -/** \defgroup group_mcu Supported MCU - * \ref CFG_TUSB_MCU must be defined to one of these - * @{ */ +//--------------------------------------------------------------------+ +// Supported MCUs +// CFG_TUSB_MCU must be defined to one of following value +//--------------------------------------------------------------------+ +#define TU_CHECK_MCU(_m) (CFG_TUSB_MCU == OPT_MCU_##_m) #define OPT_MCU_NONE 0 @@ -119,18 +121,16 @@ // Mind Motion #define OPT_MCU_MM32F327X 1500 ///< Mind Motion MM32F327 -/** @} */ +//--------------------------------------------------------------------+ +// Supported OS +//--------------------------------------------------------------------+ -/** \defgroup group_supported_os Supported RTOS - * \ref CFG_TUSB_OS must be defined to one of these - * @{ */ #define OPT_OS_NONE 1 ///< No RTOS #define OPT_OS_FREERTOS 2 ///< FreeRTOS #define OPT_OS_MYNEWT 3 ///< Mynewt OS #define OPT_OS_CUSTOM 4 ///< Custom OS is implemented by application #define OPT_OS_PICO 5 ///< Raspberry Pi Pico SDK #define OPT_OS_RTTHREAD 6 ///< RT-Thread -/** @} */ // Allow to use command line to change the config name/location #ifdef CFG_TUSB_CONFIG_FILE @@ -139,10 +139,6 @@ #include "tusb_config.h" #endif -/** \addtogroup group_configuration - * @{ */ - - //-------------------------------------------------------------------- // RootHub Mode Configuration // CFG_TUSB_RHPORTx_MODE contains operation mode and speed for that port @@ -214,10 +210,6 @@ // DEVICE OPTIONS //-------------------------------------------------------------------- -#ifndef CFG_TUD_ENDPOINT0_SIZE - #define CFG_TUD_ENDPOINT0_SIZE 64 -#endif - #ifndef CFG_TUD_CDC #define CFG_TUD_CDC 0 #endif @@ -277,7 +269,7 @@ //------------- HUB CLASS -------------// #if CFG_TUH_HUB && (CFG_TUSB_HOST_DEVICE_MAX == 1) - #error there is no benefit enable hub with max device is 1. Please disable hub or increase CFG_TUSB_HOST_DEVICE_MAX + #error There is no benefit enable hub with max device is 1. Please disable hub or increase CFG_TUSB_HOST_DEVICE_MAX #endif #ifndef CFG_TUH_ENUMERATION_BUFSIZE @@ -288,12 +280,11 @@ #endif // TUSB_OPT_HOST_ENABLED //--------------------------------------------------------------------+ -// Port Options -// TUP for TinyUSB Port (can be renamed) +// Port Specific +// TUP stand for TinyUSB Port (can be renamed) //--------------------------------------------------------------------+ -// TUP_ARCH_STRICT_ALIGN if arch cannot access unaligned memory - +//------------- Unaligned Memory -------------// // ARMv7+ (M3-M7, M23-M33) can access unaligned memory #if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) @@ -312,6 +303,7 @@ #define TUP_MCU_STRICT_ALIGN 0 #endif + //------------------------------------------------------------------ // Configuration Validation //------------------------------------------------------------------ -- cgit v1.3.1 From 37cac414f83fb939d8b9e4c41d5fa49a6f0e309e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 Jul 2021 17:00:02 +0700 Subject: fix ci --- src/device/dcd.h | 13 ++++++++++++- src/device/dcd_attr.h | 12 +++++++++++- src/device/usbd.c | 8 -------- src/device/usbd.h | 4 ++-- src/tusb_option.h | 4 ++++ 5 files changed, 29 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index 11f8ca5d3..8bfad9b72 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -30,13 +30,24 @@ #include "common/tusb_common.h" #include "osal/osal.h" #include "common/tusb_fifo.h" - #include "dcd_attr.h" #ifdef __cplusplus extern "C" { #endif +//--------------------------------------------------------------------+ +// Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUD_ENDPPOINT_MAX + #define CFG_TUD_ENDPPOINT_MAX DCD_ATTR_ENDPOINT_MAX +#endif + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ + typedef enum { DCD_EVENT_INVALID = 0, diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 5deba27b5..2fd235a96 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -33,6 +33,7 @@ // - ENDPOINT_MAX: max (logical) number of endpoint // - ENDPOINT_EXCLUSIVE_NUMBER: endpoint number with different direction IN and OUT aren't allowed, // e.g EP1 OUT & EP1 IN cannot exist together +// - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on. //------------- NXP -------------// #if TU_CHECK_MCU(LPC11UXX) || TU_CHECK_MCU(LPC13XX) || TU_CHECK_MCU(LPC15XX) @@ -48,7 +49,11 @@ #elif TU_CHECK_MCU(LPC51UXX) #define DCD_ATTR_ENDPOINT_MAX 5 -#elif TU_CHECK_MCU(LPC54XXX) || TU_CHECK_MCU(LPC55XX) +#elif TU_CHECK_MCU(LPC54XXX) + // TODO USB0 has 5, USB1 has 6 + #define DCD_ATTR_ENDPOINT_MAX 6 + +#elif TU_CHECK_MCU(LPC55XX) // TODO USB0 has 5, USB1 has 6 #define DCD_ATTR_ENDPOINT_MAX 6 @@ -143,4 +148,9 @@ #define DCD_ATTR_ENDPOINT_MAX 8 #endif +// Default to fullspeed if not defined +//#ifndef PORT_HIGHSPEED +// #define DCD_ATTR_PORT_HIGHSPEED 0x00 +//#endif + #endif diff --git a/src/device/usbd.c b/src/device/usbd.c index 7de3c4377..b724c73e8 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -37,18 +37,10 @@ // USBD Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUD_ENDPOINT0_SIZE - #define CFG_TUD_ENDPOINT0_SIZE 64 -#endif - #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif -#ifndef CFG_TUD_ENDPPOINT_MAX - #define CFG_TUD_ENDPPOINT_MAX DCD_ATTR_ENDPOINT_MAX -#endif - //--------------------------------------------------------------------+ // Device Data //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index e6a4d550b..9500ad70c 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -27,12 +27,12 @@ #ifndef _TUSB_USBD_H_ #define _TUSB_USBD_H_ +#include "common/tusb_common.h" + #ifdef __cplusplus extern "C" { #endif -#include "common/tusb_common.h" - //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ diff --git a/src/tusb_option.h b/src/tusb_option.h index e24e5947c..dfac46374 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -210,6 +210,10 @@ // DEVICE OPTIONS //-------------------------------------------------------------------- +#ifndef CFG_TUD_ENDPOINT0_SIZE + #define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + #ifndef CFG_TUD_CDC #define CFG_TUD_CDC 0 #endif -- cgit v1.3.1 From a9f3532252c09d2bcc0fc23994be3d0753a974ef Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 Jul 2021 18:08:19 +0700 Subject: more ci --- src/device/dcd_attr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 2fd235a96..4bba03c87 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -133,7 +133,7 @@ #define DCD_ATTR_ENDPOINT_MAX 16 //------------- Silabs -------------// -#elif TU_CHECK_MCU(EFM32GG) +#elif TU_CHECK_MCU(EFM32GG) || TU_CHECK_MCU(OPT_MCU_EFM32GG11) || TU_CHECK_MCU(OPT_MCU_EFM32GG12) #define DCD_ATTR_ENDPOINT_MAX 7 //------------- Renesas -------------// -- cgit v1.3.1 From 8ee1141a70dd40063c667ea2b117590a174d9ea6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 Jul 2021 18:25:53 +0700 Subject: correct check --- src/device/dcd_attr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 4bba03c87..544b0a75b 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -133,7 +133,7 @@ #define DCD_ATTR_ENDPOINT_MAX 16 //------------- Silabs -------------// -#elif TU_CHECK_MCU(EFM32GG) || TU_CHECK_MCU(OPT_MCU_EFM32GG11) || TU_CHECK_MCU(OPT_MCU_EFM32GG12) +#elif TU_CHECK_MCU(EFM32GG) || TU_CHECK_MCU(EFM32GG11) || TU_CHECK_MCU(EFM32GG12) #define DCD_ATTR_ENDPOINT_MAX 7 //------------- Renesas -------------// -- cgit v1.3.1 From aff7b100ca87482e9e1d29f7e854d77cadbd6b98 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Jul 2021 00:28:37 +0700 Subject: update dcd attr for samx7x --- src/device/dcd_attr.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 544b0a75b..306335642 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -77,6 +77,10 @@ #define DCD_ATTR_ENDPOINT_MAX 6 #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER +#elif TU_CHECK_MCU(SAMX7X) + #define DCD_ATTR_ENDPOINT_MAX 10 + #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER + //------------- ST -------------// #elif TU_CHECK_MCU(STM32F0) || TU_CHECK_MCU(STM32F1) || TU_CHECK_MCU(STM32F3) || \ TU_CHECK_MCU(STM32L0) || TU_CHECK_MCU(STM32L1) || TU_CHECK_MCU(STM32L4) -- cgit v1.3.1 From 9542fcdbcda23a08fb4d7901bbb01333b6465bfc Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Jul 2021 01:00:06 +0700 Subject: rename CFG_TUD_DFU_TRANSFER_BUFSIZE to CFG_TUD_DFU_XFER_BUFSIZE --- examples/device/dfu/.skip.MCU_SAMD11 | 0 examples/device/dfu/src/tusb_config.h | 2 +- examples/device/dfu/src/usb_descriptors.c | 2 +- src/class/dfu/dfu_device.c | 243 +----------------------------- src/class/dfu/dfu_device.h | 4 +- 5 files changed, 9 insertions(+), 242 deletions(-) delete mode 100644 examples/device/dfu/.skip.MCU_SAMD11 (limited to 'src') diff --git a/examples/device/dfu/.skip.MCU_SAMD11 b/examples/device/dfu/.skip.MCU_SAMD11 deleted file mode 100644 index e69de29bb..000000000 diff --git a/examples/device/dfu/src/tusb_config.h b/examples/device/dfu/src/tusb_config.h index 2e3b89f49..66e357021 100644 --- a/examples/device/dfu/src/tusb_config.h +++ b/examples/device/dfu/src/tusb_config.h @@ -80,7 +80,7 @@ #define CFG_TUD_DFU 1 // DFU buffer size, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR -#define CFG_TUD_DFU_TRANSFER_BUFSIZE 512 +#define CFG_TUD_DFU_XFER_BUFSIZE 512 #ifdef __cplusplus } diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index a15bb6136..1cfe29c53 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -100,7 +100,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size - TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, ALT_COUNT, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_TRANSFER_BUFSIZE), + TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, ALT_COUNT, 4, FUNC_ATTRS, 1000, CFG_TUD_DFU_XFER_BUFSIZE), }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 222795bec..ad87092e0 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -52,7 +52,7 @@ typedef struct uint16_t block; uint16_t length; - CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_XFER_BUFSIZE]; } dfu_state_ctx_t; // Only a single dfu state is allowed @@ -189,9 +189,9 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, _dfu_ctx.attrs = func_desc->bAttributes; - // CFG_TUD_DFU_TRANSFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR + // CFG_TUD_DFU_XFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16(&func_desc->wTransferSize) ); - TU_ASSERT(transfer_size <= CFG_TUD_DFU_TRANSFER_BUFSIZE, drv_len); + TU_ASSERT(transfer_size <= CFG_TUD_DFU_XFER_BUFSIZE, drv_len); return drv_len; } @@ -281,7 +281,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque { TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD); TU_VERIFY(tud_dfu_upload_cb); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE); + TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_ctx.transfer_buf, request->wLength); @@ -294,7 +294,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque { TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD); TU_VERIFY(_dfu_ctx.state == DFU_IDLE || _dfu_ctx.state == DFU_DNLOAD_IDLE); - TU_VERIFY(request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE); + TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); // set to true for both download and manifest _dfu_ctx.flashing_in_progress = true; @@ -455,237 +455,4 @@ static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * reque return tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t)); } - -#if 0 - -static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request); -static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request); -static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request); - -static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request) -{ - // TODO: add "zero" copy mode so the buffer we read into can be provided by the user - // if they wish, there still will be the internal control buffer copy to this buffer - // but this mode would provide zero copy from the class driver to the application - - TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE, ); - // setup for data phase - tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength); -} - -static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; - TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFSIZE, ); - tud_dfu_download_cb(_dfu_ctx.alt,_dfu_ctx.block, (uint8_t *)_dfu_ctx.transfer_buf, _dfu_ctx.length); - _dfu_ctx.flashing_in_progress = false; -} - -static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request) -{ - TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest)); - TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state)); - - switch (_dfu_ctx.state) - { - case DFU_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DNLOAD: - { - if( ((_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD) != 0) - && (request->wLength > 0) ) - { - _dfu_ctx.state = DFU_DNLOAD_SYNC; - _dfu_ctx.flashing_in_progress = true; - dfu_req_dnload_setup(rhport, request); - } else { - _dfu_ctx.state = DFU_ERROR; - } - } - break; - - case DFU_REQUEST_GETSTATUS: - reply_getstatus(rhport, request); - break; - - default: - _dfu_ctx.state = DFU_ERROR; - return false; // stall on all other requests - break; - } - } - break; - - case DFU_DNLOAD_SYNC: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - if ( _dfu_ctx.flashing_in_progress ) - { - _dfu_ctx.state = DFU_DNBUSY; - reply_getstatus(rhport, request); - dfu_req_dnload_reply(rhport, request); - } else { - _dfu_ctx.state = DFU_DNLOAD_IDLE; - reply_getstatus(rhport, request); - } - } - break; - - default: - _dfu_ctx.state = DFU_ERROR; - return false; // stall on all other requests - break; - } - } - break; - - case DFU_DNBUSY: - { - switch (request->bRequest) - { - default: - _dfu_ctx.state = DFU_ERROR; - return false; // stall on all other requests - break; - } - } - break; - - case DFU_DNLOAD_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_DNLOAD: - { - if( ((_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD) != 0) - && (request->wLength > 0) ) - { - _dfu_ctx.state = DFU_DNLOAD_SYNC; - _dfu_ctx.flashing_in_progress = true; - dfu_req_dnload_setup(rhport, request); - } else { - if ( tud_dfu_download_complete_cb(_dfu_ctx.alt) ) - { - _dfu_ctx.state = DFU_MANIFEST_SYNC; - tud_control_status(rhport, request); - } else { - _dfu_ctx.state = DFU_ERROR; - return false; // stall - } - } - } - break; - - case DFU_REQUEST_GETSTATUS: - reply_getstatus(rhport, request); - break; - - default: - _dfu_ctx.state = DFU_ERROR; - return false; // stall on all other requests - break; - } - } - break; - - case DFU_MANIFEST_SYNC: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - { - if ((_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT) == 0) - { - _dfu_ctx.state = DFU_MANIFEST; - reply_getstatus(rhport, request); - } else - { - if ( tud_dfu_manifest_cb(_dfu_ctx.alt) ) - { - _dfu_ctx.state = DFU_IDLE; - } - reply_getstatus(rhport, request); - } - } - break; - - default: - _dfu_ctx.state = DFU_ERROR; - return false; // stall on all other requests - break; - } - } - break; - - case DFU_MANIFEST: - { - switch (request->bRequest) - { - // stall on all other requests - default: - return false; - break; - } - } - break; - - case DFU_MANIFEST_WAIT_RESET: - { - // technically we should never even get here, but we will handle it just in case - TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest); - switch (request->bRequest) - { - default: - return false; // stall on all other requests - break; - } - } - break; - - case DFU_UPLOAD_IDLE: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - reply_getstatus(rhport, request); - break; - - default: - return false; // stall on all other requests - break; - } - } - break; - - case DFU_ERROR: - { - switch (request->bRequest) - { - case DFU_REQUEST_GETSTATUS: - reply_getstatus(rhport, request); - break; - - default: - return false; // stall on all other requests - break; - } - } - break; - - default: - _dfu_ctx.state = DFU_ERROR; - TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n"); - return false; // Unexpected state, stall and change to error - } - - return true; -} - -#endif - #endif diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index 2d398aada..fecf8596f 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -37,8 +37,8 @@ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -#if !defined(CFG_TUD_DFU_TRANSFER_BUFSIZE) - #error "CFG_TUD_DFU_TRANSFER_BUFSIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" +#if !defined(CFG_TUD_DFU_XFER_BUFSIZE) + #error "CFG_TUD_DFU_XFER_BUFSIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR" #endif //--------------------------------------------------------------------+ -- cgit v1.3.1 From b35ad6edcb8b723c481246532349d21b35c46ac1 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Jul 2021 17:04:55 +0700 Subject: clean up max packet size endian --- src/device/dcd_attr.h | 4 ++-- src/device/usbd.c | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 306335642..18f369332 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -141,11 +141,11 @@ #define DCD_ATTR_ENDPOINT_MAX 7 //------------- Renesas -------------// -#elif TU_CHECK_MCU(RX63X) || TU_CHECK_MCU(RX65X) +#elif TU_CHECK_MCU(RX63X) || TU_CHECK_MCU(RX65X) || TU_CHECK_MCU(RX72N) #define DCD_ATTR_ENDPOINT_MAX 10 //#elif TU_CHECK_MCU(MM32F327X) -// #define DCD_ATTR_ENDPOINT_MAX not knwon yet +// #define DCD_ATTR_ENDPOINT_MAX not known yet #else #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" diff --git a/src/device/usbd.c b/src/device/usbd.c index e4f2e1cf9..5a7d0ab0f 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1150,15 +1150,17 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { - TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, tu_le16toh(desc_ep->wMaxPacketSize.size)); - TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < DCD_ATTR_ENDPOINT_MAX); + uint16_t const max_packet_size = tu_le16toh(desc_ep->wMaxPacketSize.size); + + TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); + TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX); switch (desc_ep->bmAttributes.xfer) { case TUSB_XFER_ISOCHRONOUS: { - uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023); - TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) <= max_epsize); + uint16_t const spec_size = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023); + TU_ASSERT(max_packet_size <= spec_size); } break; @@ -1166,18 +1168,18 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) if (_usbd_dev.speed == TUSB_SPEED_HIGH) { // Bulk highspeed must be EXACTLY 512 - TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) == 512); + TU_ASSERT(max_packet_size == 512); }else { // TODO Bulk fullspeed can only be 8, 16, 32, 64 - TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) <= 64); + TU_ASSERT(max_packet_size <= 64); } break; case TUSB_XFER_INTERRUPT: { - uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 64); - TU_ASSERT(tu_le16toh(desc_ep->wMaxPacketSize.size) <= max_epsize); + uint16_t const spec_size = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 64); + TU_ASSERT(max_packet_size <= spec_size); } break; -- cgit v1.3.1 From 4e50ceba48c15206543fe662f098a98152ef4235 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Jul 2021 17:07:39 +0700 Subject: rename packed begin/end --- src/class/cdc/cdc.h | 20 ++++++++++---------- src/common/tusb_compiler.h | 8 ++++---- src/common/tusb_types.h | 4 ++-- src/portable/renesas/usba/dcd_usba.c | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index f59690835..7a06711be 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -215,7 +215,7 @@ typedef enum // Class Specific Functional Descriptor (Communication Interface) //--------------------------------------------------------------------+ -TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) /// Header Functional Descriptor (Communication Interface) typedef struct TU_ATTR_PACKED @@ -236,10 +236,10 @@ typedef struct TU_ATTR_PACKED uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface }cdc_desc_func_union_t; -TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) #define cdc_desc_func_union_n_t(no_slave)\ - TU_PACK_STRUCT_BEGIN \ + TU_ATTR_PACKED_BEGIN \ struct TU_ATTR_PACKED { \ uint8_t bLength ;\ uint8_t bDescriptorType ;\ @@ -247,10 +247,10 @@ TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX too uint8_t bControlInterface ;\ uint8_t bSubordinateInterface[no_slave] ;\ } \ -TU_PACK_STRUCT_END +TU_ATTR_PACKED_END -TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) /// Country Selection Functional Descriptor (Communication Interface) typedef struct TU_ATTR_PACKED @@ -262,10 +262,10 @@ typedef struct TU_ATTR_PACKED uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. }cdc_desc_func_country_selection_t; -TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) #define cdc_desc_func_country_selection_n_t(no_country) \ - TU_PACK_STRUCT_BEGIN \ + TU_ATTR_PACKED_BEGIN \ struct TU_ATTR_PACKED { \ uint8_t bLength ;\ uint8_t bDescriptorType ;\ @@ -273,13 +273,13 @@ TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX too uint8_t iCountryCodeRelDate ;\ uint16_t wCountryCode[no_country] ;\ } \ -TU_PACK_STRUCT_END +TU_ATTR_PACKED_END //--------------------------------------------------------------------+ // PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS //--------------------------------------------------------------------+ -TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) /// \brief Call Management Functional Descriptor /// \details This functional descriptor describes the processing of calls for the Communications Class interface. @@ -419,7 +419,7 @@ typedef struct TU_ATTR_PACKED } cdc_line_control_state_t; TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 6fdd08032..1f3128e0e 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -79,8 +79,8 @@ #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used - #define TU_PACK_STRUCT_BEGIN - #define TU_PACK_STRUCT_END + #define TU_ATTR_PACKED_BEGIN + #define TU_ATTR_PACKED_END #define TU_BIT_FIELD_ORDER_BEGIN #define TU_BIT_FIELD_ORDER_END @@ -150,8 +150,8 @@ #define TU_ATTR_UNUSED #define TU_ATTR_USED - #define TU_PACK_STRUCT_BEGIN _Pragma("pack") - #define TU_PACK_STRUCT_END _Pragma("packoption") + #define TU_ATTR_PACKED_BEGIN _Pragma("pack") + #define TU_ATTR_PACKED_END _Pragma("packoption") #define TU_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right") #define TU_BIT_FIELD_ORDER_END _Pragma("bit_order") diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index f34eb3075..34395365e 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -262,7 +262,7 @@ enum // USB Descriptors //--------------------------------------------------------------------+ -TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) /// USB Device Descriptor typedef struct TU_ATTR_PACKED @@ -479,7 +479,7 @@ typedef struct TU_ATTR_PACKED{ } tusb_control_request_t; TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 67b92dc89..0c206fdd0 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -120,7 +120,7 @@ typedef union { } hw_fifo_t; TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED @@ -135,7 +135,7 @@ typedef struct TU_ATTR_PACKED } pipe_state_t; TU_BIT_FIELD_ORDER_END -TU_PACK_STRUCT_END // End of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) typedef struct { -- cgit v1.3.1 From c4da1abb1eaa7aff432535878ada519d02382419 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Jul 2021 17:24:59 +0700 Subject: rename bit filed order clean up packed/bit order begin end --- src/class/cdc/cdc.h | 41 +++++++----------------------------- src/common/tusb_compiler.h | 8 +++---- src/common/tusb_types.h | 24 +++++++++------------ src/portable/renesas/usba/dcd_usba.c | 12 +++++------ 4 files changed, 28 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 7a06711be..6042cefe3 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -215,7 +215,9 @@ typedef enum // Class Specific Functional Descriptor (Communication Interface) //--------------------------------------------------------------------+ -TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) +// Start of all packed definitions for compiler without per-type packed +TU_ATTR_PACKED_BEGIN +TU_ATTR_BIT_FIELD_ORDER_BEGIN /// Header Functional Descriptor (Communication Interface) typedef struct TU_ATTR_PACKED @@ -236,10 +238,7 @@ typedef struct TU_ATTR_PACKED uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface }cdc_desc_func_union_t; -TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) - #define cdc_desc_func_union_n_t(no_slave)\ - TU_ATTR_PACKED_BEGIN \ struct TU_ATTR_PACKED { \ uint8_t bLength ;\ uint8_t bDescriptorType ;\ @@ -247,10 +246,6 @@ TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX too uint8_t bControlInterface ;\ uint8_t bSubordinateInterface[no_slave] ;\ } \ -TU_ATTR_PACKED_END - - -TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) /// Country Selection Functional Descriptor (Communication Interface) typedef struct TU_ATTR_PACKED @@ -262,10 +257,7 @@ typedef struct TU_ATTR_PACKED uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. }cdc_desc_func_country_selection_t; -TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) - #define cdc_desc_func_country_selection_n_t(no_country) \ - TU_ATTR_PACKED_BEGIN \ struct TU_ATTR_PACKED { \ uint8_t bLength ;\ uint8_t bDescriptorType ;\ @@ -273,17 +265,13 @@ TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX too uint8_t iCountryCodeRelDate ;\ uint16_t wCountryCode[no_country] ;\ } \ -TU_ATTR_PACKED_END //--------------------------------------------------------------------+ // PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS //--------------------------------------------------------------------+ -TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) - /// \brief Call Management Functional Descriptor /// \details This functional descriptor describes the processing of calls for the Communications Class interface. -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -298,10 +286,7 @@ typedef struct TU_ATTR_PACKED uint8_t bDataInterface; }cdc_desc_func_call_management_t; -TU_BIT_FIELD_ORDER_END - -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature. @@ -310,12 +295,11 @@ typedef struct TU_ATTR_PACKED uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection. uint8_t TU_RESERVED : 4; }cdc_acm_capability_t; -TU_BIT_FIELD_ORDER_END TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); -/// \brief Abstract Control Management Functional Descriptor -/// \details This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL +/// Abstract Control Management Functional Descriptor +/// This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -326,7 +310,6 @@ typedef struct TU_ATTR_PACKED /// \brief Direct Line Management Functional Descriptor /// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -339,7 +322,6 @@ typedef struct TU_ATTR_PACKED uint8_t TU_RESERVED : 5; } bmCapabilities; }cdc_desc_func_direct_line_management_t; -TU_BIT_FIELD_ORDER_END /// \brief Telephone Ringer Functional Descriptor /// \details The Telephone Ringer functional descriptor describes the ringer capabilities supported by the Communications Class interface, @@ -356,7 +338,6 @@ typedef struct TU_ATTR_PACKED /// \brief Telephone Operational Modes Functional Descriptor /// \details The Telephone Operational Modes functional descriptor describes the operational modes supported by /// the Communications Class interface, with the SubClass code of \ref CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -369,12 +350,10 @@ typedef struct TU_ATTR_PACKED uint8_t TU_RESERVED : 5; } bmCapabilities; }cdc_desc_func_telephone_operational_modes_t; -TU_BIT_FIELD_ORDER_END /// \brief Telephone Call and Line State Reporting Capabilities Descriptor /// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a /// telephone device to report optional call and line states. -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. @@ -390,8 +369,8 @@ typedef struct TU_ATTR_PACKED uint32_t TU_RESERVED : 26; } bmCapabilities; }cdc_desc_func_telephone_call_state_reporting_capabilities_t; -TU_BIT_FIELD_ORDER_END +// TODO remove static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) { return p_desc[2]; @@ -410,21 +389,17 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint16_t dte_is_present : 1; ///< Indicates to DCE if DTE is presentor not. This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR. uint16_t half_duplex_carrier_control : 1; uint16_t : 14; } cdc_line_control_state_t; -TU_BIT_FIELD_ORDER_END - -TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) - TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); -/** @} */ +TU_ATTR_PACKED_END // End of all packed definitions +TU_ATTR_BIT_FIELD_ORDER_END #ifdef __cplusplus } diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 1f3128e0e..820782d65 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -82,8 +82,8 @@ #define TU_ATTR_PACKED_BEGIN #define TU_ATTR_PACKED_END - #define TU_BIT_FIELD_ORDER_BEGIN - #define TU_BIT_FIELD_ORDER_END + #define TU_ATTR_BIT_FIELD_ORDER_BEGIN + #define TU_ATTR_BIT_FIELD_ORDER_END // Endian conversion use well-known host to network (big endian) naming #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ @@ -153,8 +153,8 @@ #define TU_ATTR_PACKED_BEGIN _Pragma("pack") #define TU_ATTR_PACKED_END _Pragma("packoption") - #define TU_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right") - #define TU_BIT_FIELD_ORDER_END _Pragma("bit_order") + #define TU_ATTR_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right") + #define TU_ATTR_BIT_FIELD_ORDER_END _Pragma("bit_order") // Endian conversion use well-known host to network (big endian) naming #if defined(__LIT) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 34395365e..d23c6b2dd 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -262,7 +262,9 @@ enum // USB Descriptors //--------------------------------------------------------------------+ -TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) +// Start of all packed definitions for compiler without per-type packed +TU_ATTR_PACKED_BEGIN +TU_ATTR_BIT_FIELD_ORDER_BEGIN /// USB Device Descriptor typedef struct TU_ATTR_PACKED @@ -297,6 +299,8 @@ typedef struct TU_ATTR_PACKED uint8_t bNumDeviceCaps ; ///< Number of device capability descriptors in the BOS } tusb_desc_bos_t; +TU_VERIFY_STATIC( sizeof(tusb_desc_bos_t) == 5, "size is not correct"); + /// USB Configuration Descriptor typedef struct TU_ATTR_PACKED { @@ -328,8 +332,9 @@ typedef struct TU_ATTR_PACKED uint8_t iInterface ; ///< Index of string descriptor describing this interface } tusb_desc_interface_t; +TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9, "size is not correct"); + /// USB Endpoint Descriptor -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -357,7 +362,6 @@ typedef struct TU_ATTR_PACKED uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. } tusb_desc_endpoint_t; -TU_BIT_FIELD_ORDER_END /// USB Other Speed Configuration Descriptor typedef struct TU_ATTR_PACKED @@ -433,7 +437,6 @@ typedef struct TU_ATTR_PACKED } tusb_desc_webusb_url_t; // DFU Functional Descriptor -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -455,12 +458,10 @@ typedef struct TU_ATTR_PACKED uint16_t wTransferSize; uint16_t bcdDFUVersion; } tusb_desc_dfu_functional_t; -TU_BIT_FIELD_ORDER_END /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ -TU_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED{ union { struct TU_ATTR_PACKED { @@ -477,17 +478,12 @@ typedef struct TU_ATTR_PACKED{ uint16_t wIndex; uint16_t wLength; } tusb_control_request_t; -TU_BIT_FIELD_ORDER_END - -TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); -// TODO move to somewhere suitable -static inline uint8_t bm_request_type(uint8_t direction, uint8_t type, uint8_t recipient) -{ - return ((uint8_t) (direction << 7)) | ((uint8_t) (type << 5)) | (recipient); -} + +TU_ATTR_PACKED_END // End of all packed definitions +TU_ATTR_BIT_FIELD_ORDER_END //--------------------------------------------------------------------+ // Endpoint helper diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 0c206fdd0..f68f97458 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -95,7 +95,7 @@ #define FIFO_REQ_CLR (1u) #define FIFO_COMPLETE (1u<<1) -TU_BIT_FIELD_ORDER_BEGIN +TU_ATTR_BIT_FIELD_ORDER_BEGIN typedef struct { union { struct { @@ -108,9 +108,9 @@ typedef struct { }; uint16_t TRN; } reg_pipetre_t; -TU_BIT_FIELD_ORDER_END +TU_ATTR_BIT_FIELD_ORDER_END -TU_BIT_FIELD_ORDER_BEGIN +TU_ATTR_BIT_FIELD_ORDER_BEGIN typedef union { struct { volatile uint16_t u8: 8; @@ -118,11 +118,11 @@ typedef union { }; volatile uint16_t u16; } hw_fifo_t; -TU_BIT_FIELD_ORDER_END +TU_ATTR_BIT_FIELD_ORDER_END TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) -TU_BIT_FIELD_ORDER_BEGIN +TU_ATTR_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uintptr_t addr; /* the start address of a transfer data buffer */ @@ -133,7 +133,7 @@ typedef struct TU_ATTR_PACKED uint32_t : 0; }; } pipe_state_t; -TU_BIT_FIELD_ORDER_END +TU_ATTR_BIT_FIELD_ORDER_END TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) -- cgit v1.3.1 From 8cd23489d518e96594850207c91dfeefb6d6fb05 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Jul 2021 17:45:24 +0700 Subject: update endian --- src/device/usbd.c | 10 ++++------ src/device/usbd_control.c | 1 - src/portable/renesas/usba/dcd_usba.c | 13 +++++-------- 3 files changed, 9 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 5a7d0ab0f..a30eab217 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -953,11 +953,10 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb(); - uint16_t total_len; // Use offsetof to avoid pointer to the odd/misaligned address - memcpy(&total_len, (uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength), 2); + uint16_t const total_len = tu_le16toh( tu_unaligned_read16((uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength)) ); - return tud_control_xfer(rhport, p_request, (void*) desc_bos, tu_le16toh(total_len)); + return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); } break; @@ -968,11 +967,10 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index); TU_ASSERT(desc_config); - uint16_t total_len; // Use offsetof to avoid pointer to the odd/misaligned address - memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2); + uint16_t const total_len = tu_le16toh( tu_unaligned_read16((uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)) ); - return tud_control_xfer(rhport, p_request, (void*) desc_config, tu_le16toh(total_len)); + return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); } break; diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 124f711a7..7a8244699 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -58,7 +58,6 @@ static usbd_control_xfer_t _ctrl_xfer; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; - //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index f68f97458..0b78a6e46 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -95,7 +95,10 @@ #define FIFO_REQ_CLR (1u) #define FIFO_COMPLETE (1u<<1) +// Start of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_PACKED_BEGIN TU_ATTR_BIT_FIELD_ORDER_BEGIN + typedef struct { union { struct { @@ -108,9 +111,7 @@ typedef struct { }; uint16_t TRN; } reg_pipetre_t; -TU_ATTR_BIT_FIELD_ORDER_END -TU_ATTR_BIT_FIELD_ORDER_BEGIN typedef union { struct { volatile uint16_t u8: 8; @@ -118,11 +119,7 @@ typedef union { }; volatile uint16_t u16; } hw_fifo_t; -TU_ATTR_BIT_FIELD_ORDER_END -TU_ATTR_PACKED_BEGIN // Start of definition of packed structs (used by the CCRX toolchain) - -TU_ATTR_BIT_FIELD_ORDER_BEGIN typedef struct TU_ATTR_PACKED { uintptr_t addr; /* the start address of a transfer data buffer */ @@ -133,9 +130,9 @@ typedef struct TU_ATTR_PACKED uint32_t : 0; }; } pipe_state_t; -TU_ATTR_BIT_FIELD_ORDER_END TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain) +TU_ATTR_BIT_FIELD_ORDER_END typedef struct { @@ -147,7 +144,7 @@ typedef struct //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION static dcd_data_t _dcd; +static dcd_data_t _dcd; static uint32_t disable_interrupt(void) { -- cgit v1.3.1 From 15112fdbba8cf4e9ad0d99fafd8b40f07f29fb6d Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Jul 2021 22:10:48 +0700 Subject: clean up compiler --- src/class/cdc/cdc.h | 4 ++-- src/common/tusb_compiler.h | 18 +++++++++++++----- src/portable/renesas/usba/dcd_usba.c | 20 ++++---------------- 3 files changed, 19 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 6042cefe3..5df47f70b 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -245,7 +245,7 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ;\ uint8_t bControlInterface ;\ uint8_t bSubordinateInterface[no_slave] ;\ -} \ +} /// Country Selection Functional Descriptor (Communication Interface) typedef struct TU_ATTR_PACKED @@ -264,7 +264,7 @@ typedef struct TU_ATTR_PACKED uint8_t bDescriptorSubType ;\ uint8_t iCountryCodeRelDate ;\ uint16_t wCountryCode[no_country] ;\ -} \ +} //--------------------------------------------------------------------+ // PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 820782d65..d3adbbc2d 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -81,7 +81,6 @@ #define TU_ATTR_PACKED_BEGIN #define TU_ATTR_PACKED_END - #define TU_ATTR_BIT_FIELD_ORDER_BEGIN #define TU_ATTR_BIT_FIELD_ORDER_END @@ -109,6 +108,11 @@ #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) + #define TU_ATTR_PACKED_BEGIN + #define TU_ATTR_PACKED_END + #define TU_ATTR_BIT_FIELD_ORDER_BEGIN + #define TU_ATTR_BIT_FIELD_ORDER_END + // __BYTE_ORDER is defined in the TI ARM compiler, but not MSP430 (which is little endian) #if ((__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__)) || defined(__MSP430__) #define TU_BYTE_ORDER TU_LITTLE_ENDIAN @@ -130,6 +134,11 @@ #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used + #define TU_ATTR_PACKED_BEGIN + #define TU_ATTR_PACKED_END + #define TU_ATTR_BIT_FIELD_ORDER_BEGIN + #define TU_ATTR_BIT_FIELD_ORDER_END + // Endian conversion use well-known host to network (big endian) naming #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define TU_BYTE_ORDER TU_LITTLE_ENDIAN @@ -150,11 +159,10 @@ #define TU_ATTR_UNUSED #define TU_ATTR_USED - #define TU_ATTR_PACKED_BEGIN _Pragma("pack") - #define TU_ATTR_PACKED_END _Pragma("packoption") - + #define TU_ATTR_PACKED_BEGIN _Pragma("pack") + #define TU_ATTR_PACKED_END _Pragma("packoption") #define TU_ATTR_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right") - #define TU_ATTR_BIT_FIELD_ORDER_END _Pragma("bit_order") + #define TU_ATTR_BIT_FIELD_ORDER_END _Pragma("bit_order") // Endian conversion use well-known host to network (big endian) naming #if defined(__LIT) diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 0b78a6e46..c7eb6e15e 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -334,11 +334,7 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, pipe_state_t *pipe = &_dcd.pipe[0]; /* configure fifo direction and access unit settings */ if (ep_addr) { /* IN, 2 bytes */ -#if TU_BYTE_ORDER == TU_BIG_ENDIAN - USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND; -#else - USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16; -#endif + USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0); while (!(USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX)) ; } else { /* OUT, a byte */ USB0.CFIFOSEL.WORD = USB_FIFOSEL_MBW_8; @@ -413,11 +409,7 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, USB0.PIPESEL.WORD = num; const unsigned mps = USB0.PIPEMAXP.WORD; if (dir) { /* IN */ -#if TU_BYTE_ORDER == TU_BIG_ENDIAN - USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND; -#else - USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16; -#endif + USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0); while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ; int r = fifo_write((void*)&USB0.D0FIFO.WORD, pipe, mps); if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; @@ -442,11 +434,7 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) { pipe_state_t *pipe = &_dcd.pipe[num]; if (tu_edpt_dir(pipe->ep)) { /* IN */ -#if TU_BYTE_ORDER == TU_BIG_ENDIAN - select_pipe(num, USB_FIFOSEL_MBW_16 | USB_FIFOSEL_BIGEND); -#else - select_pipe(num, USB_FIFOSEL_MBW_16); -#endif + select_pipe(num, USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0)); const unsigned mps = USB0.PIPEMAXP.WORD; unsigned rem = pipe->remaining; rem -= TU_MIN(rem, mps); @@ -527,7 +515,7 @@ static void process_set_address(uint8_t rhport) #else .bmRequestType = 0, #endif - .bRequest = 5, + .bRequest = TUSB_REQ_SET_ADDRESS, .wValue = addr, .wIndex = 0, .wLength = 0, -- cgit v1.3.1 From 0ba4315ae559f595c0d01ab650ea924d8e9bec69 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Tue, 27 Jul 2021 18:08:52 +0200 Subject: Fix IAR warning --- src/class/dfu/dfu_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index ad87092e0..28abf6e83 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -190,7 +190,7 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, _dfu_ctx.attrs = func_desc->bAttributes; // CFG_TUD_DFU_XFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR - uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16(&func_desc->wTransferSize) ); + uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16((uint8_t*) func_desc + offsetof(tusb_desc_dfu_functional_t, wTransferSize)) ); TU_ASSERT(transfer_size <= CFG_TUD_DFU_XFER_BUFSIZE, drv_len); return drv_len; @@ -365,7 +365,7 @@ void tud_dfu_finish_flashing(uint8_t status) { // failed while flashing, move to dfuError _dfu_ctx.state = DFU_ERROR; - _dfu_ctx.status = status; + _dfu_ctx.status = (dfu_status_t)status; } } -- cgit v1.3.1 From 1c2e353193d31ee3869a2417e17be89f0a6aa41c Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Sat, 29 May 2021 19:09:13 +0900 Subject: Refactor and clean up --- src/portable/renesas/usba/dcd_usba.c | 284 ++++++++++++++++++----------------- 1 file changed, 149 insertions(+), 135 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index c7eb6e15e..46513590e 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -122,7 +122,7 @@ typedef union { typedef struct TU_ATTR_PACKED { - uintptr_t addr; /* the start address of a transfer data buffer */ + void *buf; /* the start address of a transfer data buffer */ uint16_t length; /* the number of bytes in the buffer */ uint16_t remaining; /* the number of bytes remaining in the buffer */ struct { @@ -236,34 +236,27 @@ static volatile uint16_t* ep_addr_to_pipectr(uint8_t rhport, unsigned ep_addr) return ctr; } -static unsigned wait_for_pipe_ready(void) +static unsigned edpt0_max_packet_size(void) { - unsigned ctr; - do { - ctr = USB0.D0FIFOCTR.WORD; - } while (!(ctr & USB_FIFOCTR_FRDY)); - return ctr; + return USB0.DCPMAXP.BIT.MXPS; } -static unsigned select_pipe(unsigned num, unsigned attr) +static unsigned edpt_max_packet_size(unsigned num) { - USB0.PIPESEL.WORD = num; - USB0.D0FIFOSEL.WORD = num | attr; - while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ; - return wait_for_pipe_ready(); + USB0.PIPESEL.WORD = num; + return USB0.PIPEMAXP.WORD; } -/* 1 less than mps bytes were written to FIFO - * 2 no bytes were written to FIFO - * 0 mps bytes were written to FIFO */ -static int fifo_write(volatile void *fifo, pipe_state_t* pipe, unsigned mps) +static inline void pipe_wait_for_ready(unsigned num) { - unsigned rem = pipe->remaining; - if (!rem) return 2; - unsigned len = TU_MIN(rem, mps); + while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ; + while (!USB0.D0FIFOCTR.BIT.FRDY) ; +} +static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len) +{ hw_fifo_t *reg = (hw_fifo_t*)fifo; - uintptr_t addr = pipe->addr + pipe->length - rem; + uintptr_t addr = (uintptr_t)buf; while (len >= 2) { reg->u16 = *(const uint16_t *)addr; addr += 2; @@ -273,31 +266,107 @@ static int fifo_write(volatile void *fifo, pipe_state_t* pipe, unsigned mps) reg->u8 = *(const uint8_t *)addr; ++addr; } - if (rem < mps) return 1; - return 0; } -/* 1 less than mps bytes were read from FIFO - * 2 the end of the buffer reached. - * 0 mps bytes were read from FIFO */ -static int fifo_read(volatile void *fifo, pipe_state_t* pipe, unsigned mps, size_t len) +static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len) +{ + uint8_t *p = (uint8_t*)buf; + uint8_t *reg = (uint8_t*)fifo; /* byte access is always at base register address */ + while (len--) *p++ = *reg; +} + +static bool pipe0_xfer_in(void) { - unsigned rem = pipe->remaining; - if (!rem) return 2; - if (rem < len) len = rem; + pipe_state_t *pipe = &_dcd.pipe[0]; + const unsigned rem = pipe->remaining; + if (!rem) { + pipe->buf = NULL; + return true; + } + const unsigned mps = edpt0_max_packet_size(); + const unsigned len = TU_MIN(mps, rem); + void *buf = pipe->buf; + if (len) { + pipe_write_packet(buf, &USB0.CFIFO.WORD, len); + pipe->buf = (uint8_t*)buf + len; + } + if (len < mps) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; pipe->remaining = rem - len; + return false; +} - uint8_t *reg = (uint8_t*)fifo; /* byte access is always at base register address */ - uintptr_t addr = pipe->addr; - unsigned loop = len; - while (loop--) { - *(uint8_t *)addr = *reg; - ++addr; +static bool pipe0_xfer_out(void) +{ + pipe_state_t *pipe = &_dcd.pipe[0]; + const unsigned rem = pipe->remaining; + + const unsigned mps = edpt0_max_packet_size(); + const unsigned vld = USB0.CFIFOCTR.BIT.DTLN; + const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); + void *buf = pipe->buf; + if (len) { + pipe_read_packet(buf, &USB0.CFIFO.WORD, len); + pipe->buf = (uint8_t*)buf + len; } - pipe->addr = addr; - if (rem < mps) return 1; - if (rem == len) return 2; - return 0; + if (len < mps) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; + pipe->remaining = rem - len; + if ((len < mps) || (rem == len)) { + pipe->buf = NULL; + return true; + } + return false; +} + +static bool pipe_xfer_in(unsigned num) +{ + pipe_state_t *pipe = &_dcd.pipe[num]; + const unsigned rem = pipe->remaining; + + if (!rem) { + pipe->buf = NULL; + return true; + } + + USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16; + const unsigned mps = edpt_max_packet_size(num); + pipe_wait_for_ready(num); + const unsigned len = TU_MIN(rem, mps); + void *buf = pipe->buf; + if (len) { + pipe_write_packet(buf, &USB0.D0FIFO.WORD, len); + pipe->buf = (uint8_t*)buf + len; + } + if (len < mps) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; + USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ + pipe->remaining = rem - len; + return false; +} + +static bool pipe_xfer_out(unsigned num) +{ + pipe_state_t *pipe = &_dcd.pipe[num]; + const unsigned rem = pipe->remaining; + + USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_8; + const unsigned mps = edpt_max_packet_size(num); + pipe_wait_for_ready(num); + const unsigned vld = USB0.D0FIFOCTR.BIT.DTLN; + const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); + void *buf = pipe->buf; + if (len) { + pipe_read_packet(buf, &USB0.D0FIFO.WORD, len); + pipe->buf = (uint8_t*)buf + len; + } + if (len < mps) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BCLR; + USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ + pipe->remaining = rem - len; + if ((len < mps) || (rem == len)) { + pipe->buf = NULL; + return NULL != buf; + } + return false; } static void process_setup_packet(uint8_t rhport) @@ -327,11 +396,10 @@ static void process_status_completion(uint8_t rhport) dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, true); } -static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +static bool process_pipe0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { (void)rhport; - pipe_state_t *pipe = &_dcd.pipe[0]; /* configure fifo direction and access unit settings */ if (ep_addr) { /* IN, 2 bytes */ USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0); @@ -340,57 +408,25 @@ static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, USB0.CFIFOSEL.WORD = USB_FIFOSEL_MBW_8; while (USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX) ; } + + pipe_state_t *pipe = &_dcd.pipe[0]; + pipe->length = total_bytes; + pipe->remaining = total_bytes; if (total_bytes) { - pipe->addr = (uintptr_t)buffer; - pipe->length = total_bytes; - pipe->remaining = total_bytes; + pipe->buf = buffer; if (ep_addr) { /* IN */ TU_ASSERT(USB0.DCPCTR.BIT.BSTS && (USB0.USBREQ.WORD & 0x80)); - if (fifo_write((void*)&USB0.CFIFO.WORD, pipe, 64)) { - USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; - } + pipe0_xfer_in(); } USB0.DCPCTR.WORD = USB_PIPECTR_PID_BUF; } else { /* ZLP */ - pipe->addr = 0; - pipe->length = 0; - pipe->remaining = 0; + pipe->buf = NULL; USB0.DCPCTR.WORD = USB_PIPECTR_CCPL | USB_PIPECTR_PID_BUF; } return true; } -static void process_edpt0_bemp(uint8_t rhport) -{ - pipe_state_t *pipe = &_dcd.pipe[0]; - const unsigned rem = pipe->remaining; - if (rem > 64) { - pipe->remaining = rem - 64; - int r = fifo_write((void*)&USB0.CFIFO.WORD, &_dcd.pipe[0], 64); - if (r) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; - return; - } - pipe->addr = 0; - pipe->remaining = 0; - dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN), - pipe->length, XFER_RESULT_SUCCESS, true); -} - -static void process_edpt0_brdy(uint8_t rhport) -{ - size_t len = USB0.CFIFOCTR.BIT.DTLN; - int cplt = fifo_read((void*)&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, len); - if (cplt || (len < 64)) { - if (2 != cplt) { - USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; - } - dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), - _dcd.pipe[0].length - _dcd.pipe[0].remaining, - XFER_RESULT_SUCCESS, true); - } -} - static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { (void)rhport; @@ -401,23 +437,16 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, TU_ASSERT(num); - pipe_state_t *pipe = &_dcd.pipe[num]; - pipe->addr = (uintptr_t)buffer; + pipe_state_t *pipe = &_dcd.pipe[num]; + pipe->buf = buffer; pipe->length = total_bytes; pipe->remaining = total_bytes; - - USB0.PIPESEL.WORD = num; - const unsigned mps = USB0.PIPEMAXP.WORD; if (dir) { /* IN */ - USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0); - while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ; - int r = fifo_write((void*)&USB0.D0FIFO.WORD, pipe, mps); - if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; - USB0.D0FIFOSEL.WORD = 0; - while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ + pipe_xfer_in(num); } else { volatile reg_pipetre_t *pt = get_pipetre(num); if (pt) { + const unsigned mps = edpt_max_packet_size(num); volatile uint16_t *ctr = get_pipectr(num); if (*ctr & 0x3) *ctr = USB_PIPECTR_PID_NAK; pt->TRE = TU_BIT(8); @@ -430,47 +459,36 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, return true; } +static void process_pipe0_bemp(uint8_t rhport) +{ + bool completed = pipe0_xfer_in(); + if (completed) { + pipe_state_t *pipe = &_dcd.pipe[0]; + dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN), + pipe->length, XFER_RESULT_SUCCESS, true); + } +} + static void process_pipe_brdy(uint8_t rhport, unsigned num) { - pipe_state_t *pipe = &_dcd.pipe[num]; - if (tu_edpt_dir(pipe->ep)) { /* IN */ - select_pipe(num, USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0)); - const unsigned mps = USB0.PIPEMAXP.WORD; - unsigned rem = pipe->remaining; - rem -= TU_MIN(rem, mps); - pipe->remaining = rem; - if (rem) { - int r = 0; - r = fifo_write((void*)&USB0.D0FIFO.WORD, pipe, mps); - if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; - USB0.D0FIFOSEL.WORD = 0; - while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ - return; - } - USB0.D0FIFOSEL.WORD = 0; - while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ - pipe->addr = 0; - pipe->remaining = 0; - dcd_event_xfer_complete(rhport, pipe->ep, pipe->length, - XFER_RESULT_SUCCESS, true); + pipe_state_t *pipe = &_dcd.pipe[num]; + const unsigned dir = tu_edpt_dir(pipe->ep); + bool completed; + + if (dir) { /* IN */ + completed = pipe_xfer_in(num); } else { - const unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_8); - const unsigned len = ctr & USB_FIFOCTR_DTLN; - const unsigned mps = USB0.PIPEMAXP.WORD; - int cplt = fifo_read((void*)&USB0.D0FIFO.WORD, pipe, mps, len); - if (cplt || (len < mps)) { - if (2 != cplt) { - USB0.D0FIFO.WORD = USB_FIFOCTR_BCLR; - } - USB0.D0FIFOSEL.WORD = 0; - while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ - dcd_event_xfer_complete(rhport, pipe->ep, - pipe->length - pipe->remaining, - XFER_RESULT_SUCCESS, true); - return; + if (num) { + completed = pipe_xfer_out(num); + } else { + completed = pipe0_xfer_out(); } - USB0.D0FIFOSEL.WORD = 0; - while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ + } + if (completed) { + dcd_event_xfer_complete(rhport, pipe->ep, + pipe->length - pipe->remaining, + XFER_RESULT_SUCCESS, true); + // TU_LOG1("C %d %d\r\n", num, pipe->length - pipe->remaining); } } @@ -649,7 +667,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) if (dir || (xfer != TUSB_XFER_BULK)) { *ctr = USB_PIPECTR_PID_BUF; } - // TU_LOG1("O %d %x %x\r\n", USB0.PIPESEL.WORD, USB0.PIPECFG.WORD, USB0.PIPEMAXP.WORD); + // TU_LOG1("O %d %x %x\r\n", USB0.PIPESEL.WORD, USB0.PIPECFG.WORD, USB0.PIPEMAXP.WORD); dcd_int_enable(rhport); return true; @@ -677,7 +695,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to const unsigned epn = tu_edpt_number(ep_addr); dcd_int_disable(rhport); if (0 == epn) { - r = process_edpt0_xfer(rhport, ep_addr, buffer, total_bytes); + r = process_pipe0_xfer(rhport, ep_addr, buffer, total_bytes); } else { r = process_pipe_xfer(rhport, ep_addr, buffer, total_bytes); } @@ -779,7 +797,7 @@ void dcd_int_handler(uint8_t rhport) const unsigned s = USB0.BEMPSTS.WORD; USB0.BEMPSTS.WORD = 0; if (s & 1) { - process_edpt0_bemp(rhport); + process_pipe0_bemp(rhport); } } if (is0 & USB_IS0_BRDY) { @@ -787,10 +805,6 @@ void dcd_int_handler(uint8_t rhport) unsigned s = USB0.BRDYSTS.WORD & m; /* clear active bits (don't write 0 to already cleared bits according to the HW manual) */ USB0.BRDYSTS.WORD = ~s; - if (s & 1) { - process_edpt0_brdy(rhport); - s &= ~1; - } while (s) { #if defined(__CCRX__) static const int Mod37BitPosition[] = { -- cgit v1.3.1 From 3f49380b378601a852ed45f2b38dd48c66b0f69d Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Sun, 30 May 2021 22:49:53 +0900 Subject: added support for dcd_edpt_xfer_fifo --- src/portable/renesas/usba/dcd_usba.c | 86 ++++++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 46513590e..ada184541 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -127,6 +127,7 @@ typedef struct TU_ATTR_PACKED uint16_t remaining; /* the number of bytes remaining in the buffer */ struct { uint32_t ep : 8; /* an assigned endpoint address */ + uint32_t ff : 1; /* `buf` is TU_FUFO or POD */ uint32_t : 0; }; } pipe_state_t; @@ -287,8 +288,12 @@ static bool pipe0_xfer_in(void) const unsigned len = TU_MIN(mps, rem); void *buf = pipe->buf; if (len) { - pipe_write_packet(buf, &USB0.CFIFO.WORD, len); - pipe->buf = (uint8_t*)buf + len; + if (pipe->ff) { + tu_fifo_read_n_const_addr_full_words(buf, (void*)&USB0.CFIFO.WORD, len); + } else { + pipe_write_packet(buf, &USB0.CFIFO.WORD, len); + pipe->buf = (uint8_t*)buf + len; + } } if (len < mps) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL; pipe->remaining = rem - len; @@ -305,8 +310,12 @@ static bool pipe0_xfer_out(void) const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); void *buf = pipe->buf; if (len) { - pipe_read_packet(buf, &USB0.CFIFO.WORD, len); - pipe->buf = (uint8_t*)buf + len; + if (pipe->ff) { + tu_fifo_write_n_const_addr_full_words(buf, (void*)&USB0.CFIFO.WORD, len); + } else { + pipe_read_packet(buf, &USB0.CFIFO.WORD, len); + pipe->buf = (uint8_t*)buf + len; + } } if (len < mps) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR; pipe->remaining = rem - len; @@ -333,8 +342,12 @@ static bool pipe_xfer_in(unsigned num) const unsigned len = TU_MIN(rem, mps); void *buf = pipe->buf; if (len) { - pipe_write_packet(buf, &USB0.D0FIFO.WORD, len); - pipe->buf = (uint8_t*)buf + len; + if (pipe->ff) { + tu_fifo_read_n_const_addr_full_words(buf, (void*)&USB0.D0FIFO.WORD, len); + } else { + pipe_write_packet(buf, &USB0.D0FIFO.WORD, len); + pipe->buf = (uint8_t*)buf + len; + } } if (len < mps) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; USB0.D0FIFOSEL.WORD = 0; @@ -355,8 +368,12 @@ static bool pipe_xfer_out(unsigned num) const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); void *buf = pipe->buf; if (len) { - pipe_read_packet(buf, &USB0.D0FIFO.WORD, len); - pipe->buf = (uint8_t*)buf + len; + if (pipe->ff) { + tu_fifo_write_n_const_addr_full_words(buf, (void*)&USB0.D0FIFO.WORD, len); + } else { + pipe_read_packet(buf, &USB0.D0FIFO.WORD, len); + pipe->buf = (uint8_t*)buf + len; + } } if (len < mps) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BCLR; USB0.D0FIFOSEL.WORD = 0; @@ -396,10 +413,8 @@ static void process_status_completion(uint8_t rhport) dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, true); } -static bool process_pipe0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +static bool process_pipe0_xfer(int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes) { - (void)rhport; - /* configure fifo direction and access unit settings */ if (ep_addr) { /* IN, 2 bytes */ USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0); @@ -410,6 +425,7 @@ static bool process_pipe0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, } pipe_state_t *pipe = &_dcd.pipe[0]; + pipe->ff = buffer_type; pipe->length = total_bytes; pipe->remaining = total_bytes; if (total_bytes) { @@ -427,10 +443,8 @@ static bool process_pipe0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, return true; } -static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +static bool process_pipe_xfer(int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes) { - (void)rhport; - const unsigned epn = tu_edpt_number(ep_addr); const unsigned dir = tu_edpt_dir(ep_addr); const unsigned num = _dcd.ep[dir][epn]; @@ -438,11 +452,19 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, TU_ASSERT(num); pipe_state_t *pipe = &_dcd.pipe[num]; + pipe->ff = buffer_type; pipe->buf = buffer; pipe->length = total_bytes; pipe->remaining = total_bytes; if (dir) { /* IN */ - pipe_xfer_in(num); + if (total_bytes) { + pipe_xfer_in(num); + } else { /* ZLP */ + USB0.D0FIFOSEL.WORD = num; + pipe_wait_for_ready(num); + USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; + USB0.D0FIFOSEL.WORD = 0; + } } else { volatile reg_pipetre_t *pt = get_pipetre(num); if (pt) { @@ -459,13 +481,23 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, return true; } +static bool process_edpt_xfer(int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes) +{ + const unsigned epn = tu_edpt_number(ep_addr); + if (0 == epn) { + return process_pipe0_xfer(buffer_type, ep_addr, buffer, total_bytes); + } else { + return process_pipe_xfer(buffer_type, ep_addr, buffer, total_bytes); + } +} + static void process_pipe0_bemp(uint8_t rhport) { bool completed = pipe0_xfer_in(); if (completed) { pipe_state_t *pipe = &_dcd.pipe[0]; dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN), - pipe->length, XFER_RESULT_SUCCESS, true); + pipe->length, XFER_RESULT_SUCCESS, true); } } @@ -486,8 +518,8 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num) } if (completed) { dcd_event_xfer_complete(rhport, pipe->ep, - pipe->length - pipe->remaining, - XFER_RESULT_SUCCESS, true); + pipe->length - pipe->remaining, + XFER_RESULT_SUCCESS, true); // TU_LOG1("C %d %d\r\n", num, pipe->length - pipe->remaining); } } @@ -692,13 +724,19 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { bool r; - const unsigned epn = tu_edpt_number(ep_addr); dcd_int_disable(rhport); - if (0 == epn) { - r = process_pipe0_xfer(rhport, ep_addr, buffer, total_bytes); - } else { - r = process_pipe_xfer(rhport, ep_addr, buffer, total_bytes); - } + r = process_edpt_xfer(0, ep_addr, buffer, total_bytes); + dcd_int_enable(rhport); + return r; +} + +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 + TU_ASSERT(ff->item_size == 1); + bool r; + dcd_int_disable(rhport); + r = process_edpt_xfer(1, ep_addr, ff, total_bytes); dcd_int_enable(rhport); return r; } -- cgit v1.3.1 From e7c9cf4aea1515306765eb2b43dbe7002b50ed62 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Wed, 2 Jun 2021 22:18:15 +0900 Subject: Change the accessing method of TU_FIFO from read/write_n_const_addr_full_words to get_write/read_info and advance_write/read_pointer pairs. --- src/portable/renesas/usba/dcd_usba.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index ada184541..09622d894 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -276,6 +276,30 @@ static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len) while (len--) *p++ = *reg; } +static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigned len, unsigned dir) +{ + static const struct { + void (*tu_fifo_get_info)(tu_fifo_t *f, tu_fifo_buffer_info_t *info); + void (*tu_fifo_advance)(tu_fifo_t *f, uint16_t n); + void (*pipe_read_write)(void *buf, volatile void *fifo, unsigned len); + } ops[] = { + /* OUT */ {tu_fifo_get_write_info,tu_fifo_advance_write_pointer,pipe_read_packet}, + /* IN */ {tu_fifo_get_read_info, tu_fifo_advance_read_pointer, pipe_write_packet}, + }; + tu_fifo_buffer_info_t info; + ops[dir].tu_fifo_get_info(f, &info); + unsigned total_len = len; + len = TU_MIN(total_len, info.len_lin); + ops[dir].pipe_read_write(info.ptr_lin, fifo, len); + unsigned rem = total_len - len; + if (rem) { + len = TU_MIN(rem, info.len_wrap); + ops[dir].pipe_read_write(info.ptr_wrap, fifo, len); + rem -= len; + } + ops[dir].tu_fifo_advance(f, total_len - rem); +} + static bool pipe0_xfer_in(void) { pipe_state_t *pipe = &_dcd.pipe[0]; @@ -289,7 +313,7 @@ static bool pipe0_xfer_in(void) void *buf = pipe->buf; if (len) { if (pipe->ff) { - tu_fifo_read_n_const_addr_full_words(buf, (void*)&USB0.CFIFO.WORD, len); + pipe_read_write_packet_ff((tu_fifo_t*)buf, &USB0.CFIFO.WORD, len, TUSB_DIR_IN); } else { pipe_write_packet(buf, &USB0.CFIFO.WORD, len); pipe->buf = (uint8_t*)buf + len; @@ -311,7 +335,7 @@ static bool pipe0_xfer_out(void) void *buf = pipe->buf; if (len) { if (pipe->ff) { - tu_fifo_write_n_const_addr_full_words(buf, (void*)&USB0.CFIFO.WORD, len); + pipe_read_write_packet_ff((tu_fifo_t*)buf, &USB0.CFIFO.WORD, len, TUSB_DIR_OUT); } else { pipe_read_packet(buf, &USB0.CFIFO.WORD, len); pipe->buf = (uint8_t*)buf + len; @@ -343,7 +367,7 @@ static bool pipe_xfer_in(unsigned num) void *buf = pipe->buf; if (len) { if (pipe->ff) { - tu_fifo_read_n_const_addr_full_words(buf, (void*)&USB0.D0FIFO.WORD, len); + pipe_read_write_packet_ff((tu_fifo_t*)buf, &USB0.D0FIFO.WORD, len, TUSB_DIR_IN); } else { pipe_write_packet(buf, &USB0.D0FIFO.WORD, len); pipe->buf = (uint8_t*)buf + len; @@ -369,7 +393,7 @@ static bool pipe_xfer_out(unsigned num) void *buf = pipe->buf; if (len) { if (pipe->ff) { - tu_fifo_write_n_const_addr_full_words(buf, (void*)&USB0.D0FIFO.WORD, len); + pipe_read_write_packet_ff((tu_fifo_t*)buf, &USB0.D0FIFO.WORD, len, TUSB_DIR_OUT); } else { pipe_read_packet(buf, &USB0.D0FIFO.WORD, len); pipe->buf = (uint8_t*)buf + len; @@ -477,7 +501,7 @@ static bool process_pipe_xfer(int buffer_type, uint8_t ep_addr, void* buffer, ui *ctr = USB_PIPECTR_PID_BUF; } } - // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); + // TU_LOG1("X %x %d %d\r\n", ep_addr, total_bytes, buffer_type); return true; } -- cgit v1.3.1 From 6b9f8e454eaf5ac3a9474d0a09f019e700532093 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Fri, 4 Jun 2021 01:22:57 +0900 Subject: add a condition regarding OPT_MCU_RX63N --- src/class/audio/audio_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 404d28817..86a00ea73 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -86,7 +86,8 @@ CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ - (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) + (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) || \ + CFG_TUSB_MCU == OPT_MCU_RX63X #define USE_LINEAR_BUFFER 0 #else #define USE_LINEAR_BUFFER 1 -- cgit v1.3.1 From 3c3563288d643fc70ccff80c02a72d330cd65678 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Tue, 29 Jun 2021 20:41:16 +0900 Subject: add RX65N --- src/class/audio/audio_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 86a00ea73..092e5e125 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -87,7 +87,8 @@ CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) || \ - CFG_TUSB_MCU == OPT_MCU_RX63X + CFG_TUSB_MCU == OPT_MCU_RX63X || \ + CFG_TUSB_MCU == OPT_MCU_RX65X #define USE_LINEAR_BUFFER 0 #else #define USE_LINEAR_BUFFER 1 -- cgit v1.3.1 From ff20e4d6bcffc5d66666050c57719031fa2820e8 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Thu, 29 Jul 2021 20:45:51 +0900 Subject: add the entry for RX72N --- src/class/audio/audio_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 092e5e125..de0bddcd3 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -88,7 +88,8 @@ CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) || \ CFG_TUSB_MCU == OPT_MCU_RX63X || \ - CFG_TUSB_MCU == OPT_MCU_RX65X + CFG_TUSB_MCU == OPT_MCU_RX65X || \ + CFG_TUSB_MCU == OPT_MCU_RX72N #define USE_LINEAR_BUFFER 0 #else #define USE_LINEAR_BUFFER 1 -- cgit v1.3.1 From c4cd36980ded509bd45c26ab35410d2234ac2734 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Fri, 30 Jul 2021 12:06:02 +0200 Subject: Add cache clean/invalidate. --- src/portable/microchip/samx7x/dcd_samx7x.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index e35cf80a6..465c5953b 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -94,6 +94,18 @@ static const tusb_desc_endpoint_t ep0_desc = .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE }, }; +TU_ATTR_ALWAYS_INLINE static inline void CleanInValidateCache(uint32_t *addr, int32_t size) +{ + if (SCB->CCR & SCB_CCR_DC_Msk) + { + SCB_CleanInvalidateDCache_by_Addr(addr, size); + } + else + { + __DSB(); + __ISB(); + } +} //------------------------------------------------------------------ // Device API //------------------------------------------------------------------ @@ -141,8 +153,6 @@ void dcd_connect(uint8_t rhport) { (void) rhport; dcd_int_disable(rhport); - // Enable USB clock - PMC->PMC_PCER1 = 1 << (ID_USBHS - 32); // Enable the USB controller in device mode USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE; while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); @@ -602,6 +612,9 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) { + // Force the CPU to flush the buffer. We increase the size by 32 because the call aligns the + // address to 32-byte boundaries. + CleanInValidateCache((uint32_t*) tu_align((uint32_t) buffer, 4), total_bytes + 31); uint32_t udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); if (dir == TUSB_DIR_OUT) { @@ -679,16 +692,23 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_B_EN; } + // Clean invalidate cache of linear part + CleanInValidateCache((uint32_t*) tu_align((uint32_t) info.ptr_lin, 4), info.len_lin + 31); + USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)info.ptr_lin; if (info.len_wrap) { + // Clean invalidate cache of wrapped part + CleanInValidateCache((uint32_t*) tu_align((uint32_t) info.ptr_wrap, 4), info.len_wrap + 31); + dma_desc[epnum - 1].next_desc = 0; dma_desc[epnum - 1].buff_addr = (uint32_t)info.ptr_wrap; dma_desc[epnum - 1].chnl_ctrl = udd_dma_ctrl_wrap | USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_wrap); + // Clean cache of wrapped DMA descriptor + CleanInValidateCache((uint32_t*)&dma_desc[epnum - 1], sizeof(dma_desc_t)); + udd_dma_ctrl_lin |= USBHS_DEVDMASTATUS_DESC_LDST; - __DSB(); - __ISB(); USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMANXTDSC = (uint32_t)&dma_desc[epnum - 1]; } else { udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_BUFFIT; -- cgit v1.3.1 From 383290a634a562edc081a3935aba8073d35657c3 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Fri, 30 Jul 2021 19:43:04 +0200 Subject: Move register define to separate header. --- src/portable/microchip/samx7x/common_usb_regs.h | 2108 +++++++++++++++++++++++ src/portable/microchip/samx7x/dcd_samx7x.c | 291 ++-- 2 files changed, 2250 insertions(+), 149 deletions(-) create mode 100644 src/portable/microchip/samx7x/common_usb_regs.h (limited to 'src') diff --git a/src/portable/microchip/samx7x/common_usb_regs.h b/src/portable/microchip/samx7x/common_usb_regs.h new file mode 100644 index 000000000..d232f0bcb --- /dev/null +++ b/src/portable/microchip/samx7x/common_usb_regs.h @@ -0,0 +1,2108 @@ + /* +* The MIT License (MIT) +* +* Copyright (c) 2019 Microchip Technology Inc. +* Copyright (c) 2018, hathach (tinyusb.org) +* Copyright (c) 2021, HiFiPhile +* +* 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. +* +* This file is part of the TinyUSB stack. +*/ + +#ifndef _COMMON_USB_REGS_H_ +#define _COMMON_USB_REGS_H_ + +#if CFG_TUSB_MCU == OPT_MCU_SAMX7X + +/* -------- DEVDMANXTDSC : (USBHS Offset: 0x00) (R/W 32) Device DMA Channel Next Descriptor Address Register -------- */ + +#define DEVDMANXTDSC_OFFSET (0x00) /**< (DEVDMANXTDSC) Device DMA Channel Next Descriptor Address Register Offset */ + +#define DEVDMANXTDSC_NXT_DSC_ADD_Pos 0 /**< (DEVDMANXTDSC) Next Descriptor Address Position */ +#define DEVDMANXTDSC_NXT_DSC_ADD (_U_(0xFFFFFFFF) << DEVDMANXTDSC_NXT_DSC_ADD_Pos) /**< (DEVDMANXTDSC) Next Descriptor Address Mask */ +#define DEVDMANXTDSC_Msk _U_(0xFFFFFFFF) /**< (DEVDMANXTDSC) Register Mask */ + + +/* -------- DEVDMAADDRESS : (USBHS Offset: 0x04) (R/W 32) Device DMA Channel Address Register -------- */ + +#define DEVDMAADDRESS_OFFSET (0x04) /**< (DEVDMAADDRESS) Device DMA Channel Address Register Offset */ + +#define DEVDMAADDRESS_BUFF_ADD_Pos 0 /**< (DEVDMAADDRESS) Buffer Address Position */ +#define DEVDMAADDRESS_BUFF_ADD (_U_(0xFFFFFFFF) << DEVDMAADDRESS_BUFF_ADD_Pos) /**< (DEVDMAADDRESS) Buffer Address Mask */ +#define DEVDMAADDRESS_Msk _U_(0xFFFFFFFF) /**< (DEVDMAADDRESS) Register Mask */ + + +/* -------- DEVDMACONTROL : (USBHS Offset: 0x08) (R/W 32) Device DMA Channel Control Register -------- */ + +#define DEVDMACONTROL_OFFSET (0x08) /**< (DEVDMACONTROL) Device DMA Channel Control Register Offset */ + +#define DEVDMACONTROL_CHANN_ENB_Pos 0 /**< (DEVDMACONTROL) Channel Enable Command Position */ +#define DEVDMACONTROL_CHANN_ENB (_U_(0x1) << DEVDMACONTROL_CHANN_ENB_Pos) /**< (DEVDMACONTROL) Channel Enable Command Mask */ +#define DEVDMACONTROL_LDNXT_DSC_Pos 1 /**< (DEVDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Position */ +#define DEVDMACONTROL_LDNXT_DSC (_U_(0x1) << DEVDMACONTROL_LDNXT_DSC_Pos) /**< (DEVDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Mask */ +#define DEVDMACONTROL_END_TR_EN_Pos 2 /**< (DEVDMACONTROL) End of Transfer Enable Control (OUT transfers only) Position */ +#define DEVDMACONTROL_END_TR_EN (_U_(0x1) << DEVDMACONTROL_END_TR_EN_Pos) /**< (DEVDMACONTROL) End of Transfer Enable Control (OUT transfers only) Mask */ +#define DEVDMACONTROL_END_B_EN_Pos 3 /**< (DEVDMACONTROL) End of Buffer Enable Control Position */ +#define DEVDMACONTROL_END_B_EN (_U_(0x1) << DEVDMACONTROL_END_B_EN_Pos) /**< (DEVDMACONTROL) End of Buffer Enable Control Mask */ +#define DEVDMACONTROL_END_TR_IT_Pos 4 /**< (DEVDMACONTROL) End of Transfer Interrupt Enable Position */ +#define DEVDMACONTROL_END_TR_IT (_U_(0x1) << DEVDMACONTROL_END_TR_IT_Pos) /**< (DEVDMACONTROL) End of Transfer Interrupt Enable Mask */ +#define DEVDMACONTROL_END_BUFFIT_Pos 5 /**< (DEVDMACONTROL) End of Buffer Interrupt Enable Position */ +#define DEVDMACONTROL_END_BUFFIT (_U_(0x1) << DEVDMACONTROL_END_BUFFIT_Pos) /**< (DEVDMACONTROL) End of Buffer Interrupt Enable Mask */ +#define DEVDMACONTROL_DESC_LD_IT_Pos 6 /**< (DEVDMACONTROL) Descriptor Loaded Interrupt Enable Position */ +#define DEVDMACONTROL_DESC_LD_IT (_U_(0x1) << DEVDMACONTROL_DESC_LD_IT_Pos) /**< (DEVDMACONTROL) Descriptor Loaded Interrupt Enable Mask */ +#define DEVDMACONTROL_BURST_LCK_Pos 7 /**< (DEVDMACONTROL) Burst Lock Enable Position */ +#define DEVDMACONTROL_BURST_LCK (_U_(0x1) << DEVDMACONTROL_BURST_LCK_Pos) /**< (DEVDMACONTROL) Burst Lock Enable Mask */ +#define DEVDMACONTROL_BUFF_LENGTH_Pos 16 /**< (DEVDMACONTROL) Buffer Byte Length (Write-only) Position */ +#define DEVDMACONTROL_BUFF_LENGTH (_U_(0xFFFF) << DEVDMACONTROL_BUFF_LENGTH_Pos) /**< (DEVDMACONTROL) Buffer Byte Length (Write-only) Mask */ +#define DEVDMACONTROL_Msk _U_(0xFFFF00FF) /**< (DEVDMACONTROL) Register Mask */ + + +/* -------- DEVDMASTATUS : (USBHS Offset: 0x0c) (R/W 32) Device DMA Channel Status Register -------- */ + +#define DEVDMASTATUS_OFFSET (0x0C) /**< (DEVDMASTATUS) Device DMA Channel Status Register Offset */ + +#define DEVDMASTATUS_CHANN_ENB_Pos 0 /**< (DEVDMASTATUS) Channel Enable Status Position */ +#define DEVDMASTATUS_CHANN_ENB (_U_(0x1) << DEVDMASTATUS_CHANN_ENB_Pos) /**< (DEVDMASTATUS) Channel Enable Status Mask */ +#define DEVDMASTATUS_CHANN_ACT_Pos 1 /**< (DEVDMASTATUS) Channel Active Status Position */ +#define DEVDMASTATUS_CHANN_ACT (_U_(0x1) << DEVDMASTATUS_CHANN_ACT_Pos) /**< (DEVDMASTATUS) Channel Active Status Mask */ +#define DEVDMASTATUS_END_TR_ST_Pos 4 /**< (DEVDMASTATUS) End of Channel Transfer Status Position */ +#define DEVDMASTATUS_END_TR_ST (_U_(0x1) << DEVDMASTATUS_END_TR_ST_Pos) /**< (DEVDMASTATUS) End of Channel Transfer Status Mask */ +#define DEVDMASTATUS_END_BF_ST_Pos 5 /**< (DEVDMASTATUS) End of Channel Buffer Status Position */ +#define DEVDMASTATUS_END_BF_ST (_U_(0x1) << DEVDMASTATUS_END_BF_ST_Pos) /**< (DEVDMASTATUS) End of Channel Buffer Status Mask */ +#define DEVDMASTATUS_DESC_LDST_Pos 6 /**< (DEVDMASTATUS) Descriptor Loaded Status Position */ +#define DEVDMASTATUS_DESC_LDST (_U_(0x1) << DEVDMASTATUS_DESC_LDST_Pos) /**< (DEVDMASTATUS) Descriptor Loaded Status Mask */ +#define DEVDMASTATUS_BUFF_COUNT_Pos 16 /**< (DEVDMASTATUS) Buffer Byte Count Position */ +#define DEVDMASTATUS_BUFF_COUNT (_U_(0xFFFF) << DEVDMASTATUS_BUFF_COUNT_Pos) /**< (DEVDMASTATUS) Buffer Byte Count Mask */ +#define DEVDMASTATUS_Msk _U_(0xFFFF0073) /**< (DEVDMASTATUS) Register Mask */ + + +/* -------- HSTDMANXTDSC : (USBHS Offset: 0x00) (R/W 32) Host DMA Channel Next Descriptor Address Register -------- */ + +#define HSTDMANXTDSC_OFFSET (0x00) /**< (HSTDMANXTDSC) Host DMA Channel Next Descriptor Address Register Offset */ + +#define HSTDMANXTDSC_NXT_DSC_ADD_Pos 0 /**< (HSTDMANXTDSC) Next Descriptor Address Position */ +#define HSTDMANXTDSC_NXT_DSC_ADD (_U_(0xFFFFFFFF) << HSTDMANXTDSC_NXT_DSC_ADD_Pos) /**< (HSTDMANXTDSC) Next Descriptor Address Mask */ +#define HSTDMANXTDSC_Msk _U_(0xFFFFFFFF) /**< (HSTDMANXTDSC) Register Mask */ + + +/* -------- HSTDMAADDRESS : (USBHS Offset: 0x04) (R/W 32) Host DMA Channel Address Register -------- */ + +#define HSTDMAADDRESS_OFFSET (0x04) /**< (HSTDMAADDRESS) Host DMA Channel Address Register Offset */ + +#define HSTDMAADDRESS_BUFF_ADD_Pos 0 /**< (HSTDMAADDRESS) Buffer Address Position */ +#define HSTDMAADDRESS_BUFF_ADD (_U_(0xFFFFFFFF) << HSTDMAADDRESS_BUFF_ADD_Pos) /**< (HSTDMAADDRESS) Buffer Address Mask */ +#define HSTDMAADDRESS_Msk _U_(0xFFFFFFFF) /**< (HSTDMAADDRESS) Register Mask */ + + +/* -------- HSTDMACONTROL : (USBHS Offset: 0x08) (R/W 32) Host DMA Channel Control Register -------- */ + +#define HSTDMACONTROL_OFFSET (0x08) /**< (HSTDMACONTROL) Host DMA Channel Control Register Offset */ + +#define HSTDMACONTROL_CHANN_ENB_Pos 0 /**< (HSTDMACONTROL) Channel Enable Command Position */ +#define HSTDMACONTROL_CHANN_ENB (_U_(0x1) << HSTDMACONTROL_CHANN_ENB_Pos) /**< (HSTDMACONTROL) Channel Enable Command Mask */ +#define HSTDMACONTROL_LDNXT_DSC_Pos 1 /**< (HSTDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Position */ +#define HSTDMACONTROL_LDNXT_DSC (_U_(0x1) << HSTDMACONTROL_LDNXT_DSC_Pos) /**< (HSTDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Mask */ +#define HSTDMACONTROL_END_TR_EN_Pos 2 /**< (HSTDMACONTROL) End of Transfer Enable Control (OUT transfers only) Position */ +#define HSTDMACONTROL_END_TR_EN (_U_(0x1) << HSTDMACONTROL_END_TR_EN_Pos) /**< (HSTDMACONTROL) End of Transfer Enable Control (OUT transfers only) Mask */ +#define HSTDMACONTROL_END_B_EN_Pos 3 /**< (HSTDMACONTROL) End of Buffer Enable Control Position */ +#define HSTDMACONTROL_END_B_EN (_U_(0x1) << HSTDMACONTROL_END_B_EN_Pos) /**< (HSTDMACONTROL) End of Buffer Enable Control Mask */ +#define HSTDMACONTROL_END_TR_IT_Pos 4 /**< (HSTDMACONTROL) End of Transfer Interrupt Enable Position */ +#define HSTDMACONTROL_END_TR_IT (_U_(0x1) << HSTDMACONTROL_END_TR_IT_Pos) /**< (HSTDMACONTROL) End of Transfer Interrupt Enable Mask */ +#define HSTDMACONTROL_END_BUFFIT_Pos 5 /**< (HSTDMACONTROL) End of Buffer Interrupt Enable Position */ +#define HSTDMACONTROL_END_BUFFIT (_U_(0x1) << HSTDMACONTROL_END_BUFFIT_Pos) /**< (HSTDMACONTROL) End of Buffer Interrupt Enable Mask */ +#define HSTDMACONTROL_DESC_LD_IT_Pos 6 /**< (HSTDMACONTROL) Descriptor Loaded Interrupt Enable Position */ +#define HSTDMACONTROL_DESC_LD_IT (_U_(0x1) << HSTDMACONTROL_DESC_LD_IT_Pos) /**< (HSTDMACONTROL) Descriptor Loaded Interrupt Enable Mask */ +#define HSTDMACONTROL_BURST_LCK_Pos 7 /**< (HSTDMACONTROL) Burst Lock Enable Position */ +#define HSTDMACONTROL_BURST_LCK (_U_(0x1) << HSTDMACONTROL_BURST_LCK_Pos) /**< (HSTDMACONTROL) Burst Lock Enable Mask */ +#define HSTDMACONTROL_BUFF_LENGTH_Pos 16 /**< (HSTDMACONTROL) Buffer Byte Length (Write-only) Position */ +#define HSTDMACONTROL_BUFF_LENGTH (_U_(0xFFFF) << HSTDMACONTROL_BUFF_LENGTH_Pos) /**< (HSTDMACONTROL) Buffer Byte Length (Write-only) Mask */ +#define HSTDMACONTROL_Msk _U_(0xFFFF00FF) /**< (HSTDMACONTROL) Register Mask */ + + +/* -------- HSTDMASTATUS : (USBHS Offset: 0x0c) (R/W 32) Host DMA Channel Status Register -------- */ + +#define HSTDMASTATUS_OFFSET (0x0C) /**< (HSTDMASTATUS) Host DMA Channel Status Register Offset */ + +#define HSTDMASTATUS_CHANN_ENB_Pos 0 /**< (HSTDMASTATUS) Channel Enable Status Position */ +#define HSTDMASTATUS_CHANN_ENB (_U_(0x1) << HSTDMASTATUS_CHANN_ENB_Pos) /**< (HSTDMASTATUS) Channel Enable Status Mask */ +#define HSTDMASTATUS_CHANN_ACT_Pos 1 /**< (HSTDMASTATUS) Channel Active Status Position */ +#define HSTDMASTATUS_CHANN_ACT (_U_(0x1) << HSTDMASTATUS_CHANN_ACT_Pos) /**< (HSTDMASTATUS) Channel Active Status Mask */ +#define HSTDMASTATUS_END_TR_ST_Pos 4 /**< (HSTDMASTATUS) End of Channel Transfer Status Position */ +#define HSTDMASTATUS_END_TR_ST (_U_(0x1) << HSTDMASTATUS_END_TR_ST_Pos) /**< (HSTDMASTATUS) End of Channel Transfer Status Mask */ +#define HSTDMASTATUS_END_BF_ST_Pos 5 /**< (HSTDMASTATUS) End of Channel Buffer Status Position */ +#define HSTDMASTATUS_END_BF_ST (_U_(0x1) << HSTDMASTATUS_END_BF_ST_Pos) /**< (HSTDMASTATUS) End of Channel Buffer Status Mask */ +#define HSTDMASTATUS_DESC_LDST_Pos 6 /**< (HSTDMASTATUS) Descriptor Loaded Status Position */ +#define HSTDMASTATUS_DESC_LDST (_U_(0x1) << HSTDMASTATUS_DESC_LDST_Pos) /**< (HSTDMASTATUS) Descriptor Loaded Status Mask */ +#define HSTDMASTATUS_BUFF_COUNT_Pos 16 /**< (HSTDMASTATUS) Buffer Byte Count Position */ +#define HSTDMASTATUS_BUFF_COUNT (_U_(0xFFFF) << HSTDMASTATUS_BUFF_COUNT_Pos) /**< (HSTDMASTATUS) Buffer Byte Count Mask */ +#define HSTDMASTATUS_Msk _U_(0xFFFF0073) /**< (HSTDMASTATUS) Register Mask */ + + +/* -------- DEVCTRL : (USBHS Offset: 0x00) (R/W 32) Device General Control Register -------- */ + +#define DEVCTRL_OFFSET (0x00) /**< (DEVCTRL) Device General Control Register Offset */ + +#define DEVCTRL_UADD_Pos 0 /**< (DEVCTRL) USB Address Position */ +#define DEVCTRL_UADD (_U_(0x7F) << DEVCTRL_UADD_Pos) /**< (DEVCTRL) USB Address Mask */ +#define DEVCTRL_ADDEN_Pos 7 /**< (DEVCTRL) Address Enable Position */ +#define DEVCTRL_ADDEN (_U_(0x1) << DEVCTRL_ADDEN_Pos) /**< (DEVCTRL) Address Enable Mask */ +#define DEVCTRL_DETACH_Pos 8 /**< (DEVCTRL) Detach Position */ +#define DEVCTRL_DETACH (_U_(0x1) << DEVCTRL_DETACH_Pos) /**< (DEVCTRL) Detach Mask */ +#define DEVCTRL_RMWKUP_Pos 9 /**< (DEVCTRL) Remote Wake-Up Position */ +#define DEVCTRL_RMWKUP (_U_(0x1) << DEVCTRL_RMWKUP_Pos) /**< (DEVCTRL) Remote Wake-Up Mask */ +#define DEVCTRL_SPDCONF_Pos 10 /**< (DEVCTRL) Mode Configuration Position */ +#define DEVCTRL_SPDCONF (_U_(0x3) << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) Mode Configuration Mask */ +#define DEVCTRL_SPDCONF_NORMAL_Val _U_(0x0) /**< (DEVCTRL) The peripheral starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the host is high-speed-capable. */ +#define DEVCTRL_SPDCONF_LOW_POWER_Val _U_(0x1) /**< (DEVCTRL) For a better consumption, if high speed is not needed. */ +#define DEVCTRL_SPDCONF_HIGH_SPEED_Val _U_(0x2) /**< (DEVCTRL) Forced high speed. */ +#define DEVCTRL_SPDCONF_FORCED_FS_Val _U_(0x3) /**< (DEVCTRL) The peripheral remains in Full-speed mode whatever the host speed capability. */ +#define DEVCTRL_SPDCONF_NORMAL (DEVCTRL_SPDCONF_NORMAL_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) The peripheral starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the host is high-speed-capable. Position */ +#define DEVCTRL_SPDCONF_LOW_POWER (DEVCTRL_SPDCONF_LOW_POWER_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) For a better consumption, if high speed is not needed. Position */ +#define DEVCTRL_SPDCONF_HIGH_SPEED (DEVCTRL_SPDCONF_HIGH_SPEED_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) Forced high speed. Position */ +#define DEVCTRL_SPDCONF_FORCED_FS (DEVCTRL_SPDCONF_FORCED_FS_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) The peripheral remains in Full-speed mode whatever the host speed capability. Position */ +#define DEVCTRL_LS_Pos 12 /**< (DEVCTRL) Low-Speed Mode Force Position */ +#define DEVCTRL_LS (_U_(0x1) << DEVCTRL_LS_Pos) /**< (DEVCTRL) Low-Speed Mode Force Mask */ +#define DEVCTRL_TSTJ_Pos 13 /**< (DEVCTRL) Test mode J Position */ +#define DEVCTRL_TSTJ (_U_(0x1) << DEVCTRL_TSTJ_Pos) /**< (DEVCTRL) Test mode J Mask */ +#define DEVCTRL_TSTK_Pos 14 /**< (DEVCTRL) Test mode K Position */ +#define DEVCTRL_TSTK (_U_(0x1) << DEVCTRL_TSTK_Pos) /**< (DEVCTRL) Test mode K Mask */ +#define DEVCTRL_TSTPCKT_Pos 15 /**< (DEVCTRL) Test packet mode Position */ +#define DEVCTRL_TSTPCKT (_U_(0x1) << DEVCTRL_TSTPCKT_Pos) /**< (DEVCTRL) Test packet mode Mask */ +#define DEVCTRL_OPMODE2_Pos 16 /**< (DEVCTRL) Specific Operational mode Position */ +#define DEVCTRL_OPMODE2 (_U_(0x1) << DEVCTRL_OPMODE2_Pos) /**< (DEVCTRL) Specific Operational mode Mask */ +#define DEVCTRL_Msk _U_(0x1FFFF) /**< (DEVCTRL) Register Mask */ + +#define DEVCTRL_OPMODE_Pos 16 /**< (DEVCTRL Position) Specific Operational mode */ +#define DEVCTRL_OPMODE (_U_(0x1) << DEVCTRL_OPMODE_Pos) /**< (DEVCTRL Mask) OPMODE */ + +/* -------- DEVISR : (USBHS Offset: 0x04) (R/ 32) Device Global Interrupt Status Register -------- */ + +#define DEVISR_OFFSET (0x04) /**< (DEVISR) Device Global Interrupt Status Register Offset */ + +#define DEVISR_SUSP_Pos 0 /**< (DEVISR) Suspend Interrupt Position */ +#define DEVISR_SUSP (_U_(0x1) << DEVISR_SUSP_Pos) /**< (DEVISR) Suspend Interrupt Mask */ +#define DEVISR_MSOF_Pos 1 /**< (DEVISR) Micro Start of Frame Interrupt Position */ +#define DEVISR_MSOF (_U_(0x1) << DEVISR_MSOF_Pos) /**< (DEVISR) Micro Start of Frame Interrupt Mask */ +#define DEVISR_SOF_Pos 2 /**< (DEVISR) Start of Frame Interrupt Position */ +#define DEVISR_SOF (_U_(0x1) << DEVISR_SOF_Pos) /**< (DEVISR) Start of Frame Interrupt Mask */ +#define DEVISR_EORST_Pos 3 /**< (DEVISR) End of Reset Interrupt Position */ +#define DEVISR_EORST (_U_(0x1) << DEVISR_EORST_Pos) /**< (DEVISR) End of Reset Interrupt Mask */ +#define DEVISR_WAKEUP_Pos 4 /**< (DEVISR) Wake-Up Interrupt Position */ +#define DEVISR_WAKEUP (_U_(0x1) << DEVISR_WAKEUP_Pos) /**< (DEVISR) Wake-Up Interrupt Mask */ +#define DEVISR_EORSM_Pos 5 /**< (DEVISR) End of Resume Interrupt Position */ +#define DEVISR_EORSM (_U_(0x1) << DEVISR_EORSM_Pos) /**< (DEVISR) End of Resume Interrupt Mask */ +#define DEVISR_UPRSM_Pos 6 /**< (DEVISR) Upstream Resume Interrupt Position */ +#define DEVISR_UPRSM (_U_(0x1) << DEVISR_UPRSM_Pos) /**< (DEVISR) Upstream Resume Interrupt Mask */ +#define DEVISR_PEP_0_Pos 12 /**< (DEVISR) Endpoint 0 Interrupt Position */ +#define DEVISR_PEP_0 (_U_(0x1) << DEVISR_PEP_0_Pos) /**< (DEVISR) Endpoint 0 Interrupt Mask */ +#define DEVISR_PEP_1_Pos 13 /**< (DEVISR) Endpoint 1 Interrupt Position */ +#define DEVISR_PEP_1 (_U_(0x1) << DEVISR_PEP_1_Pos) /**< (DEVISR) Endpoint 1 Interrupt Mask */ +#define DEVISR_PEP_2_Pos 14 /**< (DEVISR) Endpoint 2 Interrupt Position */ +#define DEVISR_PEP_2 (_U_(0x1) << DEVISR_PEP_2_Pos) /**< (DEVISR) Endpoint 2 Interrupt Mask */ +#define DEVISR_PEP_3_Pos 15 /**< (DEVISR) Endpoint 3 Interrupt Position */ +#define DEVISR_PEP_3 (_U_(0x1) << DEVISR_PEP_3_Pos) /**< (DEVISR) Endpoint 3 Interrupt Mask */ +#define DEVISR_PEP_4_Pos 16 /**< (DEVISR) Endpoint 4 Interrupt Position */ +#define DEVISR_PEP_4 (_U_(0x1) << DEVISR_PEP_4_Pos) /**< (DEVISR) Endpoint 4 Interrupt Mask */ +#define DEVISR_PEP_5_Pos 17 /**< (DEVISR) Endpoint 5 Interrupt Position */ +#define DEVISR_PEP_5 (_U_(0x1) << DEVISR_PEP_5_Pos) /**< (DEVISR) Endpoint 5 Interrupt Mask */ +#define DEVISR_PEP_6_Pos 18 /**< (DEVISR) Endpoint 6 Interrupt Position */ +#define DEVISR_PEP_6 (_U_(0x1) << DEVISR_PEP_6_Pos) /**< (DEVISR) Endpoint 6 Interrupt Mask */ +#define DEVISR_PEP_7_Pos 19 /**< (DEVISR) Endpoint 7 Interrupt Position */ +#define DEVISR_PEP_7 (_U_(0x1) << DEVISR_PEP_7_Pos) /**< (DEVISR) Endpoint 7 Interrupt Mask */ +#define DEVISR_PEP_8_Pos 20 /**< (DEVISR) Endpoint 8 Interrupt Position */ +#define DEVISR_PEP_8 (_U_(0x1) << DEVISR_PEP_8_Pos) /**< (DEVISR) Endpoint 8 Interrupt Mask */ +#define DEVISR_PEP_9_Pos 21 /**< (DEVISR) Endpoint 9 Interrupt Position */ +#define DEVISR_PEP_9 (_U_(0x1) << DEVISR_PEP_9_Pos) /**< (DEVISR) Endpoint 9 Interrupt Mask */ +#define DEVISR_DMA_1_Pos 25 /**< (DEVISR) DMA Channel 1 Interrupt Position */ +#define DEVISR_DMA_1 (_U_(0x1) << DEVISR_DMA_1_Pos) /**< (DEVISR) DMA Channel 1 Interrupt Mask */ +#define DEVISR_DMA_2_Pos 26 /**< (DEVISR) DMA Channel 2 Interrupt Position */ +#define DEVISR_DMA_2 (_U_(0x1) << DEVISR_DMA_2_Pos) /**< (DEVISR) DMA Channel 2 Interrupt Mask */ +#define DEVISR_DMA_3_Pos 27 /**< (DEVISR) DMA Channel 3 Interrupt Position */ +#define DEVISR_DMA_3 (_U_(0x1) << DEVISR_DMA_3_Pos) /**< (DEVISR) DMA Channel 3 Interrupt Mask */ +#define DEVISR_DMA_4_Pos 28 /**< (DEVISR) DMA Channel 4 Interrupt Position */ +#define DEVISR_DMA_4 (_U_(0x1) << DEVISR_DMA_4_Pos) /**< (DEVISR) DMA Channel 4 Interrupt Mask */ +#define DEVISR_DMA_5_Pos 29 /**< (DEVISR) DMA Channel 5 Interrupt Position */ +#define DEVISR_DMA_5 (_U_(0x1) << DEVISR_DMA_5_Pos) /**< (DEVISR) DMA Channel 5 Interrupt Mask */ +#define DEVISR_DMA_6_Pos 30 /**< (DEVISR) DMA Channel 6 Interrupt Position */ +#define DEVISR_DMA_6 (_U_(0x1) << DEVISR_DMA_6_Pos) /**< (DEVISR) DMA Channel 6 Interrupt Mask */ +#define DEVISR_DMA_7_Pos 31 /**< (DEVISR) DMA Channel 7 Interrupt Position */ +#define DEVISR_DMA_7 (_U_(0x1) << DEVISR_DMA_7_Pos) /**< (DEVISR) DMA Channel 7 Interrupt Mask */ +#define DEVISR_Msk _U_(0xFE3FF07F) /**< (DEVISR) Register Mask */ + +#define DEVISR_PEP__Pos 12 /**< (DEVISR Position) Endpoint x Interrupt */ +#define DEVISR_PEP_ (_U_(0x3FF) << DEVISR_PEP__Pos) /**< (DEVISR Mask) PEP_ */ +#define DEVISR_DMA__Pos 25 /**< (DEVISR Position) DMA Channel 7 Interrupt */ +#define DEVISR_DMA_ (_U_(0x7F) << DEVISR_DMA__Pos) /**< (DEVISR Mask) DMA_ */ + +/* -------- DEVICR : (USBHS Offset: 0x08) (/W 32) Device Global Interrupt Clear Register -------- */ + +#define DEVICR_OFFSET (0x08) /**< (DEVICR) Device Global Interrupt Clear Register Offset */ + +#define DEVICR_SUSPC_Pos 0 /**< (DEVICR) Suspend Interrupt Clear Position */ +#define DEVICR_SUSPC (_U_(0x1) << DEVICR_SUSPC_Pos) /**< (DEVICR) Suspend Interrupt Clear Mask */ +#define DEVICR_MSOFC_Pos 1 /**< (DEVICR) Micro Start of Frame Interrupt Clear Position */ +#define DEVICR_MSOFC (_U_(0x1) << DEVICR_MSOFC_Pos) /**< (DEVICR) Micro Start of Frame Interrupt Clear Mask */ +#define DEVICR_SOFC_Pos 2 /**< (DEVICR) Start of Frame Interrupt Clear Position */ +#define DEVICR_SOFC (_U_(0x1) << DEVICR_SOFC_Pos) /**< (DEVICR) Start of Frame Interrupt Clear Mask */ +#define DEVICR_EORSTC_Pos 3 /**< (DEVICR) End of Reset Interrupt Clear Position */ +#define DEVICR_EORSTC (_U_(0x1) << DEVICR_EORSTC_Pos) /**< (DEVICR) End of Reset Interrupt Clear Mask */ +#define DEVICR_WAKEUPC_Pos 4 /**< (DEVICR) Wake-Up Interrupt Clear Position */ +#define DEVICR_WAKEUPC (_U_(0x1) << DEVICR_WAKEUPC_Pos) /**< (DEVICR) Wake-Up Interrupt Clear Mask */ +#define DEVICR_EORSMC_Pos 5 /**< (DEVICR) End of Resume Interrupt Clear Position */ +#define DEVICR_EORSMC (_U_(0x1) << DEVICR_EORSMC_Pos) /**< (DEVICR) End of Resume Interrupt Clear Mask */ +#define DEVICR_UPRSMC_Pos 6 /**< (DEVICR) Upstream Resume Interrupt Clear Position */ +#define DEVICR_UPRSMC (_U_(0x1) << DEVICR_UPRSMC_Pos) /**< (DEVICR) Upstream Resume Interrupt Clear Mask */ +#define DEVICR_Msk _U_(0x7F) /**< (DEVICR) Register Mask */ + + +/* -------- DEVIFR : (USBHS Offset: 0x0c) (/W 32) Device Global Interrupt Set Register -------- */ + +#define DEVIFR_OFFSET (0x0C) /**< (DEVIFR) Device Global Interrupt Set Register Offset */ + +#define DEVIFR_SUSPS_Pos 0 /**< (DEVIFR) Suspend Interrupt Set Position */ +#define DEVIFR_SUSPS (_U_(0x1) << DEVIFR_SUSPS_Pos) /**< (DEVIFR) Suspend Interrupt Set Mask */ +#define DEVIFR_MSOFS_Pos 1 /**< (DEVIFR) Micro Start of Frame Interrupt Set Position */ +#define DEVIFR_MSOFS (_U_(0x1) << DEVIFR_MSOFS_Pos) /**< (DEVIFR) Micro Start of Frame Interrupt Set Mask */ +#define DEVIFR_SOFS_Pos 2 /**< (DEVIFR) Start of Frame Interrupt Set Position */ +#define DEVIFR_SOFS (_U_(0x1) << DEVIFR_SOFS_Pos) /**< (DEVIFR) Start of Frame Interrupt Set Mask */ +#define DEVIFR_EORSTS_Pos 3 /**< (DEVIFR) End of Reset Interrupt Set Position */ +#define DEVIFR_EORSTS (_U_(0x1) << DEVIFR_EORSTS_Pos) /**< (DEVIFR) End of Reset Interrupt Set Mask */ +#define DEVIFR_WAKEUPS_Pos 4 /**< (DEVIFR) Wake-Up Interrupt Set Position */ +#define DEVIFR_WAKEUPS (_U_(0x1) << DEVIFR_WAKEUPS_Pos) /**< (DEVIFR) Wake-Up Interrupt Set Mask */ +#define DEVIFR_EORSMS_Pos 5 /**< (DEVIFR) End of Resume Interrupt Set Position */ +#define DEVIFR_EORSMS (_U_(0x1) << DEVIFR_EORSMS_Pos) /**< (DEVIFR) End of Resume Interrupt Set Mask */ +#define DEVIFR_UPRSMS_Pos 6 /**< (DEVIFR) Upstream Resume Interrupt Set Position */ +#define DEVIFR_UPRSMS (_U_(0x1) << DEVIFR_UPRSMS_Pos) /**< (DEVIFR) Upstream Resume Interrupt Set Mask */ +#define DEVIFR_DMA_1_Pos 25 /**< (DEVIFR) DMA Channel 1 Interrupt Set Position */ +#define DEVIFR_DMA_1 (_U_(0x1) << DEVIFR_DMA_1_Pos) /**< (DEVIFR) DMA Channel 1 Interrupt Set Mask */ +#define DEVIFR_DMA_2_Pos 26 /**< (DEVIFR) DMA Channel 2 Interrupt Set Position */ +#define DEVIFR_DMA_2 (_U_(0x1) << DEVIFR_DMA_2_Pos) /**< (DEVIFR) DMA Channel 2 Interrupt Set Mask */ +#define DEVIFR_DMA_3_Pos 27 /**< (DEVIFR) DMA Channel 3 Interrupt Set Position */ +#define DEVIFR_DMA_3 (_U_(0x1) << DEVIFR_DMA_3_Pos) /**< (DEVIFR) DMA Channel 3 Interrupt Set Mask */ +#define DEVIFR_DMA_4_Pos 28 /**< (DEVIFR) DMA Channel 4 Interrupt Set Position */ +#define DEVIFR_DMA_4 (_U_(0x1) << DEVIFR_DMA_4_Pos) /**< (DEVIFR) DMA Channel 4 Interrupt Set Mask */ +#define DEVIFR_DMA_5_Pos 29 /**< (DEVIFR) DMA Channel 5 Interrupt Set Position */ +#define DEVIFR_DMA_5 (_U_(0x1) << DEVIFR_DMA_5_Pos) /**< (DEVIFR) DMA Channel 5 Interrupt Set Mask */ +#define DEVIFR_DMA_6_Pos 30 /**< (DEVIFR) DMA Channel 6 Interrupt Set Position */ +#define DEVIFR_DMA_6 (_U_(0x1) << DEVIFR_DMA_6_Pos) /**< (DEVIFR) DMA Channel 6 Interrupt Set Mask */ +#define DEVIFR_DMA_7_Pos 31 /**< (DEVIFR) DMA Channel 7 Interrupt Set Position */ +#define DEVIFR_DMA_7 (_U_(0x1) << DEVIFR_DMA_7_Pos) /**< (DEVIFR) DMA Channel 7 Interrupt Set Mask */ +#define DEVIFR_Msk _U_(0xFE00007F) /**< (DEVIFR) Register Mask */ + +#define DEVIFR_DMA__Pos 25 /**< (DEVIFR Position) DMA Channel 7 Interrupt Set */ +#define DEVIFR_DMA_ (_U_(0x7F) << DEVIFR_DMA__Pos) /**< (DEVIFR Mask) DMA_ */ + +/* -------- DEVIMR : (USBHS Offset: 0x10) (R/ 32) Device Global Interrupt Mask Register -------- */ + +#define DEVIMR_OFFSET (0x10) /**< (DEVIMR) Device Global Interrupt Mask Register Offset */ + +#define DEVIMR_SUSPE_Pos 0 /**< (DEVIMR) Suspend Interrupt Mask Position */ +#define DEVIMR_SUSPE (_U_(0x1) << DEVIMR_SUSPE_Pos) /**< (DEVIMR) Suspend Interrupt Mask Mask */ +#define DEVIMR_MSOFE_Pos 1 /**< (DEVIMR) Micro Start of Frame Interrupt Mask Position */ +#define DEVIMR_MSOFE (_U_(0x1) << DEVIMR_MSOFE_Pos) /**< (DEVIMR) Micro Start of Frame Interrupt Mask Mask */ +#define DEVIMR_SOFE_Pos 2 /**< (DEVIMR) Start of Frame Interrupt Mask Position */ +#define DEVIMR_SOFE (_U_(0x1) << DEVIMR_SOFE_Pos) /**< (DEVIMR) Start of Frame Interrupt Mask Mask */ +#define DEVIMR_EORSTE_Pos 3 /**< (DEVIMR) End of Reset Interrupt Mask Position */ +#define DEVIMR_EORSTE (_U_(0x1) << DEVIMR_EORSTE_Pos) /**< (DEVIMR) End of Reset Interrupt Mask Mask */ +#define DEVIMR_WAKEUPE_Pos 4 /**< (DEVIMR) Wake-Up Interrupt Mask Position */ +#define DEVIMR_WAKEUPE (_U_(0x1) << DEVIMR_WAKEUPE_Pos) /**< (DEVIMR) Wake-Up Interrupt Mask Mask */ +#define DEVIMR_EORSME_Pos 5 /**< (DEVIMR) End of Resume Interrupt Mask Position */ +#define DEVIMR_EORSME (_U_(0x1) << DEVIMR_EORSME_Pos) /**< (DEVIMR) End of Resume Interrupt Mask Mask */ +#define DEVIMR_UPRSME_Pos 6 /**< (DEVIMR) Upstream Resume Interrupt Mask Position */ +#define DEVIMR_UPRSME (_U_(0x1) << DEVIMR_UPRSME_Pos) /**< (DEVIMR) Upstream Resume Interrupt Mask Mask */ +#define DEVIMR_PEP_0_Pos 12 /**< (DEVIMR) Endpoint 0 Interrupt Mask Position */ +#define DEVIMR_PEP_0 (_U_(0x1) << DEVIMR_PEP_0_Pos) /**< (DEVIMR) Endpoint 0 Interrupt Mask Mask */ +#define DEVIMR_PEP_1_Pos 13 /**< (DEVIMR) Endpoint 1 Interrupt Mask Position */ +#define DEVIMR_PEP_1 (_U_(0x1) << DEVIMR_PEP_1_Pos) /**< (DEVIMR) Endpoint 1 Interrupt Mask Mask */ +#define DEVIMR_PEP_2_Pos 14 /**< (DEVIMR) Endpoint 2 Interrupt Mask Position */ +#define DEVIMR_PEP_2 (_U_(0x1) << DEVIMR_PEP_2_Pos) /**< (DEVIMR) Endpoint 2 Interrupt Mask Mask */ +#define DEVIMR_PEP_3_Pos 15 /**< (DEVIMR) Endpoint 3 Interrupt Mask Position */ +#define DEVIMR_PEP_3 (_U_(0x1) << DEVIMR_PEP_3_Pos) /**< (DEVIMR) Endpoint 3 Interrupt Mask Mask */ +#define DEVIMR_PEP_4_Pos 16 /**< (DEVIMR) Endpoint 4 Interrupt Mask Position */ +#define DEVIMR_PEP_4 (_U_(0x1) << DEVIMR_PEP_4_Pos) /**< (DEVIMR) Endpoint 4 Interrupt Mask Mask */ +#define DEVIMR_PEP_5_Pos 17 /**< (DEVIMR) Endpoint 5 Interrupt Mask Position */ +#define DEVIMR_PEP_5 (_U_(0x1) << DEVIMR_PEP_5_Pos) /**< (DEVIMR) Endpoint 5 Interrupt Mask Mask */ +#define DEVIMR_PEP_6_Pos 18 /**< (DEVIMR) Endpoint 6 Interrupt Mask Position */ +#define DEVIMR_PEP_6 (_U_(0x1) << DEVIMR_PEP_6_Pos) /**< (DEVIMR) Endpoint 6 Interrupt Mask Mask */ +#define DEVIMR_PEP_7_Pos 19 /**< (DEVIMR) Endpoint 7 Interrupt Mask Position */ +#define DEVIMR_PEP_7 (_U_(0x1) << DEVIMR_PEP_7_Pos) /**< (DEVIMR) Endpoint 7 Interrupt Mask Mask */ +#define DEVIMR_PEP_8_Pos 20 /**< (DEVIMR) Endpoint 8 Interrupt Mask Position */ +#define DEVIMR_PEP_8 (_U_(0x1) << DEVIMR_PEP_8_Pos) /**< (DEVIMR) Endpoint 8 Interrupt Mask Mask */ +#define DEVIMR_PEP_9_Pos 21 /**< (DEVIMR) Endpoint 9 Interrupt Mask Position */ +#define DEVIMR_PEP_9 (_U_(0x1) << DEVIMR_PEP_9_Pos) /**< (DEVIMR) Endpoint 9 Interrupt Mask Mask */ +#define DEVIMR_DMA_1_Pos 25 /**< (DEVIMR) DMA Channel 1 Interrupt Mask Position */ +#define DEVIMR_DMA_1 (_U_(0x1) << DEVIMR_DMA_1_Pos) /**< (DEVIMR) DMA Channel 1 Interrupt Mask Mask */ +#define DEVIMR_DMA_2_Pos 26 /**< (DEVIMR) DMA Channel 2 Interrupt Mask Position */ +#define DEVIMR_DMA_2 (_U_(0x1) << DEVIMR_DMA_2_Pos) /**< (DEVIMR) DMA Channel 2 Interrupt Mask Mask */ +#define DEVIMR_DMA_3_Pos 27 /**< (DEVIMR) DMA Channel 3 Interrupt Mask Position */ +#define DEVIMR_DMA_3 (_U_(0x1) << DEVIMR_DMA_3_Pos) /**< (DEVIMR) DMA Channel 3 Interrupt Mask Mask */ +#define DEVIMR_DMA_4_Pos 28 /**< (DEVIMR) DMA Channel 4 Interrupt Mask Position */ +#define DEVIMR_DMA_4 (_U_(0x1) << DEVIMR_DMA_4_Pos) /**< (DEVIMR) DMA Channel 4 Interrupt Mask Mask */ +#define DEVIMR_DMA_5_Pos 29 /**< (DEVIMR) DMA Channel 5 Interrupt Mask Position */ +#define DEVIMR_DMA_5 (_U_(0x1) << DEVIMR_DMA_5_Pos) /**< (DEVIMR) DMA Channel 5 Interrupt Mask Mask */ +#define DEVIMR_DMA_6_Pos 30 /**< (DEVIMR) DMA Channel 6 Interrupt Mask Position */ +#define DEVIMR_DMA_6 (_U_(0x1) << DEVIMR_DMA_6_Pos) /**< (DEVIMR) DMA Channel 6 Interrupt Mask Mask */ +#define DEVIMR_DMA_7_Pos 31 /**< (DEVIMR) DMA Channel 7 Interrupt Mask Position */ +#define DEVIMR_DMA_7 (_U_(0x1) << DEVIMR_DMA_7_Pos) /**< (DEVIMR) DMA Channel 7 Interrupt Mask Mask */ +#define DEVIMR_Msk _U_(0xFE3FF07F) /**< (DEVIMR) Register Mask */ + +#define DEVIMR_PEP__Pos 12 /**< (DEVIMR Position) Endpoint x Interrupt Mask */ +#define DEVIMR_PEP_ (_U_(0x3FF) << DEVIMR_PEP__Pos) /**< (DEVIMR Mask) PEP_ */ +#define DEVIMR_DMA__Pos 25 /**< (DEVIMR Position) DMA Channel 7 Interrupt Mask */ +#define DEVIMR_DMA_ (_U_(0x7F) << DEVIMR_DMA__Pos) /**< (DEVIMR Mask) DMA_ */ + +/* -------- DEVIDR : (USBHS Offset: 0x14) (/W 32) Device Global Interrupt Disable Register -------- */ + +#define DEVIDR_OFFSET (0x14) /**< (DEVIDR) Device Global Interrupt Disable Register Offset */ + +#define DEVIDR_SUSPEC_Pos 0 /**< (DEVIDR) Suspend Interrupt Disable Position */ +#define DEVIDR_SUSPEC (_U_(0x1) << DEVIDR_SUSPEC_Pos) /**< (DEVIDR) Suspend Interrupt Disable Mask */ +#define DEVIDR_MSOFEC_Pos 1 /**< (DEVIDR) Micro Start of Frame Interrupt Disable Position */ +#define DEVIDR_MSOFEC (_U_(0x1) << DEVIDR_MSOFEC_Pos) /**< (DEVIDR) Micro Start of Frame Interrupt Disable Mask */ +#define DEVIDR_SOFEC_Pos 2 /**< (DEVIDR) Start of Frame Interrupt Disable Position */ +#define DEVIDR_SOFEC (_U_(0x1) << DEVIDR_SOFEC_Pos) /**< (DEVIDR) Start of Frame Interrupt Disable Mask */ +#define DEVIDR_EORSTEC_Pos 3 /**< (DEVIDR) End of Reset Interrupt Disable Position */ +#define DEVIDR_EORSTEC (_U_(0x1) << DEVIDR_EORSTEC_Pos) /**< (DEVIDR) End of Reset Interrupt Disable Mask */ +#define DEVIDR_WAKEUPEC_Pos 4 /**< (DEVIDR) Wake-Up Interrupt Disable Position */ +#define DEVIDR_WAKEUPEC (_U_(0x1) << DEVIDR_WAKEUPEC_Pos) /**< (DEVIDR) Wake-Up Interrupt Disable Mask */ +#define DEVIDR_EORSMEC_Pos 5 /**< (DEVIDR) End of Resume Interrupt Disable Position */ +#define DEVIDR_EORSMEC (_U_(0x1) << DEVIDR_EORSMEC_Pos) /**< (DEVIDR) End of Resume Interrupt Disable Mask */ +#define DEVIDR_UPRSMEC_Pos 6 /**< (DEVIDR) Upstream Resume Interrupt Disable Position */ +#define DEVIDR_UPRSMEC (_U_(0x1) << DEVIDR_UPRSMEC_Pos) /**< (DEVIDR) Upstream Resume Interrupt Disable Mask */ +#define DEVIDR_PEP_0_Pos 12 /**< (DEVIDR) Endpoint 0 Interrupt Disable Position */ +#define DEVIDR_PEP_0 (_U_(0x1) << DEVIDR_PEP_0_Pos) /**< (DEVIDR) Endpoint 0 Interrupt Disable Mask */ +#define DEVIDR_PEP_1_Pos 13 /**< (DEVIDR) Endpoint 1 Interrupt Disable Position */ +#define DEVIDR_PEP_1 (_U_(0x1) << DEVIDR_PEP_1_Pos) /**< (DEVIDR) Endpoint 1 Interrupt Disable Mask */ +#define DEVIDR_PEP_2_Pos 14 /**< (DEVIDR) Endpoint 2 Interrupt Disable Position */ +#define DEVIDR_PEP_2 (_U_(0x1) << DEVIDR_PEP_2_Pos) /**< (DEVIDR) Endpoint 2 Interrupt Disable Mask */ +#define DEVIDR_PEP_3_Pos 15 /**< (DEVIDR) Endpoint 3 Interrupt Disable Position */ +#define DEVIDR_PEP_3 (_U_(0x1) << DEVIDR_PEP_3_Pos) /**< (DEVIDR) Endpoint 3 Interrupt Disable Mask */ +#define DEVIDR_PEP_4_Pos 16 /**< (DEVIDR) Endpoint 4 Interrupt Disable Position */ +#define DEVIDR_PEP_4 (_U_(0x1) << DEVIDR_PEP_4_Pos) /**< (DEVIDR) Endpoint 4 Interrupt Disable Mask */ +#define DEVIDR_PEP_5_Pos 17 /**< (DEVIDR) Endpoint 5 Interrupt Disable Position */ +#define DEVIDR_PEP_5 (_U_(0x1) << DEVIDR_PEP_5_Pos) /**< (DEVIDR) Endpoint 5 Interrupt Disable Mask */ +#define DEVIDR_PEP_6_Pos 18 /**< (DEVIDR) Endpoint 6 Interrupt Disable Position */ +#define DEVIDR_PEP_6 (_U_(0x1) << DEVIDR_PEP_6_Pos) /**< (DEVIDR) Endpoint 6 Interrupt Disable Mask */ +#define DEVIDR_PEP_7_Pos 19 /**< (DEVIDR) Endpoint 7 Interrupt Disable Position */ +#define DEVIDR_PEP_7 (_U_(0x1) << DEVIDR_PEP_7_Pos) /**< (DEVIDR) Endpoint 7 Interrupt Disable Mask */ +#define DEVIDR_PEP_8_Pos 20 /**< (DEVIDR) Endpoint 8 Interrupt Disable Position */ +#define DEVIDR_PEP_8 (_U_(0x1) << DEVIDR_PEP_8_Pos) /**< (DEVIDR) Endpoint 8 Interrupt Disable Mask */ +#define DEVIDR_PEP_9_Pos 21 /**< (DEVIDR) Endpoint 9 Interrupt Disable Position */ +#define DEVIDR_PEP_9 (_U_(0x1) << DEVIDR_PEP_9_Pos) /**< (DEVIDR) Endpoint 9 Interrupt Disable Mask */ +#define DEVIDR_DMA_1_Pos 25 /**< (DEVIDR) DMA Channel 1 Interrupt Disable Position */ +#define DEVIDR_DMA_1 (_U_(0x1) << DEVIDR_DMA_1_Pos) /**< (DEVIDR) DMA Channel 1 Interrupt Disable Mask */ +#define DEVIDR_DMA_2_Pos 26 /**< (DEVIDR) DMA Channel 2 Interrupt Disable Position */ +#define DEVIDR_DMA_2 (_U_(0x1) << DEVIDR_DMA_2_Pos) /**< (DEVIDR) DMA Channel 2 Interrupt Disable Mask */ +#define DEVIDR_DMA_3_Pos 27 /**< (DEVIDR) DMA Channel 3 Interrupt Disable Position */ +#define DEVIDR_DMA_3 (_U_(0x1) << DEVIDR_DMA_3_Pos) /**< (DEVIDR) DMA Channel 3 Interrupt Disable Mask */ +#define DEVIDR_DMA_4_Pos 28 /**< (DEVIDR) DMA Channel 4 Interrupt Disable Position */ +#define DEVIDR_DMA_4 (_U_(0x1) << DEVIDR_DMA_4_Pos) /**< (DEVIDR) DMA Channel 4 Interrupt Disable Mask */ +#define DEVIDR_DMA_5_Pos 29 /**< (DEVIDR) DMA Channel 5 Interrupt Disable Position */ +#define DEVIDR_DMA_5 (_U_(0x1) << DEVIDR_DMA_5_Pos) /**< (DEVIDR) DMA Channel 5 Interrupt Disable Mask */ +#define DEVIDR_DMA_6_Pos 30 /**< (DEVIDR) DMA Channel 6 Interrupt Disable Position */ +#define DEVIDR_DMA_6 (_U_(0x1) << DEVIDR_DMA_6_Pos) /**< (DEVIDR) DMA Channel 6 Interrupt Disable Mask */ +#define DEVIDR_DMA_7_Pos 31 /**< (DEVIDR) DMA Channel 7 Interrupt Disable Position */ +#define DEVIDR_DMA_7 (_U_(0x1) << DEVIDR_DMA_7_Pos) /**< (DEVIDR) DMA Channel 7 Interrupt Disable Mask */ +#define DEVIDR_Msk _U_(0xFE3FF07F) /**< (DEVIDR) Register Mask */ + +#define DEVIDR_PEP__Pos 12 /**< (DEVIDR Position) Endpoint x Interrupt Disable */ +#define DEVIDR_PEP_ (_U_(0x3FF) << DEVIDR_PEP__Pos) /**< (DEVIDR Mask) PEP_ */ +#define DEVIDR_DMA__Pos 25 /**< (DEVIDR Position) DMA Channel 7 Interrupt Disable */ +#define DEVIDR_DMA_ (_U_(0x7F) << DEVIDR_DMA__Pos) /**< (DEVIDR Mask) DMA_ */ + +/* -------- DEVIER : (USBHS Offset: 0x18) (/W 32) Device Global Interrupt Enable Register -------- */ + +#define DEVIER_OFFSET (0x18) /**< (DEVIER) Device Global Interrupt Enable Register Offset */ + +#define DEVIER_SUSPES_Pos 0 /**< (DEVIER) Suspend Interrupt Enable Position */ +#define DEVIER_SUSPES (_U_(0x1) << DEVIER_SUSPES_Pos) /**< (DEVIER) Suspend Interrupt Enable Mask */ +#define DEVIER_MSOFES_Pos 1 /**< (DEVIER) Micro Start of Frame Interrupt Enable Position */ +#define DEVIER_MSOFES (_U_(0x1) << DEVIER_MSOFES_Pos) /**< (DEVIER) Micro Start of Frame Interrupt Enable Mask */ +#define DEVIER_SOFES_Pos 2 /**< (DEVIER) Start of Frame Interrupt Enable Position */ +#define DEVIER_SOFES (_U_(0x1) << DEVIER_SOFES_Pos) /**< (DEVIER) Start of Frame Interrupt Enable Mask */ +#define DEVIER_EORSTES_Pos 3 /**< (DEVIER) End of Reset Interrupt Enable Position */ +#define DEVIER_EORSTES (_U_(0x1) << DEVIER_EORSTES_Pos) /**< (DEVIER) End of Reset Interrupt Enable Mask */ +#define DEVIER_WAKEUPES_Pos 4 /**< (DEVIER) Wake-Up Interrupt Enable Position */ +#define DEVIER_WAKEUPES (_U_(0x1) << DEVIER_WAKEUPES_Pos) /**< (DEVIER) Wake-Up Interrupt Enable Mask */ +#define DEVIER_EORSMES_Pos 5 /**< (DEVIER) End of Resume Interrupt Enable Position */ +#define DEVIER_EORSMES (_U_(0x1) << DEVIER_EORSMES_Pos) /**< (DEVIER) End of Resume Interrupt Enable Mask */ +#define DEVIER_UPRSMES_Pos 6 /**< (DEVIER) Upstream Resume Interrupt Enable Position */ +#define DEVIER_UPRSMES (_U_(0x1) << DEVIER_UPRSMES_Pos) /**< (DEVIER) Upstream Resume Interrupt Enable Mask */ +#define DEVIER_PEP_0_Pos 12 /**< (DEVIER) Endpoint 0 Interrupt Enable Position */ +#define DEVIER_PEP_0 (_U_(0x1) << DEVIER_PEP_0_Pos) /**< (DEVIER) Endpoint 0 Interrupt Enable Mask */ +#define DEVIER_PEP_1_Pos 13 /**< (DEVIER) Endpoint 1 Interrupt Enable Position */ +#define DEVIER_PEP_1 (_U_(0x1) << DEVIER_PEP_1_Pos) /**< (DEVIER) Endpoint 1 Interrupt Enable Mask */ +#define DEVIER_PEP_2_Pos 14 /**< (DEVIER) Endpoint 2 Interrupt Enable Position */ +#define DEVIER_PEP_2 (_U_(0x1) << DEVIER_PEP_2_Pos) /**< (DEVIER) Endpoint 2 Interrupt Enable Mask */ +#define DEVIER_PEP_3_Pos 15 /**< (DEVIER) Endpoint 3 Interrupt Enable Position */ +#define DEVIER_PEP_3 (_U_(0x1) << DEVIER_PEP_3_Pos) /**< (DEVIER) Endpoint 3 Interrupt Enable Mask */ +#define DEVIER_PEP_4_Pos 16 /**< (DEVIER) Endpoint 4 Interrupt Enable Position */ +#define DEVIER_PEP_4 (_U_(0x1) << DEVIER_PEP_4_Pos) /**< (DEVIER) Endpoint 4 Interrupt Enable Mask */ +#define DEVIER_PEP_5_Pos 17 /**< (DEVIER) Endpoint 5 Interrupt Enable Position */ +#define DEVIER_PEP_5 (_U_(0x1) << DEVIER_PEP_5_Pos) /**< (DEVIER) Endpoint 5 Interrupt Enable Mask */ +#define DEVIER_PEP_6_Pos 18 /**< (DEVIER) Endpoint 6 Interrupt Enable Position */ +#define DEVIER_PEP_6 (_U_(0x1) << DEVIER_PEP_6_Pos) /**< (DEVIER) Endpoint 6 Interrupt Enable Mask */ +#define DEVIER_PEP_7_Pos 19 /**< (DEVIER) Endpoint 7 Interrupt Enable Position */ +#define DEVIER_PEP_7 (_U_(0x1) << DEVIER_PEP_7_Pos) /**< (DEVIER) Endpoint 7 Interrupt Enable Mask */ +#define DEVIER_PEP_8_Pos 20 /**< (DEVIER) Endpoint 8 Interrupt Enable Position */ +#define DEVIER_PEP_8 (_U_(0x1) << DEVIER_PEP_8_Pos) /**< (DEVIER) Endpoint 8 Interrupt Enable Mask */ +#define DEVIER_PEP_9_Pos 21 /**< (DEVIER) Endpoint 9 Interrupt Enable Position */ +#define DEVIER_PEP_9 (_U_(0x1) << DEVIER_PEP_9_Pos) /**< (DEVIER) Endpoint 9 Interrupt Enable Mask */ +#define DEVIER_DMA_1_Pos 25 /**< (DEVIER) DMA Channel 1 Interrupt Enable Position */ +#define DEVIER_DMA_1 (_U_(0x1) << DEVIER_DMA_1_Pos) /**< (DEVIER) DMA Channel 1 Interrupt Enable Mask */ +#define DEVIER_DMA_2_Pos 26 /**< (DEVIER) DMA Channel 2 Interrupt Enable Position */ +#define DEVIER_DMA_2 (_U_(0x1) << DEVIER_DMA_2_Pos) /**< (DEVIER) DMA Channel 2 Interrupt Enable Mask */ +#define DEVIER_DMA_3_Pos 27 /**< (DEVIER) DMA Channel 3 Interrupt Enable Position */ +#define DEVIER_DMA_3 (_U_(0x1) << DEVIER_DMA_3_Pos) /**< (DEVIER) DMA Channel 3 Interrupt Enable Mask */ +#define DEVIER_DMA_4_Pos 28 /**< (DEVIER) DMA Channel 4 Interrupt Enable Position */ +#define DEVIER_DMA_4 (_U_(0x1) << DEVIER_DMA_4_Pos) /**< (DEVIER) DMA Channel 4 Interrupt Enable Mask */ +#define DEVIER_DMA_5_Pos 29 /**< (DEVIER) DMA Channel 5 Interrupt Enable Position */ +#define DEVIER_DMA_5 (_U_(0x1) << DEVIER_DMA_5_Pos) /**< (DEVIER) DMA Channel 5 Interrupt Enable Mask */ +#define DEVIER_DMA_6_Pos 30 /**< (DEVIER) DMA Channel 6 Interrupt Enable Position */ +#define DEVIER_DMA_6 (_U_(0x1) << DEVIER_DMA_6_Pos) /**< (DEVIER) DMA Channel 6 Interrupt Enable Mask */ +#define DEVIER_DMA_7_Pos 31 /**< (DEVIER) DMA Channel 7 Interrupt Enable Position */ +#define DEVIER_DMA_7 (_U_(0x1) << DEVIER_DMA_7_Pos) /**< (DEVIER) DMA Channel 7 Interrupt Enable Mask */ +#define DEVIER_Msk _U_(0xFE3FF07F) /**< (DEVIER) Register Mask */ + +#define DEVIER_PEP__Pos 12 /**< (DEVIER Position) Endpoint x Interrupt Enable */ +#define DEVIER_PEP_ (_U_(0x3FF) << DEVIER_PEP__Pos) /**< (DEVIER Mask) PEP_ */ +#define DEVIER_DMA__Pos 25 /**< (DEVIER Position) DMA Channel 7 Interrupt Enable */ +#define DEVIER_DMA_ (_U_(0x7F) << DEVIER_DMA__Pos) /**< (DEVIER Mask) DMA_ */ + +/* -------- DEVEPT : (USBHS Offset: 0x1c) (R/W 32) Device Endpoint Register -------- */ + +#define DEVEPT_OFFSET (0x1C) /**< (DEVEPT) Device Endpoint Register Offset */ + +#define DEVEPT_EPEN0_Pos 0 /**< (DEVEPT) Endpoint 0 Enable Position */ +#define DEVEPT_EPEN0 (_U_(0x1) << DEVEPT_EPEN0_Pos) /**< (DEVEPT) Endpoint 0 Enable Mask */ +#define DEVEPT_EPEN1_Pos 1 /**< (DEVEPT) Endpoint 1 Enable Position */ +#define DEVEPT_EPEN1 (_U_(0x1) << DEVEPT_EPEN1_Pos) /**< (DEVEPT) Endpoint 1 Enable Mask */ +#define DEVEPT_EPEN2_Pos 2 /**< (DEVEPT) Endpoint 2 Enable Position */ +#define DEVEPT_EPEN2 (_U_(0x1) << DEVEPT_EPEN2_Pos) /**< (DEVEPT) Endpoint 2 Enable Mask */ +#define DEVEPT_EPEN3_Pos 3 /**< (DEVEPT) Endpoint 3 Enable Position */ +#define DEVEPT_EPEN3 (_U_(0x1) << DEVEPT_EPEN3_Pos) /**< (DEVEPT) Endpoint 3 Enable Mask */ +#define DEVEPT_EPEN4_Pos 4 /**< (DEVEPT) Endpoint 4 Enable Position */ +#define DEVEPT_EPEN4 (_U_(0x1) << DEVEPT_EPEN4_Pos) /**< (DEVEPT) Endpoint 4 Enable Mask */ +#define DEVEPT_EPEN5_Pos 5 /**< (DEVEPT) Endpoint 5 Enable Position */ +#define DEVEPT_EPEN5 (_U_(0x1) << DEVEPT_EPEN5_Pos) /**< (DEVEPT) Endpoint 5 Enable Mask */ +#define DEVEPT_EPEN6_Pos 6 /**< (DEVEPT) Endpoint 6 Enable Position */ +#define DEVEPT_EPEN6 (_U_(0x1) << DEVEPT_EPEN6_Pos) /**< (DEVEPT) Endpoint 6 Enable Mask */ +#define DEVEPT_EPEN7_Pos 7 /**< (DEVEPT) Endpoint 7 Enable Position */ +#define DEVEPT_EPEN7 (_U_(0x1) << DEVEPT_EPEN7_Pos) /**< (DEVEPT) Endpoint 7 Enable Mask */ +#define DEVEPT_EPEN8_Pos 8 /**< (DEVEPT) Endpoint 8 Enable Position */ +#define DEVEPT_EPEN8 (_U_(0x1) << DEVEPT_EPEN8_Pos) /**< (DEVEPT) Endpoint 8 Enable Mask */ +#define DEVEPT_EPEN9_Pos 9 /**< (DEVEPT) Endpoint 9 Enable Position */ +#define DEVEPT_EPEN9 (_U_(0x1) << DEVEPT_EPEN9_Pos) /**< (DEVEPT) Endpoint 9 Enable Mask */ +#define DEVEPT_EPRST0_Pos 16 /**< (DEVEPT) Endpoint 0 Reset Position */ +#define DEVEPT_EPRST0 (_U_(0x1) << DEVEPT_EPRST0_Pos) /**< (DEVEPT) Endpoint 0 Reset Mask */ +#define DEVEPT_EPRST1_Pos 17 /**< (DEVEPT) Endpoint 1 Reset Position */ +#define DEVEPT_EPRST1 (_U_(0x1) << DEVEPT_EPRST1_Pos) /**< (DEVEPT) Endpoint 1 Reset Mask */ +#define DEVEPT_EPRST2_Pos 18 /**< (DEVEPT) Endpoint 2 Reset Position */ +#define DEVEPT_EPRST2 (_U_(0x1) << DEVEPT_EPRST2_Pos) /**< (DEVEPT) Endpoint 2 Reset Mask */ +#define DEVEPT_EPRST3_Pos 19 /**< (DEVEPT) Endpoint 3 Reset Position */ +#define DEVEPT_EPRST3 (_U_(0x1) << DEVEPT_EPRST3_Pos) /**< (DEVEPT) Endpoint 3 Reset Mask */ +#define DEVEPT_EPRST4_Pos 20 /**< (DEVEPT) Endpoint 4 Reset Position */ +#define DEVEPT_EPRST4 (_U_(0x1) << DEVEPT_EPRST4_Pos) /**< (DEVEPT) Endpoint 4 Reset Mask */ +#define DEVEPT_EPRST5_Pos 21 /**< (DEVEPT) Endpoint 5 Reset Position */ +#define DEVEPT_EPRST5 (_U_(0x1) << DEVEPT_EPRST5_Pos) /**< (DEVEPT) Endpoint 5 Reset Mask */ +#define DEVEPT_EPRST6_Pos 22 /**< (DEVEPT) Endpoint 6 Reset Position */ +#define DEVEPT_EPRST6 (_U_(0x1) << DEVEPT_EPRST6_Pos) /**< (DEVEPT) Endpoint 6 Reset Mask */ +#define DEVEPT_EPRST7_Pos 23 /**< (DEVEPT) Endpoint 7 Reset Position */ +#define DEVEPT_EPRST7 (_U_(0x1) << DEVEPT_EPRST7_Pos) /**< (DEVEPT) Endpoint 7 Reset Mask */ +#define DEVEPT_EPRST8_Pos 24 /**< (DEVEPT) Endpoint 8 Reset Position */ +#define DEVEPT_EPRST8 (_U_(0x1) << DEVEPT_EPRST8_Pos) /**< (DEVEPT) Endpoint 8 Reset Mask */ +#define DEVEPT_EPRST9_Pos 25 /**< (DEVEPT) Endpoint 9 Reset Position */ +#define DEVEPT_EPRST9 (_U_(0x1) << DEVEPT_EPRST9_Pos) /**< (DEVEPT) Endpoint 9 Reset Mask */ +#define DEVEPT_Msk _U_(0x3FF03FF) /**< (DEVEPT) Register Mask */ + +#define DEVEPT_EPEN_Pos 0 /**< (DEVEPT Position) Endpoint x Enable */ +#define DEVEPT_EPEN (_U_(0x3FF) << DEVEPT_EPEN_Pos) /**< (DEVEPT Mask) EPEN */ +#define DEVEPT_EPRST_Pos 16 /**< (DEVEPT Position) Endpoint 9 Reset */ +#define DEVEPT_EPRST (_U_(0x3FF) << DEVEPT_EPRST_Pos) /**< (DEVEPT Mask) EPRST */ + +/* -------- DEVFNUM : (USBHS Offset: 0x20) (R/ 32) Device Frame Number Register -------- */ + +#define DEVFNUM_OFFSET (0x20) /**< (DEVFNUM) Device Frame Number Register Offset */ + +#define DEVFNUM_MFNUM_Pos 0 /**< (DEVFNUM) Micro Frame Number Position */ +#define DEVFNUM_MFNUM (_U_(0x7) << DEVFNUM_MFNUM_Pos) /**< (DEVFNUM) Micro Frame Number Mask */ +#define DEVFNUM_FNUM_Pos 3 /**< (DEVFNUM) Frame Number Position */ +#define DEVFNUM_FNUM (_U_(0x7FF) << DEVFNUM_FNUM_Pos) /**< (DEVFNUM) Frame Number Mask */ +#define DEVFNUM_FNCERR_Pos 15 /**< (DEVFNUM) Frame Number CRC Error Position */ +#define DEVFNUM_FNCERR (_U_(0x1) << DEVFNUM_FNCERR_Pos) /**< (DEVFNUM) Frame Number CRC Error Mask */ +#define DEVFNUM_Msk _U_(0xBFFF) /**< (DEVFNUM) Register Mask */ + + +/* -------- DEVEPTCFG : (USBHS Offset: 0x100) (R/W 32) Device Endpoint Configuration Register -------- */ + +#define DEVEPTCFG_OFFSET (0x100) /**< (DEVEPTCFG) Device Endpoint Configuration Register Offset */ + +#define DEVEPTCFG_ALLOC_Pos 1 /**< (DEVEPTCFG) Endpoint Memory Allocate Position */ +#define DEVEPTCFG_ALLOC (_U_(0x1) << DEVEPTCFG_ALLOC_Pos) /**< (DEVEPTCFG) Endpoint Memory Allocate Mask */ +#define DEVEPTCFG_EPBK_Pos 2 /**< (DEVEPTCFG) Endpoint Banks Position */ +#define DEVEPTCFG_EPBK (_U_(0x3) << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Endpoint Banks Mask */ +#define DEVEPTCFG_EPBK_1_BANK_Val _U_(0x0) /**< (DEVEPTCFG) Single-bank endpoint */ +#define DEVEPTCFG_EPBK_2_BANK_Val _U_(0x1) /**< (DEVEPTCFG) Double-bank endpoint */ +#define DEVEPTCFG_EPBK_3_BANK_Val _U_(0x2) /**< (DEVEPTCFG) Triple-bank endpoint */ +#define DEVEPTCFG_EPBK_1_BANK (DEVEPTCFG_EPBK_1_BANK_Val << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Single-bank endpoint Position */ +#define DEVEPTCFG_EPBK_2_BANK (DEVEPTCFG_EPBK_2_BANK_Val << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Double-bank endpoint Position */ +#define DEVEPTCFG_EPBK_3_BANK (DEVEPTCFG_EPBK_3_BANK_Val << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Triple-bank endpoint Position */ +#define DEVEPTCFG_EPSIZE_Pos 4 /**< (DEVEPTCFG) Endpoint Size Position */ +#define DEVEPTCFG_EPSIZE (_U_(0x7) << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) Endpoint Size Mask */ +#define DEVEPTCFG_EPSIZE_8_BYTE_Val _U_(0x0) /**< (DEVEPTCFG) 8 bytes */ +#define DEVEPTCFG_EPSIZE_16_BYTE_Val _U_(0x1) /**< (DEVEPTCFG) 16 bytes */ +#define DEVEPTCFG_EPSIZE_32_BYTE_Val _U_(0x2) /**< (DEVEPTCFG) 32 bytes */ +#define DEVEPTCFG_EPSIZE_64_BYTE_Val _U_(0x3) /**< (DEVEPTCFG) 64 bytes */ +#define DEVEPTCFG_EPSIZE_128_BYTE_Val _U_(0x4) /**< (DEVEPTCFG) 128 bytes */ +#define DEVEPTCFG_EPSIZE_256_BYTE_Val _U_(0x5) /**< (DEVEPTCFG) 256 bytes */ +#define DEVEPTCFG_EPSIZE_512_BYTE_Val _U_(0x6) /**< (DEVEPTCFG) 512 bytes */ +#define DEVEPTCFG_EPSIZE_1024_BYTE_Val _U_(0x7) /**< (DEVEPTCFG) 1024 bytes */ +#define DEVEPTCFG_EPSIZE_8_BYTE (DEVEPTCFG_EPSIZE_8_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 8 bytes Position */ +#define DEVEPTCFG_EPSIZE_16_BYTE (DEVEPTCFG_EPSIZE_16_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 16 bytes Position */ +#define DEVEPTCFG_EPSIZE_32_BYTE (DEVEPTCFG_EPSIZE_32_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 32 bytes Position */ +#define DEVEPTCFG_EPSIZE_64_BYTE (DEVEPTCFG_EPSIZE_64_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 64 bytes Position */ +#define DEVEPTCFG_EPSIZE_128_BYTE (DEVEPTCFG_EPSIZE_128_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 128 bytes Position */ +#define DEVEPTCFG_EPSIZE_256_BYTE (DEVEPTCFG_EPSIZE_256_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 256 bytes Position */ +#define DEVEPTCFG_EPSIZE_512_BYTE (DEVEPTCFG_EPSIZE_512_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 512 bytes Position */ +#define DEVEPTCFG_EPSIZE_1024_BYTE (DEVEPTCFG_EPSIZE_1024_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 1024 bytes Position */ +#define DEVEPTCFG_EPDIR_Pos 8 /**< (DEVEPTCFG) Endpoint Direction Position */ +#define DEVEPTCFG_EPDIR (_U_(0x1) << DEVEPTCFG_EPDIR_Pos) /**< (DEVEPTCFG) Endpoint Direction Mask */ +#define DEVEPTCFG_EPDIR_OUT_Val _U_(0x0) /**< (DEVEPTCFG) The endpoint direction is OUT. */ +#define DEVEPTCFG_EPDIR_IN_Val _U_(0x1) /**< (DEVEPTCFG) The endpoint direction is IN (nor for control endpoints). */ +#define DEVEPTCFG_EPDIR_OUT (DEVEPTCFG_EPDIR_OUT_Val << DEVEPTCFG_EPDIR_Pos) /**< (DEVEPTCFG) The endpoint direction is OUT. Position */ +#define DEVEPTCFG_EPDIR_IN (DEVEPTCFG_EPDIR_IN_Val << DEVEPTCFG_EPDIR_Pos) /**< (DEVEPTCFG) The endpoint direction is IN (nor for control endpoints). Position */ +#define DEVEPTCFG_AUTOSW_Pos 9 /**< (DEVEPTCFG) Automatic Switch Position */ +#define DEVEPTCFG_AUTOSW (_U_(0x1) << DEVEPTCFG_AUTOSW_Pos) /**< (DEVEPTCFG) Automatic Switch Mask */ +#define DEVEPTCFG_EPTYPE_Pos 11 /**< (DEVEPTCFG) Endpoint Type Position */ +#define DEVEPTCFG_EPTYPE (_U_(0x3) << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Endpoint Type Mask */ +#define DEVEPTCFG_EPTYPE_CTRL_Val _U_(0x0) /**< (DEVEPTCFG) Control */ +#define DEVEPTCFG_EPTYPE_ISO_Val _U_(0x1) /**< (DEVEPTCFG) Isochronous */ +#define DEVEPTCFG_EPTYPE_BLK_Val _U_(0x2) /**< (DEVEPTCFG) Bulk */ +#define DEVEPTCFG_EPTYPE_INTRPT_Val _U_(0x3) /**< (DEVEPTCFG) Interrupt */ +#define DEVEPTCFG_EPTYPE_CTRL (DEVEPTCFG_EPTYPE_CTRL_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Control Position */ +#define DEVEPTCFG_EPTYPE_ISO (DEVEPTCFG_EPTYPE_ISO_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Isochronous Position */ +#define DEVEPTCFG_EPTYPE_BLK (DEVEPTCFG_EPTYPE_BLK_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Bulk Position */ +#define DEVEPTCFG_EPTYPE_INTRPT (DEVEPTCFG_EPTYPE_INTRPT_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Interrupt Position */ +#define DEVEPTCFG_NBTRANS_Pos 13 /**< (DEVEPTCFG) Number of transactions per microframe for isochronous endpoint Position */ +#define DEVEPTCFG_NBTRANS (_U_(0x3) << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Number of transactions per microframe for isochronous endpoint Mask */ +#define DEVEPTCFG_NBTRANS_0_TRANS_Val _U_(0x0) /**< (DEVEPTCFG) Reserved to endpoint that does not have the high-bandwidth isochronous capability. */ +#define DEVEPTCFG_NBTRANS_1_TRANS_Val _U_(0x1) /**< (DEVEPTCFG) Default value: one transaction per microframe. */ +#define DEVEPTCFG_NBTRANS_2_TRANS_Val _U_(0x2) /**< (DEVEPTCFG) Two transactions per microframe. This endpoint should be configured as double-bank. */ +#define DEVEPTCFG_NBTRANS_3_TRANS_Val _U_(0x3) /**< (DEVEPTCFG) Three transactions per microframe. This endpoint should be configured as triple-bank. */ +#define DEVEPTCFG_NBTRANS_0_TRANS (DEVEPTCFG_NBTRANS_0_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Reserved to endpoint that does not have the high-bandwidth isochronous capability. Position */ +#define DEVEPTCFG_NBTRANS_1_TRANS (DEVEPTCFG_NBTRANS_1_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Default value: one transaction per microframe. Position */ +#define DEVEPTCFG_NBTRANS_2_TRANS (DEVEPTCFG_NBTRANS_2_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Two transactions per microframe. This endpoint should be configured as double-bank. Position */ +#define DEVEPTCFG_NBTRANS_3_TRANS (DEVEPTCFG_NBTRANS_3_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Three transactions per microframe. This endpoint should be configured as triple-bank. Position */ +#define DEVEPTCFG_Msk _U_(0x7B7E) /**< (DEVEPTCFG) Register Mask */ + + +/* -------- DEVEPTISR : (USBHS Offset: 0x130) (R/ 32) Device Endpoint Interrupt Status Register -------- */ + +#define DEVEPTISR_OFFSET (0x130) /**< (DEVEPTISR) Device Endpoint Interrupt Status Register Offset */ + +#define DEVEPTISR_TXINI_Pos 0 /**< (DEVEPTISR) Transmitted IN Data Interrupt Position */ +#define DEVEPTISR_TXINI (_U_(0x1) << DEVEPTISR_TXINI_Pos) /**< (DEVEPTISR) Transmitted IN Data Interrupt Mask */ +#define DEVEPTISR_RXOUTI_Pos 1 /**< (DEVEPTISR) Received OUT Data Interrupt Position */ +#define DEVEPTISR_RXOUTI (_U_(0x1) << DEVEPTISR_RXOUTI_Pos) /**< (DEVEPTISR) Received OUT Data Interrupt Mask */ +#define DEVEPTISR_OVERFI_Pos 5 /**< (DEVEPTISR) Overflow Interrupt Position */ +#define DEVEPTISR_OVERFI (_U_(0x1) << DEVEPTISR_OVERFI_Pos) /**< (DEVEPTISR) Overflow Interrupt Mask */ +#define DEVEPTISR_SHORTPACKET_Pos 7 /**< (DEVEPTISR) Short Packet Interrupt Position */ +#define DEVEPTISR_SHORTPACKET (_U_(0x1) << DEVEPTISR_SHORTPACKET_Pos) /**< (DEVEPTISR) Short Packet Interrupt Mask */ +#define DEVEPTISR_DTSEQ_Pos 8 /**< (DEVEPTISR) Data Toggle Sequence Position */ +#define DEVEPTISR_DTSEQ (_U_(0x3) << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Data Toggle Sequence Mask */ +#define DEVEPTISR_DTSEQ_DATA0_Val _U_(0x0) /**< (DEVEPTISR) Data0 toggle sequence */ +#define DEVEPTISR_DTSEQ_DATA1_Val _U_(0x1) /**< (DEVEPTISR) Data1 toggle sequence */ +#define DEVEPTISR_DTSEQ_DATA2_Val _U_(0x2) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint */ +#define DEVEPTISR_DTSEQ_MDATA_Val _U_(0x3) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint */ +#define DEVEPTISR_DTSEQ_DATA0 (DEVEPTISR_DTSEQ_DATA0_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Data0 toggle sequence Position */ +#define DEVEPTISR_DTSEQ_DATA1 (DEVEPTISR_DTSEQ_DATA1_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Data1 toggle sequence Position */ +#define DEVEPTISR_DTSEQ_DATA2 (DEVEPTISR_DTSEQ_DATA2_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint Position */ +#define DEVEPTISR_DTSEQ_MDATA (DEVEPTISR_DTSEQ_MDATA_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint Position */ +#define DEVEPTISR_NBUSYBK_Pos 12 /**< (DEVEPTISR) Number of Busy Banks Position */ +#define DEVEPTISR_NBUSYBK (_U_(0x3) << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) Number of Busy Banks Mask */ +#define DEVEPTISR_NBUSYBK_0_BUSY_Val _U_(0x0) /**< (DEVEPTISR) 0 busy bank (all banks free) */ +#define DEVEPTISR_NBUSYBK_1_BUSY_Val _U_(0x1) /**< (DEVEPTISR) 1 busy bank */ +#define DEVEPTISR_NBUSYBK_2_BUSY_Val _U_(0x2) /**< (DEVEPTISR) 2 busy banks */ +#define DEVEPTISR_NBUSYBK_3_BUSY_Val _U_(0x3) /**< (DEVEPTISR) 3 busy banks */ +#define DEVEPTISR_NBUSYBK_0_BUSY (DEVEPTISR_NBUSYBK_0_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 0 busy bank (all banks free) Position */ +#define DEVEPTISR_NBUSYBK_1_BUSY (DEVEPTISR_NBUSYBK_1_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 1 busy bank Position */ +#define DEVEPTISR_NBUSYBK_2_BUSY (DEVEPTISR_NBUSYBK_2_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 2 busy banks Position */ +#define DEVEPTISR_NBUSYBK_3_BUSY (DEVEPTISR_NBUSYBK_3_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 3 busy banks Position */ +#define DEVEPTISR_CURRBK_Pos 14 /**< (DEVEPTISR) Current Bank Position */ +#define DEVEPTISR_CURRBK (_U_(0x3) << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current Bank Mask */ +#define DEVEPTISR_CURRBK_BANK0_Val _U_(0x0) /**< (DEVEPTISR) Current bank is bank0 */ +#define DEVEPTISR_CURRBK_BANK1_Val _U_(0x1) /**< (DEVEPTISR) Current bank is bank1 */ +#define DEVEPTISR_CURRBK_BANK2_Val _U_(0x2) /**< (DEVEPTISR) Current bank is bank2 */ +#define DEVEPTISR_CURRBK_BANK0 (DEVEPTISR_CURRBK_BANK0_Val << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current bank is bank0 Position */ +#define DEVEPTISR_CURRBK_BANK1 (DEVEPTISR_CURRBK_BANK1_Val << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current bank is bank1 Position */ +#define DEVEPTISR_CURRBK_BANK2 (DEVEPTISR_CURRBK_BANK2_Val << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current bank is bank2 Position */ +#define DEVEPTISR_RWALL_Pos 16 /**< (DEVEPTISR) Read/Write Allowed Position */ +#define DEVEPTISR_RWALL (_U_(0x1) << DEVEPTISR_RWALL_Pos) /**< (DEVEPTISR) Read/Write Allowed Mask */ +#define DEVEPTISR_CFGOK_Pos 18 /**< (DEVEPTISR) Configuration OK Status Position */ +#define DEVEPTISR_CFGOK (_U_(0x1) << DEVEPTISR_CFGOK_Pos) /**< (DEVEPTISR) Configuration OK Status Mask */ +#define DEVEPTISR_BYCT_Pos 20 /**< (DEVEPTISR) Byte Count Position */ +#define DEVEPTISR_BYCT (_U_(0x7FF) << DEVEPTISR_BYCT_Pos) /**< (DEVEPTISR) Byte Count Mask */ +#define DEVEPTISR_Msk _U_(0x7FF5F3A3) /**< (DEVEPTISR) Register Mask */ + +/* CTRL mode */ +#define DEVEPTISR_CTRL_RXSTPI_Pos 2 /**< (DEVEPTISR) Received SETUP Interrupt Position */ +#define DEVEPTISR_CTRL_RXSTPI (_U_(0x1) << DEVEPTISR_CTRL_RXSTPI_Pos) /**< (DEVEPTISR) Received SETUP Interrupt Mask */ +#define DEVEPTISR_CTRL_NAKOUTI_Pos 3 /**< (DEVEPTISR) NAKed OUT Interrupt Position */ +#define DEVEPTISR_CTRL_NAKOUTI (_U_(0x1) << DEVEPTISR_CTRL_NAKOUTI_Pos) /**< (DEVEPTISR) NAKed OUT Interrupt Mask */ +#define DEVEPTISR_CTRL_NAKINI_Pos 4 /**< (DEVEPTISR) NAKed IN Interrupt Position */ +#define DEVEPTISR_CTRL_NAKINI (_U_(0x1) << DEVEPTISR_CTRL_NAKINI_Pos) /**< (DEVEPTISR) NAKed IN Interrupt Mask */ +#define DEVEPTISR_CTRL_STALLEDI_Pos 6 /**< (DEVEPTISR) STALLed Interrupt Position */ +#define DEVEPTISR_CTRL_STALLEDI (_U_(0x1) << DEVEPTISR_CTRL_STALLEDI_Pos) /**< (DEVEPTISR) STALLed Interrupt Mask */ +#define DEVEPTISR_CTRL_CTRLDIR_Pos 17 /**< (DEVEPTISR) Control Direction Position */ +#define DEVEPTISR_CTRL_CTRLDIR (_U_(0x1) << DEVEPTISR_CTRL_CTRLDIR_Pos) /**< (DEVEPTISR) Control Direction Mask */ +#define DEVEPTISR_CTRL_Msk _U_(0x2005C) /**< (DEVEPTISR_CTRL) Register Mask */ + +/* ISO mode */ +#define DEVEPTISR_ISO_UNDERFI_Pos 2 /**< (DEVEPTISR) Underflow Interrupt Position */ +#define DEVEPTISR_ISO_UNDERFI (_U_(0x1) << DEVEPTISR_ISO_UNDERFI_Pos) /**< (DEVEPTISR) Underflow Interrupt Mask */ +#define DEVEPTISR_ISO_HBISOINERRI_Pos 3 /**< (DEVEPTISR) High Bandwidth Isochronous IN Underflow Error Interrupt Position */ +#define DEVEPTISR_ISO_HBISOINERRI (_U_(0x1) << DEVEPTISR_ISO_HBISOINERRI_Pos) /**< (DEVEPTISR) High Bandwidth Isochronous IN Underflow Error Interrupt Mask */ +#define DEVEPTISR_ISO_HBISOFLUSHI_Pos 4 /**< (DEVEPTISR) High Bandwidth Isochronous IN Flush Interrupt Position */ +#define DEVEPTISR_ISO_HBISOFLUSHI (_U_(0x1) << DEVEPTISR_ISO_HBISOFLUSHI_Pos) /**< (DEVEPTISR) High Bandwidth Isochronous IN Flush Interrupt Mask */ +#define DEVEPTISR_ISO_CRCERRI_Pos 6 /**< (DEVEPTISR) CRC Error Interrupt Position */ +#define DEVEPTISR_ISO_CRCERRI (_U_(0x1) << DEVEPTISR_ISO_CRCERRI_Pos) /**< (DEVEPTISR) CRC Error Interrupt Mask */ +#define DEVEPTISR_ISO_ERRORTRANS_Pos 10 /**< (DEVEPTISR) High-bandwidth Isochronous OUT Endpoint Transaction Error Interrupt Position */ +#define DEVEPTISR_ISO_ERRORTRANS (_U_(0x1) << DEVEPTISR_ISO_ERRORTRANS_Pos) /**< (DEVEPTISR) High-bandwidth Isochronous OUT Endpoint Transaction Error Interrupt Mask */ +#define DEVEPTISR_ISO_Msk _U_(0x45C) /**< (DEVEPTISR_ISO) Register Mask */ + +/* BLK mode */ +#define DEVEPTISR_BLK_RXSTPI_Pos 2 /**< (DEVEPTISR) Received SETUP Interrupt Position */ +#define DEVEPTISR_BLK_RXSTPI (_U_(0x1) << DEVEPTISR_BLK_RXSTPI_Pos) /**< (DEVEPTISR) Received SETUP Interrupt Mask */ +#define DEVEPTISR_BLK_NAKOUTI_Pos 3 /**< (DEVEPTISR) NAKed OUT Interrupt Position */ +#define DEVEPTISR_BLK_NAKOUTI (_U_(0x1) << DEVEPTISR_BLK_NAKOUTI_Pos) /**< (DEVEPTISR) NAKed OUT Interrupt Mask */ +#define DEVEPTISR_BLK_NAKINI_Pos 4 /**< (DEVEPTISR) NAKed IN Interrupt Position */ +#define DEVEPTISR_BLK_NAKINI (_U_(0x1) << DEVEPTISR_BLK_NAKINI_Pos) /**< (DEVEPTISR) NAKed IN Interrupt Mask */ +#define DEVEPTISR_BLK_STALLEDI_Pos 6 /**< (DEVEPTISR) STALLed Interrupt Position */ +#define DEVEPTISR_BLK_STALLEDI (_U_(0x1) << DEVEPTISR_BLK_STALLEDI_Pos) /**< (DEVEPTISR) STALLed Interrupt Mask */ +#define DEVEPTISR_BLK_CTRLDIR_Pos 17 /**< (DEVEPTISR) Control Direction Position */ +#define DEVEPTISR_BLK_CTRLDIR (_U_(0x1) << DEVEPTISR_BLK_CTRLDIR_Pos) /**< (DEVEPTISR) Control Direction Mask */ +#define DEVEPTISR_BLK_Msk _U_(0x2005C) /**< (DEVEPTISR_BLK) Register Mask */ + +/* INTRPT mode */ +#define DEVEPTISR_INTRPT_RXSTPI_Pos 2 /**< (DEVEPTISR) Received SETUP Interrupt Position */ +#define DEVEPTISR_INTRPT_RXSTPI (_U_(0x1) << DEVEPTISR_INTRPT_RXSTPI_Pos) /**< (DEVEPTISR) Received SETUP Interrupt Mask */ +#define DEVEPTISR_INTRPT_NAKOUTI_Pos 3 /**< (DEVEPTISR) NAKed OUT Interrupt Position */ +#define DEVEPTISR_INTRPT_NAKOUTI (_U_(0x1) << DEVEPTISR_INTRPT_NAKOUTI_Pos) /**< (DEVEPTISR) NAKed OUT Interrupt Mask */ +#define DEVEPTISR_INTRPT_NAKINI_Pos 4 /**< (DEVEPTISR) NAKed IN Interrupt Position */ +#define DEVEPTISR_INTRPT_NAKINI (_U_(0x1) << DEVEPTISR_INTRPT_NAKINI_Pos) /**< (DEVEPTISR) NAKed IN Interrupt Mask */ +#define DEVEPTISR_INTRPT_STALLEDI_Pos 6 /**< (DEVEPTISR) STALLed Interrupt Position */ +#define DEVEPTISR_INTRPT_STALLEDI (_U_(0x1) << DEVEPTISR_INTRPT_STALLEDI_Pos) /**< (DEVEPTISR) STALLed Interrupt Mask */ +#define DEVEPTISR_INTRPT_CTRLDIR_Pos 17 /**< (DEVEPTISR) Control Direction Position */ +#define DEVEPTISR_INTRPT_CTRLDIR (_U_(0x1) << DEVEPTISR_INTRPT_CTRLDIR_Pos) /**< (DEVEPTISR) Control Direction Mask */ +#define DEVEPTISR_INTRPT_Msk _U_(0x2005C) /**< (DEVEPTISR_INTRPT) Register Mask */ + + +/* -------- DEVEPTICR : (USBHS Offset: 0x160) (/W 32) Device Endpoint Interrupt Clear Register -------- */ + +#define DEVEPTICR_OFFSET (0x160) /**< (DEVEPTICR) Device Endpoint Interrupt Clear Register Offset */ + +#define DEVEPTICR_TXINIC_Pos 0 /**< (DEVEPTICR) Transmitted IN Data Interrupt Clear Position */ +#define DEVEPTICR_TXINIC (_U_(0x1) << DEVEPTICR_TXINIC_Pos) /**< (DEVEPTICR) Transmitted IN Data Interrupt Clear Mask */ +#define DEVEPTICR_RXOUTIC_Pos 1 /**< (DEVEPTICR) Received OUT Data Interrupt Clear Position */ +#define DEVEPTICR_RXOUTIC (_U_(0x1) << DEVEPTICR_RXOUTIC_Pos) /**< (DEVEPTICR) Received OUT Data Interrupt Clear Mask */ +#define DEVEPTICR_OVERFIC_Pos 5 /**< (DEVEPTICR) Overflow Interrupt Clear Position */ +#define DEVEPTICR_OVERFIC (_U_(0x1) << DEVEPTICR_OVERFIC_Pos) /**< (DEVEPTICR) Overflow Interrupt Clear Mask */ +#define DEVEPTICR_SHORTPACKETC_Pos 7 /**< (DEVEPTICR) Short Packet Interrupt Clear Position */ +#define DEVEPTICR_SHORTPACKETC (_U_(0x1) << DEVEPTICR_SHORTPACKETC_Pos) /**< (DEVEPTICR) Short Packet Interrupt Clear Mask */ +#define DEVEPTICR_Msk _U_(0xA3) /**< (DEVEPTICR) Register Mask */ + +/* CTRL mode */ +#define DEVEPTICR_CTRL_RXSTPIC_Pos 2 /**< (DEVEPTICR) Received SETUP Interrupt Clear Position */ +#define DEVEPTICR_CTRL_RXSTPIC (_U_(0x1) << DEVEPTICR_CTRL_RXSTPIC_Pos) /**< (DEVEPTICR) Received SETUP Interrupt Clear Mask */ +#define DEVEPTICR_CTRL_NAKOUTIC_Pos 3 /**< (DEVEPTICR) NAKed OUT Interrupt Clear Position */ +#define DEVEPTICR_CTRL_NAKOUTIC (_U_(0x1) << DEVEPTICR_CTRL_NAKOUTIC_Pos) /**< (DEVEPTICR) NAKed OUT Interrupt Clear Mask */ +#define DEVEPTICR_CTRL_NAKINIC_Pos 4 /**< (DEVEPTICR) NAKed IN Interrupt Clear Position */ +#define DEVEPTICR_CTRL_NAKINIC (_U_(0x1) << DEVEPTICR_CTRL_NAKINIC_Pos) /**< (DEVEPTICR) NAKed IN Interrupt Clear Mask */ +#define DEVEPTICR_CTRL_STALLEDIC_Pos 6 /**< (DEVEPTICR) STALLed Interrupt Clear Position */ +#define DEVEPTICR_CTRL_STALLEDIC (_U_(0x1) << DEVEPTICR_CTRL_STALLEDIC_Pos) /**< (DEVEPTICR) STALLed Interrupt Clear Mask */ +#define DEVEPTICR_CTRL_Msk _U_(0x5C) /**< (DEVEPTICR_CTRL) Register Mask */ + +/* ISO mode */ +#define DEVEPTICR_ISO_UNDERFIC_Pos 2 /**< (DEVEPTICR) Underflow Interrupt Clear Position */ +#define DEVEPTICR_ISO_UNDERFIC (_U_(0x1) << DEVEPTICR_ISO_UNDERFIC_Pos) /**< (DEVEPTICR) Underflow Interrupt Clear Mask */ +#define DEVEPTICR_ISO_HBISOINERRIC_Pos 3 /**< (DEVEPTICR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Position */ +#define DEVEPTICR_ISO_HBISOINERRIC (_U_(0x1) << DEVEPTICR_ISO_HBISOINERRIC_Pos) /**< (DEVEPTICR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Mask */ +#define DEVEPTICR_ISO_HBISOFLUSHIC_Pos 4 /**< (DEVEPTICR) High Bandwidth Isochronous IN Flush Interrupt Clear Position */ +#define DEVEPTICR_ISO_HBISOFLUSHIC (_U_(0x1) << DEVEPTICR_ISO_HBISOFLUSHIC_Pos) /**< (DEVEPTICR) High Bandwidth Isochronous IN Flush Interrupt Clear Mask */ +#define DEVEPTICR_ISO_CRCERRIC_Pos 6 /**< (DEVEPTICR) CRC Error Interrupt Clear Position */ +#define DEVEPTICR_ISO_CRCERRIC (_U_(0x1) << DEVEPTICR_ISO_CRCERRIC_Pos) /**< (DEVEPTICR) CRC Error Interrupt Clear Mask */ +#define DEVEPTICR_ISO_Msk _U_(0x5C) /**< (DEVEPTICR_ISO) Register Mask */ + +/* BLK mode */ +#define DEVEPTICR_BLK_RXSTPIC_Pos 2 /**< (DEVEPTICR) Received SETUP Interrupt Clear Position */ +#define DEVEPTICR_BLK_RXSTPIC (_U_(0x1) << DEVEPTICR_BLK_RXSTPIC_Pos) /**< (DEVEPTICR) Received SETUP Interrupt Clear Mask */ +#define DEVEPTICR_BLK_NAKOUTIC_Pos 3 /**< (DEVEPTICR) NAKed OUT Interrupt Clear Position */ +#define DEVEPTICR_BLK_NAKOUTIC (_U_(0x1) << DEVEPTICR_BLK_NAKOUTIC_Pos) /**< (DEVEPTICR) NAKed OUT Interrupt Clear Mask */ +#define DEVEPTICR_BLK_NAKINIC_Pos 4 /**< (DEVEPTICR) NAKed IN Interrupt Clear Position */ +#define DEVEPTICR_BLK_NAKINIC (_U_(0x1) << DEVEPTICR_BLK_NAKINIC_Pos) /**< (DEVEPTICR) NAKed IN Interrupt Clear Mask */ +#define DEVEPTICR_BLK_STALLEDIC_Pos 6 /**< (DEVEPTICR) STALLed Interrupt Clear Position */ +#define DEVEPTICR_BLK_STALLEDIC (_U_(0x1) << DEVEPTICR_BLK_STALLEDIC_Pos) /**< (DEVEPTICR) STALLed Interrupt Clear Mask */ +#define DEVEPTICR_BLK_Msk _U_(0x5C) /**< (DEVEPTICR_BLK) Register Mask */ + +/* INTRPT mode */ +#define DEVEPTICR_INTRPT_RXSTPIC_Pos 2 /**< (DEVEPTICR) Received SETUP Interrupt Clear Position */ +#define DEVEPTICR_INTRPT_RXSTPIC (_U_(0x1) << DEVEPTICR_INTRPT_RXSTPIC_Pos) /**< (DEVEPTICR) Received SETUP Interrupt Clear Mask */ +#define DEVEPTICR_INTRPT_NAKOUTIC_Pos 3 /**< (DEVEPTICR) NAKed OUT Interrupt Clear Position */ +#define DEVEPTICR_INTRPT_NAKOUTIC (_U_(0x1) << DEVEPTICR_INTRPT_NAKOUTIC_Pos) /**< (DEVEPTICR) NAKed OUT Interrupt Clear Mask */ +#define DEVEPTICR_INTRPT_NAKINIC_Pos 4 /**< (DEVEPTICR) NAKed IN Interrupt Clear Position */ +#define DEVEPTICR_INTRPT_NAKINIC (_U_(0x1) << DEVEPTICR_INTRPT_NAKINIC_Pos) /**< (DEVEPTICR) NAKed IN Interrupt Clear Mask */ +#define DEVEPTICR_INTRPT_STALLEDIC_Pos 6 /**< (DEVEPTICR) STALLed Interrupt Clear Position */ +#define DEVEPTICR_INTRPT_STALLEDIC (_U_(0x1) << DEVEPTICR_INTRPT_STALLEDIC_Pos) /**< (DEVEPTICR) STALLed Interrupt Clear Mask */ +#define DEVEPTICR_INTRPT_Msk _U_(0x5C) /**< (DEVEPTICR_INTRPT) Register Mask */ + + +/* -------- DEVEPTIFR : (USBHS Offset: 0x190) (/W 32) Device Endpoint Interrupt Set Register -------- */ + +#define DEVEPTIFR_OFFSET (0x190) /**< (DEVEPTIFR) Device Endpoint Interrupt Set Register Offset */ + +#define DEVEPTIFR_TXINIS_Pos 0 /**< (DEVEPTIFR) Transmitted IN Data Interrupt Set Position */ +#define DEVEPTIFR_TXINIS (_U_(0x1) << DEVEPTIFR_TXINIS_Pos) /**< (DEVEPTIFR) Transmitted IN Data Interrupt Set Mask */ +#define DEVEPTIFR_RXOUTIS_Pos 1 /**< (DEVEPTIFR) Received OUT Data Interrupt Set Position */ +#define DEVEPTIFR_RXOUTIS (_U_(0x1) << DEVEPTIFR_RXOUTIS_Pos) /**< (DEVEPTIFR) Received OUT Data Interrupt Set Mask */ +#define DEVEPTIFR_OVERFIS_Pos 5 /**< (DEVEPTIFR) Overflow Interrupt Set Position */ +#define DEVEPTIFR_OVERFIS (_U_(0x1) << DEVEPTIFR_OVERFIS_Pos) /**< (DEVEPTIFR) Overflow Interrupt Set Mask */ +#define DEVEPTIFR_SHORTPACKETS_Pos 7 /**< (DEVEPTIFR) Short Packet Interrupt Set Position */ +#define DEVEPTIFR_SHORTPACKETS (_U_(0x1) << DEVEPTIFR_SHORTPACKETS_Pos) /**< (DEVEPTIFR) Short Packet Interrupt Set Mask */ +#define DEVEPTIFR_NBUSYBKS_Pos 12 /**< (DEVEPTIFR) Number of Busy Banks Interrupt Set Position */ +#define DEVEPTIFR_NBUSYBKS (_U_(0x1) << DEVEPTIFR_NBUSYBKS_Pos) /**< (DEVEPTIFR) Number of Busy Banks Interrupt Set Mask */ +#define DEVEPTIFR_Msk _U_(0x10A3) /**< (DEVEPTIFR) Register Mask */ + +/* CTRL mode */ +#define DEVEPTIFR_CTRL_RXSTPIS_Pos 2 /**< (DEVEPTIFR) Received SETUP Interrupt Set Position */ +#define DEVEPTIFR_CTRL_RXSTPIS (_U_(0x1) << DEVEPTIFR_CTRL_RXSTPIS_Pos) /**< (DEVEPTIFR) Received SETUP Interrupt Set Mask */ +#define DEVEPTIFR_CTRL_NAKOUTIS_Pos 3 /**< (DEVEPTIFR) NAKed OUT Interrupt Set Position */ +#define DEVEPTIFR_CTRL_NAKOUTIS (_U_(0x1) << DEVEPTIFR_CTRL_NAKOUTIS_Pos) /**< (DEVEPTIFR) NAKed OUT Interrupt Set Mask */ +#define DEVEPTIFR_CTRL_NAKINIS_Pos 4 /**< (DEVEPTIFR) NAKed IN Interrupt Set Position */ +#define DEVEPTIFR_CTRL_NAKINIS (_U_(0x1) << DEVEPTIFR_CTRL_NAKINIS_Pos) /**< (DEVEPTIFR) NAKed IN Interrupt Set Mask */ +#define DEVEPTIFR_CTRL_STALLEDIS_Pos 6 /**< (DEVEPTIFR) STALLed Interrupt Set Position */ +#define DEVEPTIFR_CTRL_STALLEDIS (_U_(0x1) << DEVEPTIFR_CTRL_STALLEDIS_Pos) /**< (DEVEPTIFR) STALLed Interrupt Set Mask */ +#define DEVEPTIFR_CTRL_Msk _U_(0x5C) /**< (DEVEPTIFR_CTRL) Register Mask */ + +/* ISO mode */ +#define DEVEPTIFR_ISO_UNDERFIS_Pos 2 /**< (DEVEPTIFR) Underflow Interrupt Set Position */ +#define DEVEPTIFR_ISO_UNDERFIS (_U_(0x1) << DEVEPTIFR_ISO_UNDERFIS_Pos) /**< (DEVEPTIFR) Underflow Interrupt Set Mask */ +#define DEVEPTIFR_ISO_HBISOINERRIS_Pos 3 /**< (DEVEPTIFR) High Bandwidth Isochronous IN Underflow Error Interrupt Set Position */ +#define DEVEPTIFR_ISO_HBISOINERRIS (_U_(0x1) << DEVEPTIFR_ISO_HBISOINERRIS_Pos) /**< (DEVEPTIFR) High Bandwidth Isochronous IN Underflow Error Interrupt Set Mask */ +#define DEVEPTIFR_ISO_HBISOFLUSHIS_Pos 4 /**< (DEVEPTIFR) High Bandwidth Isochronous IN Flush Interrupt Set Position */ +#define DEVEPTIFR_ISO_HBISOFLUSHIS (_U_(0x1) << DEVEPTIFR_ISO_HBISOFLUSHIS_Pos) /**< (DEVEPTIFR) High Bandwidth Isochronous IN Flush Interrupt Set Mask */ +#define DEVEPTIFR_ISO_CRCERRIS_Pos 6 /**< (DEVEPTIFR) CRC Error Interrupt Set Position */ +#define DEVEPTIFR_ISO_CRCERRIS (_U_(0x1) << DEVEPTIFR_ISO_CRCERRIS_Pos) /**< (DEVEPTIFR) CRC Error Interrupt Set Mask */ +#define DEVEPTIFR_ISO_Msk _U_(0x5C) /**< (DEVEPTIFR_ISO) Register Mask */ + +/* BLK mode */ +#define DEVEPTIFR_BLK_RXSTPIS_Pos 2 /**< (DEVEPTIFR) Received SETUP Interrupt Set Position */ +#define DEVEPTIFR_BLK_RXSTPIS (_U_(0x1) << DEVEPTIFR_BLK_RXSTPIS_Pos) /**< (DEVEPTIFR) Received SETUP Interrupt Set Mask */ +#define DEVEPTIFR_BLK_NAKOUTIS_Pos 3 /**< (DEVEPTIFR) NAKed OUT Interrupt Set Position */ +#define DEVEPTIFR_BLK_NAKOUTIS (_U_(0x1) << DEVEPTIFR_BLK_NAKOUTIS_Pos) /**< (DEVEPTIFR) NAKed OUT Interrupt Set Mask */ +#define DEVEPTIFR_BLK_NAKINIS_Pos 4 /**< (DEVEPTIFR) NAKed IN Interrupt Set Position */ +#define DEVEPTIFR_BLK_NAKINIS (_U_(0x1) << DEVEPTIFR_BLK_NAKINIS_Pos) /**< (DEVEPTIFR) NAKed IN Interrupt Set Mask */ +#define DEVEPTIFR_BLK_STALLEDIS_Pos 6 /**< (DEVEPTIFR) STALLed Interrupt Set Position */ +#define DEVEPTIFR_BLK_STALLEDIS (_U_(0x1) << DEVEPTIFR_BLK_STALLEDIS_Pos) /**< (DEVEPTIFR) STALLed Interrupt Set Mask */ +#define DEVEPTIFR_BLK_Msk _U_(0x5C) /**< (DEVEPTIFR_BLK) Register Mask */ + +/* INTRPT mode */ +#define DEVEPTIFR_INTRPT_RXSTPIS_Pos 2 /**< (DEVEPTIFR) Received SETUP Interrupt Set Position */ +#define DEVEPTIFR_INTRPT_RXSTPIS (_U_(0x1) << DEVEPTIFR_INTRPT_RXSTPIS_Pos) /**< (DEVEPTIFR) Received SETUP Interrupt Set Mask */ +#define DEVEPTIFR_INTRPT_NAKOUTIS_Pos 3 /**< (DEVEPTIFR) NAKed OUT Interrupt Set Position */ +#define DEVEPTIFR_INTRPT_NAKOUTIS (_U_(0x1) << DEVEPTIFR_INTRPT_NAKOUTIS_Pos) /**< (DEVEPTIFR) NAKed OUT Interrupt Set Mask */ +#define DEVEPTIFR_INTRPT_NAKINIS_Pos 4 /**< (DEVEPTIFR) NAKed IN Interrupt Set Position */ +#define DEVEPTIFR_INTRPT_NAKINIS (_U_(0x1) << DEVEPTIFR_INTRPT_NAKINIS_Pos) /**< (DEVEPTIFR) NAKed IN Interrupt Set Mask */ +#define DEVEPTIFR_INTRPT_STALLEDIS_Pos 6 /**< (DEVEPTIFR) STALLed Interrupt Set Position */ +#define DEVEPTIFR_INTRPT_STALLEDIS (_U_(0x1) << DEVEPTIFR_INTRPT_STALLEDIS_Pos) /**< (DEVEPTIFR) STALLed Interrupt Set Mask */ +#define DEVEPTIFR_INTRPT_Msk _U_(0x5C) /**< (DEVEPTIFR_INTRPT) Register Mask */ + + +/* -------- DEVEPTIMR : (USBHS Offset: 0x1c0) (R/ 32) Device Endpoint Interrupt Mask Register -------- */ + +#define DEVEPTIMR_OFFSET (0x1C0) /**< (DEVEPTIMR) Device Endpoint Interrupt Mask Register Offset */ + +#define DEVEPTIMR_TXINE_Pos 0 /**< (DEVEPTIMR) Transmitted IN Data Interrupt Position */ +#define DEVEPTIMR_TXINE (_U_(0x1) << DEVEPTIMR_TXINE_Pos) /**< (DEVEPTIMR) Transmitted IN Data Interrupt Mask */ +#define DEVEPTIMR_RXOUTE_Pos 1 /**< (DEVEPTIMR) Received OUT Data Interrupt Position */ +#define DEVEPTIMR_RXOUTE (_U_(0x1) << DEVEPTIMR_RXOUTE_Pos) /**< (DEVEPTIMR) Received OUT Data Interrupt Mask */ +#define DEVEPTIMR_OVERFE_Pos 5 /**< (DEVEPTIMR) Overflow Interrupt Position */ +#define DEVEPTIMR_OVERFE (_U_(0x1) << DEVEPTIMR_OVERFE_Pos) /**< (DEVEPTIMR) Overflow Interrupt Mask */ +#define DEVEPTIMR_SHORTPACKETE_Pos 7 /**< (DEVEPTIMR) Short Packet Interrupt Position */ +#define DEVEPTIMR_SHORTPACKETE (_U_(0x1) << DEVEPTIMR_SHORTPACKETE_Pos) /**< (DEVEPTIMR) Short Packet Interrupt Mask */ +#define DEVEPTIMR_NBUSYBKE_Pos 12 /**< (DEVEPTIMR) Number of Busy Banks Interrupt Position */ +#define DEVEPTIMR_NBUSYBKE (_U_(0x1) << DEVEPTIMR_NBUSYBKE_Pos) /**< (DEVEPTIMR) Number of Busy Banks Interrupt Mask */ +#define DEVEPTIMR_KILLBK_Pos 13 /**< (DEVEPTIMR) Kill IN Bank Position */ +#define DEVEPTIMR_KILLBK (_U_(0x1) << DEVEPTIMR_KILLBK_Pos) /**< (DEVEPTIMR) Kill IN Bank Mask */ +#define DEVEPTIMR_FIFOCON_Pos 14 /**< (DEVEPTIMR) FIFO Control Position */ +#define DEVEPTIMR_FIFOCON (_U_(0x1) << DEVEPTIMR_FIFOCON_Pos) /**< (DEVEPTIMR) FIFO Control Mask */ +#define DEVEPTIMR_EPDISHDMA_Pos 16 /**< (DEVEPTIMR) Endpoint Interrupts Disable HDMA Request Position */ +#define DEVEPTIMR_EPDISHDMA (_U_(0x1) << DEVEPTIMR_EPDISHDMA_Pos) /**< (DEVEPTIMR) Endpoint Interrupts Disable HDMA Request Mask */ +#define DEVEPTIMR_RSTDT_Pos 18 /**< (DEVEPTIMR) Reset Data Toggle Position */ +#define DEVEPTIMR_RSTDT (_U_(0x1) << DEVEPTIMR_RSTDT_Pos) /**< (DEVEPTIMR) Reset Data Toggle Mask */ +#define DEVEPTIMR_Msk _U_(0x570A3) /**< (DEVEPTIMR) Register Mask */ + +/* CTRL mode */ +#define DEVEPTIMR_CTRL_RXSTPE_Pos 2 /**< (DEVEPTIMR) Received SETUP Interrupt Position */ +#define DEVEPTIMR_CTRL_RXSTPE (_U_(0x1) << DEVEPTIMR_CTRL_RXSTPE_Pos) /**< (DEVEPTIMR) Received SETUP Interrupt Mask */ +#define DEVEPTIMR_CTRL_NAKOUTE_Pos 3 /**< (DEVEPTIMR) NAKed OUT Interrupt Position */ +#define DEVEPTIMR_CTRL_NAKOUTE (_U_(0x1) << DEVEPTIMR_CTRL_NAKOUTE_Pos) /**< (DEVEPTIMR) NAKed OUT Interrupt Mask */ +#define DEVEPTIMR_CTRL_NAKINE_Pos 4 /**< (DEVEPTIMR) NAKed IN Interrupt Position */ +#define DEVEPTIMR_CTRL_NAKINE (_U_(0x1) << DEVEPTIMR_CTRL_NAKINE_Pos) /**< (DEVEPTIMR) NAKed IN Interrupt Mask */ +#define DEVEPTIMR_CTRL_STALLEDE_Pos 6 /**< (DEVEPTIMR) STALLed Interrupt Position */ +#define DEVEPTIMR_CTRL_STALLEDE (_U_(0x1) << DEVEPTIMR_CTRL_STALLEDE_Pos) /**< (DEVEPTIMR) STALLed Interrupt Mask */ +#define DEVEPTIMR_CTRL_NYETDIS_Pos 17 /**< (DEVEPTIMR) NYET Token Disable Position */ +#define DEVEPTIMR_CTRL_NYETDIS (_U_(0x1) << DEVEPTIMR_CTRL_NYETDIS_Pos) /**< (DEVEPTIMR) NYET Token Disable Mask */ +#define DEVEPTIMR_CTRL_STALLRQ_Pos 19 /**< (DEVEPTIMR) STALL Request Position */ +#define DEVEPTIMR_CTRL_STALLRQ (_U_(0x1) << DEVEPTIMR_CTRL_STALLRQ_Pos) /**< (DEVEPTIMR) STALL Request Mask */ +#define DEVEPTIMR_CTRL_Msk _U_(0xA005C) /**< (DEVEPTIMR_CTRL) Register Mask */ + +/* ISO mode */ +#define DEVEPTIMR_ISO_UNDERFE_Pos 2 /**< (DEVEPTIMR) Underflow Interrupt Position */ +#define DEVEPTIMR_ISO_UNDERFE (_U_(0x1) << DEVEPTIMR_ISO_UNDERFE_Pos) /**< (DEVEPTIMR) Underflow Interrupt Mask */ +#define DEVEPTIMR_ISO_HBISOINERRE_Pos 3 /**< (DEVEPTIMR) High Bandwidth Isochronous IN Underflow Error Interrupt Position */ +#define DEVEPTIMR_ISO_HBISOINERRE (_U_(0x1) << DEVEPTIMR_ISO_HBISOINERRE_Pos) /**< (DEVEPTIMR) High Bandwidth Isochronous IN Underflow Error Interrupt Mask */ +#define DEVEPTIMR_ISO_HBISOFLUSHE_Pos 4 /**< (DEVEPTIMR) High Bandwidth Isochronous IN Flush Interrupt Position */ +#define DEVEPTIMR_ISO_HBISOFLUSHE (_U_(0x1) << DEVEPTIMR_ISO_HBISOFLUSHE_Pos) /**< (DEVEPTIMR) High Bandwidth Isochronous IN Flush Interrupt Mask */ +#define DEVEPTIMR_ISO_CRCERRE_Pos 6 /**< (DEVEPTIMR) CRC Error Interrupt Position */ +#define DEVEPTIMR_ISO_CRCERRE (_U_(0x1) << DEVEPTIMR_ISO_CRCERRE_Pos) /**< (DEVEPTIMR) CRC Error Interrupt Mask */ +#define DEVEPTIMR_ISO_MDATAE_Pos 8 /**< (DEVEPTIMR) MData Interrupt Position */ +#define DEVEPTIMR_ISO_MDATAE (_U_(0x1) << DEVEPTIMR_ISO_MDATAE_Pos) /**< (DEVEPTIMR) MData Interrupt Mask */ +#define DEVEPTIMR_ISO_DATAXE_Pos 9 /**< (DEVEPTIMR) DataX Interrupt Position */ +#define DEVEPTIMR_ISO_DATAXE (_U_(0x1) << DEVEPTIMR_ISO_DATAXE_Pos) /**< (DEVEPTIMR) DataX Interrupt Mask */ +#define DEVEPTIMR_ISO_ERRORTRANSE_Pos 10 /**< (DEVEPTIMR) Transaction Error Interrupt Position */ +#define DEVEPTIMR_ISO_ERRORTRANSE (_U_(0x1) << DEVEPTIMR_ISO_ERRORTRANSE_Pos) /**< (DEVEPTIMR) Transaction Error Interrupt Mask */ +#define DEVEPTIMR_ISO_Msk _U_(0x75C) /**< (DEVEPTIMR_ISO) Register Mask */ + +/* BLK mode */ +#define DEVEPTIMR_BLK_RXSTPE_Pos 2 /**< (DEVEPTIMR) Received SETUP Interrupt Position */ +#define DEVEPTIMR_BLK_RXSTPE (_U_(0x1) << DEVEPTIMR_BLK_RXSTPE_Pos) /**< (DEVEPTIMR) Received SETUP Interrupt Mask */ +#define DEVEPTIMR_BLK_NAKOUTE_Pos 3 /**< (DEVEPTIMR) NAKed OUT Interrupt Position */ +#define DEVEPTIMR_BLK_NAKOUTE (_U_(0x1) << DEVEPTIMR_BLK_NAKOUTE_Pos) /**< (DEVEPTIMR) NAKed OUT Interrupt Mask */ +#define DEVEPTIMR_BLK_NAKINE_Pos 4 /**< (DEVEPTIMR) NAKed IN Interrupt Position */ +#define DEVEPTIMR_BLK_NAKINE (_U_(0x1) << DEVEPTIMR_BLK_NAKINE_Pos) /**< (DEVEPTIMR) NAKed IN Interrupt Mask */ +#define DEVEPTIMR_BLK_STALLEDE_Pos 6 /**< (DEVEPTIMR) STALLed Interrupt Position */ +#define DEVEPTIMR_BLK_STALLEDE (_U_(0x1) << DEVEPTIMR_BLK_STALLEDE_Pos) /**< (DEVEPTIMR) STALLed Interrupt Mask */ +#define DEVEPTIMR_BLK_NYETDIS_Pos 17 /**< (DEVEPTIMR) NYET Token Disable Position */ +#define DEVEPTIMR_BLK_NYETDIS (_U_(0x1) << DEVEPTIMR_BLK_NYETDIS_Pos) /**< (DEVEPTIMR) NYET Token Disable Mask */ +#define DEVEPTIMR_BLK_STALLRQ_Pos 19 /**< (DEVEPTIMR) STALL Request Position */ +#define DEVEPTIMR_BLK_STALLRQ (_U_(0x1) << DEVEPTIMR_BLK_STALLRQ_Pos) /**< (DEVEPTIMR) STALL Request Mask */ +#define DEVEPTIMR_BLK_Msk _U_(0xA005C) /**< (DEVEPTIMR_BLK) Register Mask */ + +/* INTRPT mode */ +#define DEVEPTIMR_INTRPT_RXSTPE_Pos 2 /**< (DEVEPTIMR) Received SETUP Interrupt Position */ +#define DEVEPTIMR_INTRPT_RXSTPE (_U_(0x1) << DEVEPTIMR_INTRPT_RXSTPE_Pos) /**< (DEVEPTIMR) Received SETUP Interrupt Mask */ +#define DEVEPTIMR_INTRPT_NAKOUTE_Pos 3 /**< (DEVEPTIMR) NAKed OUT Interrupt Position */ +#define DEVEPTIMR_INTRPT_NAKOUTE (_U_(0x1) << DEVEPTIMR_INTRPT_NAKOUTE_Pos) /**< (DEVEPTIMR) NAKed OUT Interrupt Mask */ +#define DEVEPTIMR_INTRPT_NAKINE_Pos 4 /**< (DEVEPTIMR) NAKed IN Interrupt Position */ +#define DEVEPTIMR_INTRPT_NAKINE (_U_(0x1) << DEVEPTIMR_INTRPT_NAKINE_Pos) /**< (DEVEPTIMR) NAKed IN Interrupt Mask */ +#define DEVEPTIMR_INTRPT_STALLEDE_Pos 6 /**< (DEVEPTIMR) STALLed Interrupt Position */ +#define DEVEPTIMR_INTRPT_STALLEDE (_U_(0x1) << DEVEPTIMR_INTRPT_STALLEDE_Pos) /**< (DEVEPTIMR) STALLed Interrupt Mask */ +#define DEVEPTIMR_INTRPT_NYETDIS_Pos 17 /**< (DEVEPTIMR) NYET Token Disable Position */ +#define DEVEPTIMR_INTRPT_NYETDIS (_U_(0x1) << DEVEPTIMR_INTRPT_NYETDIS_Pos) /**< (DEVEPTIMR) NYET Token Disable Mask */ +#define DEVEPTIMR_INTRPT_STALLRQ_Pos 19 /**< (DEVEPTIMR) STALL Request Position */ +#define DEVEPTIMR_INTRPT_STALLRQ (_U_(0x1) << DEVEPTIMR_INTRPT_STALLRQ_Pos) /**< (DEVEPTIMR) STALL Request Mask */ +#define DEVEPTIMR_INTRPT_Msk _U_(0xA005C) /**< (DEVEPTIMR_INTRPT) Register Mask */ + + +/* -------- DEVEPTIER : (USBHS Offset: 0x1f0) (/W 32) Device Endpoint Interrupt Enable Register -------- */ + +#define DEVEPTIER_OFFSET (0x1F0) /**< (DEVEPTIER) Device Endpoint Interrupt Enable Register Offset */ + +#define DEVEPTIER_TXINES_Pos 0 /**< (DEVEPTIER) Transmitted IN Data Interrupt Enable Position */ +#define DEVEPTIER_TXINES (_U_(0x1) << DEVEPTIER_TXINES_Pos) /**< (DEVEPTIER) Transmitted IN Data Interrupt Enable Mask */ +#define DEVEPTIER_RXOUTES_Pos 1 /**< (DEVEPTIER) Received OUT Data Interrupt Enable Position */ +#define DEVEPTIER_RXOUTES (_U_(0x1) << DEVEPTIER_RXOUTES_Pos) /**< (DEVEPTIER) Received OUT Data Interrupt Enable Mask */ +#define DEVEPTIER_OVERFES_Pos 5 /**< (DEVEPTIER) Overflow Interrupt Enable Position */ +#define DEVEPTIER_OVERFES (_U_(0x1) << DEVEPTIER_OVERFES_Pos) /**< (DEVEPTIER) Overflow Interrupt Enable Mask */ +#define DEVEPTIER_SHORTPACKETES_Pos 7 /**< (DEVEPTIER) Short Packet Interrupt Enable Position */ +#define DEVEPTIER_SHORTPACKETES (_U_(0x1) << DEVEPTIER_SHORTPACKETES_Pos) /**< (DEVEPTIER) Short Packet Interrupt Enable Mask */ +#define DEVEPTIER_NBUSYBKES_Pos 12 /**< (DEVEPTIER) Number of Busy Banks Interrupt Enable Position */ +#define DEVEPTIER_NBUSYBKES (_U_(0x1) << DEVEPTIER_NBUSYBKES_Pos) /**< (DEVEPTIER) Number of Busy Banks Interrupt Enable Mask */ +#define DEVEPTIER_KILLBKS_Pos 13 /**< (DEVEPTIER) Kill IN Bank Position */ +#define DEVEPTIER_KILLBKS (_U_(0x1) << DEVEPTIER_KILLBKS_Pos) /**< (DEVEPTIER) Kill IN Bank Mask */ +#define DEVEPTIER_FIFOCONS_Pos 14 /**< (DEVEPTIER) FIFO Control Position */ +#define DEVEPTIER_FIFOCONS (_U_(0x1) << DEVEPTIER_FIFOCONS_Pos) /**< (DEVEPTIER) FIFO Control Mask */ +#define DEVEPTIER_EPDISHDMAS_Pos 16 /**< (DEVEPTIER) Endpoint Interrupts Disable HDMA Request Enable Position */ +#define DEVEPTIER_EPDISHDMAS (_U_(0x1) << DEVEPTIER_EPDISHDMAS_Pos) /**< (DEVEPTIER) Endpoint Interrupts Disable HDMA Request Enable Mask */ +#define DEVEPTIER_RSTDTS_Pos 18 /**< (DEVEPTIER) Reset Data Toggle Enable Position */ +#define DEVEPTIER_RSTDTS (_U_(0x1) << DEVEPTIER_RSTDTS_Pos) /**< (DEVEPTIER) Reset Data Toggle Enable Mask */ +#define DEVEPTIER_Msk _U_(0x570A3) /**< (DEVEPTIER) Register Mask */ + +/* CTRL mode */ +#define DEVEPTIER_CTRL_RXSTPES_Pos 2 /**< (DEVEPTIER) Received SETUP Interrupt Enable Position */ +#define DEVEPTIER_CTRL_RXSTPES (_U_(0x1) << DEVEPTIER_CTRL_RXSTPES_Pos) /**< (DEVEPTIER) Received SETUP Interrupt Enable Mask */ +#define DEVEPTIER_CTRL_NAKOUTES_Pos 3 /**< (DEVEPTIER) NAKed OUT Interrupt Enable Position */ +#define DEVEPTIER_CTRL_NAKOUTES (_U_(0x1) << DEVEPTIER_CTRL_NAKOUTES_Pos) /**< (DEVEPTIER) NAKed OUT Interrupt Enable Mask */ +#define DEVEPTIER_CTRL_NAKINES_Pos 4 /**< (DEVEPTIER) NAKed IN Interrupt Enable Position */ +#define DEVEPTIER_CTRL_NAKINES (_U_(0x1) << DEVEPTIER_CTRL_NAKINES_Pos) /**< (DEVEPTIER) NAKed IN Interrupt Enable Mask */ +#define DEVEPTIER_CTRL_STALLEDES_Pos 6 /**< (DEVEPTIER) STALLed Interrupt Enable Position */ +#define DEVEPTIER_CTRL_STALLEDES (_U_(0x1) << DEVEPTIER_CTRL_STALLEDES_Pos) /**< (DEVEPTIER) STALLed Interrupt Enable Mask */ +#define DEVEPTIER_CTRL_NYETDISS_Pos 17 /**< (DEVEPTIER) NYET Token Disable Enable Position */ +#define DEVEPTIER_CTRL_NYETDISS (_U_(0x1) << DEVEPTIER_CTRL_NYETDISS_Pos) /**< (DEVEPTIER) NYET Token Disable Enable Mask */ +#define DEVEPTIER_CTRL_STALLRQS_Pos 19 /**< (DEVEPTIER) STALL Request Enable Position */ +#define DEVEPTIER_CTRL_STALLRQS (_U_(0x1) << DEVEPTIER_CTRL_STALLRQS_Pos) /**< (DEVEPTIER) STALL Request Enable Mask */ +#define DEVEPTIER_CTRL_Msk _U_(0xA005C) /**< (DEVEPTIER_CTRL) Register Mask */ + +/* ISO mode */ +#define DEVEPTIER_ISO_UNDERFES_Pos 2 /**< (DEVEPTIER) Underflow Interrupt Enable Position */ +#define DEVEPTIER_ISO_UNDERFES (_U_(0x1) << DEVEPTIER_ISO_UNDERFES_Pos) /**< (DEVEPTIER) Underflow Interrupt Enable Mask */ +#define DEVEPTIER_ISO_HBISOINERRES_Pos 3 /**< (DEVEPTIER) High Bandwidth Isochronous IN Underflow Error Interrupt Enable Position */ +#define DEVEPTIER_ISO_HBISOINERRES (_U_(0x1) << DEVEPTIER_ISO_HBISOINERRES_Pos) /**< (DEVEPTIER) High Bandwidth Isochronous IN Underflow Error Interrupt Enable Mask */ +#define DEVEPTIER_ISO_HBISOFLUSHES_Pos 4 /**< (DEVEPTIER) High Bandwidth Isochronous IN Flush Interrupt Enable Position */ +#define DEVEPTIER_ISO_HBISOFLUSHES (_U_(0x1) << DEVEPTIER_ISO_HBISOFLUSHES_Pos) /**< (DEVEPTIER) High Bandwidth Isochronous IN Flush Interrupt Enable Mask */ +#define DEVEPTIER_ISO_CRCERRES_Pos 6 /**< (DEVEPTIER) CRC Error Interrupt Enable Position */ +#define DEVEPTIER_ISO_CRCERRES (_U_(0x1) << DEVEPTIER_ISO_CRCERRES_Pos) /**< (DEVEPTIER) CRC Error Interrupt Enable Mask */ +#define DEVEPTIER_ISO_MDATAES_Pos 8 /**< (DEVEPTIER) MData Interrupt Enable Position */ +#define DEVEPTIER_ISO_MDATAES (_U_(0x1) << DEVEPTIER_ISO_MDATAES_Pos) /**< (DEVEPTIER) MData Interrupt Enable Mask */ +#define DEVEPTIER_ISO_DATAXES_Pos 9 /**< (DEVEPTIER) DataX Interrupt Enable Position */ +#define DEVEPTIER_ISO_DATAXES (_U_(0x1) << DEVEPTIER_ISO_DATAXES_Pos) /**< (DEVEPTIER) DataX Interrupt Enable Mask */ +#define DEVEPTIER_ISO_ERRORTRANSES_Pos 10 /**< (DEVEPTIER) Transaction Error Interrupt Enable Position */ +#define DEVEPTIER_ISO_ERRORTRANSES (_U_(0x1) << DEVEPTIER_ISO_ERRORTRANSES_Pos) /**< (DEVEPTIER) Transaction Error Interrupt Enable Mask */ +#define DEVEPTIER_ISO_Msk _U_(0x75C) /**< (DEVEPTIER_ISO) Register Mask */ + +/* BLK mode */ +#define DEVEPTIER_BLK_RXSTPES_Pos 2 /**< (DEVEPTIER) Received SETUP Interrupt Enable Position */ +#define DEVEPTIER_BLK_RXSTPES (_U_(0x1) << DEVEPTIER_BLK_RXSTPES_Pos) /**< (DEVEPTIER) Received SETUP Interrupt Enable Mask */ +#define DEVEPTIER_BLK_NAKOUTES_Pos 3 /**< (DEVEPTIER) NAKed OUT Interrupt Enable Position */ +#define DEVEPTIER_BLK_NAKOUTES (_U_(0x1) << DEVEPTIER_BLK_NAKOUTES_Pos) /**< (DEVEPTIER) NAKed OUT Interrupt Enable Mask */ +#define DEVEPTIER_BLK_NAKINES_Pos 4 /**< (DEVEPTIER) NAKed IN Interrupt Enable Position */ +#define DEVEPTIER_BLK_NAKINES (_U_(0x1) << DEVEPTIER_BLK_NAKINES_Pos) /**< (DEVEPTIER) NAKed IN Interrupt Enable Mask */ +#define DEVEPTIER_BLK_STALLEDES_Pos 6 /**< (DEVEPTIER) STALLed Interrupt Enable Position */ +#define DEVEPTIER_BLK_STALLEDES (_U_(0x1) << DEVEPTIER_BLK_STALLEDES_Pos) /**< (DEVEPTIER) STALLed Interrupt Enable Mask */ +#define DEVEPTIER_BLK_NYETDISS_Pos 17 /**< (DEVEPTIER) NYET Token Disable Enable Position */ +#define DEVEPTIER_BLK_NYETDISS (_U_(0x1) << DEVEPTIER_BLK_NYETDISS_Pos) /**< (DEVEPTIER) NYET Token Disable Enable Mask */ +#define DEVEPTIER_BLK_STALLRQS_Pos 19 /**< (DEVEPTIER) STALL Request Enable Position */ +#define DEVEPTIER_BLK_STALLRQS (_U_(0x1) << DEVEPTIER_BLK_STALLRQS_Pos) /**< (DEVEPTIER) STALL Request Enable Mask */ +#define DEVEPTIER_BLK_Msk _U_(0xA005C) /**< (DEVEPTIER_BLK) Register Mask */ + +/* INTRPT mode */ +#define DEVEPTIER_INTRPT_RXSTPES_Pos 2 /**< (DEVEPTIER) Received SETUP Interrupt Enable Position */ +#define DEVEPTIER_INTRPT_RXSTPES (_U_(0x1) << DEVEPTIER_INTRPT_RXSTPES_Pos) /**< (DEVEPTIER) Received SETUP Interrupt Enable Mask */ +#define DEVEPTIER_INTRPT_NAKOUTES_Pos 3 /**< (DEVEPTIER) NAKed OUT Interrupt Enable Position */ +#define DEVEPTIER_INTRPT_NAKOUTES (_U_(0x1) << DEVEPTIER_INTRPT_NAKOUTES_Pos) /**< (DEVEPTIER) NAKed OUT Interrupt Enable Mask */ +#define DEVEPTIER_INTRPT_NAKINES_Pos 4 /**< (DEVEPTIER) NAKed IN Interrupt Enable Position */ +#define DEVEPTIER_INTRPT_NAKINES (_U_(0x1) << DEVEPTIER_INTRPT_NAKINES_Pos) /**< (DEVEPTIER) NAKed IN Interrupt Enable Mask */ +#define DEVEPTIER_INTRPT_STALLEDES_Pos 6 /**< (DEVEPTIER) STALLed Interrupt Enable Position */ +#define DEVEPTIER_INTRPT_STALLEDES (_U_(0x1) << DEVEPTIER_INTRPT_STALLEDES_Pos) /**< (DEVEPTIER) STALLed Interrupt Enable Mask */ +#define DEVEPTIER_INTRPT_NYETDISS_Pos 17 /**< (DEVEPTIER) NYET Token Disable Enable Position */ +#define DEVEPTIER_INTRPT_NYETDISS (_U_(0x1) << DEVEPTIER_INTRPT_NYETDISS_Pos) /**< (DEVEPTIER) NYET Token Disable Enable Mask */ +#define DEVEPTIER_INTRPT_STALLRQS_Pos 19 /**< (DEVEPTIER) STALL Request Enable Position */ +#define DEVEPTIER_INTRPT_STALLRQS (_U_(0x1) << DEVEPTIER_INTRPT_STALLRQS_Pos) /**< (DEVEPTIER) STALL Request Enable Mask */ +#define DEVEPTIER_INTRPT_Msk _U_(0xA005C) /**< (DEVEPTIER_INTRPT) Register Mask */ + + +/* -------- DEVEPTIDR : (USBHS Offset: 0x220) (/W 32) Device Endpoint Interrupt Disable Register -------- */ + +#define DEVEPTIDR_OFFSET (0x220) /**< (DEVEPTIDR) Device Endpoint Interrupt Disable Register Offset */ + +#define DEVEPTIDR_TXINEC_Pos 0 /**< (DEVEPTIDR) Transmitted IN Interrupt Clear Position */ +#define DEVEPTIDR_TXINEC (_U_(0x1) << DEVEPTIDR_TXINEC_Pos) /**< (DEVEPTIDR) Transmitted IN Interrupt Clear Mask */ +#define DEVEPTIDR_RXOUTEC_Pos 1 /**< (DEVEPTIDR) Received OUT Data Interrupt Clear Position */ +#define DEVEPTIDR_RXOUTEC (_U_(0x1) << DEVEPTIDR_RXOUTEC_Pos) /**< (DEVEPTIDR) Received OUT Data Interrupt Clear Mask */ +#define DEVEPTIDR_OVERFEC_Pos 5 /**< (DEVEPTIDR) Overflow Interrupt Clear Position */ +#define DEVEPTIDR_OVERFEC (_U_(0x1) << DEVEPTIDR_OVERFEC_Pos) /**< (DEVEPTIDR) Overflow Interrupt Clear Mask */ +#define DEVEPTIDR_SHORTPACKETEC_Pos 7 /**< (DEVEPTIDR) Shortpacket Interrupt Clear Position */ +#define DEVEPTIDR_SHORTPACKETEC (_U_(0x1) << DEVEPTIDR_SHORTPACKETEC_Pos) /**< (DEVEPTIDR) Shortpacket Interrupt Clear Mask */ +#define DEVEPTIDR_NBUSYBKEC_Pos 12 /**< (DEVEPTIDR) Number of Busy Banks Interrupt Clear Position */ +#define DEVEPTIDR_NBUSYBKEC (_U_(0x1) << DEVEPTIDR_NBUSYBKEC_Pos) /**< (DEVEPTIDR) Number of Busy Banks Interrupt Clear Mask */ +#define DEVEPTIDR_FIFOCONC_Pos 14 /**< (DEVEPTIDR) FIFO Control Clear Position */ +#define DEVEPTIDR_FIFOCONC (_U_(0x1) << DEVEPTIDR_FIFOCONC_Pos) /**< (DEVEPTIDR) FIFO Control Clear Mask */ +#define DEVEPTIDR_EPDISHDMAC_Pos 16 /**< (DEVEPTIDR) Endpoint Interrupts Disable HDMA Request Clear Position */ +#define DEVEPTIDR_EPDISHDMAC (_U_(0x1) << DEVEPTIDR_EPDISHDMAC_Pos) /**< (DEVEPTIDR) Endpoint Interrupts Disable HDMA Request Clear Mask */ +#define DEVEPTIDR_Msk _U_(0x150A3) /**< (DEVEPTIDR) Register Mask */ + +/* CTRL mode */ +#define DEVEPTIDR_CTRL_RXSTPEC_Pos 2 /**< (DEVEPTIDR) Received SETUP Interrupt Clear Position */ +#define DEVEPTIDR_CTRL_RXSTPEC (_U_(0x1) << DEVEPTIDR_CTRL_RXSTPEC_Pos) /**< (DEVEPTIDR) Received SETUP Interrupt Clear Mask */ +#define DEVEPTIDR_CTRL_NAKOUTEC_Pos 3 /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Position */ +#define DEVEPTIDR_CTRL_NAKOUTEC (_U_(0x1) << DEVEPTIDR_CTRL_NAKOUTEC_Pos) /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Mask */ +#define DEVEPTIDR_CTRL_NAKINEC_Pos 4 /**< (DEVEPTIDR) NAKed IN Interrupt Clear Position */ +#define DEVEPTIDR_CTRL_NAKINEC (_U_(0x1) << DEVEPTIDR_CTRL_NAKINEC_Pos) /**< (DEVEPTIDR) NAKed IN Interrupt Clear Mask */ +#define DEVEPTIDR_CTRL_STALLEDEC_Pos 6 /**< (DEVEPTIDR) STALLed Interrupt Clear Position */ +#define DEVEPTIDR_CTRL_STALLEDEC (_U_(0x1) << DEVEPTIDR_CTRL_STALLEDEC_Pos) /**< (DEVEPTIDR) STALLed Interrupt Clear Mask */ +#define DEVEPTIDR_CTRL_NYETDISC_Pos 17 /**< (DEVEPTIDR) NYET Token Disable Clear Position */ +#define DEVEPTIDR_CTRL_NYETDISC (_U_(0x1) << DEVEPTIDR_CTRL_NYETDISC_Pos) /**< (DEVEPTIDR) NYET Token Disable Clear Mask */ +#define DEVEPTIDR_CTRL_STALLRQC_Pos 19 /**< (DEVEPTIDR) STALL Request Clear Position */ +#define DEVEPTIDR_CTRL_STALLRQC (_U_(0x1) << DEVEPTIDR_CTRL_STALLRQC_Pos) /**< (DEVEPTIDR) STALL Request Clear Mask */ +#define DEVEPTIDR_CTRL_Msk _U_(0xA005C) /**< (DEVEPTIDR_CTRL) Register Mask */ + +/* ISO mode */ +#define DEVEPTIDR_ISO_UNDERFEC_Pos 2 /**< (DEVEPTIDR) Underflow Interrupt Clear Position */ +#define DEVEPTIDR_ISO_UNDERFEC (_U_(0x1) << DEVEPTIDR_ISO_UNDERFEC_Pos) /**< (DEVEPTIDR) Underflow Interrupt Clear Mask */ +#define DEVEPTIDR_ISO_HBISOINERREC_Pos 3 /**< (DEVEPTIDR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Position */ +#define DEVEPTIDR_ISO_HBISOINERREC (_U_(0x1) << DEVEPTIDR_ISO_HBISOINERREC_Pos) /**< (DEVEPTIDR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Mask */ +#define DEVEPTIDR_ISO_HBISOFLUSHEC_Pos 4 /**< (DEVEPTIDR) High Bandwidth Isochronous IN Flush Interrupt Clear Position */ +#define DEVEPTIDR_ISO_HBISOFLUSHEC (_U_(0x1) << DEVEPTIDR_ISO_HBISOFLUSHEC_Pos) /**< (DEVEPTIDR) High Bandwidth Isochronous IN Flush Interrupt Clear Mask */ +#define DEVEPTIDR_ISO_MDATAEC_Pos 8 /**< (DEVEPTIDR) MData Interrupt Clear Position */ +#define DEVEPTIDR_ISO_MDATAEC (_U_(0x1) << DEVEPTIDR_ISO_MDATAEC_Pos) /**< (DEVEPTIDR) MData Interrupt Clear Mask */ +#define DEVEPTIDR_ISO_DATAXEC_Pos 9 /**< (DEVEPTIDR) DataX Interrupt Clear Position */ +#define DEVEPTIDR_ISO_DATAXEC (_U_(0x1) << DEVEPTIDR_ISO_DATAXEC_Pos) /**< (DEVEPTIDR) DataX Interrupt Clear Mask */ +#define DEVEPTIDR_ISO_ERRORTRANSEC_Pos 10 /**< (DEVEPTIDR) Transaction Error Interrupt Clear Position */ +#define DEVEPTIDR_ISO_ERRORTRANSEC (_U_(0x1) << DEVEPTIDR_ISO_ERRORTRANSEC_Pos) /**< (DEVEPTIDR) Transaction Error Interrupt Clear Mask */ +#define DEVEPTIDR_ISO_Msk _U_(0x71C) /**< (DEVEPTIDR_ISO) Register Mask */ + +/* BLK mode */ +#define DEVEPTIDR_BLK_RXSTPEC_Pos 2 /**< (DEVEPTIDR) Received SETUP Interrupt Clear Position */ +#define DEVEPTIDR_BLK_RXSTPEC (_U_(0x1) << DEVEPTIDR_BLK_RXSTPEC_Pos) /**< (DEVEPTIDR) Received SETUP Interrupt Clear Mask */ +#define DEVEPTIDR_BLK_NAKOUTEC_Pos 3 /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Position */ +#define DEVEPTIDR_BLK_NAKOUTEC (_U_(0x1) << DEVEPTIDR_BLK_NAKOUTEC_Pos) /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Mask */ +#define DEVEPTIDR_BLK_NAKINEC_Pos 4 /**< (DEVEPTIDR) NAKed IN Interrupt Clear Position */ +#define DEVEPTIDR_BLK_NAKINEC (_U_(0x1) << DEVEPTIDR_BLK_NAKINEC_Pos) /**< (DEVEPTIDR) NAKed IN Interrupt Clear Mask */ +#define DEVEPTIDR_BLK_STALLEDEC_Pos 6 /**< (DEVEPTIDR) STALLed Interrupt Clear Position */ +#define DEVEPTIDR_BLK_STALLEDEC (_U_(0x1) << DEVEPTIDR_BLK_STALLEDEC_Pos) /**< (DEVEPTIDR) STALLed Interrupt Clear Mask */ +#define DEVEPTIDR_BLK_NYETDISC_Pos 17 /**< (DEVEPTIDR) NYET Token Disable Clear Position */ +#define DEVEPTIDR_BLK_NYETDISC (_U_(0x1) << DEVEPTIDR_BLK_NYETDISC_Pos) /**< (DEVEPTIDR) NYET Token Disable Clear Mask */ +#define DEVEPTIDR_BLK_STALLRQC_Pos 19 /**< (DEVEPTIDR) STALL Request Clear Position */ +#define DEVEPTIDR_BLK_STALLRQC (_U_(0x1) << DEVEPTIDR_BLK_STALLRQC_Pos) /**< (DEVEPTIDR) STALL Request Clear Mask */ +#define DEVEPTIDR_BLK_Msk _U_(0xA005C) /**< (DEVEPTIDR_BLK) Register Mask */ + +/* INTRPT mode */ +#define DEVEPTIDR_INTRPT_RXSTPEC_Pos 2 /**< (DEVEPTIDR) Received SETUP Interrupt Clear Position */ +#define DEVEPTIDR_INTRPT_RXSTPEC (_U_(0x1) << DEVEPTIDR_INTRPT_RXSTPEC_Pos) /**< (DEVEPTIDR) Received SETUP Interrupt Clear Mask */ +#define DEVEPTIDR_INTRPT_NAKOUTEC_Pos 3 /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Position */ +#define DEVEPTIDR_INTRPT_NAKOUTEC (_U_(0x1) << DEVEPTIDR_INTRPT_NAKOUTEC_Pos) /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Mask */ +#define DEVEPTIDR_INTRPT_NAKINEC_Pos 4 /**< (DEVEPTIDR) NAKed IN Interrupt Clear Position */ +#define DEVEPTIDR_INTRPT_NAKINEC (_U_(0x1) << DEVEPTIDR_INTRPT_NAKINEC_Pos) /**< (DEVEPTIDR) NAKed IN Interrupt Clear Mask */ +#define DEVEPTIDR_INTRPT_STALLEDEC_Pos 6 /**< (DEVEPTIDR) STALLed Interrupt Clear Position */ +#define DEVEPTIDR_INTRPT_STALLEDEC (_U_(0x1) << DEVEPTIDR_INTRPT_STALLEDEC_Pos) /**< (DEVEPTIDR) STALLed Interrupt Clear Mask */ +#define DEVEPTIDR_INTRPT_NYETDISC_Pos 17 /**< (DEVEPTIDR) NYET Token Disable Clear Position */ +#define DEVEPTIDR_INTRPT_NYETDISC (_U_(0x1) << DEVEPTIDR_INTRPT_NYETDISC_Pos) /**< (DEVEPTIDR) NYET Token Disable Clear Mask */ +#define DEVEPTIDR_INTRPT_STALLRQC_Pos 19 /**< (DEVEPTIDR) STALL Request Clear Position */ +#define DEVEPTIDR_INTRPT_STALLRQC (_U_(0x1) << DEVEPTIDR_INTRPT_STALLRQC_Pos) /**< (DEVEPTIDR) STALL Request Clear Mask */ +#define DEVEPTIDR_INTRPT_Msk _U_(0xA005C) /**< (DEVEPTIDR_INTRPT) Register Mask */ + + +/* -------- HSTCTRL : (USBHS Offset: 0x400) (R/W 32) Host General Control Register -------- */ + +#define HSTCTRL_OFFSET (0x400) /**< (HSTCTRL) Host General Control Register Offset */ + +#define HSTCTRL_SOFE_Pos 8 /**< (HSTCTRL) Start of Frame Generation Enable Position */ +#define HSTCTRL_SOFE (_U_(0x1) << HSTCTRL_SOFE_Pos) /**< (HSTCTRL) Start of Frame Generation Enable Mask */ +#define HSTCTRL_RESET_Pos 9 /**< (HSTCTRL) Send USB Reset Position */ +#define HSTCTRL_RESET (_U_(0x1) << HSTCTRL_RESET_Pos) /**< (HSTCTRL) Send USB Reset Mask */ +#define HSTCTRL_RESUME_Pos 10 /**< (HSTCTRL) Send USB Resume Position */ +#define HSTCTRL_RESUME (_U_(0x1) << HSTCTRL_RESUME_Pos) /**< (HSTCTRL) Send USB Resume Mask */ +#define HSTCTRL_SPDCONF_Pos 12 /**< (HSTCTRL) Mode Configuration Position */ +#define HSTCTRL_SPDCONF (_U_(0x3) << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) Mode Configuration Mask */ +#define HSTCTRL_SPDCONF_NORMAL_Val _U_(0x0) /**< (HSTCTRL) The host starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the downstream peripheral is high-speed capable. */ +#define HSTCTRL_SPDCONF_LOW_POWER_Val _U_(0x1) /**< (HSTCTRL) For a better consumption, if high speed is not needed. */ +#define HSTCTRL_SPDCONF_HIGH_SPEED_Val _U_(0x2) /**< (HSTCTRL) Forced high speed. */ +#define HSTCTRL_SPDCONF_FORCED_FS_Val _U_(0x3) /**< (HSTCTRL) The host remains in Full-speed mode whatever the peripheral speed capability. */ +#define HSTCTRL_SPDCONF_NORMAL (HSTCTRL_SPDCONF_NORMAL_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) The host starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the downstream peripheral is high-speed capable. Position */ +#define HSTCTRL_SPDCONF_LOW_POWER (HSTCTRL_SPDCONF_LOW_POWER_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) For a better consumption, if high speed is not needed. Position */ +#define HSTCTRL_SPDCONF_HIGH_SPEED (HSTCTRL_SPDCONF_HIGH_SPEED_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) Forced high speed. Position */ +#define HSTCTRL_SPDCONF_FORCED_FS (HSTCTRL_SPDCONF_FORCED_FS_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) The host remains in Full-speed mode whatever the peripheral speed capability. Position */ +#define HSTCTRL_Msk _U_(0x3700) /**< (HSTCTRL) Register Mask */ + + +/* -------- HSTISR : (USBHS Offset: 0x404) (R/ 32) Host Global Interrupt Status Register -------- */ + +#define HSTISR_OFFSET (0x404) /**< (HSTISR) Host Global Interrupt Status Register Offset */ + +#define HSTISR_DCONNI_Pos 0 /**< (HSTISR) Device Connection Interrupt Position */ +#define HSTISR_DCONNI (_U_(0x1) << HSTISR_DCONNI_Pos) /**< (HSTISR) Device Connection Interrupt Mask */ +#define HSTISR_DDISCI_Pos 1 /**< (HSTISR) Device Disconnection Interrupt Position */ +#define HSTISR_DDISCI (_U_(0x1) << HSTISR_DDISCI_Pos) /**< (HSTISR) Device Disconnection Interrupt Mask */ +#define HSTISR_RSTI_Pos 2 /**< (HSTISR) USB Reset Sent Interrupt Position */ +#define HSTISR_RSTI (_U_(0x1) << HSTISR_RSTI_Pos) /**< (HSTISR) USB Reset Sent Interrupt Mask */ +#define HSTISR_RSMEDI_Pos 3 /**< (HSTISR) Downstream Resume Sent Interrupt Position */ +#define HSTISR_RSMEDI (_U_(0x1) << HSTISR_RSMEDI_Pos) /**< (HSTISR) Downstream Resume Sent Interrupt Mask */ +#define HSTISR_RXRSMI_Pos 4 /**< (HSTISR) Upstream Resume Received Interrupt Position */ +#define HSTISR_RXRSMI (_U_(0x1) << HSTISR_RXRSMI_Pos) /**< (HSTISR) Upstream Resume Received Interrupt Mask */ +#define HSTISR_HSOFI_Pos 5 /**< (HSTISR) Host Start of Frame Interrupt Position */ +#define HSTISR_HSOFI (_U_(0x1) << HSTISR_HSOFI_Pos) /**< (HSTISR) Host Start of Frame Interrupt Mask */ +#define HSTISR_HWUPI_Pos 6 /**< (HSTISR) Host Wake-Up Interrupt Position */ +#define HSTISR_HWUPI (_U_(0x1) << HSTISR_HWUPI_Pos) /**< (HSTISR) Host Wake-Up Interrupt Mask */ +#define HSTISR_PEP_0_Pos 8 /**< (HSTISR) Pipe 0 Interrupt Position */ +#define HSTISR_PEP_0 (_U_(0x1) << HSTISR_PEP_0_Pos) /**< (HSTISR) Pipe 0 Interrupt Mask */ +#define HSTISR_PEP_1_Pos 9 /**< (HSTISR) Pipe 1 Interrupt Position */ +#define HSTISR_PEP_1 (_U_(0x1) << HSTISR_PEP_1_Pos) /**< (HSTISR) Pipe 1 Interrupt Mask */ +#define HSTISR_PEP_2_Pos 10 /**< (HSTISR) Pipe 2 Interrupt Position */ +#define HSTISR_PEP_2 (_U_(0x1) << HSTISR_PEP_2_Pos) /**< (HSTISR) Pipe 2 Interrupt Mask */ +#define HSTISR_PEP_3_Pos 11 /**< (HSTISR) Pipe 3 Interrupt Position */ +#define HSTISR_PEP_3 (_U_(0x1) << HSTISR_PEP_3_Pos) /**< (HSTISR) Pipe 3 Interrupt Mask */ +#define HSTISR_PEP_4_Pos 12 /**< (HSTISR) Pipe 4 Interrupt Position */ +#define HSTISR_PEP_4 (_U_(0x1) << HSTISR_PEP_4_Pos) /**< (HSTISR) Pipe 4 Interrupt Mask */ +#define HSTISR_PEP_5_Pos 13 /**< (HSTISR) Pipe 5 Interrupt Position */ +#define HSTISR_PEP_5 (_U_(0x1) << HSTISR_PEP_5_Pos) /**< (HSTISR) Pipe 5 Interrupt Mask */ +#define HSTISR_PEP_6_Pos 14 /**< (HSTISR) Pipe 6 Interrupt Position */ +#define HSTISR_PEP_6 (_U_(0x1) << HSTISR_PEP_6_Pos) /**< (HSTISR) Pipe 6 Interrupt Mask */ +#define HSTISR_PEP_7_Pos 15 /**< (HSTISR) Pipe 7 Interrupt Position */ +#define HSTISR_PEP_7 (_U_(0x1) << HSTISR_PEP_7_Pos) /**< (HSTISR) Pipe 7 Interrupt Mask */ +#define HSTISR_PEP_8_Pos 16 /**< (HSTISR) Pipe 8 Interrupt Position */ +#define HSTISR_PEP_8 (_U_(0x1) << HSTISR_PEP_8_Pos) /**< (HSTISR) Pipe 8 Interrupt Mask */ +#define HSTISR_PEP_9_Pos 17 /**< (HSTISR) Pipe 9 Interrupt Position */ +#define HSTISR_PEP_9 (_U_(0x1) << HSTISR_PEP_9_Pos) /**< (HSTISR) Pipe 9 Interrupt Mask */ +#define HSTISR_DMA_0_Pos 25 /**< (HSTISR) DMA Channel 0 Interrupt Position */ +#define HSTISR_DMA_0 (_U_(0x1) << HSTISR_DMA_0_Pos) /**< (HSTISR) DMA Channel 0 Interrupt Mask */ +#define HSTISR_DMA_1_Pos 26 /**< (HSTISR) DMA Channel 1 Interrupt Position */ +#define HSTISR_DMA_1 (_U_(0x1) << HSTISR_DMA_1_Pos) /**< (HSTISR) DMA Channel 1 Interrupt Mask */ +#define HSTISR_DMA_2_Pos 27 /**< (HSTISR) DMA Channel 2 Interrupt Position */ +#define HSTISR_DMA_2 (_U_(0x1) << HSTISR_DMA_2_Pos) /**< (HSTISR) DMA Channel 2 Interrupt Mask */ +#define HSTISR_DMA_3_Pos 28 /**< (HSTISR) DMA Channel 3 Interrupt Position */ +#define HSTISR_DMA_3 (_U_(0x1) << HSTISR_DMA_3_Pos) /**< (HSTISR) DMA Channel 3 Interrupt Mask */ +#define HSTISR_DMA_4_Pos 29 /**< (HSTISR) DMA Channel 4 Interrupt Position */ +#define HSTISR_DMA_4 (_U_(0x1) << HSTISR_DMA_4_Pos) /**< (HSTISR) DMA Channel 4 Interrupt Mask */ +#define HSTISR_DMA_5_Pos 30 /**< (HSTISR) DMA Channel 5 Interrupt Position */ +#define HSTISR_DMA_5 (_U_(0x1) << HSTISR_DMA_5_Pos) /**< (HSTISR) DMA Channel 5 Interrupt Mask */ +#define HSTISR_DMA_6_Pos 31 /**< (HSTISR) DMA Channel 6 Interrupt Position */ +#define HSTISR_DMA_6 (_U_(0x1) << HSTISR_DMA_6_Pos) /**< (HSTISR) DMA Channel 6 Interrupt Mask */ +#define HSTISR_Msk _U_(0xFE03FF7F) /**< (HSTISR) Register Mask */ + +#define HSTISR_PEP__Pos 8 /**< (HSTISR Position) Pipe x Interrupt */ +#define HSTISR_PEP_ (_U_(0x3FF) << HSTISR_PEP__Pos) /**< (HSTISR Mask) PEP_ */ +#define HSTISR_DMA__Pos 25 /**< (HSTISR Position) DMA Channel 6 Interrupt */ +#define HSTISR_DMA_ (_U_(0x7F) << HSTISR_DMA__Pos) /**< (HSTISR Mask) DMA_ */ + +/* -------- HSTICR : (USBHS Offset: 0x408) (/W 32) Host Global Interrupt Clear Register -------- */ + +#define HSTICR_OFFSET (0x408) /**< (HSTICR) Host Global Interrupt Clear Register Offset */ + +#define HSTICR_DCONNIC_Pos 0 /**< (HSTICR) Device Connection Interrupt Clear Position */ +#define HSTICR_DCONNIC (_U_(0x1) << HSTICR_DCONNIC_Pos) /**< (HSTICR) Device Connection Interrupt Clear Mask */ +#define HSTICR_DDISCIC_Pos 1 /**< (HSTICR) Device Disconnection Interrupt Clear Position */ +#define HSTICR_DDISCIC (_U_(0x1) << HSTICR_DDISCIC_Pos) /**< (HSTICR) Device Disconnection Interrupt Clear Mask */ +#define HSTICR_RSTIC_Pos 2 /**< (HSTICR) USB Reset Sent Interrupt Clear Position */ +#define HSTICR_RSTIC (_U_(0x1) << HSTICR_RSTIC_Pos) /**< (HSTICR) USB Reset Sent Interrupt Clear Mask */ +#define HSTICR_RSMEDIC_Pos 3 /**< (HSTICR) Downstream Resume Sent Interrupt Clear Position */ +#define HSTICR_RSMEDIC (_U_(0x1) << HSTICR_RSMEDIC_Pos) /**< (HSTICR) Downstream Resume Sent Interrupt Clear Mask */ +#define HSTICR_RXRSMIC_Pos 4 /**< (HSTICR) Upstream Resume Received Interrupt Clear Position */ +#define HSTICR_RXRSMIC (_U_(0x1) << HSTICR_RXRSMIC_Pos) /**< (HSTICR) Upstream Resume Received Interrupt Clear Mask */ +#define HSTICR_HSOFIC_Pos 5 /**< (HSTICR) Host Start of Frame Interrupt Clear Position */ +#define HSTICR_HSOFIC (_U_(0x1) << HSTICR_HSOFIC_Pos) /**< (HSTICR) Host Start of Frame Interrupt Clear Mask */ +#define HSTICR_HWUPIC_Pos 6 /**< (HSTICR) Host Wake-Up Interrupt Clear Position */ +#define HSTICR_HWUPIC (_U_(0x1) << HSTICR_HWUPIC_Pos) /**< (HSTICR) Host Wake-Up Interrupt Clear Mask */ +#define HSTICR_Msk _U_(0x7F) /**< (HSTICR) Register Mask */ + + +/* -------- HSTIFR : (USBHS Offset: 0x40c) (/W 32) Host Global Interrupt Set Register -------- */ + +#define HSTIFR_OFFSET (0x40C) /**< (HSTIFR) Host Global Interrupt Set Register Offset */ + +#define HSTIFR_DCONNIS_Pos 0 /**< (HSTIFR) Device Connection Interrupt Set Position */ +#define HSTIFR_DCONNIS (_U_(0x1) << HSTIFR_DCONNIS_Pos) /**< (HSTIFR) Device Connection Interrupt Set Mask */ +#define HSTIFR_DDISCIS_Pos 1 /**< (HSTIFR) Device Disconnection Interrupt Set Position */ +#define HSTIFR_DDISCIS (_U_(0x1) << HSTIFR_DDISCIS_Pos) /**< (HSTIFR) Device Disconnection Interrupt Set Mask */ +#define HSTIFR_RSTIS_Pos 2 /**< (HSTIFR) USB Reset Sent Interrupt Set Position */ +#define HSTIFR_RSTIS (_U_(0x1) << HSTIFR_RSTIS_Pos) /**< (HSTIFR) USB Reset Sent Interrupt Set Mask */ +#define HSTIFR_RSMEDIS_Pos 3 /**< (HSTIFR) Downstream Resume Sent Interrupt Set Position */ +#define HSTIFR_RSMEDIS (_U_(0x1) << HSTIFR_RSMEDIS_Pos) /**< (HSTIFR) Downstream Resume Sent Interrupt Set Mask */ +#define HSTIFR_RXRSMIS_Pos 4 /**< (HSTIFR) Upstream Resume Received Interrupt Set Position */ +#define HSTIFR_RXRSMIS (_U_(0x1) << HSTIFR_RXRSMIS_Pos) /**< (HSTIFR) Upstream Resume Received Interrupt Set Mask */ +#define HSTIFR_HSOFIS_Pos 5 /**< (HSTIFR) Host Start of Frame Interrupt Set Position */ +#define HSTIFR_HSOFIS (_U_(0x1) << HSTIFR_HSOFIS_Pos) /**< (HSTIFR) Host Start of Frame Interrupt Set Mask */ +#define HSTIFR_HWUPIS_Pos 6 /**< (HSTIFR) Host Wake-Up Interrupt Set Position */ +#define HSTIFR_HWUPIS (_U_(0x1) << HSTIFR_HWUPIS_Pos) /**< (HSTIFR) Host Wake-Up Interrupt Set Mask */ +#define HSTIFR_DMA_0_Pos 25 /**< (HSTIFR) DMA Channel 0 Interrupt Set Position */ +#define HSTIFR_DMA_0 (_U_(0x1) << HSTIFR_DMA_0_Pos) /**< (HSTIFR) DMA Channel 0 Interrupt Set Mask */ +#define HSTIFR_DMA_1_Pos 26 /**< (HSTIFR) DMA Channel 1 Interrupt Set Position */ +#define HSTIFR_DMA_1 (_U_(0x1) << HSTIFR_DMA_1_Pos) /**< (HSTIFR) DMA Channel 1 Interrupt Set Mask */ +#define HSTIFR_DMA_2_Pos 27 /**< (HSTIFR) DMA Channel 2 Interrupt Set Position */ +#define HSTIFR_DMA_2 (_U_(0x1) << HSTIFR_DMA_2_Pos) /**< (HSTIFR) DMA Channel 2 Interrupt Set Mask */ +#define HSTIFR_DMA_3_Pos 28 /**< (HSTIFR) DMA Channel 3 Interrupt Set Position */ +#define HSTIFR_DMA_3 (_U_(0x1) << HSTIFR_DMA_3_Pos) /**< (HSTIFR) DMA Channel 3 Interrupt Set Mask */ +#define HSTIFR_DMA_4_Pos 29 /**< (HSTIFR) DMA Channel 4 Interrupt Set Position */ +#define HSTIFR_DMA_4 (_U_(0x1) << HSTIFR_DMA_4_Pos) /**< (HSTIFR) DMA Channel 4 Interrupt Set Mask */ +#define HSTIFR_DMA_5_Pos 30 /**< (HSTIFR) DMA Channel 5 Interrupt Set Position */ +#define HSTIFR_DMA_5 (_U_(0x1) << HSTIFR_DMA_5_Pos) /**< (HSTIFR) DMA Channel 5 Interrupt Set Mask */ +#define HSTIFR_DMA_6_Pos 31 /**< (HSTIFR) DMA Channel 6 Interrupt Set Position */ +#define HSTIFR_DMA_6 (_U_(0x1) << HSTIFR_DMA_6_Pos) /**< (HSTIFR) DMA Channel 6 Interrupt Set Mask */ +#define HSTIFR_Msk _U_(0xFE00007F) /**< (HSTIFR) Register Mask */ + +#define HSTIFR_DMA__Pos 25 /**< (HSTIFR Position) DMA Channel 6 Interrupt Set */ +#define HSTIFR_DMA_ (_U_(0x7F) << HSTIFR_DMA__Pos) /**< (HSTIFR Mask) DMA_ */ + +/* -------- HSTIMR : (USBHS Offset: 0x410) (R/ 32) Host Global Interrupt Mask Register -------- */ + +#define HSTIMR_OFFSET (0x410) /**< (HSTIMR) Host Global Interrupt Mask Register Offset */ + +#define HSTIMR_DCONNIE_Pos 0 /**< (HSTIMR) Device Connection Interrupt Enable Position */ +#define HSTIMR_DCONNIE (_U_(0x1) << HSTIMR_DCONNIE_Pos) /**< (HSTIMR) Device Connection Interrupt Enable Mask */ +#define HSTIMR_DDISCIE_Pos 1 /**< (HSTIMR) Device Disconnection Interrupt Enable Position */ +#define HSTIMR_DDISCIE (_U_(0x1) << HSTIMR_DDISCIE_Pos) /**< (HSTIMR) Device Disconnection Interrupt Enable Mask */ +#define HSTIMR_RSTIE_Pos 2 /**< (HSTIMR) USB Reset Sent Interrupt Enable Position */ +#define HSTIMR_RSTIE (_U_(0x1) << HSTIMR_RSTIE_Pos) /**< (HSTIMR) USB Reset Sent Interrupt Enable Mask */ +#define HSTIMR_RSMEDIE_Pos 3 /**< (HSTIMR) Downstream Resume Sent Interrupt Enable Position */ +#define HSTIMR_RSMEDIE (_U_(0x1) << HSTIMR_RSMEDIE_Pos) /**< (HSTIMR) Downstream Resume Sent Interrupt Enable Mask */ +#define HSTIMR_RXRSMIE_Pos 4 /**< (HSTIMR) Upstream Resume Received Interrupt Enable Position */ +#define HSTIMR_RXRSMIE (_U_(0x1) << HSTIMR_RXRSMIE_Pos) /**< (HSTIMR) Upstream Resume Received Interrupt Enable Mask */ +#define HSTIMR_HSOFIE_Pos 5 /**< (HSTIMR) Host Start of Frame Interrupt Enable Position */ +#define HSTIMR_HSOFIE (_U_(0x1) << HSTIMR_HSOFIE_Pos) /**< (HSTIMR) Host Start of Frame Interrupt Enable Mask */ +#define HSTIMR_HWUPIE_Pos 6 /**< (HSTIMR) Host Wake-Up Interrupt Enable Position */ +#define HSTIMR_HWUPIE (_U_(0x1) << HSTIMR_HWUPIE_Pos) /**< (HSTIMR) Host Wake-Up Interrupt Enable Mask */ +#define HSTIMR_PEP_0_Pos 8 /**< (HSTIMR) Pipe 0 Interrupt Enable Position */ +#define HSTIMR_PEP_0 (_U_(0x1) << HSTIMR_PEP_0_Pos) /**< (HSTIMR) Pipe 0 Interrupt Enable Mask */ +#define HSTIMR_PEP_1_Pos 9 /**< (HSTIMR) Pipe 1 Interrupt Enable Position */ +#define HSTIMR_PEP_1 (_U_(0x1) << HSTIMR_PEP_1_Pos) /**< (HSTIMR) Pipe 1 Interrupt Enable Mask */ +#define HSTIMR_PEP_2_Pos 10 /**< (HSTIMR) Pipe 2 Interrupt Enable Position */ +#define HSTIMR_PEP_2 (_U_(0x1) << HSTIMR_PEP_2_Pos) /**< (HSTIMR) Pipe 2 Interrupt Enable Mask */ +#define HSTIMR_PEP_3_Pos 11 /**< (HSTIMR) Pipe 3 Interrupt Enable Position */ +#define HSTIMR_PEP_3 (_U_(0x1) << HSTIMR_PEP_3_Pos) /**< (HSTIMR) Pipe 3 Interrupt Enable Mask */ +#define HSTIMR_PEP_4_Pos 12 /**< (HSTIMR) Pipe 4 Interrupt Enable Position */ +#define HSTIMR_PEP_4 (_U_(0x1) << HSTIMR_PEP_4_Pos) /**< (HSTIMR) Pipe 4 Interrupt Enable Mask */ +#define HSTIMR_PEP_5_Pos 13 /**< (HSTIMR) Pipe 5 Interrupt Enable Position */ +#define HSTIMR_PEP_5 (_U_(0x1) << HSTIMR_PEP_5_Pos) /**< (HSTIMR) Pipe 5 Interrupt Enable Mask */ +#define HSTIMR_PEP_6_Pos 14 /**< (HSTIMR) Pipe 6 Interrupt Enable Position */ +#define HSTIMR_PEP_6 (_U_(0x1) << HSTIMR_PEP_6_Pos) /**< (HSTIMR) Pipe 6 Interrupt Enable Mask */ +#define HSTIMR_PEP_7_Pos 15 /**< (HSTIMR) Pipe 7 Interrupt Enable Position */ +#define HSTIMR_PEP_7 (_U_(0x1) << HSTIMR_PEP_7_Pos) /**< (HSTIMR) Pipe 7 Interrupt Enable Mask */ +#define HSTIMR_PEP_8_Pos 16 /**< (HSTIMR) Pipe 8 Interrupt Enable Position */ +#define HSTIMR_PEP_8 (_U_(0x1) << HSTIMR_PEP_8_Pos) /**< (HSTIMR) Pipe 8 Interrupt Enable Mask */ +#define HSTIMR_PEP_9_Pos 17 /**< (HSTIMR) Pipe 9 Interrupt Enable Position */ +#define HSTIMR_PEP_9 (_U_(0x1) << HSTIMR_PEP_9_Pos) /**< (HSTIMR) Pipe 9 Interrupt Enable Mask */ +#define HSTIMR_DMA_0_Pos 25 /**< (HSTIMR) DMA Channel 0 Interrupt Enable Position */ +#define HSTIMR_DMA_0 (_U_(0x1) << HSTIMR_DMA_0_Pos) /**< (HSTIMR) DMA Channel 0 Interrupt Enable Mask */ +#define HSTIMR_DMA_1_Pos 26 /**< (HSTIMR) DMA Channel 1 Interrupt Enable Position */ +#define HSTIMR_DMA_1 (_U_(0x1) << HSTIMR_DMA_1_Pos) /**< (HSTIMR) DMA Channel 1 Interrupt Enable Mask */ +#define HSTIMR_DMA_2_Pos 27 /**< (HSTIMR) DMA Channel 2 Interrupt Enable Position */ +#define HSTIMR_DMA_2 (_U_(0x1) << HSTIMR_DMA_2_Pos) /**< (HSTIMR) DMA Channel 2 Interrupt Enable Mask */ +#define HSTIMR_DMA_3_Pos 28 /**< (HSTIMR) DMA Channel 3 Interrupt Enable Position */ +#define HSTIMR_DMA_3 (_U_(0x1) << HSTIMR_DMA_3_Pos) /**< (HSTIMR) DMA Channel 3 Interrupt Enable Mask */ +#define HSTIMR_DMA_4_Pos 29 /**< (HSTIMR) DMA Channel 4 Interrupt Enable Position */ +#define HSTIMR_DMA_4 (_U_(0x1) << HSTIMR_DMA_4_Pos) /**< (HSTIMR) DMA Channel 4 Interrupt Enable Mask */ +#define HSTIMR_DMA_5_Pos 30 /**< (HSTIMR) DMA Channel 5 Interrupt Enable Position */ +#define HSTIMR_DMA_5 (_U_(0x1) << HSTIMR_DMA_5_Pos) /**< (HSTIMR) DMA Channel 5 Interrupt Enable Mask */ +#define HSTIMR_DMA_6_Pos 31 /**< (HSTIMR) DMA Channel 6 Interrupt Enable Position */ +#define HSTIMR_DMA_6 (_U_(0x1) << HSTIMR_DMA_6_Pos) /**< (HSTIMR) DMA Channel 6 Interrupt Enable Mask */ +#define HSTIMR_Msk _U_(0xFE03FF7F) /**< (HSTIMR) Register Mask */ + +#define HSTIMR_PEP__Pos 8 /**< (HSTIMR Position) Pipe x Interrupt Enable */ +#define HSTIMR_PEP_ (_U_(0x3FF) << HSTIMR_PEP__Pos) /**< (HSTIMR Mask) PEP_ */ +#define HSTIMR_DMA__Pos 25 /**< (HSTIMR Position) DMA Channel 6 Interrupt Enable */ +#define HSTIMR_DMA_ (_U_(0x7F) << HSTIMR_DMA__Pos) /**< (HSTIMR Mask) DMA_ */ + +/* -------- HSTIDR : (USBHS Offset: 0x414) (/W 32) Host Global Interrupt Disable Register -------- */ + +#define HSTIDR_OFFSET (0x414) /**< (HSTIDR) Host Global Interrupt Disable Register Offset */ + +#define HSTIDR_DCONNIEC_Pos 0 /**< (HSTIDR) Device Connection Interrupt Disable Position */ +#define HSTIDR_DCONNIEC (_U_(0x1) << HSTIDR_DCONNIEC_Pos) /**< (HSTIDR) Device Connection Interrupt Disable Mask */ +#define HSTIDR_DDISCIEC_Pos 1 /**< (HSTIDR) Device Disconnection Interrupt Disable Position */ +#define HSTIDR_DDISCIEC (_U_(0x1) << HSTIDR_DDISCIEC_Pos) /**< (HSTIDR) Device Disconnection Interrupt Disable Mask */ +#define HSTIDR_RSTIEC_Pos 2 /**< (HSTIDR) USB Reset Sent Interrupt Disable Position */ +#define HSTIDR_RSTIEC (_U_(0x1) << HSTIDR_RSTIEC_Pos) /**< (HSTIDR) USB Reset Sent Interrupt Disable Mask */ +#define HSTIDR_RSMEDIEC_Pos 3 /**< (HSTIDR) Downstream Resume Sent Interrupt Disable Position */ +#define HSTIDR_RSMEDIEC (_U_(0x1) << HSTIDR_RSMEDIEC_Pos) /**< (HSTIDR) Downstream Resume Sent Interrupt Disable Mask */ +#define HSTIDR_RXRSMIEC_Pos 4 /**< (HSTIDR) Upstream Resume Received Interrupt Disable Position */ +#define HSTIDR_RXRSMIEC (_U_(0x1) << HSTIDR_RXRSMIEC_Pos) /**< (HSTIDR) Upstream Resume Received Interrupt Disable Mask */ +#define HSTIDR_HSOFIEC_Pos 5 /**< (HSTIDR) Host Start of Frame Interrupt Disable Position */ +#define HSTIDR_HSOFIEC (_U_(0x1) << HSTIDR_HSOFIEC_Pos) /**< (HSTIDR) Host Start of Frame Interrupt Disable Mask */ +#define HSTIDR_HWUPIEC_Pos 6 /**< (HSTIDR) Host Wake-Up Interrupt Disable Position */ +#define HSTIDR_HWUPIEC (_U_(0x1) << HSTIDR_HWUPIEC_Pos) /**< (HSTIDR) Host Wake-Up Interrupt Disable Mask */ +#define HSTIDR_PEP_0_Pos 8 /**< (HSTIDR) Pipe 0 Interrupt Disable Position */ +#define HSTIDR_PEP_0 (_U_(0x1) << HSTIDR_PEP_0_Pos) /**< (HSTIDR) Pipe 0 Interrupt Disable Mask */ +#define HSTIDR_PEP_1_Pos 9 /**< (HSTIDR) Pipe 1 Interrupt Disable Position */ +#define HSTIDR_PEP_1 (_U_(0x1) << HSTIDR_PEP_1_Pos) /**< (HSTIDR) Pipe 1 Interrupt Disable Mask */ +#define HSTIDR_PEP_2_Pos 10 /**< (HSTIDR) Pipe 2 Interrupt Disable Position */ +#define HSTIDR_PEP_2 (_U_(0x1) << HSTIDR_PEP_2_Pos) /**< (HSTIDR) Pipe 2 Interrupt Disable Mask */ +#define HSTIDR_PEP_3_Pos 11 /**< (HSTIDR) Pipe 3 Interrupt Disable Position */ +#define HSTIDR_PEP_3 (_U_(0x1) << HSTIDR_PEP_3_Pos) /**< (HSTIDR) Pipe 3 Interrupt Disable Mask */ +#define HSTIDR_PEP_4_Pos 12 /**< (HSTIDR) Pipe 4 Interrupt Disable Position */ +#define HSTIDR_PEP_4 (_U_(0x1) << HSTIDR_PEP_4_Pos) /**< (HSTIDR) Pipe 4 Interrupt Disable Mask */ +#define HSTIDR_PEP_5_Pos 13 /**< (HSTIDR) Pipe 5 Interrupt Disable Position */ +#define HSTIDR_PEP_5 (_U_(0x1) << HSTIDR_PEP_5_Pos) /**< (HSTIDR) Pipe 5 Interrupt Disable Mask */ +#define HSTIDR_PEP_6_Pos 14 /**< (HSTIDR) Pipe 6 Interrupt Disable Position */ +#define HSTIDR_PEP_6 (_U_(0x1) << HSTIDR_PEP_6_Pos) /**< (HSTIDR) Pipe 6 Interrupt Disable Mask */ +#define HSTIDR_PEP_7_Pos 15 /**< (HSTIDR) Pipe 7 Interrupt Disable Position */ +#define HSTIDR_PEP_7 (_U_(0x1) << HSTIDR_PEP_7_Pos) /**< (HSTIDR) Pipe 7 Interrupt Disable Mask */ +#define HSTIDR_PEP_8_Pos 16 /**< (HSTIDR) Pipe 8 Interrupt Disable Position */ +#define HSTIDR_PEP_8 (_U_(0x1) << HSTIDR_PEP_8_Pos) /**< (HSTIDR) Pipe 8 Interrupt Disable Mask */ +#define HSTIDR_PEP_9_Pos 17 /**< (HSTIDR) Pipe 9 Interrupt Disable Position */ +#define HSTIDR_PEP_9 (_U_(0x1) << HSTIDR_PEP_9_Pos) /**< (HSTIDR) Pipe 9 Interrupt Disable Mask */ +#define HSTIDR_DMA_0_Pos 25 /**< (HSTIDR) DMA Channel 0 Interrupt Disable Position */ +#define HSTIDR_DMA_0 (_U_(0x1) << HSTIDR_DMA_0_Pos) /**< (HSTIDR) DMA Channel 0 Interrupt Disable Mask */ +#define HSTIDR_DMA_1_Pos 26 /**< (HSTIDR) DMA Channel 1 Interrupt Disable Position */ +#define HSTIDR_DMA_1 (_U_(0x1) << HSTIDR_DMA_1_Pos) /**< (HSTIDR) DMA Channel 1 Interrupt Disable Mask */ +#define HSTIDR_DMA_2_Pos 27 /**< (HSTIDR) DMA Channel 2 Interrupt Disable Position */ +#define HSTIDR_DMA_2 (_U_(0x1) << HSTIDR_DMA_2_Pos) /**< (HSTIDR) DMA Channel 2 Interrupt Disable Mask */ +#define HSTIDR_DMA_3_Pos 28 /**< (HSTIDR) DMA Channel 3 Interrupt Disable Position */ +#define HSTIDR_DMA_3 (_U_(0x1) << HSTIDR_DMA_3_Pos) /**< (HSTIDR) DMA Channel 3 Interrupt Disable Mask */ +#define HSTIDR_DMA_4_Pos 29 /**< (HSTIDR) DMA Channel 4 Interrupt Disable Position */ +#define HSTIDR_DMA_4 (_U_(0x1) << HSTIDR_DMA_4_Pos) /**< (HSTIDR) DMA Channel 4 Interrupt Disable Mask */ +#define HSTIDR_DMA_5_Pos 30 /**< (HSTIDR) DMA Channel 5 Interrupt Disable Position */ +#define HSTIDR_DMA_5 (_U_(0x1) << HSTIDR_DMA_5_Pos) /**< (HSTIDR) DMA Channel 5 Interrupt Disable Mask */ +#define HSTIDR_DMA_6_Pos 31 /**< (HSTIDR) DMA Channel 6 Interrupt Disable Position */ +#define HSTIDR_DMA_6 (_U_(0x1) << HSTIDR_DMA_6_Pos) /**< (HSTIDR) DMA Channel 6 Interrupt Disable Mask */ +#define HSTIDR_Msk _U_(0xFE03FF7F) /**< (HSTIDR) Register Mask */ + +#define HSTIDR_PEP__Pos 8 /**< (HSTIDR Position) Pipe x Interrupt Disable */ +#define HSTIDR_PEP_ (_U_(0x3FF) << HSTIDR_PEP__Pos) /**< (HSTIDR Mask) PEP_ */ +#define HSTIDR_DMA__Pos 25 /**< (HSTIDR Position) DMA Channel 6 Interrupt Disable */ +#define HSTIDR_DMA_ (_U_(0x7F) << HSTIDR_DMA__Pos) /**< (HSTIDR Mask) DMA_ */ + +/* -------- HSTIER : (USBHS Offset: 0x418) (/W 32) Host Global Interrupt Enable Register -------- */ + +#define HSTIER_OFFSET (0x418) /**< (HSTIER) Host Global Interrupt Enable Register Offset */ + +#define HSTIER_DCONNIES_Pos 0 /**< (HSTIER) Device Connection Interrupt Enable Position */ +#define HSTIER_DCONNIES (_U_(0x1) << HSTIER_DCONNIES_Pos) /**< (HSTIER) Device Connection Interrupt Enable Mask */ +#define HSTIER_DDISCIES_Pos 1 /**< (HSTIER) Device Disconnection Interrupt Enable Position */ +#define HSTIER_DDISCIES (_U_(0x1) << HSTIER_DDISCIES_Pos) /**< (HSTIER) Device Disconnection Interrupt Enable Mask */ +#define HSTIER_RSTIES_Pos 2 /**< (HSTIER) USB Reset Sent Interrupt Enable Position */ +#define HSTIER_RSTIES (_U_(0x1) << HSTIER_RSTIES_Pos) /**< (HSTIER) USB Reset Sent Interrupt Enable Mask */ +#define HSTIER_RSMEDIES_Pos 3 /**< (HSTIER) Downstream Resume Sent Interrupt Enable Position */ +#define HSTIER_RSMEDIES (_U_(0x1) << HSTIER_RSMEDIES_Pos) /**< (HSTIER) Downstream Resume Sent Interrupt Enable Mask */ +#define HSTIER_RXRSMIES_Pos 4 /**< (HSTIER) Upstream Resume Received Interrupt Enable Position */ +#define HSTIER_RXRSMIES (_U_(0x1) << HSTIER_RXRSMIES_Pos) /**< (HSTIER) Upstream Resume Received Interrupt Enable Mask */ +#define HSTIER_HSOFIES_Pos 5 /**< (HSTIER) Host Start of Frame Interrupt Enable Position */ +#define HSTIER_HSOFIES (_U_(0x1) << HSTIER_HSOFIES_Pos) /**< (HSTIER) Host Start of Frame Interrupt Enable Mask */ +#define HSTIER_HWUPIES_Pos 6 /**< (HSTIER) Host Wake-Up Interrupt Enable Position */ +#define HSTIER_HWUPIES (_U_(0x1) << HSTIER_HWUPIES_Pos) /**< (HSTIER) Host Wake-Up Interrupt Enable Mask */ +#define HSTIER_PEP_0_Pos 8 /**< (HSTIER) Pipe 0 Interrupt Enable Position */ +#define HSTIER_PEP_0 (_U_(0x1) << HSTIER_PEP_0_Pos) /**< (HSTIER) Pipe 0 Interrupt Enable Mask */ +#define HSTIER_PEP_1_Pos 9 /**< (HSTIER) Pipe 1 Interrupt Enable Position */ +#define HSTIER_PEP_1 (_U_(0x1) << HSTIER_PEP_1_Pos) /**< (HSTIER) Pipe 1 Interrupt Enable Mask */ +#define HSTIER_PEP_2_Pos 10 /**< (HSTIER) Pipe 2 Interrupt Enable Position */ +#define HSTIER_PEP_2 (_U_(0x1) << HSTIER_PEP_2_Pos) /**< (HSTIER) Pipe 2 Interrupt Enable Mask */ +#define HSTIER_PEP_3_Pos 11 /**< (HSTIER) Pipe 3 Interrupt Enable Position */ +#define HSTIER_PEP_3 (_U_(0x1) << HSTIER_PEP_3_Pos) /**< (HSTIER) Pipe 3 Interrupt Enable Mask */ +#define HSTIER_PEP_4_Pos 12 /**< (HSTIER) Pipe 4 Interrupt Enable Position */ +#define HSTIER_PEP_4 (_U_(0x1) << HSTIER_PEP_4_Pos) /**< (HSTIER) Pipe 4 Interrupt Enable Mask */ +#define HSTIER_PEP_5_Pos 13 /**< (HSTIER) Pipe 5 Interrupt Enable Position */ +#define HSTIER_PEP_5 (_U_(0x1) << HSTIER_PEP_5_Pos) /**< (HSTIER) Pipe 5 Interrupt Enable Mask */ +#define HSTIER_PEP_6_Pos 14 /**< (HSTIER) Pipe 6 Interrupt Enable Position */ +#define HSTIER_PEP_6 (_U_(0x1) << HSTIER_PEP_6_Pos) /**< (HSTIER) Pipe 6 Interrupt Enable Mask */ +#define HSTIER_PEP_7_Pos 15 /**< (HSTIER) Pipe 7 Interrupt Enable Position */ +#define HSTIER_PEP_7 (_U_(0x1) << HSTIER_PEP_7_Pos) /**< (HSTIER) Pipe 7 Interrupt Enable Mask */ +#define HSTIER_PEP_8_Pos 16 /**< (HSTIER) Pipe 8 Interrupt Enable Position */ +#define HSTIER_PEP_8 (_U_(0x1) << HSTIER_PEP_8_Pos) /**< (HSTIER) Pipe 8 Interrupt Enable Mask */ +#define HSTIER_PEP_9_Pos 17 /**< (HSTIER) Pipe 9 Interrupt Enable Position */ +#define HSTIER_PEP_9 (_U_(0x1) << HSTIER_PEP_9_Pos) /**< (HSTIER) Pipe 9 Interrupt Enable Mask */ +#define HSTIER_DMA_0_Pos 25 /**< (HSTIER) DMA Channel 0 Interrupt Enable Position */ +#define HSTIER_DMA_0 (_U_(0x1) << HSTIER_DMA_0_Pos) /**< (HSTIER) DMA Channel 0 Interrupt Enable Mask */ +#define HSTIER_DMA_1_Pos 26 /**< (HSTIER) DMA Channel 1 Interrupt Enable Position */ +#define HSTIER_DMA_1 (_U_(0x1) << HSTIER_DMA_1_Pos) /**< (HSTIER) DMA Channel 1 Interrupt Enable Mask */ +#define HSTIER_DMA_2_Pos 27 /**< (HSTIER) DMA Channel 2 Interrupt Enable Position */ +#define HSTIER_DMA_2 (_U_(0x1) << HSTIER_DMA_2_Pos) /**< (HSTIER) DMA Channel 2 Interrupt Enable Mask */ +#define HSTIER_DMA_3_Pos 28 /**< (HSTIER) DMA Channel 3 Interrupt Enable Position */ +#define HSTIER_DMA_3 (_U_(0x1) << HSTIER_DMA_3_Pos) /**< (HSTIER) DMA Channel 3 Interrupt Enable Mask */ +#define HSTIER_DMA_4_Pos 29 /**< (HSTIER) DMA Channel 4 Interrupt Enable Position */ +#define HSTIER_DMA_4 (_U_(0x1) << HSTIER_DMA_4_Pos) /**< (HSTIER) DMA Channel 4 Interrupt Enable Mask */ +#define HSTIER_DMA_5_Pos 30 /**< (HSTIER) DMA Channel 5 Interrupt Enable Position */ +#define HSTIER_DMA_5 (_U_(0x1) << HSTIER_DMA_5_Pos) /**< (HSTIER) DMA Channel 5 Interrupt Enable Mask */ +#define HSTIER_DMA_6_Pos 31 /**< (HSTIER) DMA Channel 6 Interrupt Enable Position */ +#define HSTIER_DMA_6 (_U_(0x1) << HSTIER_DMA_6_Pos) /**< (HSTIER) DMA Channel 6 Interrupt Enable Mask */ +#define HSTIER_Msk _U_(0xFE03FF7F) /**< (HSTIER) Register Mask */ + +#define HSTIER_PEP__Pos 8 /**< (HSTIER Position) Pipe x Interrupt Enable */ +#define HSTIER_PEP_ (_U_(0x3FF) << HSTIER_PEP__Pos) /**< (HSTIER Mask) PEP_ */ +#define HSTIER_DMA__Pos 25 /**< (HSTIER Position) DMA Channel 6 Interrupt Enable */ +#define HSTIER_DMA_ (_U_(0x7F) << HSTIER_DMA__Pos) /**< (HSTIER Mask) DMA_ */ + +/* -------- HSTPIP : (USBHS Offset: 0x41c) (R/W 32) Host Pipe Register -------- */ + +#define HSTPIP_OFFSET (0x41C) /**< (HSTPIP) Host Pipe Register Offset */ + +#define HSTPIP_PEN0_Pos 0 /**< (HSTPIP) Pipe 0 Enable Position */ +#define HSTPIP_PEN0 (_U_(0x1) << HSTPIP_PEN0_Pos) /**< (HSTPIP) Pipe 0 Enable Mask */ +#define HSTPIP_PEN1_Pos 1 /**< (HSTPIP) Pipe 1 Enable Position */ +#define HSTPIP_PEN1 (_U_(0x1) << HSTPIP_PEN1_Pos) /**< (HSTPIP) Pipe 1 Enable Mask */ +#define HSTPIP_PEN2_Pos 2 /**< (HSTPIP) Pipe 2 Enable Position */ +#define HSTPIP_PEN2 (_U_(0x1) << HSTPIP_PEN2_Pos) /**< (HSTPIP) Pipe 2 Enable Mask */ +#define HSTPIP_PEN3_Pos 3 /**< (HSTPIP) Pipe 3 Enable Position */ +#define HSTPIP_PEN3 (_U_(0x1) << HSTPIP_PEN3_Pos) /**< (HSTPIP) Pipe 3 Enable Mask */ +#define HSTPIP_PEN4_Pos 4 /**< (HSTPIP) Pipe 4 Enable Position */ +#define HSTPIP_PEN4 (_U_(0x1) << HSTPIP_PEN4_Pos) /**< (HSTPIP) Pipe 4 Enable Mask */ +#define HSTPIP_PEN5_Pos 5 /**< (HSTPIP) Pipe 5 Enable Position */ +#define HSTPIP_PEN5 (_U_(0x1) << HSTPIP_PEN5_Pos) /**< (HSTPIP) Pipe 5 Enable Mask */ +#define HSTPIP_PEN6_Pos 6 /**< (HSTPIP) Pipe 6 Enable Position */ +#define HSTPIP_PEN6 (_U_(0x1) << HSTPIP_PEN6_Pos) /**< (HSTPIP) Pipe 6 Enable Mask */ +#define HSTPIP_PEN7_Pos 7 /**< (HSTPIP) Pipe 7 Enable Position */ +#define HSTPIP_PEN7 (_U_(0x1) << HSTPIP_PEN7_Pos) /**< (HSTPIP) Pipe 7 Enable Mask */ +#define HSTPIP_PEN8_Pos 8 /**< (HSTPIP) Pipe 8 Enable Position */ +#define HSTPIP_PEN8 (_U_(0x1) << HSTPIP_PEN8_Pos) /**< (HSTPIP) Pipe 8 Enable Mask */ +#define HSTPIP_PRST0_Pos 16 /**< (HSTPIP) Pipe 0 Reset Position */ +#define HSTPIP_PRST0 (_U_(0x1) << HSTPIP_PRST0_Pos) /**< (HSTPIP) Pipe 0 Reset Mask */ +#define HSTPIP_PRST1_Pos 17 /**< (HSTPIP) Pipe 1 Reset Position */ +#define HSTPIP_PRST1 (_U_(0x1) << HSTPIP_PRST1_Pos) /**< (HSTPIP) Pipe 1 Reset Mask */ +#define HSTPIP_PRST2_Pos 18 /**< (HSTPIP) Pipe 2 Reset Position */ +#define HSTPIP_PRST2 (_U_(0x1) << HSTPIP_PRST2_Pos) /**< (HSTPIP) Pipe 2 Reset Mask */ +#define HSTPIP_PRST3_Pos 19 /**< (HSTPIP) Pipe 3 Reset Position */ +#define HSTPIP_PRST3 (_U_(0x1) << HSTPIP_PRST3_Pos) /**< (HSTPIP) Pipe 3 Reset Mask */ +#define HSTPIP_PRST4_Pos 20 /**< (HSTPIP) Pipe 4 Reset Position */ +#define HSTPIP_PRST4 (_U_(0x1) << HSTPIP_PRST4_Pos) /**< (HSTPIP) Pipe 4 Reset Mask */ +#define HSTPIP_PRST5_Pos 21 /**< (HSTPIP) Pipe 5 Reset Position */ +#define HSTPIP_PRST5 (_U_(0x1) << HSTPIP_PRST5_Pos) /**< (HSTPIP) Pipe 5 Reset Mask */ +#define HSTPIP_PRST6_Pos 22 /**< (HSTPIP) Pipe 6 Reset Position */ +#define HSTPIP_PRST6 (_U_(0x1) << HSTPIP_PRST6_Pos) /**< (HSTPIP) Pipe 6 Reset Mask */ +#define HSTPIP_PRST7_Pos 23 /**< (HSTPIP) Pipe 7 Reset Position */ +#define HSTPIP_PRST7 (_U_(0x1) << HSTPIP_PRST7_Pos) /**< (HSTPIP) Pipe 7 Reset Mask */ +#define HSTPIP_PRST8_Pos 24 /**< (HSTPIP) Pipe 8 Reset Position */ +#define HSTPIP_PRST8 (_U_(0x1) << HSTPIP_PRST8_Pos) /**< (HSTPIP) Pipe 8 Reset Mask */ +#define HSTPIP_Msk _U_(0x1FF01FF) /**< (HSTPIP) Register Mask */ + +#define HSTPIP_PEN_Pos 0 /**< (HSTPIP Position) Pipe x Enable */ +#define HSTPIP_PEN (_U_(0x1FF) << HSTPIP_PEN_Pos) /**< (HSTPIP Mask) PEN */ +#define HSTPIP_PRST_Pos 16 /**< (HSTPIP Position) Pipe 8 Reset */ +#define HSTPIP_PRST (_U_(0x1FF) << HSTPIP_PRST_Pos) /**< (HSTPIP Mask) PRST */ + +/* -------- HSTFNUM : (USBHS Offset: 0x420) (R/W 32) Host Frame Number Register -------- */ + +#define HSTFNUM_OFFSET (0x420) /**< (HSTFNUM) Host Frame Number Register Offset */ + +#define HSTFNUM_MFNUM_Pos 0 /**< (HSTFNUM) Micro Frame Number Position */ +#define HSTFNUM_MFNUM (_U_(0x7) << HSTFNUM_MFNUM_Pos) /**< (HSTFNUM) Micro Frame Number Mask */ +#define HSTFNUM_FNUM_Pos 3 /**< (HSTFNUM) Frame Number Position */ +#define HSTFNUM_FNUM (_U_(0x7FF) << HSTFNUM_FNUM_Pos) /**< (HSTFNUM) Frame Number Mask */ +#define HSTFNUM_FLENHIGH_Pos 16 /**< (HSTFNUM) Frame Length Position */ +#define HSTFNUM_FLENHIGH (_U_(0xFF) << HSTFNUM_FLENHIGH_Pos) /**< (HSTFNUM) Frame Length Mask */ +#define HSTFNUM_Msk _U_(0xFF3FFF) /**< (HSTFNUM) Register Mask */ + + +/* -------- HSTADDR1 : (USBHS Offset: 0x424) (R/W 32) Host Address 1 Register -------- */ + +#define HSTADDR1_OFFSET (0x424) /**< (HSTADDR1) Host Address 1 Register Offset */ + +#define HSTADDR1_HSTADDRP0_Pos 0 /**< (HSTADDR1) USB Host Address Position */ +#define HSTADDR1_HSTADDRP0 (_U_(0x7F) << HSTADDR1_HSTADDRP0_Pos) /**< (HSTADDR1) USB Host Address Mask */ +#define HSTADDR1_HSTADDRP1_Pos 8 /**< (HSTADDR1) USB Host Address Position */ +#define HSTADDR1_HSTADDRP1 (_U_(0x7F) << HSTADDR1_HSTADDRP1_Pos) /**< (HSTADDR1) USB Host Address Mask */ +#define HSTADDR1_HSTADDRP2_Pos 16 /**< (HSTADDR1) USB Host Address Position */ +#define HSTADDR1_HSTADDRP2 (_U_(0x7F) << HSTADDR1_HSTADDRP2_Pos) /**< (HSTADDR1) USB Host Address Mask */ +#define HSTADDR1_HSTADDRP3_Pos 24 /**< (HSTADDR1) USB Host Address Position */ +#define HSTADDR1_HSTADDRP3 (_U_(0x7F) << HSTADDR1_HSTADDRP3_Pos) /**< (HSTADDR1) USB Host Address Mask */ +#define HSTADDR1_Msk _U_(0x7F7F7F7F) /**< (HSTADDR1) Register Mask */ + + +/* -------- HSTADDR2 : (USBHS Offset: 0x428) (R/W 32) Host Address 2 Register -------- */ + +#define HSTADDR2_OFFSET (0x428) /**< (HSTADDR2) Host Address 2 Register Offset */ + +#define HSTADDR2_HSTADDRP4_Pos 0 /**< (HSTADDR2) USB Host Address Position */ +#define HSTADDR2_HSTADDRP4 (_U_(0x7F) << HSTADDR2_HSTADDRP4_Pos) /**< (HSTADDR2) USB Host Address Mask */ +#define HSTADDR2_HSTADDRP5_Pos 8 /**< (HSTADDR2) USB Host Address Position */ +#define HSTADDR2_HSTADDRP5 (_U_(0x7F) << HSTADDR2_HSTADDRP5_Pos) /**< (HSTADDR2) USB Host Address Mask */ +#define HSTADDR2_HSTADDRP6_Pos 16 /**< (HSTADDR2) USB Host Address Position */ +#define HSTADDR2_HSTADDRP6 (_U_(0x7F) << HSTADDR2_HSTADDRP6_Pos) /**< (HSTADDR2) USB Host Address Mask */ +#define HSTADDR2_HSTADDRP7_Pos 24 /**< (HSTADDR2) USB Host Address Position */ +#define HSTADDR2_HSTADDRP7 (_U_(0x7F) << HSTADDR2_HSTADDRP7_Pos) /**< (HSTADDR2) USB Host Address Mask */ +#define HSTADDR2_Msk _U_(0x7F7F7F7F) /**< (HSTADDR2) Register Mask */ + + +/* -------- HSTADDR3 : (USBHS Offset: 0x42c) (R/W 32) Host Address 3 Register -------- */ + +#define HSTADDR3_OFFSET (0x42C) /**< (HSTADDR3) Host Address 3 Register Offset */ + +#define HSTADDR3_HSTADDRP8_Pos 0 /**< (HSTADDR3) USB Host Address Position */ +#define HSTADDR3_HSTADDRP8 (_U_(0x7F) << HSTADDR3_HSTADDRP8_Pos) /**< (HSTADDR3) USB Host Address Mask */ +#define HSTADDR3_HSTADDRP9_Pos 8 /**< (HSTADDR3) USB Host Address Position */ +#define HSTADDR3_HSTADDRP9 (_U_(0x7F) << HSTADDR3_HSTADDRP9_Pos) /**< (HSTADDR3) USB Host Address Mask */ +#define HSTADDR3_Msk _U_(0x7F7F) /**< (HSTADDR3) Register Mask */ + + +/* -------- HSTPIPCFG : (USBHS Offset: 0x500) (R/W 32) Host Pipe Configuration Register -------- */ + +#define HSTPIPCFG_OFFSET (0x500) /**< (HSTPIPCFG) Host Pipe Configuration Register Offset */ + +#define HSTPIPCFG_ALLOC_Pos 1 /**< (HSTPIPCFG) Pipe Memory Allocate Position */ +#define HSTPIPCFG_ALLOC (_U_(0x1) << HSTPIPCFG_ALLOC_Pos) /**< (HSTPIPCFG) Pipe Memory Allocate Mask */ +#define HSTPIPCFG_PBK_Pos 2 /**< (HSTPIPCFG) Pipe Banks Position */ +#define HSTPIPCFG_PBK (_U_(0x3) << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Pipe Banks Mask */ +#define HSTPIPCFG_PBK_1_BANK_Val _U_(0x0) /**< (HSTPIPCFG) Single-bank pipe */ +#define HSTPIPCFG_PBK_2_BANK_Val _U_(0x1) /**< (HSTPIPCFG) Double-bank pipe */ +#define HSTPIPCFG_PBK_3_BANK_Val _U_(0x2) /**< (HSTPIPCFG) Triple-bank pipe */ +#define HSTPIPCFG_PBK_1_BANK (HSTPIPCFG_PBK_1_BANK_Val << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Single-bank pipe Position */ +#define HSTPIPCFG_PBK_2_BANK (HSTPIPCFG_PBK_2_BANK_Val << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Double-bank pipe Position */ +#define HSTPIPCFG_PBK_3_BANK (HSTPIPCFG_PBK_3_BANK_Val << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Triple-bank pipe Position */ +#define HSTPIPCFG_PSIZE_Pos 4 /**< (HSTPIPCFG) Pipe Size Position */ +#define HSTPIPCFG_PSIZE (_U_(0x7) << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) Pipe Size Mask */ +#define HSTPIPCFG_PSIZE_8_BYTE_Val _U_(0x0) /**< (HSTPIPCFG) 8 bytes */ +#define HSTPIPCFG_PSIZE_16_BYTE_Val _U_(0x1) /**< (HSTPIPCFG) 16 bytes */ +#define HSTPIPCFG_PSIZE_32_BYTE_Val _U_(0x2) /**< (HSTPIPCFG) 32 bytes */ +#define HSTPIPCFG_PSIZE_64_BYTE_Val _U_(0x3) /**< (HSTPIPCFG) 64 bytes */ +#define HSTPIPCFG_PSIZE_128_BYTE_Val _U_(0x4) /**< (HSTPIPCFG) 128 bytes */ +#define HSTPIPCFG_PSIZE_256_BYTE_Val _U_(0x5) /**< (HSTPIPCFG) 256 bytes */ +#define HSTPIPCFG_PSIZE_512_BYTE_Val _U_(0x6) /**< (HSTPIPCFG) 512 bytes */ +#define HSTPIPCFG_PSIZE_1024_BYTE_Val _U_(0x7) /**< (HSTPIPCFG) 1024 bytes */ +#define HSTPIPCFG_PSIZE_8_BYTE (HSTPIPCFG_PSIZE_8_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 8 bytes Position */ +#define HSTPIPCFG_PSIZE_16_BYTE (HSTPIPCFG_PSIZE_16_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 16 bytes Position */ +#define HSTPIPCFG_PSIZE_32_BYTE (HSTPIPCFG_PSIZE_32_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 32 bytes Position */ +#define HSTPIPCFG_PSIZE_64_BYTE (HSTPIPCFG_PSIZE_64_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 64 bytes Position */ +#define HSTPIPCFG_PSIZE_128_BYTE (HSTPIPCFG_PSIZE_128_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 128 bytes Position */ +#define HSTPIPCFG_PSIZE_256_BYTE (HSTPIPCFG_PSIZE_256_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 256 bytes Position */ +#define HSTPIPCFG_PSIZE_512_BYTE (HSTPIPCFG_PSIZE_512_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 512 bytes Position */ +#define HSTPIPCFG_PSIZE_1024_BYTE (HSTPIPCFG_PSIZE_1024_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 1024 bytes Position */ +#define HSTPIPCFG_PTOKEN_Pos 8 /**< (HSTPIPCFG) Pipe Token Position */ +#define HSTPIPCFG_PTOKEN (_U_(0x3) << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) Pipe Token Mask */ +#define HSTPIPCFG_PTOKEN_SETUP_Val _U_(0x0) /**< (HSTPIPCFG) SETUP */ +#define HSTPIPCFG_PTOKEN_IN_Val _U_(0x1) /**< (HSTPIPCFG) IN */ +#define HSTPIPCFG_PTOKEN_OUT_Val _U_(0x2) /**< (HSTPIPCFG) OUT */ +#define HSTPIPCFG_PTOKEN_SETUP (HSTPIPCFG_PTOKEN_SETUP_Val << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) SETUP Position */ +#define HSTPIPCFG_PTOKEN_IN (HSTPIPCFG_PTOKEN_IN_Val << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) IN Position */ +#define HSTPIPCFG_PTOKEN_OUT (HSTPIPCFG_PTOKEN_OUT_Val << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) OUT Position */ +#define HSTPIPCFG_AUTOSW_Pos 10 /**< (HSTPIPCFG) Automatic Switch Position */ +#define HSTPIPCFG_AUTOSW (_U_(0x1) << HSTPIPCFG_AUTOSW_Pos) /**< (HSTPIPCFG) Automatic Switch Mask */ +#define HSTPIPCFG_PTYPE_Pos 12 /**< (HSTPIPCFG) Pipe Type Position */ +#define HSTPIPCFG_PTYPE (_U_(0x3) << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Pipe Type Mask */ +#define HSTPIPCFG_PTYPE_CTRL_Val _U_(0x0) /**< (HSTPIPCFG) Control */ +#define HSTPIPCFG_PTYPE_ISO_Val _U_(0x1) /**< (HSTPIPCFG) Isochronous */ +#define HSTPIPCFG_PTYPE_BLK_Val _U_(0x2) /**< (HSTPIPCFG) Bulk */ +#define HSTPIPCFG_PTYPE_INTRPT_Val _U_(0x3) /**< (HSTPIPCFG) Interrupt */ +#define HSTPIPCFG_PTYPE_CTRL (HSTPIPCFG_PTYPE_CTRL_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Control Position */ +#define HSTPIPCFG_PTYPE_ISO (HSTPIPCFG_PTYPE_ISO_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Isochronous Position */ +#define HSTPIPCFG_PTYPE_BLK (HSTPIPCFG_PTYPE_BLK_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Bulk Position */ +#define HSTPIPCFG_PTYPE_INTRPT (HSTPIPCFG_PTYPE_INTRPT_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Interrupt Position */ +#define HSTPIPCFG_PEPNUM_Pos 16 /**< (HSTPIPCFG) Pipe Endpoint Number Position */ +#define HSTPIPCFG_PEPNUM (_U_(0xF) << HSTPIPCFG_PEPNUM_Pos) /**< (HSTPIPCFG) Pipe Endpoint Number Mask */ +#define HSTPIPCFG_INTFRQ_Pos 24 /**< (HSTPIPCFG) Pipe Interrupt Request Frequency Position */ +#define HSTPIPCFG_INTFRQ (_U_(0xFF) << HSTPIPCFG_INTFRQ_Pos) /**< (HSTPIPCFG) Pipe Interrupt Request Frequency Mask */ +#define HSTPIPCFG_Msk _U_(0xFF0F377E) /**< (HSTPIPCFG) Register Mask */ + +/* CTRL_BULK mode */ +#define HSTPIPCFG_CTRL_BULK_PINGEN_Pos 20 /**< (HSTPIPCFG) Ping Enable Position */ +#define HSTPIPCFG_CTRL_BULK_PINGEN (_U_(0x1) << HSTPIPCFG_CTRL_BULK_PINGEN_Pos) /**< (HSTPIPCFG) Ping Enable Mask */ +#define HSTPIPCFG_CTRL_BULK_BINTERVAL_Pos 24 /**< (HSTPIPCFG) bInterval Parameter for the Bulk-Out/Ping Transaction Position */ +#define HSTPIPCFG_CTRL_BULK_BINTERVAL (_U_(0xFF) << HSTPIPCFG_CTRL_BULK_BINTERVAL_Pos) /**< (HSTPIPCFG) bInterval Parameter for the Bulk-Out/Ping Transaction Mask */ +#define HSTPIPCFG_CTRL_BULK_Msk _U_(0xFF100000) /**< (HSTPIPCFG_CTRL_BULK) Register Mask */ + + +/* -------- HSTPIPISR : (USBHS Offset: 0x530) (R/ 32) Host Pipe Status Register -------- */ + +#define HSTPIPISR_OFFSET (0x530) /**< (HSTPIPISR) Host Pipe Status Register Offset */ + +#define HSTPIPISR_RXINI_Pos 0 /**< (HSTPIPISR) Received IN Data Interrupt Position */ +#define HSTPIPISR_RXINI (_U_(0x1) << HSTPIPISR_RXINI_Pos) /**< (HSTPIPISR) Received IN Data Interrupt Mask */ +#define HSTPIPISR_TXOUTI_Pos 1 /**< (HSTPIPISR) Transmitted OUT Data Interrupt Position */ +#define HSTPIPISR_TXOUTI (_U_(0x1) << HSTPIPISR_TXOUTI_Pos) /**< (HSTPIPISR) Transmitted OUT Data Interrupt Mask */ +#define HSTPIPISR_PERRI_Pos 3 /**< (HSTPIPISR) Pipe Error Interrupt Position */ +#define HSTPIPISR_PERRI (_U_(0x1) << HSTPIPISR_PERRI_Pos) /**< (HSTPIPISR) Pipe Error Interrupt Mask */ +#define HSTPIPISR_NAKEDI_Pos 4 /**< (HSTPIPISR) NAKed Interrupt Position */ +#define HSTPIPISR_NAKEDI (_U_(0x1) << HSTPIPISR_NAKEDI_Pos) /**< (HSTPIPISR) NAKed Interrupt Mask */ +#define HSTPIPISR_OVERFI_Pos 5 /**< (HSTPIPISR) Overflow Interrupt Position */ +#define HSTPIPISR_OVERFI (_U_(0x1) << HSTPIPISR_OVERFI_Pos) /**< (HSTPIPISR) Overflow Interrupt Mask */ +#define HSTPIPISR_SHORTPACKETI_Pos 7 /**< (HSTPIPISR) Short Packet Interrupt Position */ +#define HSTPIPISR_SHORTPACKETI (_U_(0x1) << HSTPIPISR_SHORTPACKETI_Pos) /**< (HSTPIPISR) Short Packet Interrupt Mask */ +#define HSTPIPISR_DTSEQ_Pos 8 /**< (HSTPIPISR) Data Toggle Sequence Position */ +#define HSTPIPISR_DTSEQ (_U_(0x3) << HSTPIPISR_DTSEQ_Pos) /**< (HSTPIPISR) Data Toggle Sequence Mask */ +#define HSTPIPISR_DTSEQ_DATA0_Val _U_(0x0) /**< (HSTPIPISR) Data0 toggle sequence */ +#define HSTPIPISR_DTSEQ_DATA1_Val _U_(0x1) /**< (HSTPIPISR) Data1 toggle sequence */ +#define HSTPIPISR_DTSEQ_DATA0 (HSTPIPISR_DTSEQ_DATA0_Val << HSTPIPISR_DTSEQ_Pos) /**< (HSTPIPISR) Data0 toggle sequence Position */ +#define HSTPIPISR_DTSEQ_DATA1 (HSTPIPISR_DTSEQ_DATA1_Val << HSTPIPISR_DTSEQ_Pos) /**< (HSTPIPISR) Data1 toggle sequence Position */ +#define HSTPIPISR_NBUSYBK_Pos 12 /**< (HSTPIPISR) Number of Busy Banks Position */ +#define HSTPIPISR_NBUSYBK (_U_(0x3) << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) Number of Busy Banks Mask */ +#define HSTPIPISR_NBUSYBK_0_BUSY_Val _U_(0x0) /**< (HSTPIPISR) 0 busy bank (all banks free) */ +#define HSTPIPISR_NBUSYBK_1_BUSY_Val _U_(0x1) /**< (HSTPIPISR) 1 busy bank */ +#define HSTPIPISR_NBUSYBK_2_BUSY_Val _U_(0x2) /**< (HSTPIPISR) 2 busy banks */ +#define HSTPIPISR_NBUSYBK_3_BUSY_Val _U_(0x3) /**< (HSTPIPISR) 3 busy banks */ +#define HSTPIPISR_NBUSYBK_0_BUSY (HSTPIPISR_NBUSYBK_0_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 0 busy bank (all banks free) Position */ +#define HSTPIPISR_NBUSYBK_1_BUSY (HSTPIPISR_NBUSYBK_1_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 1 busy bank Position */ +#define HSTPIPISR_NBUSYBK_2_BUSY (HSTPIPISR_NBUSYBK_2_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 2 busy banks Position */ +#define HSTPIPISR_NBUSYBK_3_BUSY (HSTPIPISR_NBUSYBK_3_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 3 busy banks Position */ +#define HSTPIPISR_CURRBK_Pos 14 /**< (HSTPIPISR) Current Bank Position */ +#define HSTPIPISR_CURRBK (_U_(0x3) << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current Bank Mask */ +#define HSTPIPISR_CURRBK_BANK0_Val _U_(0x0) /**< (HSTPIPISR) Current bank is bank0 */ +#define HSTPIPISR_CURRBK_BANK1_Val _U_(0x1) /**< (HSTPIPISR) Current bank is bank1 */ +#define HSTPIPISR_CURRBK_BANK2_Val _U_(0x2) /**< (HSTPIPISR) Current bank is bank2 */ +#define HSTPIPISR_CURRBK_BANK0 (HSTPIPISR_CURRBK_BANK0_Val << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current bank is bank0 Position */ +#define HSTPIPISR_CURRBK_BANK1 (HSTPIPISR_CURRBK_BANK1_Val << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current bank is bank1 Position */ +#define HSTPIPISR_CURRBK_BANK2 (HSTPIPISR_CURRBK_BANK2_Val << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current bank is bank2 Position */ +#define HSTPIPISR_RWALL_Pos 16 /**< (HSTPIPISR) Read/Write Allowed Position */ +#define HSTPIPISR_RWALL (_U_(0x1) << HSTPIPISR_RWALL_Pos) /**< (HSTPIPISR) Read/Write Allowed Mask */ +#define HSTPIPISR_CFGOK_Pos 18 /**< (HSTPIPISR) Configuration OK Status Position */ +#define HSTPIPISR_CFGOK (_U_(0x1) << HSTPIPISR_CFGOK_Pos) /**< (HSTPIPISR) Configuration OK Status Mask */ +#define HSTPIPISR_PBYCT_Pos 20 /**< (HSTPIPISR) Pipe Byte Count Position */ +#define HSTPIPISR_PBYCT (_U_(0x7FF) << HSTPIPISR_PBYCT_Pos) /**< (HSTPIPISR) Pipe Byte Count Mask */ +#define HSTPIPISR_Msk _U_(0x7FF5F3BB) /**< (HSTPIPISR) Register Mask */ + +/* CTRL mode */ +#define HSTPIPISR_CTRL_TXSTPI_Pos 2 /**< (HSTPIPISR) Transmitted SETUP Interrupt Position */ +#define HSTPIPISR_CTRL_TXSTPI (_U_(0x1) << HSTPIPISR_CTRL_TXSTPI_Pos) /**< (HSTPIPISR) Transmitted SETUP Interrupt Mask */ +#define HSTPIPISR_CTRL_RXSTALLDI_Pos 6 /**< (HSTPIPISR) Received STALLed Interrupt Position */ +#define HSTPIPISR_CTRL_RXSTALLDI (_U_(0x1) << HSTPIPISR_CTRL_RXSTALLDI_Pos) /**< (HSTPIPISR) Received STALLed Interrupt Mask */ +#define HSTPIPISR_CTRL_Msk _U_(0x44) /**< (HSTPIPISR_CTRL) Register Mask */ + +/* ISO mode */ +#define HSTPIPISR_ISO_UNDERFI_Pos 2 /**< (HSTPIPISR) Underflow Interrupt Position */ +#define HSTPIPISR_ISO_UNDERFI (_U_(0x1) << HSTPIPISR_ISO_UNDERFI_Pos) /**< (HSTPIPISR) Underflow Interrupt Mask */ +#define HSTPIPISR_ISO_CRCERRI_Pos 6 /**< (HSTPIPISR) CRC Error Interrupt Position */ +#define HSTPIPISR_ISO_CRCERRI (_U_(0x1) << HSTPIPISR_ISO_CRCERRI_Pos) /**< (HSTPIPISR) CRC Error Interrupt Mask */ +#define HSTPIPISR_ISO_Msk _U_(0x44) /**< (HSTPIPISR_ISO) Register Mask */ + +/* BLK mode */ +#define HSTPIPISR_BLK_TXSTPI_Pos 2 /**< (HSTPIPISR) Transmitted SETUP Interrupt Position */ +#define HSTPIPISR_BLK_TXSTPI (_U_(0x1) << HSTPIPISR_BLK_TXSTPI_Pos) /**< (HSTPIPISR) Transmitted SETUP Interrupt Mask */ +#define HSTPIPISR_BLK_RXSTALLDI_Pos 6 /**< (HSTPIPISR) Received STALLed Interrupt Position */ +#define HSTPIPISR_BLK_RXSTALLDI (_U_(0x1) << HSTPIPISR_BLK_RXSTALLDI_Pos) /**< (HSTPIPISR) Received STALLed Interrupt Mask */ +#define HSTPIPISR_BLK_Msk _U_(0x44) /**< (HSTPIPISR_BLK) Register Mask */ + +/* INTRPT mode */ +#define HSTPIPISR_INTRPT_UNDERFI_Pos 2 /**< (HSTPIPISR) Underflow Interrupt Position */ +#define HSTPIPISR_INTRPT_UNDERFI (_U_(0x1) << HSTPIPISR_INTRPT_UNDERFI_Pos) /**< (HSTPIPISR) Underflow Interrupt Mask */ +#define HSTPIPISR_INTRPT_RXSTALLDI_Pos 6 /**< (HSTPIPISR) Received STALLed Interrupt Position */ +#define HSTPIPISR_INTRPT_RXSTALLDI (_U_(0x1) << HSTPIPISR_INTRPT_RXSTALLDI_Pos) /**< (HSTPIPISR) Received STALLed Interrupt Mask */ +#define HSTPIPISR_INTRPT_Msk _U_(0x44) /**< (HSTPIPISR_INTRPT) Register Mask */ + + +/* -------- HSTPIPICR : (USBHS Offset: 0x560) (/W 32) Host Pipe Clear Register -------- */ + +#define HSTPIPICR_OFFSET (0x560) /**< (HSTPIPICR) Host Pipe Clear Register Offset */ + +#define HSTPIPICR_RXINIC_Pos 0 /**< (HSTPIPICR) Received IN Data Interrupt Clear Position */ +#define HSTPIPICR_RXINIC (_U_(0x1) << HSTPIPICR_RXINIC_Pos) /**< (HSTPIPICR) Received IN Data Interrupt Clear Mask */ +#define HSTPIPICR_TXOUTIC_Pos 1 /**< (HSTPIPICR) Transmitted OUT Data Interrupt Clear Position */ +#define HSTPIPICR_TXOUTIC (_U_(0x1) << HSTPIPICR_TXOUTIC_Pos) /**< (HSTPIPICR) Transmitted OUT Data Interrupt Clear Mask */ +#define HSTPIPICR_NAKEDIC_Pos 4 /**< (HSTPIPICR) NAKed Interrupt Clear Position */ +#define HSTPIPICR_NAKEDIC (_U_(0x1) << HSTPIPICR_NAKEDIC_Pos) /**< (HSTPIPICR) NAKed Interrupt Clear Mask */ +#define HSTPIPICR_OVERFIC_Pos 5 /**< (HSTPIPICR) Overflow Interrupt Clear Position */ +#define HSTPIPICR_OVERFIC (_U_(0x1) << HSTPIPICR_OVERFIC_Pos) /**< (HSTPIPICR) Overflow Interrupt Clear Mask */ +#define HSTPIPICR_SHORTPACKETIC_Pos 7 /**< (HSTPIPICR) Short Packet Interrupt Clear Position */ +#define HSTPIPICR_SHORTPACKETIC (_U_(0x1) << HSTPIPICR_SHORTPACKETIC_Pos) /**< (HSTPIPICR) Short Packet Interrupt Clear Mask */ +#define HSTPIPICR_Msk _U_(0xB3) /**< (HSTPIPICR) Register Mask */ + +/* CTRL mode */ +#define HSTPIPICR_CTRL_TXSTPIC_Pos 2 /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Position */ +#define HSTPIPICR_CTRL_TXSTPIC (_U_(0x1) << HSTPIPICR_CTRL_TXSTPIC_Pos) /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Mask */ +#define HSTPIPICR_CTRL_RXSTALLDIC_Pos 6 /**< (HSTPIPICR) Received STALLed Interrupt Clear Position */ +#define HSTPIPICR_CTRL_RXSTALLDIC (_U_(0x1) << HSTPIPICR_CTRL_RXSTALLDIC_Pos) /**< (HSTPIPICR) Received STALLed Interrupt Clear Mask */ +#define HSTPIPICR_CTRL_Msk _U_(0x44) /**< (HSTPIPICR_CTRL) Register Mask */ + +/* ISO mode */ +#define HSTPIPICR_ISO_UNDERFIC_Pos 2 /**< (HSTPIPICR) Underflow Interrupt Clear Position */ +#define HSTPIPICR_ISO_UNDERFIC (_U_(0x1) << HSTPIPICR_ISO_UNDERFIC_Pos) /**< (HSTPIPICR) Underflow Interrupt Clear Mask */ +#define HSTPIPICR_ISO_CRCERRIC_Pos 6 /**< (HSTPIPICR) CRC Error Interrupt Clear Position */ +#define HSTPIPICR_ISO_CRCERRIC (_U_(0x1) << HSTPIPICR_ISO_CRCERRIC_Pos) /**< (HSTPIPICR) CRC Error Interrupt Clear Mask */ +#define HSTPIPICR_ISO_Msk _U_(0x44) /**< (HSTPIPICR_ISO) Register Mask */ + +/* BLK mode */ +#define HSTPIPICR_BLK_TXSTPIC_Pos 2 /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Position */ +#define HSTPIPICR_BLK_TXSTPIC (_U_(0x1) << HSTPIPICR_BLK_TXSTPIC_Pos) /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Mask */ +#define HSTPIPICR_BLK_RXSTALLDIC_Pos 6 /**< (HSTPIPICR) Received STALLed Interrupt Clear Position */ +#define HSTPIPICR_BLK_RXSTALLDIC (_U_(0x1) << HSTPIPICR_BLK_RXSTALLDIC_Pos) /**< (HSTPIPICR) Received STALLed Interrupt Clear Mask */ +#define HSTPIPICR_BLK_Msk _U_(0x44) /**< (HSTPIPICR_BLK) Register Mask */ + +/* INTRPT mode */ +#define HSTPIPICR_INTRPT_UNDERFIC_Pos 2 /**< (HSTPIPICR) Underflow Interrupt Clear Position */ +#define HSTPIPICR_INTRPT_UNDERFIC (_U_(0x1) << HSTPIPICR_INTRPT_UNDERFIC_Pos) /**< (HSTPIPICR) Underflow Interrupt Clear Mask */ +#define HSTPIPICR_INTRPT_RXSTALLDIC_Pos 6 /**< (HSTPIPICR) Received STALLed Interrupt Clear Position */ +#define HSTPIPICR_INTRPT_RXSTALLDIC (_U_(0x1) << HSTPIPICR_INTRPT_RXSTALLDIC_Pos) /**< (HSTPIPICR) Received STALLed Interrupt Clear Mask */ +#define HSTPIPICR_INTRPT_Msk _U_(0x44) /**< (HSTPIPICR_INTRPT) Register Mask */ + + +/* -------- HSTPIPIFR : (USBHS Offset: 0x590) (/W 32) Host Pipe Set Register -------- */ + +#define HSTPIPIFR_OFFSET (0x590) /**< (HSTPIPIFR) Host Pipe Set Register Offset */ + +#define HSTPIPIFR_RXINIS_Pos 0 /**< (HSTPIPIFR) Received IN Data Interrupt Set Position */ +#define HSTPIPIFR_RXINIS (_U_(0x1) << HSTPIPIFR_RXINIS_Pos) /**< (HSTPIPIFR) Received IN Data Interrupt Set Mask */ +#define HSTPIPIFR_TXOUTIS_Pos 1 /**< (HSTPIPIFR) Transmitted OUT Data Interrupt Set Position */ +#define HSTPIPIFR_TXOUTIS (_U_(0x1) << HSTPIPIFR_TXOUTIS_Pos) /**< (HSTPIPIFR) Transmitted OUT Data Interrupt Set Mask */ +#define HSTPIPIFR_PERRIS_Pos 3 /**< (HSTPIPIFR) Pipe Error Interrupt Set Position */ +#define HSTPIPIFR_PERRIS (_U_(0x1) << HSTPIPIFR_PERRIS_Pos) /**< (HSTPIPIFR) Pipe Error Interrupt Set Mask */ +#define HSTPIPIFR_NAKEDIS_Pos 4 /**< (HSTPIPIFR) NAKed Interrupt Set Position */ +#define HSTPIPIFR_NAKEDIS (_U_(0x1) << HSTPIPIFR_NAKEDIS_Pos) /**< (HSTPIPIFR) NAKed Interrupt Set Mask */ +#define HSTPIPIFR_OVERFIS_Pos 5 /**< (HSTPIPIFR) Overflow Interrupt Set Position */ +#define HSTPIPIFR_OVERFIS (_U_(0x1) << HSTPIPIFR_OVERFIS_Pos) /**< (HSTPIPIFR) Overflow Interrupt Set Mask */ +#define HSTPIPIFR_SHORTPACKETIS_Pos 7 /**< (HSTPIPIFR) Short Packet Interrupt Set Position */ +#define HSTPIPIFR_SHORTPACKETIS (_U_(0x1) << HSTPIPIFR_SHORTPACKETIS_Pos) /**< (HSTPIPIFR) Short Packet Interrupt Set Mask */ +#define HSTPIPIFR_NBUSYBKS_Pos 12 /**< (HSTPIPIFR) Number of Busy Banks Set Position */ +#define HSTPIPIFR_NBUSYBKS (_U_(0x1) << HSTPIPIFR_NBUSYBKS_Pos) /**< (HSTPIPIFR) Number of Busy Banks Set Mask */ +#define HSTPIPIFR_Msk _U_(0x10BB) /**< (HSTPIPIFR) Register Mask */ + +/* CTRL mode */ +#define HSTPIPIFR_CTRL_TXSTPIS_Pos 2 /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Position */ +#define HSTPIPIFR_CTRL_TXSTPIS (_U_(0x1) << HSTPIPIFR_CTRL_TXSTPIS_Pos) /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Mask */ +#define HSTPIPIFR_CTRL_RXSTALLDIS_Pos 6 /**< (HSTPIPIFR) Received STALLed Interrupt Set Position */ +#define HSTPIPIFR_CTRL_RXSTALLDIS (_U_(0x1) << HSTPIPIFR_CTRL_RXSTALLDIS_Pos) /**< (HSTPIPIFR) Received STALLed Interrupt Set Mask */ +#define HSTPIPIFR_CTRL_Msk _U_(0x44) /**< (HSTPIPIFR_CTRL) Register Mask */ + +/* ISO mode */ +#define HSTPIPIFR_ISO_UNDERFIS_Pos 2 /**< (HSTPIPIFR) Underflow Interrupt Set Position */ +#define HSTPIPIFR_ISO_UNDERFIS (_U_(0x1) << HSTPIPIFR_ISO_UNDERFIS_Pos) /**< (HSTPIPIFR) Underflow Interrupt Set Mask */ +#define HSTPIPIFR_ISO_CRCERRIS_Pos 6 /**< (HSTPIPIFR) CRC Error Interrupt Set Position */ +#define HSTPIPIFR_ISO_CRCERRIS (_U_(0x1) << HSTPIPIFR_ISO_CRCERRIS_Pos) /**< (HSTPIPIFR) CRC Error Interrupt Set Mask */ +#define HSTPIPIFR_ISO_Msk _U_(0x44) /**< (HSTPIPIFR_ISO) Register Mask */ + +/* BLK mode */ +#define HSTPIPIFR_BLK_TXSTPIS_Pos 2 /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Position */ +#define HSTPIPIFR_BLK_TXSTPIS (_U_(0x1) << HSTPIPIFR_BLK_TXSTPIS_Pos) /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Mask */ +#define HSTPIPIFR_BLK_RXSTALLDIS_Pos 6 /**< (HSTPIPIFR) Received STALLed Interrupt Set Position */ +#define HSTPIPIFR_BLK_RXSTALLDIS (_U_(0x1) << HSTPIPIFR_BLK_RXSTALLDIS_Pos) /**< (HSTPIPIFR) Received STALLed Interrupt Set Mask */ +#define HSTPIPIFR_BLK_Msk _U_(0x44) /**< (HSTPIPIFR_BLK) Register Mask */ + +/* INTRPT mode */ +#define HSTPIPIFR_INTRPT_UNDERFIS_Pos 2 /**< (HSTPIPIFR) Underflow Interrupt Set Position */ +#define HSTPIPIFR_INTRPT_UNDERFIS (_U_(0x1) << HSTPIPIFR_INTRPT_UNDERFIS_Pos) /**< (HSTPIPIFR) Underflow Interrupt Set Mask */ +#define HSTPIPIFR_INTRPT_RXSTALLDIS_Pos 6 /**< (HSTPIPIFR) Received STALLed Interrupt Set Position */ +#define HSTPIPIFR_INTRPT_RXSTALLDIS (_U_(0x1) << HSTPIPIFR_INTRPT_RXSTALLDIS_Pos) /**< (HSTPIPIFR) Received STALLed Interrupt Set Mask */ +#define HSTPIPIFR_INTRPT_Msk _U_(0x44) /**< (HSTPIPIFR_INTRPT) Register Mask */ + + +/* -------- HSTPIPIMR : (USBHS Offset: 0x5c0) (R/ 32) Host Pipe Mask Register -------- */ + +#define HSTPIPIMR_OFFSET (0x5C0) /**< (HSTPIPIMR) Host Pipe Mask Register Offset */ + +#define HSTPIPIMR_RXINE_Pos 0 /**< (HSTPIPIMR) Received IN Data Interrupt Enable Position */ +#define HSTPIPIMR_RXINE (_U_(0x1) << HSTPIPIMR_RXINE_Pos) /**< (HSTPIPIMR) Received IN Data Interrupt Enable Mask */ +#define HSTPIPIMR_TXOUTE_Pos 1 /**< (HSTPIPIMR) Transmitted OUT Data Interrupt Enable Position */ +#define HSTPIPIMR_TXOUTE (_U_(0x1) << HSTPIPIMR_TXOUTE_Pos) /**< (HSTPIPIMR) Transmitted OUT Data Interrupt Enable Mask */ +#define HSTPIPIMR_PERRE_Pos 3 /**< (HSTPIPIMR) Pipe Error Interrupt Enable Position */ +#define HSTPIPIMR_PERRE (_U_(0x1) << HSTPIPIMR_PERRE_Pos) /**< (HSTPIPIMR) Pipe Error Interrupt Enable Mask */ +#define HSTPIPIMR_NAKEDE_Pos 4 /**< (HSTPIPIMR) NAKed Interrupt Enable Position */ +#define HSTPIPIMR_NAKEDE (_U_(0x1) << HSTPIPIMR_NAKEDE_Pos) /**< (HSTPIPIMR) NAKed Interrupt Enable Mask */ +#define HSTPIPIMR_OVERFIE_Pos 5 /**< (HSTPIPIMR) Overflow Interrupt Enable Position */ +#define HSTPIPIMR_OVERFIE (_U_(0x1) << HSTPIPIMR_OVERFIE_Pos) /**< (HSTPIPIMR) Overflow Interrupt Enable Mask */ +#define HSTPIPIMR_SHORTPACKETIE_Pos 7 /**< (HSTPIPIMR) Short Packet Interrupt Enable Position */ +#define HSTPIPIMR_SHORTPACKETIE (_U_(0x1) << HSTPIPIMR_SHORTPACKETIE_Pos) /**< (HSTPIPIMR) Short Packet Interrupt Enable Mask */ +#define HSTPIPIMR_NBUSYBKE_Pos 12 /**< (HSTPIPIMR) Number of Busy Banks Interrupt Enable Position */ +#define HSTPIPIMR_NBUSYBKE (_U_(0x1) << HSTPIPIMR_NBUSYBKE_Pos) /**< (HSTPIPIMR) Number of Busy Banks Interrupt Enable Mask */ +#define HSTPIPIMR_FIFOCON_Pos 14 /**< (HSTPIPIMR) FIFO Control Position */ +#define HSTPIPIMR_FIFOCON (_U_(0x1) << HSTPIPIMR_FIFOCON_Pos) /**< (HSTPIPIMR) FIFO Control Mask */ +#define HSTPIPIMR_PDISHDMA_Pos 16 /**< (HSTPIPIMR) Pipe Interrupts Disable HDMA Request Enable Position */ +#define HSTPIPIMR_PDISHDMA (_U_(0x1) << HSTPIPIMR_PDISHDMA_Pos) /**< (HSTPIPIMR) Pipe Interrupts Disable HDMA Request Enable Mask */ +#define HSTPIPIMR_PFREEZE_Pos 17 /**< (HSTPIPIMR) Pipe Freeze Position */ +#define HSTPIPIMR_PFREEZE (_U_(0x1) << HSTPIPIMR_PFREEZE_Pos) /**< (HSTPIPIMR) Pipe Freeze Mask */ +#define HSTPIPIMR_RSTDT_Pos 18 /**< (HSTPIPIMR) Reset Data Toggle Position */ +#define HSTPIPIMR_RSTDT (_U_(0x1) << HSTPIPIMR_RSTDT_Pos) /**< (HSTPIPIMR) Reset Data Toggle Mask */ +#define HSTPIPIMR_Msk _U_(0x750BB) /**< (HSTPIPIMR) Register Mask */ + +/* CTRL mode */ +#define HSTPIPIMR_CTRL_TXSTPE_Pos 2 /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Position */ +#define HSTPIPIMR_CTRL_TXSTPE (_U_(0x1) << HSTPIPIMR_CTRL_TXSTPE_Pos) /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Mask */ +#define HSTPIPIMR_CTRL_RXSTALLDE_Pos 6 /**< (HSTPIPIMR) Received STALLed Interrupt Enable Position */ +#define HSTPIPIMR_CTRL_RXSTALLDE (_U_(0x1) << HSTPIPIMR_CTRL_RXSTALLDE_Pos) /**< (HSTPIPIMR) Received STALLed Interrupt Enable Mask */ +#define HSTPIPIMR_CTRL_Msk _U_(0x44) /**< (HSTPIPIMR_CTRL) Register Mask */ + +/* ISO mode */ +#define HSTPIPIMR_ISO_UNDERFIE_Pos 2 /**< (HSTPIPIMR) Underflow Interrupt Enable Position */ +#define HSTPIPIMR_ISO_UNDERFIE (_U_(0x1) << HSTPIPIMR_ISO_UNDERFIE_Pos) /**< (HSTPIPIMR) Underflow Interrupt Enable Mask */ +#define HSTPIPIMR_ISO_CRCERRE_Pos 6 /**< (HSTPIPIMR) CRC Error Interrupt Enable Position */ +#define HSTPIPIMR_ISO_CRCERRE (_U_(0x1) << HSTPIPIMR_ISO_CRCERRE_Pos) /**< (HSTPIPIMR) CRC Error Interrupt Enable Mask */ +#define HSTPIPIMR_ISO_Msk _U_(0x44) /**< (HSTPIPIMR_ISO) Register Mask */ + +/* BLK mode */ +#define HSTPIPIMR_BLK_TXSTPE_Pos 2 /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Position */ +#define HSTPIPIMR_BLK_TXSTPE (_U_(0x1) << HSTPIPIMR_BLK_TXSTPE_Pos) /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Mask */ +#define HSTPIPIMR_BLK_RXSTALLDE_Pos 6 /**< (HSTPIPIMR) Received STALLed Interrupt Enable Position */ +#define HSTPIPIMR_BLK_RXSTALLDE (_U_(0x1) << HSTPIPIMR_BLK_RXSTALLDE_Pos) /**< (HSTPIPIMR) Received STALLed Interrupt Enable Mask */ +#define HSTPIPIMR_BLK_Msk _U_(0x44) /**< (HSTPIPIMR_BLK) Register Mask */ + +/* INTRPT mode */ +#define HSTPIPIMR_INTRPT_UNDERFIE_Pos 2 /**< (HSTPIPIMR) Underflow Interrupt Enable Position */ +#define HSTPIPIMR_INTRPT_UNDERFIE (_U_(0x1) << HSTPIPIMR_INTRPT_UNDERFIE_Pos) /**< (HSTPIPIMR) Underflow Interrupt Enable Mask */ +#define HSTPIPIMR_INTRPT_RXSTALLDE_Pos 6 /**< (HSTPIPIMR) Received STALLed Interrupt Enable Position */ +#define HSTPIPIMR_INTRPT_RXSTALLDE (_U_(0x1) << HSTPIPIMR_INTRPT_RXSTALLDE_Pos) /**< (HSTPIPIMR) Received STALLed Interrupt Enable Mask */ +#define HSTPIPIMR_INTRPT_Msk _U_(0x44) /**< (HSTPIPIMR_INTRPT) Register Mask */ + + +/* -------- HSTPIPIER : (USBHS Offset: 0x5f0) (/W 32) Host Pipe Enable Register -------- */ + +#define HSTPIPIER_OFFSET (0x5F0) /**< (HSTPIPIER) Host Pipe Enable Register Offset */ + +#define HSTPIPIER_RXINES_Pos 0 /**< (HSTPIPIER) Received IN Data Interrupt Enable Position */ +#define HSTPIPIER_RXINES (_U_(0x1) << HSTPIPIER_RXINES_Pos) /**< (HSTPIPIER) Received IN Data Interrupt Enable Mask */ +#define HSTPIPIER_TXOUTES_Pos 1 /**< (HSTPIPIER) Transmitted OUT Data Interrupt Enable Position */ +#define HSTPIPIER_TXOUTES (_U_(0x1) << HSTPIPIER_TXOUTES_Pos) /**< (HSTPIPIER) Transmitted OUT Data Interrupt Enable Mask */ +#define HSTPIPIER_PERRES_Pos 3 /**< (HSTPIPIER) Pipe Error Interrupt Enable Position */ +#define HSTPIPIER_PERRES (_U_(0x1) << HSTPIPIER_PERRES_Pos) /**< (HSTPIPIER) Pipe Error Interrupt Enable Mask */ +#define HSTPIPIER_NAKEDES_Pos 4 /**< (HSTPIPIER) NAKed Interrupt Enable Position */ +#define HSTPIPIER_NAKEDES (_U_(0x1) << HSTPIPIER_NAKEDES_Pos) /**< (HSTPIPIER) NAKed Interrupt Enable Mask */ +#define HSTPIPIER_OVERFIES_Pos 5 /**< (HSTPIPIER) Overflow Interrupt Enable Position */ +#define HSTPIPIER_OVERFIES (_U_(0x1) << HSTPIPIER_OVERFIES_Pos) /**< (HSTPIPIER) Overflow Interrupt Enable Mask */ +#define HSTPIPIER_SHORTPACKETIES_Pos 7 /**< (HSTPIPIER) Short Packet Interrupt Enable Position */ +#define HSTPIPIER_SHORTPACKETIES (_U_(0x1) << HSTPIPIER_SHORTPACKETIES_Pos) /**< (HSTPIPIER) Short Packet Interrupt Enable Mask */ +#define HSTPIPIER_NBUSYBKES_Pos 12 /**< (HSTPIPIER) Number of Busy Banks Enable Position */ +#define HSTPIPIER_NBUSYBKES (_U_(0x1) << HSTPIPIER_NBUSYBKES_Pos) /**< (HSTPIPIER) Number of Busy Banks Enable Mask */ +#define HSTPIPIER_PDISHDMAS_Pos 16 /**< (HSTPIPIER) Pipe Interrupts Disable HDMA Request Enable Position */ +#define HSTPIPIER_PDISHDMAS (_U_(0x1) << HSTPIPIER_PDISHDMAS_Pos) /**< (HSTPIPIER) Pipe Interrupts Disable HDMA Request Enable Mask */ +#define HSTPIPIER_PFREEZES_Pos 17 /**< (HSTPIPIER) Pipe Freeze Enable Position */ +#define HSTPIPIER_PFREEZES (_U_(0x1) << HSTPIPIER_PFREEZES_Pos) /**< (HSTPIPIER) Pipe Freeze Enable Mask */ +#define HSTPIPIER_RSTDTS_Pos 18 /**< (HSTPIPIER) Reset Data Toggle Enable Position */ +#define HSTPIPIER_RSTDTS (_U_(0x1) << HSTPIPIER_RSTDTS_Pos) /**< (HSTPIPIER) Reset Data Toggle Enable Mask */ +#define HSTPIPIER_Msk _U_(0x710BB) /**< (HSTPIPIER) Register Mask */ + +/* CTRL mode */ +#define HSTPIPIER_CTRL_TXSTPES_Pos 2 /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Position */ +#define HSTPIPIER_CTRL_TXSTPES (_U_(0x1) << HSTPIPIER_CTRL_TXSTPES_Pos) /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Mask */ +#define HSTPIPIER_CTRL_RXSTALLDES_Pos 6 /**< (HSTPIPIER) Received STALLed Interrupt Enable Position */ +#define HSTPIPIER_CTRL_RXSTALLDES (_U_(0x1) << HSTPIPIER_CTRL_RXSTALLDES_Pos) /**< (HSTPIPIER) Received STALLed Interrupt Enable Mask */ +#define HSTPIPIER_CTRL_Msk _U_(0x44) /**< (HSTPIPIER_CTRL) Register Mask */ + +/* ISO mode */ +#define HSTPIPIER_ISO_UNDERFIES_Pos 2 /**< (HSTPIPIER) Underflow Interrupt Enable Position */ +#define HSTPIPIER_ISO_UNDERFIES (_U_(0x1) << HSTPIPIER_ISO_UNDERFIES_Pos) /**< (HSTPIPIER) Underflow Interrupt Enable Mask */ +#define HSTPIPIER_ISO_CRCERRES_Pos 6 /**< (HSTPIPIER) CRC Error Interrupt Enable Position */ +#define HSTPIPIER_ISO_CRCERRES (_U_(0x1) << HSTPIPIER_ISO_CRCERRES_Pos) /**< (HSTPIPIER) CRC Error Interrupt Enable Mask */ +#define HSTPIPIER_ISO_Msk _U_(0x44) /**< (HSTPIPIER_ISO) Register Mask */ + +/* BLK mode */ +#define HSTPIPIER_BLK_TXSTPES_Pos 2 /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Position */ +#define HSTPIPIER_BLK_TXSTPES (_U_(0x1) << HSTPIPIER_BLK_TXSTPES_Pos) /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Mask */ +#define HSTPIPIER_BLK_RXSTALLDES_Pos 6 /**< (HSTPIPIER) Received STALLed Interrupt Enable Position */ +#define HSTPIPIER_BLK_RXSTALLDES (_U_(0x1) << HSTPIPIER_BLK_RXSTALLDES_Pos) /**< (HSTPIPIER) Received STALLed Interrupt Enable Mask */ +#define HSTPIPIER_BLK_Msk _U_(0x44) /**< (HSTPIPIER_BLK) Register Mask */ + +/* INTRPT mode */ +#define HSTPIPIER_INTRPT_UNDERFIES_Pos 2 /**< (HSTPIPIER) Underflow Interrupt Enable Position */ +#define HSTPIPIER_INTRPT_UNDERFIES (_U_(0x1) << HSTPIPIER_INTRPT_UNDERFIES_Pos) /**< (HSTPIPIER) Underflow Interrupt Enable Mask */ +#define HSTPIPIER_INTRPT_RXSTALLDES_Pos 6 /**< (HSTPIPIER) Received STALLed Interrupt Enable Position */ +#define HSTPIPIER_INTRPT_RXSTALLDES (_U_(0x1) << HSTPIPIER_INTRPT_RXSTALLDES_Pos) /**< (HSTPIPIER) Received STALLed Interrupt Enable Mask */ +#define HSTPIPIER_INTRPT_Msk _U_(0x44) /**< (HSTPIPIER_INTRPT) Register Mask */ + + +/* -------- HSTPIPIDR : (USBHS Offset: 0x620) (/W 32) Host Pipe Disable Register -------- */ + +#define HSTPIPIDR_OFFSET (0x620) /**< (HSTPIPIDR) Host Pipe Disable Register Offset */ + +#define HSTPIPIDR_RXINEC_Pos 0 /**< (HSTPIPIDR) Received IN Data Interrupt Disable Position */ +#define HSTPIPIDR_RXINEC (_U_(0x1) << HSTPIPIDR_RXINEC_Pos) /**< (HSTPIPIDR) Received IN Data Interrupt Disable Mask */ +#define HSTPIPIDR_TXOUTEC_Pos 1 /**< (HSTPIPIDR) Transmitted OUT Data Interrupt Disable Position */ +#define HSTPIPIDR_TXOUTEC (_U_(0x1) << HSTPIPIDR_TXOUTEC_Pos) /**< (HSTPIPIDR) Transmitted OUT Data Interrupt Disable Mask */ +#define HSTPIPIDR_PERREC_Pos 3 /**< (HSTPIPIDR) Pipe Error Interrupt Disable Position */ +#define HSTPIPIDR_PERREC (_U_(0x1) << HSTPIPIDR_PERREC_Pos) /**< (HSTPIPIDR) Pipe Error Interrupt Disable Mask */ +#define HSTPIPIDR_NAKEDEC_Pos 4 /**< (HSTPIPIDR) NAKed Interrupt Disable Position */ +#define HSTPIPIDR_NAKEDEC (_U_(0x1) << HSTPIPIDR_NAKEDEC_Pos) /**< (HSTPIPIDR) NAKed Interrupt Disable Mask */ +#define HSTPIPIDR_OVERFIEC_Pos 5 /**< (HSTPIPIDR) Overflow Interrupt Disable Position */ +#define HSTPIPIDR_OVERFIEC (_U_(0x1) << HSTPIPIDR_OVERFIEC_Pos) /**< (HSTPIPIDR) Overflow Interrupt Disable Mask */ +#define HSTPIPIDR_SHORTPACKETIEC_Pos 7 /**< (HSTPIPIDR) Short Packet Interrupt Disable Position */ +#define HSTPIPIDR_SHORTPACKETIEC (_U_(0x1) << HSTPIPIDR_SHORTPACKETIEC_Pos) /**< (HSTPIPIDR) Short Packet Interrupt Disable Mask */ +#define HSTPIPIDR_NBUSYBKEC_Pos 12 /**< (HSTPIPIDR) Number of Busy Banks Disable Position */ +#define HSTPIPIDR_NBUSYBKEC (_U_(0x1) << HSTPIPIDR_NBUSYBKEC_Pos) /**< (HSTPIPIDR) Number of Busy Banks Disable Mask */ +#define HSTPIPIDR_FIFOCONC_Pos 14 /**< (HSTPIPIDR) FIFO Control Disable Position */ +#define HSTPIPIDR_FIFOCONC (_U_(0x1) << HSTPIPIDR_FIFOCONC_Pos) /**< (HSTPIPIDR) FIFO Control Disable Mask */ +#define HSTPIPIDR_PDISHDMAC_Pos 16 /**< (HSTPIPIDR) Pipe Interrupts Disable HDMA Request Disable Position */ +#define HSTPIPIDR_PDISHDMAC (_U_(0x1) << HSTPIPIDR_PDISHDMAC_Pos) /**< (HSTPIPIDR) Pipe Interrupts Disable HDMA Request Disable Mask */ +#define HSTPIPIDR_PFREEZEC_Pos 17 /**< (HSTPIPIDR) Pipe Freeze Disable Position */ +#define HSTPIPIDR_PFREEZEC (_U_(0x1) << HSTPIPIDR_PFREEZEC_Pos) /**< (HSTPIPIDR) Pipe Freeze Disable Mask */ +#define HSTPIPIDR_Msk _U_(0x350BB) /**< (HSTPIPIDR) Register Mask */ + +/* CTRL mode */ +#define HSTPIPIDR_CTRL_TXSTPEC_Pos 2 /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Position */ +#define HSTPIPIDR_CTRL_TXSTPEC (_U_(0x1) << HSTPIPIDR_CTRL_TXSTPEC_Pos) /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Mask */ +#define HSTPIPIDR_CTRL_RXSTALLDEC_Pos 6 /**< (HSTPIPIDR) Received STALLed Interrupt Disable Position */ +#define HSTPIPIDR_CTRL_RXSTALLDEC (_U_(0x1) << HSTPIPIDR_CTRL_RXSTALLDEC_Pos) /**< (HSTPIPIDR) Received STALLed Interrupt Disable Mask */ +#define HSTPIPIDR_CTRL_Msk _U_(0x44) /**< (HSTPIPIDR_CTRL) Register Mask */ + +/* ISO mode */ +#define HSTPIPIDR_ISO_UNDERFIEC_Pos 2 /**< (HSTPIPIDR) Underflow Interrupt Disable Position */ +#define HSTPIPIDR_ISO_UNDERFIEC (_U_(0x1) << HSTPIPIDR_ISO_UNDERFIEC_Pos) /**< (HSTPIPIDR) Underflow Interrupt Disable Mask */ +#define HSTPIPIDR_ISO_CRCERREC_Pos 6 /**< (HSTPIPIDR) CRC Error Interrupt Disable Position */ +#define HSTPIPIDR_ISO_CRCERREC (_U_(0x1) << HSTPIPIDR_ISO_CRCERREC_Pos) /**< (HSTPIPIDR) CRC Error Interrupt Disable Mask */ +#define HSTPIPIDR_ISO_Msk _U_(0x44) /**< (HSTPIPIDR_ISO) Register Mask */ + +/* BLK mode */ +#define HSTPIPIDR_BLK_TXSTPEC_Pos 2 /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Position */ +#define HSTPIPIDR_BLK_TXSTPEC (_U_(0x1) << HSTPIPIDR_BLK_TXSTPEC_Pos) /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Mask */ +#define HSTPIPIDR_BLK_RXSTALLDEC_Pos 6 /**< (HSTPIPIDR) Received STALLed Interrupt Disable Position */ +#define HSTPIPIDR_BLK_RXSTALLDEC (_U_(0x1) << HSTPIPIDR_BLK_RXSTALLDEC_Pos) /**< (HSTPIPIDR) Received STALLed Interrupt Disable Mask */ +#define HSTPIPIDR_BLK_Msk _U_(0x44) /**< (HSTPIPIDR_BLK) Register Mask */ + +/* INTRPT mode */ +#define HSTPIPIDR_INTRPT_UNDERFIEC_Pos 2 /**< (HSTPIPIDR) Underflow Interrupt Disable Position */ +#define HSTPIPIDR_INTRPT_UNDERFIEC (_U_(0x1) << HSTPIPIDR_INTRPT_UNDERFIEC_Pos) /**< (HSTPIPIDR) Underflow Interrupt Disable Mask */ +#define HSTPIPIDR_INTRPT_RXSTALLDEC_Pos 6 /**< (HSTPIPIDR) Received STALLed Interrupt Disable Position */ +#define HSTPIPIDR_INTRPT_RXSTALLDEC (_U_(0x1) << HSTPIPIDR_INTRPT_RXSTALLDEC_Pos) /**< (HSTPIPIDR) Received STALLed Interrupt Disable Mask */ +#define HSTPIPIDR_INTRPT_Msk _U_(0x44) /**< (HSTPIPIDR_INTRPT) Register Mask */ + + +/* -------- HSTPIPINRQ : (USBHS Offset: 0x650) (R/W 32) Host Pipe IN Request Register -------- */ + +#define HSTPIPINRQ_OFFSET (0x650) /**< (HSTPIPINRQ) Host Pipe IN Request Register Offset */ + +#define HSTPIPINRQ_INRQ_Pos 0 /**< (HSTPIPINRQ) IN Request Number before Freeze Position */ +#define HSTPIPINRQ_INRQ (_U_(0xFF) << HSTPIPINRQ_INRQ_Pos) /**< (HSTPIPINRQ) IN Request Number before Freeze Mask */ +#define HSTPIPINRQ_INMODE_Pos 8 /**< (HSTPIPINRQ) IN Request Mode Position */ +#define HSTPIPINRQ_INMODE (_U_(0x1) << HSTPIPINRQ_INMODE_Pos) /**< (HSTPIPINRQ) IN Request Mode Mask */ +#define HSTPIPINRQ_Msk _U_(0x1FF) /**< (HSTPIPINRQ) Register Mask */ + + +/* -------- HSTPIPERR : (USBHS Offset: 0x680) (R/W 32) Host Pipe Error Register -------- */ + +#define HSTPIPERR_OFFSET (0x680) /**< (HSTPIPERR) Host Pipe Error Register Offset */ + +#define HSTPIPERR_DATATGL_Pos 0 /**< (HSTPIPERR) Data Toggle Error Position */ +#define HSTPIPERR_DATATGL (_U_(0x1) << HSTPIPERR_DATATGL_Pos) /**< (HSTPIPERR) Data Toggle Error Mask */ +#define HSTPIPERR_DATAPID_Pos 1 /**< (HSTPIPERR) Data PID Error Position */ +#define HSTPIPERR_DATAPID (_U_(0x1) << HSTPIPERR_DATAPID_Pos) /**< (HSTPIPERR) Data PID Error Mask */ +#define HSTPIPERR_PID_Pos 2 /**< (HSTPIPERR) Data PID Error Position */ +#define HSTPIPERR_PID (_U_(0x1) << HSTPIPERR_PID_Pos) /**< (HSTPIPERR) Data PID Error Mask */ +#define HSTPIPERR_TIMEOUT_Pos 3 /**< (HSTPIPERR) Time-Out Error Position */ +#define HSTPIPERR_TIMEOUT (_U_(0x1) << HSTPIPERR_TIMEOUT_Pos) /**< (HSTPIPERR) Time-Out Error Mask */ +#define HSTPIPERR_CRC16_Pos 4 /**< (HSTPIPERR) CRC16 Error Position */ +#define HSTPIPERR_CRC16 (_U_(0x1) << HSTPIPERR_CRC16_Pos) /**< (HSTPIPERR) CRC16 Error Mask */ +#define HSTPIPERR_COUNTER_Pos 5 /**< (HSTPIPERR) Error Counter Position */ +#define HSTPIPERR_COUNTER (_U_(0x3) << HSTPIPERR_COUNTER_Pos) /**< (HSTPIPERR) Error Counter Mask */ +#define HSTPIPERR_Msk _U_(0x7F) /**< (HSTPIPERR) Register Mask */ + +#define HSTPIPERR_CRC_Pos 4 /**< (HSTPIPERR Position) CRCx6 Error */ +#define HSTPIPERR_CRC (_U_(0x1) << HSTPIPERR_CRC_Pos) /**< (HSTPIPERR Mask) CRC */ + +/* -------- CTRL : (USBHS Offset: 0x800) (R/W 32) General Control Register -------- */ + +#define CTRL_OFFSET (0x800) /**< (CTRL) General Control Register Offset */ + +#define CTRL_RDERRE_Pos 4 /**< (CTRL) Remote Device Connection Error Interrupt Enable Position */ +#define CTRL_RDERRE (_U_(0x1) << CTRL_RDERRE_Pos) /**< (CTRL) Remote Device Connection Error Interrupt Enable Mask */ +#define CTRL_VBUSHWC_Pos 8 /**< (CTRL) VBUS Hardware Control Position */ +#define CTRL_VBUSHWC (_U_(0x1) << CTRL_VBUSHWC_Pos) /**< (CTRL) VBUS Hardware Control Mask */ +#define CTRL_FRZCLK_Pos 14 /**< (CTRL) Freeze USB Clock Position */ +#define CTRL_FRZCLK (_U_(0x1) << CTRL_FRZCLK_Pos) /**< (CTRL) Freeze USB Clock Mask */ +#define CTRL_USBE_Pos 15 /**< (CTRL) USBHS Enable Position */ +#define CTRL_USBE (_U_(0x1) << CTRL_USBE_Pos) /**< (CTRL) USBHS Enable Mask */ +#define CTRL_UID_Pos 24 /**< (CTRL) UID Pin Enable Position */ +#define CTRL_UID (_U_(0x1) << CTRL_UID_Pos) /**< (CTRL) UID Pin Enable Mask */ +#define CTRL_UIMOD_Pos 25 /**< (CTRL) USBHS Mode Position */ +#define CTRL_UIMOD (_U_(0x1) << CTRL_UIMOD_Pos) /**< (CTRL) USBHS Mode Mask */ +#define CTRL_UIMOD_HOST_Val _U_(0x0) /**< (CTRL) The module is in USB Host mode. */ +#define CTRL_UIMOD_DEVICE_Val _U_(0x1) /**< (CTRL) The module is in USB Device mode. */ +#define CTRL_UIMOD_HOST (CTRL_UIMOD_HOST_Val << CTRL_UIMOD_Pos) /**< (CTRL) The module is in USB Host mode. Position */ +#define CTRL_UIMOD_DEVICE (CTRL_UIMOD_DEVICE_Val << CTRL_UIMOD_Pos) /**< (CTRL) The module is in USB Device mode. Position */ +#define CTRL_Msk _U_(0x300C110) /**< (CTRL) Register Mask */ + + +/* -------- SR : (USBHS Offset: 0x804) (R/ 32) General Status Register -------- */ + +#define SR_OFFSET (0x804) /**< (SR) General Status Register Offset */ + +#define SR_RDERRI_Pos 4 /**< (SR) Remote Device Connection Error Interrupt (Host mode only) Position */ +#define SR_RDERRI (_U_(0x1) << SR_RDERRI_Pos) /**< (SR) Remote Device Connection Error Interrupt (Host mode only) Mask */ +#define SR_SPEED_Pos 12 /**< (SR) Speed Status (Device mode only) Position */ +#define SR_SPEED (_U_(0x3) << SR_SPEED_Pos) /**< (SR) Speed Status (Device mode only) Mask */ +#define SR_SPEED_FULL_SPEED_Val _U_(0x0) /**< (SR) Full-Speed mode */ +#define SR_SPEED_HIGH_SPEED_Val _U_(0x1) /**< (SR) High-Speed mode */ +#define SR_SPEED_LOW_SPEED_Val _U_(0x2) /**< (SR) Low-Speed mode */ +#define SR_SPEED_FULL_SPEED (SR_SPEED_FULL_SPEED_Val << SR_SPEED_Pos) /**< (SR) Full-Speed mode Position */ +#define SR_SPEED_HIGH_SPEED (SR_SPEED_HIGH_SPEED_Val << SR_SPEED_Pos) /**< (SR) High-Speed mode Position */ +#define SR_SPEED_LOW_SPEED (SR_SPEED_LOW_SPEED_Val << SR_SPEED_Pos) /**< (SR) Low-Speed mode Position */ +#define SR_CLKUSABLE_Pos 14 /**< (SR) UTMI Clock Usable Position */ +#define SR_CLKUSABLE (_U_(0x1) << SR_CLKUSABLE_Pos) /**< (SR) UTMI Clock Usable Mask */ +#define SR_Msk _U_(0x7010) /**< (SR) Register Mask */ + + +/* -------- SCR : (USBHS Offset: 0x808) (/W 32) General Status Clear Register -------- */ + +#define SCR_OFFSET (0x808) /**< (SCR) General Status Clear Register Offset */ + +#define SCR_RDERRIC_Pos 4 /**< (SCR) Remote Device Connection Error Interrupt Clear Position */ +#define SCR_RDERRIC (_U_(0x1) << SCR_RDERRIC_Pos) /**< (SCR) Remote Device Connection Error Interrupt Clear Mask */ +#define SCR_Msk _U_(0x10) /**< (SCR) Register Mask */ + + +/* -------- SFR : (USBHS Offset: 0x80c) (/W 32) General Status Set Register -------- */ + +#define SFR_OFFSET (0x80C) /**< (SFR) General Status Set Register Offset */ + +#define SFR_RDERRIS_Pos 4 /**< (SFR) Remote Device Connection Error Interrupt Set Position */ +#define SFR_RDERRIS (_U_(0x1) << SFR_RDERRIS_Pos) /**< (SFR) Remote Device Connection Error Interrupt Set Mask */ +#define SFR_VBUSRQS_Pos 9 /**< (SFR) VBUS Request Set Position */ +#define SFR_VBUSRQS (_U_(0x1) << SFR_VBUSRQS_Pos) /**< (SFR) VBUS Request Set Mask */ +#define SFR_Msk _U_(0x210) /**< (SFR) Register Mask */ + + +/** \brief DEVDMA hardware registers */ +typedef struct +{ + __IO uint32_t DEVDMANXTDSC; /**< (DEVDMA Offset: 0x00) Device DMA Channel Next Descriptor Address Register */ + __IO uint32_t DEVDMAADDRESS; /**< (DEVDMA Offset: 0x04) Device DMA Channel Address Register */ + __IO uint32_t DEVDMACONTROL; /**< (DEVDMA Offset: 0x08) Device DMA Channel Control Register */ + __IO uint32_t DEVDMASTATUS; /**< (DEVDMA Offset: 0x0C) Device DMA Channel Status Register */ +} devdma_t; + +/** \brief HSTDMA hardware registers */ +typedef struct +{ + __IO uint32_t HSTDMANXTDSC; /**< (HSTDMA Offset: 0x00) Host DMA Channel Next Descriptor Address Register */ + __IO uint32_t HSTDMAADDRESS; /**< (HSTDMA Offset: 0x04) Host DMA Channel Address Register */ + __IO uint32_t HSTDMACONTROL; /**< (HSTDMA Offset: 0x08) Host DMA Channel Control Register */ + __IO uint32_t HSTDMASTATUS; /**< (HSTDMA Offset: 0x0C) Host DMA Channel Status Register */ +} hstdma_t; + +/** \brief USBHS hardware registers */ +typedef struct +{ + __IO uint32_t DEVCTRL; /**< (USBHS Offset: 0x00) Device General Control Register */ + __I uint32_t DEVISR; /**< (USBHS Offset: 0x04) Device Global Interrupt Status Register */ + __O uint32_t DEVICR; /**< (USBHS Offset: 0x08) Device Global Interrupt Clear Register */ + __O uint32_t DEVIFR; /**< (USBHS Offset: 0x0C) Device Global Interrupt Set Register */ + __I uint32_t DEVIMR; /**< (USBHS Offset: 0x10) Device Global Interrupt Mask Register */ + __O uint32_t DEVIDR; /**< (USBHS Offset: 0x14) Device Global Interrupt Disable Register */ + __O uint32_t DEVIER; /**< (USBHS Offset: 0x18) Device Global Interrupt Enable Register */ + __IO uint32_t DEVEPT; /**< (USBHS Offset: 0x1C) Device Endpoint Register */ + __I uint32_t DEVFNUM; /**< (USBHS Offset: 0x20) Device Frame Number Register */ + __I uint8_t Reserved1[220]; + __IO uint32_t DEVEPTCFG[10]; /**< (USBHS Offset: 0x100) Device Endpoint Configuration Register */ + __I uint8_t Reserved2[8]; + __I uint32_t DEVEPTISR[10]; /**< (USBHS Offset: 0x130) Device Endpoint Interrupt Status Register */ + __I uint8_t Reserved3[8]; + __O uint32_t DEVEPTICR[10]; /**< (USBHS Offset: 0x160) Device Endpoint Interrupt Clear Register */ + __I uint8_t Reserved4[8]; + __O uint32_t DEVEPTIFR[10]; /**< (USBHS Offset: 0x190) Device Endpoint Interrupt Set Register */ + __I uint8_t Reserved5[8]; + __I uint32_t DEVEPTIMR[10]; /**< (USBHS Offset: 0x1C0) Device Endpoint Interrupt Mask Register */ + __I uint8_t Reserved6[8]; + __O uint32_t DEVEPTIER[10]; /**< (USBHS Offset: 0x1F0) Device Endpoint Interrupt Enable Register */ + __I uint8_t Reserved7[8]; + __O uint32_t DEVEPTIDR[10]; /**< (USBHS Offset: 0x220) Device Endpoint Interrupt Disable Register */ + __I uint8_t Reserved8[200]; + devdma_t DEVDMA[7]; /**< Offset: 0x310 Device DMA Channel Next Descriptor Address Register */ + __I uint8_t Reserved9[128]; + __IO uint32_t HSTCTRL; /**< (USBHS Offset: 0x400) Host General Control Register */ + __I uint32_t HSTISR; /**< (USBHS Offset: 0x404) Host Global Interrupt Status Register */ + __O uint32_t HSTICR; /**< (USBHS Offset: 0x408) Host Global Interrupt Clear Register */ + __O uint32_t HSTIFR; /**< (USBHS Offset: 0x40C) Host Global Interrupt Set Register */ + __I uint32_t HSTIMR; /**< (USBHS Offset: 0x410) Host Global Interrupt Mask Register */ + __O uint32_t HSTIDR; /**< (USBHS Offset: 0x414) Host Global Interrupt Disable Register */ + __O uint32_t HSTIER; /**< (USBHS Offset: 0x418) Host Global Interrupt Enable Register */ + __IO uint32_t HSTPIP; /**< (USBHS Offset: 0x41C) Host Pipe Register */ + __IO uint32_t HSTFNUM; /**< (USBHS Offset: 0x420) Host Frame Number Register */ + __IO uint32_t HSTADDR1; /**< (USBHS Offset: 0x424) Host Address 1 Register */ + __IO uint32_t HSTADDR2; /**< (USBHS Offset: 0x428) Host Address 2 Register */ + __IO uint32_t HSTADDR3; /**< (USBHS Offset: 0x42C) Host Address 3 Register */ + __I uint8_t Reserved10[208]; + __IO uint32_t HSTPIPCFG[10]; /**< (USBHS Offset: 0x500) Host Pipe Configuration Register */ + __I uint8_t Reserved11[8]; + __I uint32_t HSTPIPISR[10]; /**< (USBHS Offset: 0x530) Host Pipe Status Register */ + __I uint8_t Reserved12[8]; + __O uint32_t HSTPIPICR[10]; /**< (USBHS Offset: 0x560) Host Pipe Clear Register */ + __I uint8_t Reserved13[8]; + __O uint32_t HSTPIPIFR[10]; /**< (USBHS Offset: 0x590) Host Pipe Set Register */ + __I uint8_t Reserved14[8]; + __I uint32_t HSTPIPIMR[10]; /**< (USBHS Offset: 0x5C0) Host Pipe Mask Register */ + __I uint8_t Reserved15[8]; + __O uint32_t HSTPIPIER[10]; /**< (USBHS Offset: 0x5F0) Host Pipe Enable Register */ + __I uint8_t Reserved16[8]; + __O uint32_t HSTPIPIDR[10]; /**< (USBHS Offset: 0x620) Host Pipe Disable Register */ + __I uint8_t Reserved17[8]; + __IO uint32_t HSTPIPINRQ[10]; /**< (USBHS Offset: 0x650) Host Pipe IN Request Register */ + __I uint8_t Reserved18[8]; + __IO uint32_t HSTPIPERR[10]; /**< (USBHS Offset: 0x680) Host Pipe Error Register */ + __I uint8_t Reserved19[104]; + hstdma_t HSTDMA[7]; /**< Offset: 0x710 Host DMA Channel Next Descriptor Address Register */ + __I uint8_t Reserved20[128]; + __IO uint32_t CTRL; /**< (USBHS Offset: 0x800) General Control Register */ + __I uint32_t SR; /**< (USBHS Offset: 0x804) General Status Register */ + __O uint32_t SCR; /**< (USBHS Offset: 0x808) General Status Clear Register */ + __O uint32_t SFR; /**< (USBHS Offset: 0x80C) General Status Set Register */ +} dcd_registers_t; + +#define USB_REG ((dcd_registers_t *)0x40038000U) /**< \brief (USBHS) Base Address */ + +#define EP_MAX 10 + +#define FIFO_RAM_ADDR 0xA0100000u + +// Errata: The DMA feature is not available for Pipe/Endpoint 7 +#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) + +#else // TODO : SAM3U + + +#endif + +#endif /* _COMMON_USB_REGS_H_ */ diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 465c5953b..419265723 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -30,8 +30,8 @@ #if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAMX7X #include "device/dcd.h" - #include "sam.h" +#include "common_usb_regs.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ @@ -53,14 +53,7 @@ # endif #endif -#define EP_MAX 10 - -#define USBHS_RAM_ADDR 0xA0100000u - -#define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])USBHS_RAM_ADDR)[(ep)]) - -// Errata: The DMA feature is not available for Pipe/Endpoint 7 -#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) +#define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])FIFO_RAM_ADDR)[(ep)]) // DMA Channel Transfer Descriptor typedef struct { @@ -145,7 +138,7 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) void dcd_remote_wakeup (uint8_t rhport) { (void) rhport; - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_RMWKUP; + USB_REG->DEVCTRL |= DEVCTRL_RMWKUP; } // Connect by enabling internal pull-up resistor on D+/D- @@ -154,28 +147,28 @@ void dcd_connect(uint8_t rhport) (void) rhport; dcd_int_disable(rhport); // Enable the USB controller in device mode - USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD | USBHS_CTRL_USBE; - while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + USB_REG->CTRL = CTRL_UIMOD | CTRL_USBE; + while (SR_CLKUSABLE != (USB_REG->SR & SR_CLKUSABLE)); #if TUD_OPT_HIGH_SPEED - USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_SPDCONF_Msk; + USB_REG->DEVCTRL &= ~DEVCTRL_SPDCONF; #else - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_SPDCONF_LOW_POWER; + USB_REG->DEVCTRL |= DEVCTRL_SPDCONF_LOW_POWER; #endif // Enable the End Of Reset, Suspend & Wakeup interrupts - USBHS->USBHS_DEVIER = (USBHS_DEVIER_EORSTES | USBHS_DEVIER_SUSPES | USBHS_DEVIER_WAKEUPES); + USB_REG->DEVIER = (DEVIER_EORSTES | DEVIER_SUSPES | DEVIER_WAKEUPES); #if USE_SOF - USBHS->USBHS_DEVIER = USBHS_DEVIER_SOFES; + USB_REG->DEVIER = DEVIER_SOFES; #endif // Clear the End Of Reset, SOF & Wakeup interrupts - USBHS->USBHS_DEVICR = (USBHS_DEVICR_EORSTC | USBHS_DEVICR_SOFC | USBHS_DEVICR_WAKEUPC); + USB_REG->DEVICR = (DEVICR_EORSTC | DEVICR_SOFC | DEVICR_WAKEUPC); // Manually set the Suspend Interrupt - USBHS->USBHS_DEVIFR |= USBHS_DEVIFR_SUSPS; + USB_REG->DEVIFR |= DEVIFR_SUSPS; // Ack the Wakeup Interrupt - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; + USB_REG->DEVICR = DEVICR_WAKEUPC; // Attach the device - USBHS->USBHS_DEVCTRL &= ~USBHS_DEVCTRL_DETACH; + USB_REG->DEVCTRL &= ~DEVCTRL_DETACH; // Freeze USB clock - USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; + USB_REG->CTRL |= CTRL_FRZCLK; } // Disconnect by disabling internal pull-up resistor on D+/D- @@ -184,49 +177,49 @@ void dcd_disconnect(uint8_t rhport) (void) rhport; dcd_int_disable(rhport); // Disable all endpoints - USBHS->USBHS_DEVEPT &= ~(0x3FF << USBHS_DEVEPT_EPEN0_Pos); + USB_REG->DEVEPT &= ~(0x3FF << DEVEPT_EPEN0_Pos); // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + USB_REG->CTRL &= ~CTRL_FRZCLK; + while (SR_CLKUSABLE != (USB_REG->SR & SR_CLKUSABLE)); // Clear all the pending interrupts - USBHS->USBHS_DEVICR = USBHS_DEVICR_Msk; + USB_REG->DEVICR = DEVICR_Msk; // Disable all interrupts - USBHS->USBHS_DEVIDR = USBHS_DEVCTRL_UADD_Msk; + USB_REG->DEVIDR = DEVIDR_Msk; // Detach the device - USBHS->USBHS_DEVCTRL |= USBHS_DEVCTRL_DETACH; + USB_REG->DEVCTRL |= DEVCTRL_DETACH; // Disable the device address - USBHS->USBHS_DEVCTRL &=~(USBHS_DEVCTRL_ADDEN | USBHS_DEVCTRL_UADD_Msk); + USB_REG->DEVCTRL &=~(DEVCTRL_ADDEN | DEVCTRL_UADD); } static tusb_speed_t get_speed(void) { - switch ((USBHS->USBHS_SR & USBHS_SR_SPEED_Msk) >> USBHS_SR_SPEED_Pos) { - case USBHS_SR_SPEED_FULL_SPEED_Val: + switch ((USB_REG->SR & SR_SPEED) >> SR_SPEED_Pos) { + case SR_SPEED_FULL_SPEED: default: return TUSB_SPEED_FULL; - case USBHS_SR_SPEED_HIGH_SPEED_Val: + case SR_SPEED_HIGH_SPEED: return TUSB_SPEED_HIGH; - case USBHS_SR_SPEED_LOW_SPEED_Val: + case SR_SPEED_LOW_SPEED: return TUSB_SPEED_LOW; } } static void dcd_ep_handler(uint8_t ep_ix) { - uint32_t int_status = USBHS->USBHS_DEVEPTISR[ep_ix]; - int_status &= USBHS->USBHS_DEVEPTIMR[ep_ix]; + uint32_t int_status = USB_REG->DEVEPTISR[ep_ix]; + int_status &= USB_REG->DEVEPTIMR[ep_ix]; - uint16_t count = (USBHS->USBHS_DEVEPTISR[ep_ix] & - USBHS_DEVEPTISR_BYCT_Msk) >> USBHS_DEVEPTISR_BYCT_Pos; + uint16_t count = (USB_REG->DEVEPTISR[ep_ix] & + DEVEPTISR_BYCT) >> DEVEPTISR_BYCT_Pos; xfer_ctl_t *xfer = &xfer_status[ep_ix]; if (ep_ix == 0U) { static uint8_t ctrl_dir; - if (int_status & USBHS_DEVEPTISR_CTRL_RXSTPI) + if (int_status & DEVEPTISR_CTRL_RXSTPI) { - ctrl_dir = (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CTRL_CTRLDIR_Msk) >> USBHS_DEVEPTISR_CTRL_CTRLDIR_Pos; + ctrl_dir = (USB_REG->DEVEPTISR[0] & DEVEPTISR_CTRL_CTRLDIR) >> DEVEPTISR_CTRL_CTRLDIR_Pos; // Setup packet should always be 8 bytes. If not, ignore it, and try again. if (count == 8) { @@ -234,10 +227,10 @@ static void dcd_ep_handler(uint8_t ep_ix) dcd_event_setup_received(0, ptr, true); } // Ack and disable SETUP interrupt - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_CTRL_RXSTPIC; - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_CTRL_RXSTPEC; + USB_REG->DEVEPTICR[0] = DEVEPTICR_CTRL_RXSTPIC; + USB_REG->DEVEPTIDR[0] = DEVEPTIDR_CTRL_RXSTPEC; } - if (int_status & USBHS_DEVEPTISR_RXOUTI) + if (int_status & DEVEPTISR_RXOUTI) { uint8_t *ptr = EP_GET_FIFO_PTR(0,8); @@ -258,24 +251,24 @@ static void dcd_ep_handler(uint8_t ep_ix) xfer->queued_len = (uint16_t)(xfer->queued_len + count); } // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_RXOUTIC; + USB_REG->DEVEPTICR[0] = DEVEPTICR_RXOUTIC; if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { // RX COMPLETE dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_RXOUTEC; + USB_REG->DEVEPTIDR[0] = DEVEPTIDR_RXOUTEC; // Re-enable SETUP interrupt if (ctrl_dir == 1) { - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; + USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES; } } } - if (int_status & USBHS_DEVEPTISR_TXINI) + if (int_status & DEVEPTISR_TXINI) { // Disable the interrupt - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_TXINEC; + USB_REG->DEVEPTIDR[0] = DEVEPTIDR_TXINEC; if ((xfer->total_len != xfer->queued_len)) { // TX not complete @@ -287,13 +280,13 @@ static void dcd_ep_handler(uint8_t ep_ix) // Re-enable SETUP interrupt if (ctrl_dir == 0) { - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; + USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES; } } } } else { - if (int_status & USBHS_DEVEPTISR_RXOUTI) + if (int_status & DEVEPTISR_RXOUTI) { if (count && xfer->total_len) { @@ -312,22 +305,22 @@ static void dcd_ep_handler(uint8_t ep_ix) xfer->queued_len = (uint16_t)(xfer->queued_len + count); } // Clear the FIFO control flag to receive more data. - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + USB_REG->DEVEPTIDR[ep_ix] = DEVEPTIDR_FIFOCONC; // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_RXOUTIC; + USB_REG->DEVEPTICR[ep_ix] = DEVEPTICR_RXOUTIC; if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { // RX COMPLETE dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_RXOUTEC; + USB_REG->DEVEPTIDR[ep_ix] = DEVEPTIDR_RXOUTEC; // Though the host could still send, we don't know. } } - if (int_status & USBHS_DEVEPTISR_TXINI) + if (int_status & DEVEPTISR_TXINI) { // Acknowledge the interrupt - USBHS->USBHS_DEVEPTICR[ep_ix] = USBHS_DEVEPTICR_TXINIC; + USB_REG->DEVEPTICR[ep_ix] = DEVEPTICR_TXINIC; if ((xfer->total_len != xfer->queued_len)) { // TX not complete @@ -337,7 +330,7 @@ static void dcd_ep_handler(uint8_t ep_ix) // TX complete dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_TXINEC; + USB_REG->DEVEPTIDR[ep_ix] = DEVEPTIDR_TXINEC; } } } @@ -345,17 +338,17 @@ static void dcd_ep_handler(uint8_t ep_ix) static void dcd_dma_handler(uint8_t ep_ix) { - uint32_t status = USBHS->UsbhsDevdma[ep_ix - 1].USBHS_DEVDMASTATUS; - if (status & USBHS_DEVDMASTATUS_CHANN_ENB) + uint32_t status = USB_REG->DEVDMA[ep_ix - 1].DEVDMASTATUS; + if (status & DEVDMASTATUS_CHANN_ENB) { return; // Ignore EOT_STA interrupt } // Disable DMA interrupt - USBHS->USBHS_DEVIDR = USBHS_DEVIDR_DMA_1 << (ep_ix - 1); + USB_REG->DEVIDR = DEVIDR_DMA_1 << (ep_ix - 1); xfer_ctl_t *xfer = &xfer_status[ep_ix]; - uint16_t count = xfer->total_len - ((status & USBHS_DEVDMASTATUS_BUFF_COUNT_Msk) >> USBHS_DEVDMASTATUS_BUFF_COUNT_Pos); - if(USBHS->USBHS_DEVEPTCFG[ep_ix] & USBHS_DEVEPTCFG_EPDIR) + uint16_t count = xfer->total_len - ((status & DEVDMASTATUS_BUFF_COUNT) >> DEVDMASTATUS_BUFF_COUNT_Pos); + if(USB_REG->DEVEPTCFG[ep_ix] & DEVEPTCFG_EPDIR) { dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); } else @@ -367,56 +360,56 @@ static void dcd_dma_handler(uint8_t ep_ix) void dcd_int_handler(uint8_t rhport) { (void) rhport; - uint32_t int_status = USBHS->USBHS_DEVISR; - int_status &= USBHS->USBHS_DEVIMR; + uint32_t int_status = USB_REG->DEVISR; + int_status &= USB_REG->DEVIMR; // End of reset interrupt - if (int_status & USBHS_DEVISR_EORST) + if (int_status & DEVISR_EORST) { // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - while(USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); + USB_REG->CTRL &= ~CTRL_FRZCLK; + while(SR_CLKUSABLE != (USB_REG->SR & SR_CLKUSABLE)); // Reset all endpoints for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) { - USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix); - USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + ep_ix)); + USB_REG->DEVEPT |= 1 << (DEVEPT_EPRST0_Pos + ep_ix); + USB_REG->DEVEPT &=~(1 << (DEVEPT_EPRST0_Pos + ep_ix)); } dcd_edpt_open (0, &ep0_desc); - USBHS->USBHS_DEVICR = USBHS_DEVICR_EORSTC; - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; - USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; + USB_REG->DEVICR = DEVICR_EORSTC; + USB_REG->DEVICR = DEVICR_WAKEUPC; + USB_REG->DEVICR = DEVICR_SUSPC; + USB_REG->DEVIER = DEVIER_SUSPES; dcd_event_bus_reset(rhport, get_speed(), true); } // End of Wakeup interrupt - if (int_status & USBHS_DEVISR_WAKEUP) + if (int_status & DEVISR_WAKEUP) { - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - USBHS->USBHS_DEVICR = USBHS_DEVICR_WAKEUPC; - USBHS->USBHS_DEVIDR = USBHS_DEVIDR_WAKEUPEC; - USBHS->USBHS_DEVIER = USBHS_DEVIER_SUSPES; + USB_REG->CTRL &= ~CTRL_FRZCLK; + while (SR_CLKUSABLE != (USB_REG->SR & SR_CLKUSABLE)); + USB_REG->DEVICR = DEVICR_WAKEUPC; + USB_REG->DEVIDR = DEVIDR_WAKEUPEC; + USB_REG->DEVIER = DEVIER_SUSPES; dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } // Suspend interrupt - if (int_status & USBHS_DEVISR_SUSP) + if (int_status & DEVISR_SUSP) { // Unfreeze USB clock - USBHS->USBHS_CTRL &= ~USBHS_CTRL_FRZCLK; - while (USBHS_SR_CLKUSABLE != (USBHS->USBHS_SR & USBHS_SR_CLKUSABLE)); - USBHS->USBHS_DEVICR = USBHS_DEVICR_SUSPC; - USBHS->USBHS_DEVIDR = USBHS_DEVIDR_SUSPEC; - USBHS->USBHS_DEVIER = USBHS_DEVIER_WAKEUPES; - USBHS->USBHS_CTRL |= USBHS_CTRL_FRZCLK; + USB_REG->CTRL &= ~CTRL_FRZCLK; + while (SR_CLKUSABLE != (USB_REG->SR & SR_CLKUSABLE)); + USB_REG->DEVICR = DEVICR_SUSPC; + USB_REG->DEVIDR = DEVIDR_SUSPEC; + USB_REG->DEVIER = DEVIER_WAKEUPES; + USB_REG->CTRL |= CTRL_FRZCLK; dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } #if USE_SOF - if(int_status & USBHS_DEVISR_SOF) + if(int_status & DEVISR_SOF) { - USBHS->USBHS_DEVICR = USBHS_DEVICR_SOFC; + USB_REG->DEVICR = DEVICR_SOFC; dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } @@ -424,7 +417,7 @@ void dcd_int_handler(uint8_t rhport) // Endpoints interrupt for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { - if (int_status & (USBHS_DEVISR_PEP_0 << ep_ix)) + if (int_status & (DEVISR_PEP_0 << ep_ix)) { dcd_ep_handler(ep_ix); } @@ -434,7 +427,7 @@ void dcd_int_handler(uint8_t rhport) { if (EP_DMA_SUPPORT(ep_ix)) { - if (int_status & (USBHS_DEVISR_DMA_1 << (ep_ix - 1))) + if (int_status & (DEVISR_DMA_1 << (ep_ix - 1))) { dcd_dma_handler(ep_ix); } @@ -457,7 +450,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re { uint8_t const dev_addr = (uint8_t) request->wValue; - USBHS->USBHS_DEVCTRL |= dev_addr | USBHS_DEVCTRL_ADDEN; + USB_REG->DEVCTRL |= dev_addr | DEVCTRL_ADDEN; } } @@ -482,29 +475,29 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) } xfer_status[epnum].max_packet_size = epMaxPktSize; - USBHS->USBHS_DEVEPT |= 1 << (USBHS_DEVEPT_EPRST0_Pos + epnum); - USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPRST0_Pos + epnum)); + USB_REG->DEVEPT |= 1 << (DEVEPT_EPRST0_Pos + epnum); + USB_REG->DEVEPT &=~(1 << (DEVEPT_EPRST0_Pos + epnum)); if (epnum == 0) { // Enable the control endpoint - Endpoint 0 - USBHS->USBHS_DEVEPT |= USBHS_DEVEPT_EPEN0; + USB_REG->DEVEPT |= DEVEPT_EPEN0; // Configure the Endpoint 0 configuration register - USBHS->USBHS_DEVEPTCFG[0] = + USB_REG->DEVEPTCFG[0] = ( - USBHS_DEVEPTCFG_EPSIZE(fifoSize) | - USBHS_DEVEPTCFG_EPTYPE(TUSB_XFER_CONTROL) | - USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | - USBHS_DEVEPTCFG_ALLOC + (fifoSize << DEVEPTCFG_EPSIZE_Pos) | + (TUSB_XFER_CONTROL << DEVEPTCFG_EPTYPE_Pos) | + (DEVEPTCFG_EPBK_1_BANK << DEVEPTCFG_EPBK_Pos) | + DEVEPTCFG_ALLOC ); - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_RSTDTS; - USBHS->USBHS_DEVEPTIDR[0] = USBHS_DEVEPTIDR_CTRL_STALLRQC; - if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[0] & USBHS_DEVEPTISR_CFGOK)) + USB_REG->DEVEPTIER[0] = DEVEPTIER_RSTDTS; + USB_REG->DEVEPTIDR[0] = DEVEPTIDR_CTRL_STALLRQC; + if (DEVEPTISR_CFGOK == (USB_REG->DEVEPTISR[0] & DEVEPTISR_CFGOK)) { // Endpoint configuration is successful - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; + USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES; // Enable Endpoint 0 Interrupts - USBHS->USBHS_DEVIER = USBHS_DEVIER_PEP_0; + USB_REG->DEVIER = DEVIER_PEP_0; return true; } else { @@ -514,34 +507,34 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) } else { // Enable the endpoint - USBHS->USBHS_DEVEPT |= ((0x01 << epnum) << USBHS_DEVEPT_EPEN0_Pos); + USB_REG->DEVEPT |= ((0x01 << epnum) << DEVEPT_EPEN0_Pos); // Set up the maxpacket size, fifo start address fifosize // and enable the interrupt. CLear the data toggle. // AUTOSW is needed for DMA ack ! - USBHS->USBHS_DEVEPTCFG[epnum] = + USB_REG->DEVEPTCFG[epnum] = ( - USBHS_DEVEPTCFG_EPSIZE(fifoSize) | - USBHS_DEVEPTCFG_EPTYPE(eptype) | - USBHS_DEVEPTCFG_EPBK(USBHS_DEVEPTCFG_EPBK_1_BANK) | - USBHS_DEVEPTCFG_AUTOSW | - ((dir & 0x01) << USBHS_DEVEPTCFG_EPDIR_Pos) + (fifoSize << DEVEPTCFG_EPSIZE_Pos) | + (eptype << DEVEPTCFG_EPTYPE_Pos) | + (DEVEPTCFG_EPBK_1_BANK << DEVEPTCFG_EPBK_Pos) | + DEVEPTCFG_AUTOSW | + ((dir & 0x01) << DEVEPTCFG_EPDIR_Pos) ); if (eptype == TUSB_XFER_ISOCHRONOUS) { - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_NBTRANS(1); + USB_REG->DEVEPTCFG[epnum] |= DEVEPTCFG_NBTRANS_1_TRANS; } #if USE_DUAL_BANK if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK) { - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_EPBK_2_BANK; + USB_REG->DEVEPTCFG[epnum] |= DEVEPTCFG_EPBK_2_BANK; } #endif - USBHS->USBHS_DEVEPTCFG[epnum] |= USBHS_DEVEPTCFG_ALLOC; - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RSTDTS; - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_CTRL_STALLRQC; - if (USBHS_DEVEPTISR_CFGOK == (USBHS->USBHS_DEVEPTISR[epnum] & USBHS_DEVEPTISR_CFGOK)) + USB_REG->DEVEPTCFG[epnum] |= DEVEPTCFG_ALLOC; + USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RSTDTS; + USB_REG->DEVEPTIDR[epnum] = DEVEPTIDR_CTRL_STALLRQC; + if (DEVEPTISR_CFGOK == (USB_REG->DEVEPTISR[epnum] & DEVEPTISR_CFGOK)) { - USBHS->USBHS_DEVIER = ((0x01 << epnum) << USBHS_DEVIER_PEP_0_Pos); + USB_REG->DEVIER = ((0x01 << epnum) << DEVIER_PEP_0_Pos); return true; } else { @@ -557,9 +550,9 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) uint8_t const epnum = tu_edpt_number(ep_addr); // Disable endpoint interrupt - USBHS->USBHS_DEVIDR = 1 << (USBHS_DEVIDR_PEP_0_Pos + epnum); + USB_REG->DEVIDR = 1 << (DEVIDR_PEP_0_Pos + epnum); // Disable EP - USBHS->USBHS_DEVEPT &=~(1 << (USBHS_DEVEPT_EPEN0_Pos + epnum)); + USB_REG->DEVEPT &=~(1 << (DEVEPT_EPEN0_Pos + epnum)); } static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) @@ -587,13 +580,13 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) if (ep_ix == 0U) { // Control endpoint: clear the interrupt flag to send the data - USBHS->USBHS_DEVEPTICR[0] = USBHS_DEVEPTICR_TXINIC; + USB_REG->DEVEPTICR[0] = DEVEPTICR_TXINIC; } else { // Other endpoint types: clear the FIFO control flag to send the data - USBHS->USBHS_DEVEPTIDR[ep_ix] = USBHS_DEVEPTIDR_FIFOCONC; + USB_REG->DEVEPTIDR[ep_ix] = DEVEPTIDR_FIFOCONC; } - USBHS->USBHS_DEVEPTIER[ep_ix] = USBHS_DEVEPTIER_TXINES; + USB_REG->DEVEPTIER[ep_ix] = DEVEPTIER_TXINES; } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack @@ -615,23 +608,23 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // Force the CPU to flush the buffer. We increase the size by 32 because the call aligns the // address to 32-byte boundaries. CleanInValidateCache((uint32_t*) tu_align((uint32_t) buffer, 4), total_bytes + 31); - uint32_t udd_dma_ctrl = USBHS_DEVDMACONTROL_BUFF_LENGTH(total_bytes); + uint32_t udd_dma_ctrl = total_bytes << DEVDMACONTROL_BUFF_LENGTH_Pos; if (dir == TUSB_DIR_OUT) { - udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; + udd_dma_ctrl |= DEVDMACONTROL_END_TR_IT | DEVDMACONTROL_END_TR_EN; } else { - udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_B_EN; + udd_dma_ctrl |= DEVDMACONTROL_END_B_EN; } - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)buffer; - udd_dma_ctrl |= USBHS_DEVDMACONTROL_END_BUFFIT | USBHS_DEVDMACONTROL_CHANN_ENB; + USB_REG->DEVDMA[epnum - 1].DEVDMAADDRESS = (uint32_t)buffer; + udd_dma_ctrl |= DEVDMACONTROL_END_BUFFIT | DEVDMACONTROL_CHANN_ENB; // Disable IRQs to have a short sequence // between read of EOT_STA and DMA enable uint32_t irq_state = __get_PRIMASK(); __disable_irq(); - if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) + if (!(USB_REG->DEVDMA[epnum - 1].DEVDMASTATUS & DEVDMASTATUS_END_TR_ST)) { - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl; - USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); + USB_REG->DEVDMA[epnum - 1].DEVDMACONTROL = udd_dma_ctrl; + USB_REG->DEVIER = DEVIER_DMA_1 << (epnum - 1); __set_PRIMASK(irq_state); return true; } @@ -645,7 +638,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t { if (dir == TUSB_DIR_OUT) { - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RXOUTES; } else { dcd_transmit_packet(xfer,epnum); @@ -676,26 +669,26 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) { tu_fifo_buffer_info_t info; - uint32_t udd_dma_ctrl_lin = USBHS_DEVDMACONTROL_CHANN_ENB; - uint32_t udd_dma_ctrl_wrap = USBHS_DEVDMACONTROL_CHANN_ENB | USBHS_DEVDMACONTROL_END_BUFFIT; + uint32_t udd_dma_ctrl_lin = DEVDMACONTROL_CHANN_ENB; + uint32_t udd_dma_ctrl_wrap = DEVDMACONTROL_CHANN_ENB | DEVDMACONTROL_END_BUFFIT; if (dir == TUSB_DIR_OUT) { tu_fifo_get_write_info(ff, &info); - udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; - udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_TR_IT | USBHS_DEVDMACONTROL_END_TR_EN; + udd_dma_ctrl_lin |= DEVDMACONTROL_END_TR_IT | DEVDMACONTROL_END_TR_EN; + udd_dma_ctrl_wrap |= DEVDMACONTROL_END_TR_IT | DEVDMACONTROL_END_TR_EN; } else { tu_fifo_get_read_info(ff, &info); if(info.len_wrap == 0) { - udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_B_EN; + udd_dma_ctrl_lin |= DEVDMACONTROL_END_B_EN; } - udd_dma_ctrl_wrap |= USBHS_DEVDMACONTROL_END_B_EN; + udd_dma_ctrl_wrap |= DEVDMACONTROL_END_B_EN; } // Clean invalidate cache of linear part CleanInValidateCache((uint32_t*) tu_align((uint32_t) info.ptr_lin, 4), info.len_lin + 31); - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMAADDRESS = (uint32_t)info.ptr_lin; + USB_REG->DEVDMA[epnum - 1].DEVDMAADDRESS = (uint32_t)info.ptr_lin; if (info.len_wrap) { // Clean invalidate cache of wrapped part @@ -704,24 +697,24 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 dma_desc[epnum - 1].next_desc = 0; dma_desc[epnum - 1].buff_addr = (uint32_t)info.ptr_wrap; dma_desc[epnum - 1].chnl_ctrl = - udd_dma_ctrl_wrap | USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_wrap); + udd_dma_ctrl_wrap | (info.len_wrap << DEVDMACONTROL_BUFF_LENGTH_Pos); // Clean cache of wrapped DMA descriptor CleanInValidateCache((uint32_t*)&dma_desc[epnum - 1], sizeof(dma_desc_t)); - udd_dma_ctrl_lin |= USBHS_DEVDMASTATUS_DESC_LDST; - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMANXTDSC = (uint32_t)&dma_desc[epnum - 1]; + udd_dma_ctrl_lin |= DEVDMASTATUS_DESC_LDST; + USB_REG->DEVDMA[epnum - 1].DEVDMANXTDSC = (uint32_t)&dma_desc[epnum - 1]; } else { - udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_END_BUFFIT; + udd_dma_ctrl_lin |= DEVDMACONTROL_END_BUFFIT; } - udd_dma_ctrl_lin |= USBHS_DEVDMACONTROL_BUFF_LENGTH(info.len_lin); + udd_dma_ctrl_lin |= (info.len_lin << DEVDMACONTROL_BUFF_LENGTH_Pos); // Disable IRQs to have a short sequence // between read of EOT_STA and DMA enable uint32_t irq_state = __get_PRIMASK(); __disable_irq(); - if (!(USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMASTATUS & USBHS_DEVDMASTATUS_END_TR_ST)) + if (!(USB_REG->DEVDMA[epnum - 1].DEVDMASTATUS & DEVDMASTATUS_END_TR_ST)) { - USBHS->UsbhsDevdma[epnum - 1].USBHS_DEVDMACONTROL = udd_dma_ctrl_lin; - USBHS->USBHS_DEVIER = USBHS_DEVIER_DMA_1 << (epnum - 1); + USB_REG->DEVDMA[epnum - 1].DEVDMACONTROL = udd_dma_ctrl_lin; + USB_REG->DEVIER = DEVIER_DMA_1 << (epnum - 1); __set_PRIMASK(irq_state); return true; } @@ -735,7 +728,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16 { if (dir == TUSB_DIR_OUT) { - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_RXOUTES; + USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RXOUTES; } else { dcd_transmit_packet(xfer,epnum); @@ -749,11 +742,11 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_DEVEPTIER_CTRL_STALLRQS; + USB_REG->DEVEPTIER[epnum] = DEVEPTIER_CTRL_STALLRQS; // Re-enable SETUP interrupt if (epnum == 0) { - USBHS->USBHS_DEVEPTIER[0] = USBHS_DEVEPTIER_CTRL_RXSTPES; + USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES; } } @@ -762,8 +755,8 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); - USBHS->USBHS_DEVEPTIDR[epnum] = USBHS_DEVEPTIDR_CTRL_STALLRQC; - USBHS->USBHS_DEVEPTIER[epnum] = USBHS_HSTPIPIER_RSTDTS; + USB_REG->DEVEPTIDR[epnum] = DEVEPTIDR_CTRL_STALLRQC; + USB_REG->DEVEPTIER[epnum] = HSTPIPIER_RSTDTS; } #endif -- cgit v1.3.1 From 45e55a8ea05d1101626addb74c9a2059030f6ff2 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Sat, 31 Jul 2021 12:20:19 +0900 Subject: fix: D0FIFOSEL setting was incorrectly when big-endian is selected. In pipe_xfer_in(), the endianness setting of D0FIFOSEL was lacking due to refactoring. And add type cast operation to avoid warnings by CCRX. --- src/portable/renesas/usba/dcd_usba.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 09622d894..739861413 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -313,9 +313,9 @@ static bool pipe0_xfer_in(void) void *buf = pipe->buf; if (len) { if (pipe->ff) { - pipe_read_write_packet_ff((tu_fifo_t*)buf, &USB0.CFIFO.WORD, len, TUSB_DIR_IN); + pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&USB0.CFIFO.WORD, len, TUSB_DIR_IN); } else { - pipe_write_packet(buf, &USB0.CFIFO.WORD, len); + pipe_write_packet(buf, (volatile void*)&USB0.CFIFO.WORD, len); pipe->buf = (uint8_t*)buf + len; } } @@ -335,9 +335,9 @@ static bool pipe0_xfer_out(void) void *buf = pipe->buf; if (len) { if (pipe->ff) { - pipe_read_write_packet_ff((tu_fifo_t*)buf, &USB0.CFIFO.WORD, len, TUSB_DIR_OUT); + pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&USB0.CFIFO.WORD, len, TUSB_DIR_OUT); } else { - pipe_read_packet(buf, &USB0.CFIFO.WORD, len); + pipe_read_packet(buf, (volatile void*)&USB0.CFIFO.WORD, len); pipe->buf = (uint8_t*)buf + len; } } @@ -360,16 +360,16 @@ static bool pipe_xfer_in(unsigned num) return true; } - USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16; + USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0); const unsigned mps = edpt_max_packet_size(num); pipe_wait_for_ready(num); const unsigned len = TU_MIN(rem, mps); void *buf = pipe->buf; if (len) { if (pipe->ff) { - pipe_read_write_packet_ff((tu_fifo_t*)buf, &USB0.D0FIFO.WORD, len, TUSB_DIR_IN); + pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&USB0.D0FIFO.WORD, len, TUSB_DIR_IN); } else { - pipe_write_packet(buf, &USB0.D0FIFO.WORD, len); + pipe_write_packet(buf, (volatile void*)&USB0.D0FIFO.WORD, len); pipe->buf = (uint8_t*)buf + len; } } @@ -393,9 +393,9 @@ static bool pipe_xfer_out(unsigned num) void *buf = pipe->buf; if (len) { if (pipe->ff) { - pipe_read_write_packet_ff((tu_fifo_t*)buf, &USB0.D0FIFO.WORD, len, TUSB_DIR_OUT); + pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&USB0.D0FIFO.WORD, len, TUSB_DIR_OUT); } else { - pipe_read_packet(buf, &USB0.D0FIFO.WORD, len); + pipe_read_packet(buf, (volatile void*)&USB0.D0FIFO.WORD, len); pipe->buf = (uint8_t*)buf + len; } } @@ -488,6 +488,7 @@ static bool process_pipe_xfer(int buffer_type, uint8_t ep_addr, void* buffer, ui pipe_wait_for_ready(num); USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL; USB0.D0FIFOSEL.WORD = 0; + while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */ } } else { volatile reg_pipetre_t *pt = get_pipetre(num); -- cgit v1.3.1 From 98e4ba6a12f8ce2b060635dc01f68676b047ce25 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 2 Aug 2021 18:55:12 +0700 Subject: correct midi available with already stream read --- src/class/midi/midi_device.c | 7 ++++++- src/common/tusb_fifo.c | 2 -- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index c39e03976..9d9619132 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -122,7 +122,12 @@ static void _prep_out_transaction (midid_interface_t* p_midi) uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) { (void) cable_num; - return tu_fifo_count(&_midid_itf[itf].rx_ff); + + midid_interface_t const* midi = &_midid_itf[itf]; + midid_stream_t const* stream = &midi->stream_read; + + // when using with packet API stream total & index are both zero + return tu_fifo_count(&midi->rx_ff) + (stream->total - stream->index); } uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 73217cf75..11b8fc5f3 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -323,8 +323,6 @@ static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset) // We limit the index space of p such that a correct wrap around happens // Check for a wrap around or if we are in unused index space - This has to be checked first!! // We are exploiting the wrap around to the correct index - - // TODO warning: assuming signed overflow does not occur when assuming that (X + c) < X is always false [-Wstrict-overflow] if ((p > (uint16_t)(p + offset)) || ((uint16_t)(p + offset) > f->max_pointer_idx)) { p = (p + offset) + f->non_used_index_space; -- cgit v1.3.1 From 794bbd7177dd5f3cab35eadf9a9268eddf61736f Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 2 Aug 2021 18:58:27 +0700 Subject: fix warning --- src/class/midi/midi_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 9d9619132..eb85b668c 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -123,7 +123,7 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) { (void) cable_num; - midid_interface_t const* midi = &_midid_itf[itf]; + midid_interface_t* midi = &_midid_itf[itf]; midid_stream_t const* stream = &midi->stream_read; // when using with packet API stream total & index are both zero -- cgit v1.3.1 From 2657560b633b877fc393787755e9b1ec8dfbe843 Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Fri, 9 Jul 2021 23:39:41 +0200 Subject: Add hacky GD32VF103 support --- src/portable/st/synopsys/dcd_synopsys.c | 17 +- src/portable/st/synopsys/synopsys_common.h | 1448 ++++++++++++++++++++++++++++ src/tusb_option.h | 3 + 3 files changed, 1466 insertions(+), 2 deletions(-) create mode 100644 src/portable/st/synopsys/synopsys_common.h (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index c15694eba..4b39844a1 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -34,7 +34,7 @@ #define USE_SOF 0 #if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ - defined (STM32F107xB) || defined (STM32F107xC) + defined (STM32F107xB) || defined (STM32F107xC) || defined (GD32VF103) #define STM32F1_SYNOPSYS #endif @@ -51,7 +51,8 @@ CFG_TUSB_MCU == OPT_MCU_STM32F4 || \ CFG_TUSB_MCU == OPT_MCU_STM32F7 || \ CFG_TUSB_MCU == OPT_MCU_STM32H7 || \ - (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \ + (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS) || \ + CFG_TUSB_MCU == OPT_MCU_GD32VF103 ) \ ) // EP_MAX : Max number of bi-directional endpoints including EP0 @@ -92,6 +93,18 @@ #define EP_MAX_FS 6 #define EP_FIFO_SIZE_FS 1280 +#elif CFG_TUSB_MCU == OPT_MCU_GD32VF103 +#define STM32F1_SYNOPSYS +#include "gd32vf103.h" +#include "nmsis_core.h" +#include "core_feature_eclic.h" +#include "synopsys_common.h" +#define EP_MAX_FS 4 +#define EP_FIFO_SIZE_FS 1280 +#define OTG_FS_IRQn USBFS_IRQn +#define NVIC_EnableIRQ ECLIC_EnableIRQ +#define NVIC_DisableIRQ ECLIC_DisableIRQ + #else #error "Unsupported MCUs" #endif diff --git a/src/portable/st/synopsys/synopsys_common.h b/src/portable/st/synopsys/synopsys_common.h new file mode 100644 index 000000000..4e71e8258 --- /dev/null +++ b/src/portable/st/synopsys/synopsys_common.h @@ -0,0 +1,1448 @@ +#include "stdint.h" + +#pragma once + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M3 */ +/** + * @brief __USB_OTG_Core_register + */ + +typedef struct +{ + __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register Address offset: 000h */ + __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register Address offset: 004h */ + __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register Address offset: 008h */ + __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register Address offset: 00Ch */ + __IO uint32_t GRSTCTL; /*!< Core Reset Register Address offset: 010h */ + __IO uint32_t GINTSTS; /*!< Core Interrupt Register Address offset: 014h */ + __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register Address offset: 018h */ + __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register Address offset: 01Ch */ + __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register Address offset: 020h */ + __IO uint32_t GRXFSIZ; /*!< Receive FIFO Size Register Address offset: 024h */ + __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register Address offset: 028h */ + __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg Address offset: 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h*/ + __IO uint32_t GCCFG; /*!< General Purpose IO Register Address offset: 038h */ + __IO uint32_t CID; /*!< User ID Register Address offset: 03Ch */ + uint32_t Reserved40[48]; /*!< Reserved 040h-0FFh */ + __IO uint32_t HPTXFSIZ; /*!< Host Periodic Tx FIFO Size Reg Address offset: 100h */ + __IO uint32_t DIEPTXF[0x0F]; /*!< dev Periodic Transmit FIFO Address offset: 0x104 */ +} USB_OTG_GlobalTypeDef; + +/** + * @brief __device_Registers + */ + +typedef struct +{ + __IO uint32_t DCFG; /*!< dev Configuration Register Address offset: 800h*/ + __IO uint32_t DCTL; /*!< dev Control Register Address offset: 804h*/ + __IO uint32_t DSTS; /*!< dev Status Register (RO) Address offset: 808h*/ + uint32_t Reserved0C; /*!< Reserved 80Ch*/ + __IO uint32_t DIEPMSK; /*!< dev IN Endpoint Mask Address offset: 810h*/ + __IO uint32_t DOEPMSK; /*!< dev OUT Endpoint Mask Address offset: 814h*/ + __IO uint32_t DAINT; /*!< dev All Endpoints Itr Reg Address offset: 818h*/ + __IO uint32_t DAINTMSK; /*!< dev All Endpoints Itr Mask Address offset: 81Ch*/ + uint32_t Reserved20; /*!< Reserved 820h*/ + uint32_t Reserved9; /*!< Reserved 824h*/ + __IO uint32_t DVBUSDIS; /*!< dev VBUS discharge Register Address offset: 828h*/ + __IO uint32_t DVBUSPULSE; /*!< dev VBUS Pulse Register Address offset: 82Ch*/ + __IO uint32_t DTHRCTL; /*!< dev thr Address offset: 830h*/ + __IO uint32_t DIEPEMPMSK; /*!< dev empty msk Address offset: 834h*/ + __IO uint32_t DEACHINT; /*!< dedicated EP interrupt Address offset: 838h*/ + __IO uint32_t DEACHMSK; /*!< dedicated EP msk Address offset: 83Ch*/ + uint32_t Reserved40; /*!< dedicated EP mask Address offset: 840h*/ + __IO uint32_t DINEP1MSK; /*!< dedicated EP mask Address offset: 844h*/ + uint32_t Reserved44[15]; /*!< Reserved 844-87Ch*/ + __IO uint32_t DOUTEP1MSK; /*!< dedicated EP msk Address offset: 884h*/ +} USB_OTG_DeviceTypeDef; + +/** + * @brief __IN_Endpoint-Specific_Register + */ + +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h*/ + uint32_t Reserved04; /*!< Reserved 900h + (ep_num * 20h) + 04h*/ + __IO uint32_t DIEPINT; /*!< dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h*/ + uint32_t Reserved0C; /*!< Reserved 900h + (ep_num * 20h) + 0Ch*/ + __IO uint32_t DIEPTSIZ; /*!< IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h*/ + __IO uint32_t DIEPDMA; /*!< IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h*/ + __IO uint32_t DTXFSTS; /*!< IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h*/ + uint32_t Reserved18; /*!< Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch*/ +} USB_OTG_INEndpointTypeDef; + +/** + * @brief __OUT_Endpoint-Specific_Registers + */ + +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h*/ + uint32_t Reserved04; /*!< Reserved B00h + (ep_num * 20h) + 04h*/ + __IO uint32_t DOEPINT; /*!< dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h*/ + uint32_t Reserved0C; /*!< Reserved B00h + (ep_num * 20h) + 0Ch*/ + __IO uint32_t DOEPTSIZ; /*!< dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h*/ + __IO uint32_t DOEPDMA; /*!< dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h*/ + uint32_t Reserved18[2]; /*!< Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch*/ +} USB_OTG_OUTEndpointTypeDef; + +/** + * @brief __Host_Mode_Register_Structures + */ + +typedef struct +{ + __IO uint32_t HCFG; /*!< Host Configuration Register 400h*/ + __IO uint32_t HFIR; /*!< Host Frame Interval Register 404h*/ + __IO uint32_t HFNUM; /*!< Host Frame Nbr/Frame Remaining 408h*/ + uint32_t Reserved40C; /*!< Reserved 40Ch*/ + __IO uint32_t HPTXSTS; /*!< Host Periodic Tx FIFO/ Queue Status 410h*/ + __IO uint32_t HAINT; /*!< Host All Channels Interrupt Register 414h*/ + __IO uint32_t HAINTMSK; /*!< Host All Channels Interrupt Mask 418h*/ +} USB_OTG_HostTypeDef; + +/** + * @brief __Host_Channel_Specific_Registers + */ + +typedef struct +{ + __IO uint32_t HCCHAR; + __IO uint32_t HCSPLT; + __IO uint32_t HCINT; + __IO uint32_t HCINTMSK; + __IO uint32_t HCTSIZ; + __IO uint32_t HCDMA; + uint32_t Reserved[2]; +} USB_OTG_HostChannelTypeDef; + +/*!< USB registers base address */ +#define USB_OTG_FS_PERIPH_BASE 0x50000000UL + +#define USB_OTG_GLOBAL_BASE 0x00000000UL +#define USB_OTG_DEVICE_BASE 0x00000800UL +#define USB_OTG_IN_ENDPOINT_BASE 0x00000900UL +#define USB_OTG_OUT_ENDPOINT_BASE 0x00000B00UL +#define USB_OTG_EP_REG_SIZE 0x00000020UL +#define USB_OTG_HOST_BASE 0x00000400UL +#define USB_OTG_HOST_PORT_BASE 0x00000440UL +#define USB_OTG_HOST_CHANNEL_BASE 0x00000500UL +#define USB_OTG_HOST_CHANNEL_SIZE 0x00000020UL +#define USB_OTG_PCGCCTL_BASE 0x00000E00UL +#define USB_OTG_FIFO_BASE 0x00001000UL +#define USB_OTG_FIFO_SIZE 0x00001000UL + + +/******************************************************************************/ +/* */ +/* USB_OTG */ +/* */ +/******************************************************************************/ +/******************** Bit definition for USB_OTG_GOTGCTL register ***********/ +#define USB_OTG_GOTGCTL_SRQSCS_Pos (0U) +#define USB_OTG_GOTGCTL_SRQSCS_Msk (0x1UL << USB_OTG_GOTGCTL_SRQSCS_Pos) /*!< 0x00000001 */ +#define USB_OTG_GOTGCTL_SRQSCS USB_OTG_GOTGCTL_SRQSCS_Msk /*!< Session request success */ +#define USB_OTG_GOTGCTL_SRQ_Pos (1U) +#define USB_OTG_GOTGCTL_SRQ_Msk (0x1UL << USB_OTG_GOTGCTL_SRQ_Pos) /*!< 0x00000002 */ +#define USB_OTG_GOTGCTL_SRQ USB_OTG_GOTGCTL_SRQ_Msk /*!< Session request */ +#define USB_OTG_GOTGCTL_HNGSCS_Pos (8U) +#define USB_OTG_GOTGCTL_HNGSCS_Msk (0x1UL << USB_OTG_GOTGCTL_HNGSCS_Pos) /*!< 0x00000100 */ +#define USB_OTG_GOTGCTL_HNGSCS USB_OTG_GOTGCTL_HNGSCS_Msk /*!< Host set HNP enable */ +#define USB_OTG_GOTGCTL_HNPRQ_Pos (9U) +#define USB_OTG_GOTGCTL_HNPRQ_Msk (0x1UL << USB_OTG_GOTGCTL_HNPRQ_Pos) /*!< 0x00000200 */ +#define USB_OTG_GOTGCTL_HNPRQ USB_OTG_GOTGCTL_HNPRQ_Msk /*!< HNP request */ +#define USB_OTG_GOTGCTL_HSHNPEN_Pos (10U) +#define USB_OTG_GOTGCTL_HSHNPEN_Msk (0x1UL << USB_OTG_GOTGCTL_HSHNPEN_Pos) /*!< 0x00000400 */ +#define USB_OTG_GOTGCTL_HSHNPEN USB_OTG_GOTGCTL_HSHNPEN_Msk /*!< Host set HNP enable */ +#define USB_OTG_GOTGCTL_DHNPEN_Pos (11U) +#define USB_OTG_GOTGCTL_DHNPEN_Msk (0x1UL << USB_OTG_GOTGCTL_DHNPEN_Pos) /*!< 0x00000800 */ +#define USB_OTG_GOTGCTL_DHNPEN USB_OTG_GOTGCTL_DHNPEN_Msk /*!< Device HNP enabled */ +#define USB_OTG_GOTGCTL_CIDSTS_Pos (16U) +#define USB_OTG_GOTGCTL_CIDSTS_Msk (0x1UL << USB_OTG_GOTGCTL_CIDSTS_Pos) /*!< 0x00010000 */ +#define USB_OTG_GOTGCTL_CIDSTS USB_OTG_GOTGCTL_CIDSTS_Msk /*!< Connector ID status */ +#define USB_OTG_GOTGCTL_DBCT_Pos (17U) +#define USB_OTG_GOTGCTL_DBCT_Msk (0x1UL << USB_OTG_GOTGCTL_DBCT_Pos) /*!< 0x00020000 */ +#define USB_OTG_GOTGCTL_DBCT USB_OTG_GOTGCTL_DBCT_Msk /*!< Long/short debounce time */ +#define USB_OTG_GOTGCTL_ASVLD_Pos (18U) +#define USB_OTG_GOTGCTL_ASVLD_Msk (0x1UL << USB_OTG_GOTGCTL_ASVLD_Pos) /*!< 0x00040000 */ +#define USB_OTG_GOTGCTL_ASVLD USB_OTG_GOTGCTL_ASVLD_Msk /*!< A-session valid */ +#define USB_OTG_GOTGCTL_BSVLD_Pos (19U) +#define USB_OTG_GOTGCTL_BSVLD_Msk (0x1UL << USB_OTG_GOTGCTL_BSVLD_Pos) /*!< 0x00080000 */ +#define USB_OTG_GOTGCTL_BSVLD USB_OTG_GOTGCTL_BSVLD_Msk /*!< B-session valid */ + +/******************** Bit definition for USB_OTG_HCFG register ********************/ + +#define USB_OTG_HCFG_FSLSPCS_Pos (0U) +#define USB_OTG_HCFG_FSLSPCS_Msk (0x3UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000003 */ +#define USB_OTG_HCFG_FSLSPCS USB_OTG_HCFG_FSLSPCS_Msk /*!< FS/LS PHY clock select */ +#define USB_OTG_HCFG_FSLSPCS_0 (0x1UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000001 */ +#define USB_OTG_HCFG_FSLSPCS_1 (0x2UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000002 */ +#define USB_OTG_HCFG_FSLSS_Pos (2U) +#define USB_OTG_HCFG_FSLSS_Msk (0x1UL << USB_OTG_HCFG_FSLSS_Pos) /*!< 0x00000004 */ +#define USB_OTG_HCFG_FSLSS USB_OTG_HCFG_FSLSS_Msk /*!< FS- and LS-only support */ + +/******************** Bit definition for USB_OTG_DCFG register ********************/ + +#define USB_OTG_DCFG_DSPD_Pos (0U) +#define USB_OTG_DCFG_DSPD_Msk (0x3UL << USB_OTG_DCFG_DSPD_Pos) /*!< 0x00000003 */ +#define USB_OTG_DCFG_DSPD USB_OTG_DCFG_DSPD_Msk /*!< Device speed */ +#define USB_OTG_DCFG_DSPD_0 (0x1UL << USB_OTG_DCFG_DSPD_Pos) /*!< 0x00000001 */ +#define USB_OTG_DCFG_DSPD_1 (0x2UL << USB_OTG_DCFG_DSPD_Pos) /*!< 0x00000002 */ +#define USB_OTG_DCFG_NZLSOHSK_Pos (2U) +#define USB_OTG_DCFG_NZLSOHSK_Msk (0x1UL << USB_OTG_DCFG_NZLSOHSK_Pos) /*!< 0x00000004 */ +#define USB_OTG_DCFG_NZLSOHSK USB_OTG_DCFG_NZLSOHSK_Msk /*!< Nonzero-length status OUT handshake */ + +#define USB_OTG_DCFG_DAD_Pos (4U) +#define USB_OTG_DCFG_DAD_Msk (0x7FUL << USB_OTG_DCFG_DAD_Pos) /*!< 0x000007F0 */ +#define USB_OTG_DCFG_DAD USB_OTG_DCFG_DAD_Msk /*!< Device address */ +#define USB_OTG_DCFG_DAD_0 (0x01UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000010 */ +#define USB_OTG_DCFG_DAD_1 (0x02UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000020 */ +#define USB_OTG_DCFG_DAD_2 (0x04UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000040 */ +#define USB_OTG_DCFG_DAD_3 (0x08UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000080 */ +#define USB_OTG_DCFG_DAD_4 (0x10UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000100 */ +#define USB_OTG_DCFG_DAD_5 (0x20UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000200 */ +#define USB_OTG_DCFG_DAD_6 (0x40UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000400 */ + +#define USB_OTG_DCFG_PFIVL_Pos (11U) +#define USB_OTG_DCFG_PFIVL_Msk (0x3UL << USB_OTG_DCFG_PFIVL_Pos) /*!< 0x00001800 */ +#define USB_OTG_DCFG_PFIVL USB_OTG_DCFG_PFIVL_Msk /*!< Periodic (micro)frame interval */ +#define USB_OTG_DCFG_PFIVL_0 (0x1UL << USB_OTG_DCFG_PFIVL_Pos) /*!< 0x00000800 */ +#define USB_OTG_DCFG_PFIVL_1 (0x2UL << USB_OTG_DCFG_PFIVL_Pos) /*!< 0x00001000 */ + +#define USB_OTG_DCFG_PERSCHIVL_Pos (24U) +#define USB_OTG_DCFG_PERSCHIVL_Msk (0x3UL << USB_OTG_DCFG_PERSCHIVL_Pos) /*!< 0x03000000 */ +#define USB_OTG_DCFG_PERSCHIVL USB_OTG_DCFG_PERSCHIVL_Msk /*!< Periodic scheduling interval */ +#define USB_OTG_DCFG_PERSCHIVL_0 (0x1UL << USB_OTG_DCFG_PERSCHIVL_Pos) /*!< 0x01000000 */ +#define USB_OTG_DCFG_PERSCHIVL_1 (0x2UL << USB_OTG_DCFG_PERSCHIVL_Pos) /*!< 0x02000000 */ + +/******************** Bit definition for USB_OTG_PCGCR register ********************/ +#define USB_OTG_PCGCR_STPPCLK_Pos (0U) +#define USB_OTG_PCGCR_STPPCLK_Msk (0x1UL << USB_OTG_PCGCR_STPPCLK_Pos) /*!< 0x00000001 */ +#define USB_OTG_PCGCR_STPPCLK USB_OTG_PCGCR_STPPCLK_Msk /*!< Stop PHY clock */ +#define USB_OTG_PCGCR_GATEHCLK_Pos (1U) +#define USB_OTG_PCGCR_GATEHCLK_Msk (0x1UL << USB_OTG_PCGCR_GATEHCLK_Pos) /*!< 0x00000002 */ +#define USB_OTG_PCGCR_GATEHCLK USB_OTG_PCGCR_GATEHCLK_Msk /*!< Gate HCLK */ +#define USB_OTG_PCGCR_PHYSUSP_Pos (4U) +#define USB_OTG_PCGCR_PHYSUSP_Msk (0x1UL << USB_OTG_PCGCR_PHYSUSP_Pos) /*!< 0x00000010 */ +#define USB_OTG_PCGCR_PHYSUSP USB_OTG_PCGCR_PHYSUSP_Msk /*!< PHY suspended */ + +/******************** Bit definition for USB_OTG_GOTGINT register ********************/ +#define USB_OTG_GOTGINT_SEDET_Pos (2U) +#define USB_OTG_GOTGINT_SEDET_Msk (0x1UL << USB_OTG_GOTGINT_SEDET_Pos) /*!< 0x00000004 */ +#define USB_OTG_GOTGINT_SEDET USB_OTG_GOTGINT_SEDET_Msk /*!< Session end detected */ +#define USB_OTG_GOTGINT_SRSSCHG_Pos (8U) +#define USB_OTG_GOTGINT_SRSSCHG_Msk (0x1UL << USB_OTG_GOTGINT_SRSSCHG_Pos) /*!< 0x00000100 */ +#define USB_OTG_GOTGINT_SRSSCHG USB_OTG_GOTGINT_SRSSCHG_Msk /*!< Session request success status change */ +#define USB_OTG_GOTGINT_HNSSCHG_Pos (9U) +#define USB_OTG_GOTGINT_HNSSCHG_Msk (0x1UL << USB_OTG_GOTGINT_HNSSCHG_Pos) /*!< 0x00000200 */ +#define USB_OTG_GOTGINT_HNSSCHG USB_OTG_GOTGINT_HNSSCHG_Msk /*!< Host negotiation success status change */ +#define USB_OTG_GOTGINT_HNGDET_Pos (17U) +#define USB_OTG_GOTGINT_HNGDET_Msk (0x1UL << USB_OTG_GOTGINT_HNGDET_Pos) /*!< 0x00020000 */ +#define USB_OTG_GOTGINT_HNGDET USB_OTG_GOTGINT_HNGDET_Msk /*!< Host negotiation detected */ +#define USB_OTG_GOTGINT_ADTOCHG_Pos (18U) +#define USB_OTG_GOTGINT_ADTOCHG_Msk (0x1UL << USB_OTG_GOTGINT_ADTOCHG_Pos) /*!< 0x00040000 */ +#define USB_OTG_GOTGINT_ADTOCHG USB_OTG_GOTGINT_ADTOCHG_Msk /*!< A-device timeout change */ +#define USB_OTG_GOTGINT_DBCDNE_Pos (19U) +#define USB_OTG_GOTGINT_DBCDNE_Msk (0x1UL << USB_OTG_GOTGINT_DBCDNE_Pos) /*!< 0x00080000 */ +#define USB_OTG_GOTGINT_DBCDNE USB_OTG_GOTGINT_DBCDNE_Msk /*!< Debounce done */ + +/******************** Bit definition for USB_OTG_DCTL register ********************/ +#define USB_OTG_DCTL_RWUSIG_Pos (0U) +#define USB_OTG_DCTL_RWUSIG_Msk (0x1UL << USB_OTG_DCTL_RWUSIG_Pos) /*!< 0x00000001 */ +#define USB_OTG_DCTL_RWUSIG USB_OTG_DCTL_RWUSIG_Msk /*!< Remote wakeup signaling */ +#define USB_OTG_DCTL_SDIS_Pos (1U) +#define USB_OTG_DCTL_SDIS_Msk (0x1UL << USB_OTG_DCTL_SDIS_Pos) /*!< 0x00000002 */ +#define USB_OTG_DCTL_SDIS USB_OTG_DCTL_SDIS_Msk /*!< Soft disconnect */ +#define USB_OTG_DCTL_GINSTS_Pos (2U) +#define USB_OTG_DCTL_GINSTS_Msk (0x1UL << USB_OTG_DCTL_GINSTS_Pos) /*!< 0x00000004 */ +#define USB_OTG_DCTL_GINSTS USB_OTG_DCTL_GINSTS_Msk /*!< Global IN NAK status */ +#define USB_OTG_DCTL_GONSTS_Pos (3U) +#define USB_OTG_DCTL_GONSTS_Msk (0x1UL << USB_OTG_DCTL_GONSTS_Pos) /*!< 0x00000008 */ +#define USB_OTG_DCTL_GONSTS USB_OTG_DCTL_GONSTS_Msk /*!< Global OUT NAK status */ + +#define USB_OTG_DCTL_TCTL_Pos (4U) +#define USB_OTG_DCTL_TCTL_Msk (0x7UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000070 */ +#define USB_OTG_DCTL_TCTL USB_OTG_DCTL_TCTL_Msk /*!< Test control */ +#define USB_OTG_DCTL_TCTL_0 (0x1UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000010 */ +#define USB_OTG_DCTL_TCTL_1 (0x2UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000020 */ +#define USB_OTG_DCTL_TCTL_2 (0x4UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000040 */ +#define USB_OTG_DCTL_SGINAK_Pos (7U) +#define USB_OTG_DCTL_SGINAK_Msk (0x1UL << USB_OTG_DCTL_SGINAK_Pos) /*!< 0x00000080 */ +#define USB_OTG_DCTL_SGINAK USB_OTG_DCTL_SGINAK_Msk /*!< Set global IN NAK */ +#define USB_OTG_DCTL_CGINAK_Pos (8U) +#define USB_OTG_DCTL_CGINAK_Msk (0x1UL << USB_OTG_DCTL_CGINAK_Pos) /*!< 0x00000100 */ +#define USB_OTG_DCTL_CGINAK USB_OTG_DCTL_CGINAK_Msk /*!< Clear global IN NAK */ +#define USB_OTG_DCTL_SGONAK_Pos (9U) +#define USB_OTG_DCTL_SGONAK_Msk (0x1UL << USB_OTG_DCTL_SGONAK_Pos) /*!< 0x00000200 */ +#define USB_OTG_DCTL_SGONAK USB_OTG_DCTL_SGONAK_Msk /*!< Set global OUT NAK */ +#define USB_OTG_DCTL_CGONAK_Pos (10U) +#define USB_OTG_DCTL_CGONAK_Msk (0x1UL << USB_OTG_DCTL_CGONAK_Pos) /*!< 0x00000400 */ +#define USB_OTG_DCTL_CGONAK USB_OTG_DCTL_CGONAK_Msk /*!< Clear global OUT NAK */ +#define USB_OTG_DCTL_POPRGDNE_Pos (11U) +#define USB_OTG_DCTL_POPRGDNE_Msk (0x1UL << USB_OTG_DCTL_POPRGDNE_Pos) /*!< 0x00000800 */ +#define USB_OTG_DCTL_POPRGDNE USB_OTG_DCTL_POPRGDNE_Msk /*!< Power-on programming done */ + +/******************** Bit definition for USB_OTG_HFIR register ********************/ +#define USB_OTG_HFIR_FRIVL_Pos (0U) +#define USB_OTG_HFIR_FRIVL_Msk (0xFFFFUL << USB_OTG_HFIR_FRIVL_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_HFIR_FRIVL USB_OTG_HFIR_FRIVL_Msk /*!< Frame interval */ + +/******************** Bit definition for USB_OTG_HFNUM register ********************/ +#define USB_OTG_HFNUM_FRNUM_Pos (0U) +#define USB_OTG_HFNUM_FRNUM_Msk (0xFFFFUL << USB_OTG_HFNUM_FRNUM_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_HFNUM_FRNUM USB_OTG_HFNUM_FRNUM_Msk /*!< Frame number */ +#define USB_OTG_HFNUM_FTREM_Pos (16U) +#define USB_OTG_HFNUM_FTREM_Msk (0xFFFFUL << USB_OTG_HFNUM_FTREM_Pos) /*!< 0xFFFF0000 */ +#define USB_OTG_HFNUM_FTREM USB_OTG_HFNUM_FTREM_Msk /*!< Frame time remaining */ + +/******************** Bit definition for USB_OTG_DSTS register ********************/ +#define USB_OTG_DSTS_SUSPSTS_Pos (0U) +#define USB_OTG_DSTS_SUSPSTS_Msk (0x1UL << USB_OTG_DSTS_SUSPSTS_Pos) /*!< 0x00000001 */ +#define USB_OTG_DSTS_SUSPSTS USB_OTG_DSTS_SUSPSTS_Msk /*!< Suspend status */ + +#define USB_OTG_DSTS_ENUMSPD_Pos (1U) +#define USB_OTG_DSTS_ENUMSPD_Msk (0x3UL << USB_OTG_DSTS_ENUMSPD_Pos) /*!< 0x00000006 */ +#define USB_OTG_DSTS_ENUMSPD USB_OTG_DSTS_ENUMSPD_Msk /*!< Enumerated speed */ +#define USB_OTG_DSTS_ENUMSPD_0 (0x1UL << USB_OTG_DSTS_ENUMSPD_Pos) /*!< 0x00000002 */ +#define USB_OTG_DSTS_ENUMSPD_1 (0x2UL << USB_OTG_DSTS_ENUMSPD_Pos) /*!< 0x00000004 */ +#define USB_OTG_DSTS_EERR_Pos (3U) +#define USB_OTG_DSTS_EERR_Msk (0x1UL << USB_OTG_DSTS_EERR_Pos) /*!< 0x00000008 */ +#define USB_OTG_DSTS_EERR USB_OTG_DSTS_EERR_Msk /*!< Erratic error */ +#define USB_OTG_DSTS_FNSOF_Pos (8U) +#define USB_OTG_DSTS_FNSOF_Msk (0x3FFFUL << USB_OTG_DSTS_FNSOF_Pos) /*!< 0x003FFF00 */ +#define USB_OTG_DSTS_FNSOF USB_OTG_DSTS_FNSOF_Msk /*!< Frame number of the received SOF */ + +/******************** Bit definition for USB_OTG_GAHBCFG register ********************/ +#define USB_OTG_GAHBCFG_GINT_Pos (0U) +#define USB_OTG_GAHBCFG_GINT_Msk (0x1UL << USB_OTG_GAHBCFG_GINT_Pos) /*!< 0x00000001 */ +#define USB_OTG_GAHBCFG_GINT USB_OTG_GAHBCFG_GINT_Msk /*!< Global interrupt mask */ +#define USB_OTG_GAHBCFG_HBSTLEN_Pos (1U) +#define USB_OTG_GAHBCFG_HBSTLEN_Msk (0xFUL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< 0x0000001E */ +#define USB_OTG_GAHBCFG_HBSTLEN USB_OTG_GAHBCFG_HBSTLEN_Msk /*!< Burst length/type */ +#define USB_OTG_GAHBCFG_HBSTLEN_0 (0x0UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< Single */ +#define USB_OTG_GAHBCFG_HBSTLEN_1 (0x1UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR */ +#define USB_OTG_GAHBCFG_HBSTLEN_2 (0x3UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR4 */ +#define USB_OTG_GAHBCFG_HBSTLEN_3 (0x5UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR8 */ +#define USB_OTG_GAHBCFG_HBSTLEN_4 (0x7UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR16 */ +#define USB_OTG_GAHBCFG_DMAEN_Pos (5U) +#define USB_OTG_GAHBCFG_DMAEN_Msk (0x1UL << USB_OTG_GAHBCFG_DMAEN_Pos) /*!< 0x00000020 */ +#define USB_OTG_GAHBCFG_DMAEN USB_OTG_GAHBCFG_DMAEN_Msk /*!< DMA enable */ +#define USB_OTG_GAHBCFG_TXFELVL_Pos (7U) +#define USB_OTG_GAHBCFG_TXFELVL_Msk (0x1UL << USB_OTG_GAHBCFG_TXFELVL_Pos) /*!< 0x00000080 */ +#define USB_OTG_GAHBCFG_TXFELVL USB_OTG_GAHBCFG_TXFELVL_Msk /*!< TxFIFO empty level */ +#define USB_OTG_GAHBCFG_PTXFELVL_Pos (8U) +#define USB_OTG_GAHBCFG_PTXFELVL_Msk (0x1UL << USB_OTG_GAHBCFG_PTXFELVL_Pos) /*!< 0x00000100 */ +#define USB_OTG_GAHBCFG_PTXFELVL USB_OTG_GAHBCFG_PTXFELVL_Msk /*!< Periodic TxFIFO empty level */ + +/******************** Bit definition for USB_OTG_GUSBCFG register ********************/ + +#define USB_OTG_GUSBCFG_TOCAL_Pos (0U) +#define USB_OTG_GUSBCFG_TOCAL_Msk (0x7UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000007 */ +#define USB_OTG_GUSBCFG_TOCAL USB_OTG_GUSBCFG_TOCAL_Msk /*!< FS timeout calibration */ +#define USB_OTG_GUSBCFG_TOCAL_0 (0x1UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000001 */ +#define USB_OTG_GUSBCFG_TOCAL_1 (0x2UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000002 */ +#define USB_OTG_GUSBCFG_TOCAL_2 (0x4UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000004 */ +#define USB_OTG_GUSBCFG_PHYSEL_Pos (6U) +#define USB_OTG_GUSBCFG_PHYSEL_Msk (0x1UL << USB_OTG_GUSBCFG_PHYSEL_Pos) /*!< 0x00000040 */ +#define USB_OTG_GUSBCFG_PHYSEL USB_OTG_GUSBCFG_PHYSEL_Msk /*!< USB 2.0 high-speed ULPI PHY or USB 1.1 full-speed serial transceiver select */ +#define USB_OTG_GUSBCFG_SRPCAP_Pos (8U) +#define USB_OTG_GUSBCFG_SRPCAP_Msk (0x1UL << USB_OTG_GUSBCFG_SRPCAP_Pos) /*!< 0x00000100 */ +#define USB_OTG_GUSBCFG_SRPCAP USB_OTG_GUSBCFG_SRPCAP_Msk /*!< SRP-capable */ +#define USB_OTG_GUSBCFG_HNPCAP_Pos (9U) +#define USB_OTG_GUSBCFG_HNPCAP_Msk (0x1UL << USB_OTG_GUSBCFG_HNPCAP_Pos) /*!< 0x00000200 */ +#define USB_OTG_GUSBCFG_HNPCAP USB_OTG_GUSBCFG_HNPCAP_Msk /*!< HNP-capable */ +#define USB_OTG_GUSBCFG_TRDT_Pos (10U) +#define USB_OTG_GUSBCFG_TRDT_Msk (0xFUL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00003C00 */ +#define USB_OTG_GUSBCFG_TRDT USB_OTG_GUSBCFG_TRDT_Msk /*!< USB turnaround time */ +#define USB_OTG_GUSBCFG_TRDT_0 (0x1UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00000400 */ +#define USB_OTG_GUSBCFG_TRDT_1 (0x2UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00000800 */ +#define USB_OTG_GUSBCFG_TRDT_2 (0x4UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00001000 */ +#define USB_OTG_GUSBCFG_TRDT_3 (0x8UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00002000 */ +#define USB_OTG_GUSBCFG_PHYLPCS_Pos (15U) +#define USB_OTG_GUSBCFG_PHYLPCS_Msk (0x1UL << USB_OTG_GUSBCFG_PHYLPCS_Pos) /*!< 0x00008000 */ +#define USB_OTG_GUSBCFG_PHYLPCS USB_OTG_GUSBCFG_PHYLPCS_Msk /*!< PHY Low-power clock select */ +#define USB_OTG_GUSBCFG_ULPIFSLS_Pos (17U) +#define USB_OTG_GUSBCFG_ULPIFSLS_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIFSLS_Pos) /*!< 0x00020000 */ +#define USB_OTG_GUSBCFG_ULPIFSLS USB_OTG_GUSBCFG_ULPIFSLS_Msk /*!< ULPI FS/LS select */ +#define USB_OTG_GUSBCFG_ULPIAR_Pos (18U) +#define USB_OTG_GUSBCFG_ULPIAR_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIAR_Pos) /*!< 0x00040000 */ +#define USB_OTG_GUSBCFG_ULPIAR USB_OTG_GUSBCFG_ULPIAR_Msk /*!< ULPI Auto-resume */ +#define USB_OTG_GUSBCFG_ULPICSM_Pos (19U) +#define USB_OTG_GUSBCFG_ULPICSM_Msk (0x1UL << USB_OTG_GUSBCFG_ULPICSM_Pos) /*!< 0x00080000 */ +#define USB_OTG_GUSBCFG_ULPICSM USB_OTG_GUSBCFG_ULPICSM_Msk /*!< ULPI Clock SuspendM */ +#define USB_OTG_GUSBCFG_ULPIEVBUSD_Pos (20U) +#define USB_OTG_GUSBCFG_ULPIEVBUSD_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIEVBUSD_Pos) /*!< 0x00100000 */ +#define USB_OTG_GUSBCFG_ULPIEVBUSD USB_OTG_GUSBCFG_ULPIEVBUSD_Msk /*!< ULPI External VBUS Drive */ +#define USB_OTG_GUSBCFG_ULPIEVBUSI_Pos (21U) +#define USB_OTG_GUSBCFG_ULPIEVBUSI_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIEVBUSI_Pos) /*!< 0x00200000 */ +#define USB_OTG_GUSBCFG_ULPIEVBUSI USB_OTG_GUSBCFG_ULPIEVBUSI_Msk /*!< ULPI external VBUS indicator */ +#define USB_OTG_GUSBCFG_TSDPS_Pos (22U) +#define USB_OTG_GUSBCFG_TSDPS_Msk (0x1UL << USB_OTG_GUSBCFG_TSDPS_Pos) /*!< 0x00400000 */ +#define USB_OTG_GUSBCFG_TSDPS USB_OTG_GUSBCFG_TSDPS_Msk /*!< TermSel DLine pulsing selection */ +#define USB_OTG_GUSBCFG_PCCI_Pos (23U) +#define USB_OTG_GUSBCFG_PCCI_Msk (0x1UL << USB_OTG_GUSBCFG_PCCI_Pos) /*!< 0x00800000 */ +#define USB_OTG_GUSBCFG_PCCI USB_OTG_GUSBCFG_PCCI_Msk /*!< Indicator complement */ +#define USB_OTG_GUSBCFG_PTCI_Pos (24U) +#define USB_OTG_GUSBCFG_PTCI_Msk (0x1UL << USB_OTG_GUSBCFG_PTCI_Pos) /*!< 0x01000000 */ +#define USB_OTG_GUSBCFG_PTCI USB_OTG_GUSBCFG_PTCI_Msk /*!< Indicator pass through */ +#define USB_OTG_GUSBCFG_ULPIIPD_Pos (25U) +#define USB_OTG_GUSBCFG_ULPIIPD_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIIPD_Pos) /*!< 0x02000000 */ +#define USB_OTG_GUSBCFG_ULPIIPD USB_OTG_GUSBCFG_ULPIIPD_Msk /*!< ULPI interface protect disable */ +#define USB_OTG_GUSBCFG_FHMOD_Pos (29U) +#define USB_OTG_GUSBCFG_FHMOD_Msk (0x1UL << USB_OTG_GUSBCFG_FHMOD_Pos) /*!< 0x20000000 */ +#define USB_OTG_GUSBCFG_FHMOD USB_OTG_GUSBCFG_FHMOD_Msk /*!< Forced host mode */ +#define USB_OTG_GUSBCFG_FDMOD_Pos (30U) +#define USB_OTG_GUSBCFG_FDMOD_Msk (0x1UL << USB_OTG_GUSBCFG_FDMOD_Pos) /*!< 0x40000000 */ +#define USB_OTG_GUSBCFG_FDMOD USB_OTG_GUSBCFG_FDMOD_Msk /*!< Forced peripheral mode */ +#define USB_OTG_GUSBCFG_CTXPKT_Pos (31U) +#define USB_OTG_GUSBCFG_CTXPKT_Msk (0x1UL << USB_OTG_GUSBCFG_CTXPKT_Pos) /*!< 0x80000000 */ +#define USB_OTG_GUSBCFG_CTXPKT USB_OTG_GUSBCFG_CTXPKT_Msk /*!< Corrupt Tx packet */ + +/******************** Bit definition for USB_OTG_GRSTCTL register ********************/ +#define USB_OTG_GRSTCTL_CSRST_Pos (0U) +#define USB_OTG_GRSTCTL_CSRST_Msk (0x1UL << USB_OTG_GRSTCTL_CSRST_Pos) /*!< 0x00000001 */ +#define USB_OTG_GRSTCTL_CSRST USB_OTG_GRSTCTL_CSRST_Msk /*!< Core soft reset */ +#define USB_OTG_GRSTCTL_HSRST_Pos (1U) +#define USB_OTG_GRSTCTL_HSRST_Msk (0x1UL << USB_OTG_GRSTCTL_HSRST_Pos) /*!< 0x00000002 */ +#define USB_OTG_GRSTCTL_HSRST USB_OTG_GRSTCTL_HSRST_Msk /*!< HCLK soft reset */ +#define USB_OTG_GRSTCTL_FCRST_Pos (2U) +#define USB_OTG_GRSTCTL_FCRST_Msk (0x1UL << USB_OTG_GRSTCTL_FCRST_Pos) /*!< 0x00000004 */ +#define USB_OTG_GRSTCTL_FCRST USB_OTG_GRSTCTL_FCRST_Msk /*!< Host frame counter reset */ +#define USB_OTG_GRSTCTL_RXFFLSH_Pos (4U) +#define USB_OTG_GRSTCTL_RXFFLSH_Msk (0x1UL << USB_OTG_GRSTCTL_RXFFLSH_Pos) /*!< 0x00000010 */ +#define USB_OTG_GRSTCTL_RXFFLSH USB_OTG_GRSTCTL_RXFFLSH_Msk /*!< RxFIFO flush */ +#define USB_OTG_GRSTCTL_TXFFLSH_Pos (5U) +#define USB_OTG_GRSTCTL_TXFFLSH_Msk (0x1UL << USB_OTG_GRSTCTL_TXFFLSH_Pos) /*!< 0x00000020 */ +#define USB_OTG_GRSTCTL_TXFFLSH USB_OTG_GRSTCTL_TXFFLSH_Msk /*!< TxFIFO flush */ + + +#define USB_OTG_GRSTCTL_TXFNUM_Pos (6U) +#define USB_OTG_GRSTCTL_TXFNUM_Msk (0x1FUL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x000007C0 */ +#define USB_OTG_GRSTCTL_TXFNUM USB_OTG_GRSTCTL_TXFNUM_Msk /*!< TxFIFO number */ +#define USB_OTG_GRSTCTL_TXFNUM_0 (0x01UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000040 */ +#define USB_OTG_GRSTCTL_TXFNUM_1 (0x02UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000080 */ +#define USB_OTG_GRSTCTL_TXFNUM_2 (0x04UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000100 */ +#define USB_OTG_GRSTCTL_TXFNUM_3 (0x08UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000200 */ +#define USB_OTG_GRSTCTL_TXFNUM_4 (0x10UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000400 */ +#define USB_OTG_GRSTCTL_DMAREQ_Pos (30U) +#define USB_OTG_GRSTCTL_DMAREQ_Msk (0x1UL << USB_OTG_GRSTCTL_DMAREQ_Pos) /*!< 0x40000000 */ +#define USB_OTG_GRSTCTL_DMAREQ USB_OTG_GRSTCTL_DMAREQ_Msk /*!< DMA request signal */ +#define USB_OTG_GRSTCTL_AHBIDL_Pos (31U) +#define USB_OTG_GRSTCTL_AHBIDL_Msk (0x1UL << USB_OTG_GRSTCTL_AHBIDL_Pos) /*!< 0x80000000 */ +#define USB_OTG_GRSTCTL_AHBIDL USB_OTG_GRSTCTL_AHBIDL_Msk /*!< AHB master idle */ + +/******************** Bit definition for USB_OTG_DIEPMSK register ********************/ +#define USB_OTG_DIEPMSK_XFRCM_Pos (0U) +#define USB_OTG_DIEPMSK_XFRCM_Msk (0x1UL << USB_OTG_DIEPMSK_XFRCM_Pos) /*!< 0x00000001 */ +#define USB_OTG_DIEPMSK_XFRCM USB_OTG_DIEPMSK_XFRCM_Msk /*!< Transfer completed interrupt mask */ +#define USB_OTG_DIEPMSK_EPDM_Pos (1U) +#define USB_OTG_DIEPMSK_EPDM_Msk (0x1UL << USB_OTG_DIEPMSK_EPDM_Pos) /*!< 0x00000002 */ +#define USB_OTG_DIEPMSK_EPDM USB_OTG_DIEPMSK_EPDM_Msk /*!< Endpoint disabled interrupt mask */ +#define USB_OTG_DIEPMSK_TOM_Pos (3U) +#define USB_OTG_DIEPMSK_TOM_Msk (0x1UL << USB_OTG_DIEPMSK_TOM_Pos) /*!< 0x00000008 */ +#define USB_OTG_DIEPMSK_TOM USB_OTG_DIEPMSK_TOM_Msk /*!< Timeout condition mask (nonisochronous endpoints) */ +#define USB_OTG_DIEPMSK_ITTXFEMSK_Pos (4U) +#define USB_OTG_DIEPMSK_ITTXFEMSK_Msk (0x1UL << USB_OTG_DIEPMSK_ITTXFEMSK_Pos) /*!< 0x00000010 */ +#define USB_OTG_DIEPMSK_ITTXFEMSK USB_OTG_DIEPMSK_ITTXFEMSK_Msk /*!< IN token received when TxFIFO empty mask */ +#define USB_OTG_DIEPMSK_INEPNMM_Pos (5U) +#define USB_OTG_DIEPMSK_INEPNMM_Msk (0x1UL << USB_OTG_DIEPMSK_INEPNMM_Pos) /*!< 0x00000020 */ +#define USB_OTG_DIEPMSK_INEPNMM USB_OTG_DIEPMSK_INEPNMM_Msk /*!< IN token received with EP mismatch mask */ +#define USB_OTG_DIEPMSK_INEPNEM_Pos (6U) +#define USB_OTG_DIEPMSK_INEPNEM_Msk (0x1UL << USB_OTG_DIEPMSK_INEPNEM_Pos) /*!< 0x00000040 */ +#define USB_OTG_DIEPMSK_INEPNEM USB_OTG_DIEPMSK_INEPNEM_Msk /*!< IN endpoint NAK effective mask */ +#define USB_OTG_DIEPMSK_TXFURM_Pos (8U) +#define USB_OTG_DIEPMSK_TXFURM_Msk (0x1UL << USB_OTG_DIEPMSK_TXFURM_Pos) /*!< 0x00000100 */ +#define USB_OTG_DIEPMSK_TXFURM USB_OTG_DIEPMSK_TXFURM_Msk /*!< FIFO underrun mask */ +#define USB_OTG_DIEPMSK_BIM_Pos (9U) +#define USB_OTG_DIEPMSK_BIM_Msk (0x1UL << USB_OTG_DIEPMSK_BIM_Pos) /*!< 0x00000200 */ +#define USB_OTG_DIEPMSK_BIM USB_OTG_DIEPMSK_BIM_Msk /*!< BNA interrupt mask */ + +/******************** Bit definition for USB_OTG_HPTXSTS register ********************/ +#define USB_OTG_HPTXSTS_PTXFSAVL_Pos (0U) +#define USB_OTG_HPTXSTS_PTXFSAVL_Msk (0xFFFFUL << USB_OTG_HPTXSTS_PTXFSAVL_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_HPTXSTS_PTXFSAVL USB_OTG_HPTXSTS_PTXFSAVL_Msk /*!< Periodic transmit data FIFO space available */ +#define USB_OTG_HPTXSTS_PTXQSAV_Pos (16U) +#define USB_OTG_HPTXSTS_PTXQSAV_Msk (0xFFUL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00FF0000 */ +#define USB_OTG_HPTXSTS_PTXQSAV USB_OTG_HPTXSTS_PTXQSAV_Msk /*!< Periodic transmit request queue space available */ +#define USB_OTG_HPTXSTS_PTXQSAV_0 (0x01UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00010000 */ +#define USB_OTG_HPTXSTS_PTXQSAV_1 (0x02UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00020000 */ +#define USB_OTG_HPTXSTS_PTXQSAV_2 (0x04UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00040000 */ +#define USB_OTG_HPTXSTS_PTXQSAV_3 (0x08UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00080000 */ +#define USB_OTG_HPTXSTS_PTXQSAV_4 (0x10UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00100000 */ +#define USB_OTG_HPTXSTS_PTXQSAV_5 (0x20UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00200000 */ +#define USB_OTG_HPTXSTS_PTXQSAV_6 (0x40UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00400000 */ +#define USB_OTG_HPTXSTS_PTXQSAV_7 (0x80UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00800000 */ + +#define USB_OTG_HPTXSTS_PTXQTOP_Pos (24U) +#define USB_OTG_HPTXSTS_PTXQTOP_Msk (0xFFUL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0xFF000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP USB_OTG_HPTXSTS_PTXQTOP_Msk /*!< Top of the periodic transmit request queue */ +#define USB_OTG_HPTXSTS_PTXQTOP_0 (0x01UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x01000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP_1 (0x02UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x02000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP_2 (0x04UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x04000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP_3 (0x08UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x08000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP_4 (0x10UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x10000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP_5 (0x20UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x20000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP_6 (0x40UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x40000000 */ +#define USB_OTG_HPTXSTS_PTXQTOP_7 (0x80UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for USB_OTG_HAINT register ********************/ +#define USB_OTG_HAINT_HAINT_Pos (0U) +#define USB_OTG_HAINT_HAINT_Msk (0xFFFFUL << USB_OTG_HAINT_HAINT_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_HAINT_HAINT USB_OTG_HAINT_HAINT_Msk /*!< Channel interrupts */ + +/******************** Bit definition for USB_OTG_DOEPMSK register ********************/ +#define USB_OTG_DOEPMSK_XFRCM_Pos (0U) +#define USB_OTG_DOEPMSK_XFRCM_Msk (0x1UL << USB_OTG_DOEPMSK_XFRCM_Pos) /*!< 0x00000001 */ +#define USB_OTG_DOEPMSK_XFRCM USB_OTG_DOEPMSK_XFRCM_Msk /*!< Transfer completed interrupt mask */ +#define USB_OTG_DOEPMSK_EPDM_Pos (1U) +#define USB_OTG_DOEPMSK_EPDM_Msk (0x1UL << USB_OTG_DOEPMSK_EPDM_Pos) /*!< 0x00000002 */ +#define USB_OTG_DOEPMSK_EPDM USB_OTG_DOEPMSK_EPDM_Msk /*!< Endpoint disabled interrupt mask */ +#define USB_OTG_DOEPMSK_AHBERRM_Pos (2U) +#define USB_OTG_DOEPMSK_AHBERRM_Msk (0x1UL << USB_OTG_DOEPMSK_AHBERRM_Pos) /*!< 0x00000004 */ +#define USB_OTG_DOEPMSK_AHBERRM USB_OTG_DOEPMSK_AHBERRM_Msk /*!< OUT transaction AHB Error interrupt mask */ +#define USB_OTG_DOEPMSK_STUPM_Pos (3U) +#define USB_OTG_DOEPMSK_STUPM_Msk (0x1UL << USB_OTG_DOEPMSK_STUPM_Pos) /*!< 0x00000008 */ +#define USB_OTG_DOEPMSK_STUPM USB_OTG_DOEPMSK_STUPM_Msk /*!< SETUP phase done mask */ +#define USB_OTG_DOEPMSK_OTEPDM_Pos (4U) +#define USB_OTG_DOEPMSK_OTEPDM_Msk (0x1UL << USB_OTG_DOEPMSK_OTEPDM_Pos) /*!< 0x00000010 */ +#define USB_OTG_DOEPMSK_OTEPDM USB_OTG_DOEPMSK_OTEPDM_Msk /*!< OUT token received when endpoint disabled mask */ +#define USB_OTG_DOEPMSK_OTEPSPRM_Pos (5U) +#define USB_OTG_DOEPMSK_OTEPSPRM_Msk (0x1UL << USB_OTG_DOEPMSK_OTEPSPRM_Pos) /*!< 0x00000020 */ +#define USB_OTG_DOEPMSK_OTEPSPRM USB_OTG_DOEPMSK_OTEPSPRM_Msk /*!< Status Phase Received mask */ +#define USB_OTG_DOEPMSK_B2BSTUP_Pos (6U) +#define USB_OTG_DOEPMSK_B2BSTUP_Msk (0x1UL << USB_OTG_DOEPMSK_B2BSTUP_Pos) /*!< 0x00000040 */ +#define USB_OTG_DOEPMSK_B2BSTUP USB_OTG_DOEPMSK_B2BSTUP_Msk /*!< Back-to-back SETUP packets received mask */ +#define USB_OTG_DOEPMSK_OPEM_Pos (8U) +#define USB_OTG_DOEPMSK_OPEM_Msk (0x1UL << USB_OTG_DOEPMSK_OPEM_Pos) /*!< 0x00000100 */ +#define USB_OTG_DOEPMSK_OPEM USB_OTG_DOEPMSK_OPEM_Msk /*!< OUT packet error mask */ +#define USB_OTG_DOEPMSK_BOIM_Pos (9U) +#define USB_OTG_DOEPMSK_BOIM_Msk (0x1UL << USB_OTG_DOEPMSK_BOIM_Pos) /*!< 0x00000200 */ +#define USB_OTG_DOEPMSK_BOIM USB_OTG_DOEPMSK_BOIM_Msk /*!< BNA interrupt mask */ +#define USB_OTG_DOEPMSK_BERRM_Pos (12U) +#define USB_OTG_DOEPMSK_BERRM_Msk (0x1UL << USB_OTG_DOEPMSK_BERRM_Pos) /*!< 0x00001000 */ +#define USB_OTG_DOEPMSK_BERRM USB_OTG_DOEPMSK_BERRM_Msk /*!< Babble error interrupt mask */ +#define USB_OTG_DOEPMSK_NAKM_Pos (13U) +#define USB_OTG_DOEPMSK_NAKM_Msk (0x1UL << USB_OTG_DOEPMSK_NAKM_Pos) /*!< 0x00002000 */ +#define USB_OTG_DOEPMSK_NAKM USB_OTG_DOEPMSK_NAKM_Msk /*!< OUT Packet NAK interrupt mask */ +#define USB_OTG_DOEPMSK_NYETM_Pos (14U) +#define USB_OTG_DOEPMSK_NYETM_Msk (0x1UL << USB_OTG_DOEPMSK_NYETM_Pos) /*!< 0x00004000 */ +#define USB_OTG_DOEPMSK_NYETM USB_OTG_DOEPMSK_NYETM_Msk /*!< NYET interrupt mask */ +/******************** Bit definition for USB_OTG_GINTSTS register ********************/ +#define USB_OTG_GINTSTS_CMOD_Pos (0U) +#define USB_OTG_GINTSTS_CMOD_Msk (0x1UL << USB_OTG_GINTSTS_CMOD_Pos) /*!< 0x00000001 */ +#define USB_OTG_GINTSTS_CMOD USB_OTG_GINTSTS_CMOD_Msk /*!< Current mode of operation */ +#define USB_OTG_GINTSTS_MMIS_Pos (1U) +#define USB_OTG_GINTSTS_MMIS_Msk (0x1UL << USB_OTG_GINTSTS_MMIS_Pos) /*!< 0x00000002 */ +#define USB_OTG_GINTSTS_MMIS USB_OTG_GINTSTS_MMIS_Msk /*!< Mode mismatch interrupt */ +#define USB_OTG_GINTSTS_OTGINT_Pos (2U) +#define USB_OTG_GINTSTS_OTGINT_Msk (0x1UL << USB_OTG_GINTSTS_OTGINT_Pos) /*!< 0x00000004 */ +#define USB_OTG_GINTSTS_OTGINT USB_OTG_GINTSTS_OTGINT_Msk /*!< OTG interrupt */ +#define USB_OTG_GINTSTS_SOF_Pos (3U) +#define USB_OTG_GINTSTS_SOF_Msk (0x1UL << USB_OTG_GINTSTS_SOF_Pos) /*!< 0x00000008 */ +#define USB_OTG_GINTSTS_SOF USB_OTG_GINTSTS_SOF_Msk /*!< Start of frame */ +#define USB_OTG_GINTSTS_RXFLVL_Pos (4U) +#define USB_OTG_GINTSTS_RXFLVL_Msk (0x1UL << USB_OTG_GINTSTS_RXFLVL_Pos) /*!< 0x00000010 */ +#define USB_OTG_GINTSTS_RXFLVL USB_OTG_GINTSTS_RXFLVL_Msk /*!< RxFIFO nonempty */ +#define USB_OTG_GINTSTS_NPTXFE_Pos (5U) +#define USB_OTG_GINTSTS_NPTXFE_Msk (0x1UL << USB_OTG_GINTSTS_NPTXFE_Pos) /*!< 0x00000020 */ +#define USB_OTG_GINTSTS_NPTXFE USB_OTG_GINTSTS_NPTXFE_Msk /*!< Nonperiodic TxFIFO empty */ +#define USB_OTG_GINTSTS_GINAKEFF_Pos (6U) +#define USB_OTG_GINTSTS_GINAKEFF_Msk (0x1UL << USB_OTG_GINTSTS_GINAKEFF_Pos) /*!< 0x00000040 */ +#define USB_OTG_GINTSTS_GINAKEFF USB_OTG_GINTSTS_GINAKEFF_Msk /*!< Global IN nonperiodic NAK effective */ +#define USB_OTG_GINTSTS_BOUTNAKEFF_Pos (7U) +#define USB_OTG_GINTSTS_BOUTNAKEFF_Msk (0x1UL << USB_OTG_GINTSTS_BOUTNAKEFF_Pos) /*!< 0x00000080 */ +#define USB_OTG_GINTSTS_BOUTNAKEFF USB_OTG_GINTSTS_BOUTNAKEFF_Msk /*!< Global OUT NAK effective */ +#define USB_OTG_GINTSTS_ESUSP_Pos (10U) +#define USB_OTG_GINTSTS_ESUSP_Msk (0x1UL << USB_OTG_GINTSTS_ESUSP_Pos) /*!< 0x00000400 */ +#define USB_OTG_GINTSTS_ESUSP USB_OTG_GINTSTS_ESUSP_Msk /*!< Early suspend */ +#define USB_OTG_GINTSTS_USBSUSP_Pos (11U) +#define USB_OTG_GINTSTS_USBSUSP_Msk (0x1UL << USB_OTG_GINTSTS_USBSUSP_Pos) /*!< 0x00000800 */ +#define USB_OTG_GINTSTS_USBSUSP USB_OTG_GINTSTS_USBSUSP_Msk /*!< USB suspend */ +#define USB_OTG_GINTSTS_USBRST_Pos (12U) +#define USB_OTG_GINTSTS_USBRST_Msk (0x1UL << USB_OTG_GINTSTS_USBRST_Pos) /*!< 0x00001000 */ +#define USB_OTG_GINTSTS_USBRST USB_OTG_GINTSTS_USBRST_Msk /*!< USB reset */ +#define USB_OTG_GINTSTS_ENUMDNE_Pos (13U) +#define USB_OTG_GINTSTS_ENUMDNE_Msk (0x1UL << USB_OTG_GINTSTS_ENUMDNE_Pos) /*!< 0x00002000 */ +#define USB_OTG_GINTSTS_ENUMDNE USB_OTG_GINTSTS_ENUMDNE_Msk /*!< Enumeration done */ +#define USB_OTG_GINTSTS_ISOODRP_Pos (14U) +#define USB_OTG_GINTSTS_ISOODRP_Msk (0x1UL << USB_OTG_GINTSTS_ISOODRP_Pos) /*!< 0x00004000 */ +#define USB_OTG_GINTSTS_ISOODRP USB_OTG_GINTSTS_ISOODRP_Msk /*!< Isochronous OUT packet dropped interrupt */ +#define USB_OTG_GINTSTS_EOPF_Pos (15U) +#define USB_OTG_GINTSTS_EOPF_Msk (0x1UL << USB_OTG_GINTSTS_EOPF_Pos) /*!< 0x00008000 */ +#define USB_OTG_GINTSTS_EOPF USB_OTG_GINTSTS_EOPF_Msk /*!< End of periodic frame interrupt */ +#define USB_OTG_GINTSTS_IEPINT_Pos (18U) +#define USB_OTG_GINTSTS_IEPINT_Msk (0x1UL << USB_OTG_GINTSTS_IEPINT_Pos) /*!< 0x00040000 */ +#define USB_OTG_GINTSTS_IEPINT USB_OTG_GINTSTS_IEPINT_Msk /*!< IN endpoint interrupt */ +#define USB_OTG_GINTSTS_OEPINT_Pos (19U) +#define USB_OTG_GINTSTS_OEPINT_Msk (0x1UL << USB_OTG_GINTSTS_OEPINT_Pos) /*!< 0x00080000 */ +#define USB_OTG_GINTSTS_OEPINT USB_OTG_GINTSTS_OEPINT_Msk /*!< OUT endpoint interrupt */ +#define USB_OTG_GINTSTS_IISOIXFR_Pos (20U) +#define USB_OTG_GINTSTS_IISOIXFR_Msk (0x1UL << USB_OTG_GINTSTS_IISOIXFR_Pos) /*!< 0x00100000 */ +#define USB_OTG_GINTSTS_IISOIXFR USB_OTG_GINTSTS_IISOIXFR_Msk /*!< Incomplete isochronous IN transfer */ +#define USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Pos (21U) +#define USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Msk (0x1UL << USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Pos) /*!< 0x00200000 */ +#define USB_OTG_GINTSTS_PXFR_INCOMPISOOUT USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Msk /*!< Incomplete periodic transfer */ +#define USB_OTG_GINTSTS_DATAFSUSP_Pos (22U) +#define USB_OTG_GINTSTS_DATAFSUSP_Msk (0x1UL << USB_OTG_GINTSTS_DATAFSUSP_Pos) /*!< 0x00400000 */ +#define USB_OTG_GINTSTS_DATAFSUSP USB_OTG_GINTSTS_DATAFSUSP_Msk /*!< Data fetch suspended */ +#define USB_OTG_GINTSTS_HPRTINT_Pos (24U) +#define USB_OTG_GINTSTS_HPRTINT_Msk (0x1UL << USB_OTG_GINTSTS_HPRTINT_Pos) /*!< 0x01000000 */ +#define USB_OTG_GINTSTS_HPRTINT USB_OTG_GINTSTS_HPRTINT_Msk /*!< Host port interrupt */ +#define USB_OTG_GINTSTS_HCINT_Pos (25U) +#define USB_OTG_GINTSTS_HCINT_Msk (0x1UL << USB_OTG_GINTSTS_HCINT_Pos) /*!< 0x02000000 */ +#define USB_OTG_GINTSTS_HCINT USB_OTG_GINTSTS_HCINT_Msk /*!< Host channels interrupt */ +#define USB_OTG_GINTSTS_PTXFE_Pos (26U) +#define USB_OTG_GINTSTS_PTXFE_Msk (0x1UL << USB_OTG_GINTSTS_PTXFE_Pos) /*!< 0x04000000 */ +#define USB_OTG_GINTSTS_PTXFE USB_OTG_GINTSTS_PTXFE_Msk /*!< Periodic TxFIFO empty */ +#define USB_OTG_GINTSTS_CIDSCHG_Pos (28U) +#define USB_OTG_GINTSTS_CIDSCHG_Msk (0x1UL << USB_OTG_GINTSTS_CIDSCHG_Pos) /*!< 0x10000000 */ +#define USB_OTG_GINTSTS_CIDSCHG USB_OTG_GINTSTS_CIDSCHG_Msk /*!< Connector ID status change */ +#define USB_OTG_GINTSTS_DISCINT_Pos (29U) +#define USB_OTG_GINTSTS_DISCINT_Msk (0x1UL << USB_OTG_GINTSTS_DISCINT_Pos) /*!< 0x20000000 */ +#define USB_OTG_GINTSTS_DISCINT USB_OTG_GINTSTS_DISCINT_Msk /*!< Disconnect detected interrupt */ +#define USB_OTG_GINTSTS_SRQINT_Pos (30U) +#define USB_OTG_GINTSTS_SRQINT_Msk (0x1UL << USB_OTG_GINTSTS_SRQINT_Pos) /*!< 0x40000000 */ +#define USB_OTG_GINTSTS_SRQINT USB_OTG_GINTSTS_SRQINT_Msk /*!< Session request/new session detected interrupt */ +#define USB_OTG_GINTSTS_WKUINT_Pos (31U) +#define USB_OTG_GINTSTS_WKUINT_Msk (0x1UL << USB_OTG_GINTSTS_WKUINT_Pos) /*!< 0x80000000 */ +#define USB_OTG_GINTSTS_WKUINT USB_OTG_GINTSTS_WKUINT_Msk /*!< Resume/remote wakeup detected interrupt */ + +/******************** Bit definition for USB_OTG_GINTMSK register ********************/ +#define USB_OTG_GINTMSK_MMISM_Pos (1U) +#define USB_OTG_GINTMSK_MMISM_Msk (0x1UL << USB_OTG_GINTMSK_MMISM_Pos) /*!< 0x00000002 */ +#define USB_OTG_GINTMSK_MMISM USB_OTG_GINTMSK_MMISM_Msk /*!< Mode mismatch interrupt mask */ +#define USB_OTG_GINTMSK_OTGINT_Pos (2U) +#define USB_OTG_GINTMSK_OTGINT_Msk (0x1UL << USB_OTG_GINTMSK_OTGINT_Pos) /*!< 0x00000004 */ +#define USB_OTG_GINTMSK_OTGINT USB_OTG_GINTMSK_OTGINT_Msk /*!< OTG interrupt mask */ +#define USB_OTG_GINTMSK_SOFM_Pos (3U) +#define USB_OTG_GINTMSK_SOFM_Msk (0x1UL << USB_OTG_GINTMSK_SOFM_Pos) /*!< 0x00000008 */ +#define USB_OTG_GINTMSK_SOFM USB_OTG_GINTMSK_SOFM_Msk /*!< Start of frame mask */ +#define USB_OTG_GINTMSK_RXFLVLM_Pos (4U) +#define USB_OTG_GINTMSK_RXFLVLM_Msk (0x1UL << USB_OTG_GINTMSK_RXFLVLM_Pos) /*!< 0x00000010 */ +#define USB_OTG_GINTMSK_RXFLVLM USB_OTG_GINTMSK_RXFLVLM_Msk /*!< Receive FIFO nonempty mask */ +#define USB_OTG_GINTMSK_NPTXFEM_Pos (5U) +#define USB_OTG_GINTMSK_NPTXFEM_Msk (0x1UL << USB_OTG_GINTMSK_NPTXFEM_Pos) /*!< 0x00000020 */ +#define USB_OTG_GINTMSK_NPTXFEM USB_OTG_GINTMSK_NPTXFEM_Msk /*!< Nonperiodic TxFIFO empty mask */ +#define USB_OTG_GINTMSK_GINAKEFFM_Pos (6U) +#define USB_OTG_GINTMSK_GINAKEFFM_Msk (0x1UL << USB_OTG_GINTMSK_GINAKEFFM_Pos) /*!< 0x00000040 */ +#define USB_OTG_GINTMSK_GINAKEFFM USB_OTG_GINTMSK_GINAKEFFM_Msk /*!< Global nonperiodic IN NAK effective mask */ +#define USB_OTG_GINTMSK_GONAKEFFM_Pos (7U) +#define USB_OTG_GINTMSK_GONAKEFFM_Msk (0x1UL << USB_OTG_GINTMSK_GONAKEFFM_Pos) /*!< 0x00000080 */ +#define USB_OTG_GINTMSK_GONAKEFFM USB_OTG_GINTMSK_GONAKEFFM_Msk /*!< Global OUT NAK effective mask */ +#define USB_OTG_GINTMSK_ESUSPM_Pos (10U) +#define USB_OTG_GINTMSK_ESUSPM_Msk (0x1UL << USB_OTG_GINTMSK_ESUSPM_Pos) /*!< 0x00000400 */ +#define USB_OTG_GINTMSK_ESUSPM USB_OTG_GINTMSK_ESUSPM_Msk /*!< Early suspend mask */ +#define USB_OTG_GINTMSK_USBSUSPM_Pos (11U) +#define USB_OTG_GINTMSK_USBSUSPM_Msk (0x1UL << USB_OTG_GINTMSK_USBSUSPM_Pos) /*!< 0x00000800 */ +#define USB_OTG_GINTMSK_USBSUSPM USB_OTG_GINTMSK_USBSUSPM_Msk /*!< USB suspend mask */ +#define USB_OTG_GINTMSK_USBRST_Pos (12U) +#define USB_OTG_GINTMSK_USBRST_Msk (0x1UL << USB_OTG_GINTMSK_USBRST_Pos) /*!< 0x00001000 */ +#define USB_OTG_GINTMSK_USBRST USB_OTG_GINTMSK_USBRST_Msk /*!< USB reset mask */ +#define USB_OTG_GINTMSK_ENUMDNEM_Pos (13U) +#define USB_OTG_GINTMSK_ENUMDNEM_Msk (0x1UL << USB_OTG_GINTMSK_ENUMDNEM_Pos) /*!< 0x00002000 */ +#define USB_OTG_GINTMSK_ENUMDNEM USB_OTG_GINTMSK_ENUMDNEM_Msk /*!< Enumeration done mask */ +#define USB_OTG_GINTMSK_ISOODRPM_Pos (14U) +#define USB_OTG_GINTMSK_ISOODRPM_Msk (0x1UL << USB_OTG_GINTMSK_ISOODRPM_Pos) /*!< 0x00004000 */ +#define USB_OTG_GINTMSK_ISOODRPM USB_OTG_GINTMSK_ISOODRPM_Msk /*!< Isochronous OUT packet dropped interrupt mask */ +#define USB_OTG_GINTMSK_EOPFM_Pos (15U) +#define USB_OTG_GINTMSK_EOPFM_Msk (0x1UL << USB_OTG_GINTMSK_EOPFM_Pos) /*!< 0x00008000 */ +#define USB_OTG_GINTMSK_EOPFM USB_OTG_GINTMSK_EOPFM_Msk /*!< End of periodic frame interrupt mask */ +#define USB_OTG_GINTMSK_EPMISM_Pos (17U) +#define USB_OTG_GINTMSK_EPMISM_Msk (0x1UL << USB_OTG_GINTMSK_EPMISM_Pos) /*!< 0x00020000 */ +#define USB_OTG_GINTMSK_EPMISM USB_OTG_GINTMSK_EPMISM_Msk /*!< Endpoint mismatch interrupt mask */ +#define USB_OTG_GINTMSK_IEPINT_Pos (18U) +#define USB_OTG_GINTMSK_IEPINT_Msk (0x1UL << USB_OTG_GINTMSK_IEPINT_Pos) /*!< 0x00040000 */ +#define USB_OTG_GINTMSK_IEPINT USB_OTG_GINTMSK_IEPINT_Msk /*!< IN endpoints interrupt mask */ +#define USB_OTG_GINTMSK_OEPINT_Pos (19U) +#define USB_OTG_GINTMSK_OEPINT_Msk (0x1UL << USB_OTG_GINTMSK_OEPINT_Pos) /*!< 0x00080000 */ +#define USB_OTG_GINTMSK_OEPINT USB_OTG_GINTMSK_OEPINT_Msk /*!< OUT endpoints interrupt mask */ +#define USB_OTG_GINTMSK_IISOIXFRM_Pos (20U) +#define USB_OTG_GINTMSK_IISOIXFRM_Msk (0x1UL << USB_OTG_GINTMSK_IISOIXFRM_Pos) /*!< 0x00100000 */ +#define USB_OTG_GINTMSK_IISOIXFRM USB_OTG_GINTMSK_IISOIXFRM_Msk /*!< Incomplete isochronous IN transfer mask */ +#define USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Pos (21U) +#define USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Msk (0x1UL << USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Pos) /*!< 0x00200000 */ +#define USB_OTG_GINTMSK_PXFRM_IISOOXFRM USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Msk /*!< Incomplete periodic transfer mask */ +#define USB_OTG_GINTMSK_FSUSPM_Pos (22U) +#define USB_OTG_GINTMSK_FSUSPM_Msk (0x1UL << USB_OTG_GINTMSK_FSUSPM_Pos) /*!< 0x00400000 */ +#define USB_OTG_GINTMSK_FSUSPM USB_OTG_GINTMSK_FSUSPM_Msk /*!< Data fetch suspended mask */ +#define USB_OTG_GINTMSK_PRTIM_Pos (24U) +#define USB_OTG_GINTMSK_PRTIM_Msk (0x1UL << USB_OTG_GINTMSK_PRTIM_Pos) /*!< 0x01000000 */ +#define USB_OTG_GINTMSK_PRTIM USB_OTG_GINTMSK_PRTIM_Msk /*!< Host port interrupt mask */ +#define USB_OTG_GINTMSK_HCIM_Pos (25U) +#define USB_OTG_GINTMSK_HCIM_Msk (0x1UL << USB_OTG_GINTMSK_HCIM_Pos) /*!< 0x02000000 */ +#define USB_OTG_GINTMSK_HCIM USB_OTG_GINTMSK_HCIM_Msk /*!< Host channels interrupt mask */ +#define USB_OTG_GINTMSK_PTXFEM_Pos (26U) +#define USB_OTG_GINTMSK_PTXFEM_Msk (0x1UL << USB_OTG_GINTMSK_PTXFEM_Pos) /*!< 0x04000000 */ +#define USB_OTG_GINTMSK_PTXFEM USB_OTG_GINTMSK_PTXFEM_Msk /*!< Periodic TxFIFO empty mask */ +#define USB_OTG_GINTMSK_CIDSCHGM_Pos (28U) +#define USB_OTG_GINTMSK_CIDSCHGM_Msk (0x1UL << USB_OTG_GINTMSK_CIDSCHGM_Pos) /*!< 0x10000000 */ +#define USB_OTG_GINTMSK_CIDSCHGM USB_OTG_GINTMSK_CIDSCHGM_Msk /*!< Connector ID status change mask */ +#define USB_OTG_GINTMSK_DISCINT_Pos (29U) +#define USB_OTG_GINTMSK_DISCINT_Msk (0x1UL << USB_OTG_GINTMSK_DISCINT_Pos) /*!< 0x20000000 */ +#define USB_OTG_GINTMSK_DISCINT USB_OTG_GINTMSK_DISCINT_Msk /*!< Disconnect detected interrupt mask */ +#define USB_OTG_GINTMSK_SRQIM_Pos (30U) +#define USB_OTG_GINTMSK_SRQIM_Msk (0x1UL << USB_OTG_GINTMSK_SRQIM_Pos) /*!< 0x40000000 */ +#define USB_OTG_GINTMSK_SRQIM USB_OTG_GINTMSK_SRQIM_Msk /*!< Session request/new session detected interrupt mask */ +#define USB_OTG_GINTMSK_WUIM_Pos (31U) +#define USB_OTG_GINTMSK_WUIM_Msk (0x1UL << USB_OTG_GINTMSK_WUIM_Pos) /*!< 0x80000000 */ +#define USB_OTG_GINTMSK_WUIM USB_OTG_GINTMSK_WUIM_Msk /*!< Resume/remote wakeup detected interrupt mask */ + +/******************** Bit definition for USB_OTG_DAINT register ********************/ +#define USB_OTG_DAINT_IEPINT_Pos (0U) +#define USB_OTG_DAINT_IEPINT_Msk (0xFFFFUL << USB_OTG_DAINT_IEPINT_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_DAINT_IEPINT USB_OTG_DAINT_IEPINT_Msk /*!< IN endpoint interrupt bits */ +#define USB_OTG_DAINT_OEPINT_Pos (16U) +#define USB_OTG_DAINT_OEPINT_Msk (0xFFFFUL << USB_OTG_DAINT_OEPINT_Pos) /*!< 0xFFFF0000 */ +#define USB_OTG_DAINT_OEPINT USB_OTG_DAINT_OEPINT_Msk /*!< OUT endpoint interrupt bits */ + +/******************** Bit definition for USB_OTG_HAINTMSK register ********************/ +#define USB_OTG_HAINTMSK_HAINTM_Pos (0U) +#define USB_OTG_HAINTMSK_HAINTM_Msk (0xFFFFUL << USB_OTG_HAINTMSK_HAINTM_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_HAINTMSK_HAINTM USB_OTG_HAINTMSK_HAINTM_Msk /*!< Channel interrupt mask */ + +/******************** Bit definition for USB_OTG_GRXSTSP register ********************/ +#define USB_OTG_GRXSTSP_EPNUM_Pos (0U) +#define USB_OTG_GRXSTSP_EPNUM_Msk (0xFUL << USB_OTG_GRXSTSP_EPNUM_Pos) /*!< 0x0000000F */ +#define USB_OTG_GRXSTSP_EPNUM USB_OTG_GRXSTSP_EPNUM_Msk /*!< IN EP interrupt mask bits */ +#define USB_OTG_GRXSTSP_BCNT_Pos (4U) +#define USB_OTG_GRXSTSP_BCNT_Msk (0x7FFUL << USB_OTG_GRXSTSP_BCNT_Pos) /*!< 0x00007FF0 */ +#define USB_OTG_GRXSTSP_BCNT USB_OTG_GRXSTSP_BCNT_Msk /*!< OUT EP interrupt mask bits */ +#define USB_OTG_GRXSTSP_DPID_Pos (15U) +#define USB_OTG_GRXSTSP_DPID_Msk (0x3UL << USB_OTG_GRXSTSP_DPID_Pos) /*!< 0x00018000 */ +#define USB_OTG_GRXSTSP_DPID USB_OTG_GRXSTSP_DPID_Msk /*!< OUT EP interrupt mask bits */ +#define USB_OTG_GRXSTSP_PKTSTS_Pos (17U) +#define USB_OTG_GRXSTSP_PKTSTS_Msk (0xFUL << USB_OTG_GRXSTSP_PKTSTS_Pos) /*!< 0x001E0000 */ +#define USB_OTG_GRXSTSP_PKTSTS USB_OTG_GRXSTSP_PKTSTS_Msk /*!< OUT EP interrupt mask bits */ + +/******************** Bit definition for USB_OTG_DAINTMSK register ********************/ +#define USB_OTG_DAINTMSK_IEPM_Pos (0U) +#define USB_OTG_DAINTMSK_IEPM_Msk (0xFFFFUL << USB_OTG_DAINTMSK_IEPM_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_DAINTMSK_IEPM USB_OTG_DAINTMSK_IEPM_Msk /*!< IN EP interrupt mask bits */ +#define USB_OTG_DAINTMSK_OEPM_Pos (16U) +#define USB_OTG_DAINTMSK_OEPM_Msk (0xFFFFUL << USB_OTG_DAINTMSK_OEPM_Pos) /*!< 0xFFFF0000 */ +#define USB_OTG_DAINTMSK_OEPM USB_OTG_DAINTMSK_OEPM_Msk /*!< OUT EP interrupt mask bits */ + +/******************** Bit definition for USB_OTG_GRXFSIZ register ********************/ +#define USB_OTG_GRXFSIZ_RXFD_Pos (0U) +#define USB_OTG_GRXFSIZ_RXFD_Msk (0xFFFFUL << USB_OTG_GRXFSIZ_RXFD_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_GRXFSIZ_RXFD USB_OTG_GRXFSIZ_RXFD_Msk /*!< RxFIFO depth */ + +/******************** Bit definition for USB_OTG_DVBUSDIS register ********************/ +#define USB_OTG_DVBUSDIS_VBUSDT_Pos (0U) +#define USB_OTG_DVBUSDIS_VBUSDT_Msk (0xFFFFUL << USB_OTG_DVBUSDIS_VBUSDT_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_DVBUSDIS_VBUSDT USB_OTG_DVBUSDIS_VBUSDT_Msk /*!< Device VBUS discharge time */ + +/******************** Bit definition for OTG register ********************/ +#define USB_OTG_NPTXFSA_Pos (0U) +#define USB_OTG_NPTXFSA_Msk (0xFFFFUL << USB_OTG_NPTXFSA_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_NPTXFSA USB_OTG_NPTXFSA_Msk /*!< Nonperiodic transmit RAM start address */ +#define USB_OTG_NPTXFD_Pos (16U) +#define USB_OTG_NPTXFD_Msk (0xFFFFUL << USB_OTG_NPTXFD_Pos) /*!< 0xFFFF0000 */ +#define USB_OTG_NPTXFD USB_OTG_NPTXFD_Msk /*!< Nonperiodic TxFIFO depth */ +#define USB_OTG_TX0FSA_Pos (0U) +#define USB_OTG_TX0FSA_Msk (0xFFFFUL << USB_OTG_TX0FSA_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_TX0FSA USB_OTG_TX0FSA_Msk /*!< Endpoint 0 transmit RAM start address */ +#define USB_OTG_TX0FD_Pos (16U) +#define USB_OTG_TX0FD_Msk (0xFFFFUL << USB_OTG_TX0FD_Pos) /*!< 0xFFFF0000 */ +#define USB_OTG_TX0FD USB_OTG_TX0FD_Msk /*!< Endpoint 0 TxFIFO depth */ + +/******************** Bit definition for USB_OTG_DVBUSPULSE register ********************/ +#define USB_OTG_DVBUSPULSE_DVBUSP_Pos (0U) +#define USB_OTG_DVBUSPULSE_DVBUSP_Msk (0xFFFUL << USB_OTG_DVBUSPULSE_DVBUSP_Pos) /*!< 0x00000FFF */ +#define USB_OTG_DVBUSPULSE_DVBUSP USB_OTG_DVBUSPULSE_DVBUSP_Msk /*!< Device VBUS pulsing time */ + +/******************** Bit definition for USB_OTG_GNPTXSTS register ********************/ +#define USB_OTG_GNPTXSTS_NPTXFSAV_Pos (0U) +#define USB_OTG_GNPTXSTS_NPTXFSAV_Msk (0xFFFFUL << USB_OTG_GNPTXSTS_NPTXFSAV_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_GNPTXSTS_NPTXFSAV USB_OTG_GNPTXSTS_NPTXFSAV_Msk /*!< Nonperiodic TxFIFO space available */ + +#define USB_OTG_GNPTXSTS_NPTQXSAV_Pos (16U) +#define USB_OTG_GNPTXSTS_NPTQXSAV_Msk (0xFFUL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00FF0000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV USB_OTG_GNPTXSTS_NPTQXSAV_Msk /*!< Nonperiodic transmit request queue space available */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_0 (0x01UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00010000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_1 (0x02UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00020000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_2 (0x04UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00040000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_3 (0x08UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00080000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_4 (0x10UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00100000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_5 (0x20UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00200000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_6 (0x40UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00400000 */ +#define USB_OTG_GNPTXSTS_NPTQXSAV_7 (0x80UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00800000 */ + +#define USB_OTG_GNPTXSTS_NPTXQTOP_Pos (24U) +#define USB_OTG_GNPTXSTS_NPTXQTOP_Msk (0x7FUL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x7F000000 */ +#define USB_OTG_GNPTXSTS_NPTXQTOP USB_OTG_GNPTXSTS_NPTXQTOP_Msk /*!< Top of the nonperiodic transmit request queue */ +#define USB_OTG_GNPTXSTS_NPTXQTOP_0 (0x01UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x01000000 */ +#define USB_OTG_GNPTXSTS_NPTXQTOP_1 (0x02UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x02000000 */ +#define USB_OTG_GNPTXSTS_NPTXQTOP_2 (0x04UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x04000000 */ +#define USB_OTG_GNPTXSTS_NPTXQTOP_3 (0x08UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x08000000 */ +#define USB_OTG_GNPTXSTS_NPTXQTOP_4 (0x10UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x10000000 */ +#define USB_OTG_GNPTXSTS_NPTXQTOP_5 (0x20UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x20000000 */ +#define USB_OTG_GNPTXSTS_NPTXQTOP_6 (0x40UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x40000000 */ + +/******************** Bit definition for USB_OTG_DTHRCTL register ********************/ +#define USB_OTG_DTHRCTL_NONISOTHREN_Pos (0U) +#define USB_OTG_DTHRCTL_NONISOTHREN_Msk (0x1UL << USB_OTG_DTHRCTL_NONISOTHREN_Pos) /*!< 0x00000001 */ +#define USB_OTG_DTHRCTL_NONISOTHREN USB_OTG_DTHRCTL_NONISOTHREN_Msk /*!< Nonisochronous IN endpoints threshold enable */ +#define USB_OTG_DTHRCTL_ISOTHREN_Pos (1U) +#define USB_OTG_DTHRCTL_ISOTHREN_Msk (0x1UL << USB_OTG_DTHRCTL_ISOTHREN_Pos) /*!< 0x00000002 */ +#define USB_OTG_DTHRCTL_ISOTHREN USB_OTG_DTHRCTL_ISOTHREN_Msk /*!< ISO IN endpoint threshold enable */ + +#define USB_OTG_DTHRCTL_TXTHRLEN_Pos (2U) +#define USB_OTG_DTHRCTL_TXTHRLEN_Msk (0x1FFUL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x000007FC */ +#define USB_OTG_DTHRCTL_TXTHRLEN USB_OTG_DTHRCTL_TXTHRLEN_Msk /*!< Transmit threshold length */ +#define USB_OTG_DTHRCTL_TXTHRLEN_0 (0x001UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000004 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_1 (0x002UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000008 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_2 (0x004UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000010 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_3 (0x008UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000020 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_4 (0x010UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000040 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_5 (0x020UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000080 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_6 (0x040UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000100 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_7 (0x080UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000200 */ +#define USB_OTG_DTHRCTL_TXTHRLEN_8 (0x100UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000400 */ +#define USB_OTG_DTHRCTL_RXTHREN_Pos (16U) +#define USB_OTG_DTHRCTL_RXTHREN_Msk (0x1UL << USB_OTG_DTHRCTL_RXTHREN_Pos) /*!< 0x00010000 */ +#define USB_OTG_DTHRCTL_RXTHREN USB_OTG_DTHRCTL_RXTHREN_Msk /*!< Receive threshold enable */ + +#define USB_OTG_DTHRCTL_RXTHRLEN_Pos (17U) +#define USB_OTG_DTHRCTL_RXTHRLEN_Msk (0x1FFUL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x03FE0000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN USB_OTG_DTHRCTL_RXTHRLEN_Msk /*!< Receive threshold length */ +#define USB_OTG_DTHRCTL_RXTHRLEN_0 (0x001UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00020000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_1 (0x002UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00040000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_2 (0x004UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00080000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_3 (0x008UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00100000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_4 (0x010UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00200000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_5 (0x020UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00400000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_6 (0x040UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00800000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_7 (0x080UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x01000000 */ +#define USB_OTG_DTHRCTL_RXTHRLEN_8 (0x100UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x02000000 */ +#define USB_OTG_DTHRCTL_ARPEN_Pos (27U) +#define USB_OTG_DTHRCTL_ARPEN_Msk (0x1UL << USB_OTG_DTHRCTL_ARPEN_Pos) /*!< 0x08000000 */ +#define USB_OTG_DTHRCTL_ARPEN USB_OTG_DTHRCTL_ARPEN_Msk /*!< Arbiter parking enable */ + +/******************** Bit definition for USB_OTG_DIEPEMPMSK register ********************/ +#define USB_OTG_DIEPEMPMSK_INEPTXFEM_Pos (0U) +#define USB_OTG_DIEPEMPMSK_INEPTXFEM_Msk (0xFFFFUL << USB_OTG_DIEPEMPMSK_INEPTXFEM_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_DIEPEMPMSK_INEPTXFEM USB_OTG_DIEPEMPMSK_INEPTXFEM_Msk /*!< IN EP Tx FIFO empty interrupt mask bits */ + +/******************** Bit definition for USB_OTG_DEACHINT register ********************/ +#define USB_OTG_DEACHINT_IEP1INT_Pos (1U) +#define USB_OTG_DEACHINT_IEP1INT_Msk (0x1UL << USB_OTG_DEACHINT_IEP1INT_Pos) /*!< 0x00000002 */ +#define USB_OTG_DEACHINT_IEP1INT USB_OTG_DEACHINT_IEP1INT_Msk /*!< IN endpoint 1interrupt bit */ +#define USB_OTG_DEACHINT_OEP1INT_Pos (17U) +#define USB_OTG_DEACHINT_OEP1INT_Msk (0x1UL << USB_OTG_DEACHINT_OEP1INT_Pos) /*!< 0x00020000 */ +#define USB_OTG_DEACHINT_OEP1INT USB_OTG_DEACHINT_OEP1INT_Msk /*!< OUT endpoint 1 interrupt bit */ + +/******************** Bit definition for USB_OTG_GCCFG register ********************/ +#define USB_OTG_GCCFG_PWRDWN_Pos (16U) +#define USB_OTG_GCCFG_PWRDWN_Msk (0x1UL << USB_OTG_GCCFG_PWRDWN_Pos) /*!< 0x00010000 */ +#define USB_OTG_GCCFG_PWRDWN USB_OTG_GCCFG_PWRDWN_Msk /*!< Power down */ +#define USB_OTG_GCCFG_VBUSASEN_Pos (18U) +#define USB_OTG_GCCFG_VBUSASEN_Msk (0x1UL << USB_OTG_GCCFG_VBUSASEN_Pos) /*!< 0x00040000 */ +#define USB_OTG_GCCFG_VBUSASEN USB_OTG_GCCFG_VBUSASEN_Msk /*!< Enable the VBUS sensing device */ +#define USB_OTG_GCCFG_VBUSBSEN_Pos (19U) +#define USB_OTG_GCCFG_VBUSBSEN_Msk (0x1UL << USB_OTG_GCCFG_VBUSBSEN_Pos) /*!< 0x00080000 */ +#define USB_OTG_GCCFG_VBUSBSEN USB_OTG_GCCFG_VBUSBSEN_Msk /*!< Enable the VBUS sensing device */ +#define USB_OTG_GCCFG_SOFOUTEN_Pos (20U) +#define USB_OTG_GCCFG_SOFOUTEN_Msk (0x1UL << USB_OTG_GCCFG_SOFOUTEN_Pos) /*!< 0x00100000 */ +#define USB_OTG_GCCFG_SOFOUTEN USB_OTG_GCCFG_SOFOUTEN_Msk /*!< SOF output enable */ + +/******************** Bit definition for USB_OTG_DEACHINTMSK register ********************/ +#define USB_OTG_DEACHINTMSK_IEP1INTM_Pos (1U) +#define USB_OTG_DEACHINTMSK_IEP1INTM_Msk (0x1UL << USB_OTG_DEACHINTMSK_IEP1INTM_Pos) /*!< 0x00000002 */ +#define USB_OTG_DEACHINTMSK_IEP1INTM USB_OTG_DEACHINTMSK_IEP1INTM_Msk /*!< IN Endpoint 1 interrupt mask bit */ +#define USB_OTG_DEACHINTMSK_OEP1INTM_Pos (17U) +#define USB_OTG_DEACHINTMSK_OEP1INTM_Msk (0x1UL << USB_OTG_DEACHINTMSK_OEP1INTM_Pos) /*!< 0x00020000 */ +#define USB_OTG_DEACHINTMSK_OEP1INTM USB_OTG_DEACHINTMSK_OEP1INTM_Msk /*!< OUT Endpoint 1 interrupt mask bit */ + +/******************** Bit definition for USB_OTG_CID register ********************/ +#define USB_OTG_CID_PRODUCT_ID_Pos (0U) +#define USB_OTG_CID_PRODUCT_ID_Msk (0xFFFFFFFFUL << USB_OTG_CID_PRODUCT_ID_Pos) /*!< 0xFFFFFFFF */ +#define USB_OTG_CID_PRODUCT_ID USB_OTG_CID_PRODUCT_ID_Msk /*!< Product ID field */ + +/******************** Bit definition for USB_OTG_DIEPEACHMSK1 register ********************/ +#define USB_OTG_DIEPEACHMSK1_XFRCM_Pos (0U) +#define USB_OTG_DIEPEACHMSK1_XFRCM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_XFRCM_Pos) /*!< 0x00000001 */ +#define USB_OTG_DIEPEACHMSK1_XFRCM USB_OTG_DIEPEACHMSK1_XFRCM_Msk /*!< Transfer completed interrupt mask */ +#define USB_OTG_DIEPEACHMSK1_EPDM_Pos (1U) +#define USB_OTG_DIEPEACHMSK1_EPDM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_EPDM_Pos) /*!< 0x00000002 */ +#define USB_OTG_DIEPEACHMSK1_EPDM USB_OTG_DIEPEACHMSK1_EPDM_Msk /*!< Endpoint disabled interrupt mask */ +#define USB_OTG_DIEPEACHMSK1_TOM_Pos (3U) +#define USB_OTG_DIEPEACHMSK1_TOM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_TOM_Pos) /*!< 0x00000008 */ +#define USB_OTG_DIEPEACHMSK1_TOM USB_OTG_DIEPEACHMSK1_TOM_Msk /*!< Timeout condition mask (nonisochronous endpoints) */ +#define USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Pos (4U) +#define USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Pos) /*!< 0x00000010 */ +#define USB_OTG_DIEPEACHMSK1_ITTXFEMSK USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Msk /*!< IN token received when TxFIFO empty mask */ +#define USB_OTG_DIEPEACHMSK1_INEPNMM_Pos (5U) +#define USB_OTG_DIEPEACHMSK1_INEPNMM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_INEPNMM_Pos) /*!< 0x00000020 */ +#define USB_OTG_DIEPEACHMSK1_INEPNMM USB_OTG_DIEPEACHMSK1_INEPNMM_Msk /*!< IN token received with EP mismatch mask */ +#define USB_OTG_DIEPEACHMSK1_INEPNEM_Pos (6U) +#define USB_OTG_DIEPEACHMSK1_INEPNEM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_INEPNEM_Pos) /*!< 0x00000040 */ +#define USB_OTG_DIEPEACHMSK1_INEPNEM USB_OTG_DIEPEACHMSK1_INEPNEM_Msk /*!< IN endpoint NAK effective mask */ +#define USB_OTG_DIEPEACHMSK1_TXFURM_Pos (8U) +#define USB_OTG_DIEPEACHMSK1_TXFURM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_TXFURM_Pos) /*!< 0x00000100 */ +#define USB_OTG_DIEPEACHMSK1_TXFURM USB_OTG_DIEPEACHMSK1_TXFURM_Msk /*!< FIFO underrun mask */ +#define USB_OTG_DIEPEACHMSK1_BIM_Pos (9U) +#define USB_OTG_DIEPEACHMSK1_BIM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_BIM_Pos) /*!< 0x00000200 */ +#define USB_OTG_DIEPEACHMSK1_BIM USB_OTG_DIEPEACHMSK1_BIM_Msk /*!< BNA interrupt mask */ +#define USB_OTG_DIEPEACHMSK1_NAKM_Pos (13U) +#define USB_OTG_DIEPEACHMSK1_NAKM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_NAKM_Pos) /*!< 0x00002000 */ +#define USB_OTG_DIEPEACHMSK1_NAKM USB_OTG_DIEPEACHMSK1_NAKM_Msk /*!< NAK interrupt mask */ + +/******************** Bit definition for USB_OTG_HPRT register ********************/ +#define USB_OTG_HPRT_PCSTS_Pos (0U) +#define USB_OTG_HPRT_PCSTS_Msk (0x1UL << USB_OTG_HPRT_PCSTS_Pos) /*!< 0x00000001 */ +#define USB_OTG_HPRT_PCSTS USB_OTG_HPRT_PCSTS_Msk /*!< Port connect status */ +#define USB_OTG_HPRT_PCDET_Pos (1U) +#define USB_OTG_HPRT_PCDET_Msk (0x1UL << USB_OTG_HPRT_PCDET_Pos) /*!< 0x00000002 */ +#define USB_OTG_HPRT_PCDET USB_OTG_HPRT_PCDET_Msk /*!< Port connect detected */ +#define USB_OTG_HPRT_PENA_Pos (2U) +#define USB_OTG_HPRT_PENA_Msk (0x1UL << USB_OTG_HPRT_PENA_Pos) /*!< 0x00000004 */ +#define USB_OTG_HPRT_PENA USB_OTG_HPRT_PENA_Msk /*!< Port enable */ +#define USB_OTG_HPRT_PENCHNG_Pos (3U) +#define USB_OTG_HPRT_PENCHNG_Msk (0x1UL << USB_OTG_HPRT_PENCHNG_Pos) /*!< 0x00000008 */ +#define USB_OTG_HPRT_PENCHNG USB_OTG_HPRT_PENCHNG_Msk /*!< Port enable/disable change */ +#define USB_OTG_HPRT_POCA_Pos (4U) +#define USB_OTG_HPRT_POCA_Msk (0x1UL << USB_OTG_HPRT_POCA_Pos) /*!< 0x00000010 */ +#define USB_OTG_HPRT_POCA USB_OTG_HPRT_POCA_Msk /*!< Port overcurrent active */ +#define USB_OTG_HPRT_POCCHNG_Pos (5U) +#define USB_OTG_HPRT_POCCHNG_Msk (0x1UL << USB_OTG_HPRT_POCCHNG_Pos) /*!< 0x00000020 */ +#define USB_OTG_HPRT_POCCHNG USB_OTG_HPRT_POCCHNG_Msk /*!< Port overcurrent change */ +#define USB_OTG_HPRT_PRES_Pos (6U) +#define USB_OTG_HPRT_PRES_Msk (0x1UL << USB_OTG_HPRT_PRES_Pos) /*!< 0x00000040 */ +#define USB_OTG_HPRT_PRES USB_OTG_HPRT_PRES_Msk /*!< Port resume */ +#define USB_OTG_HPRT_PSUSP_Pos (7U) +#define USB_OTG_HPRT_PSUSP_Msk (0x1UL << USB_OTG_HPRT_PSUSP_Pos) /*!< 0x00000080 */ +#define USB_OTG_HPRT_PSUSP USB_OTG_HPRT_PSUSP_Msk /*!< Port suspend */ +#define USB_OTG_HPRT_PRST_Pos (8U) +#define USB_OTG_HPRT_PRST_Msk (0x1UL << USB_OTG_HPRT_PRST_Pos) /*!< 0x00000100 */ +#define USB_OTG_HPRT_PRST USB_OTG_HPRT_PRST_Msk /*!< Port reset */ + +#define USB_OTG_HPRT_PLSTS_Pos (10U) +#define USB_OTG_HPRT_PLSTS_Msk (0x3UL << USB_OTG_HPRT_PLSTS_Pos) /*!< 0x00000C00 */ +#define USB_OTG_HPRT_PLSTS USB_OTG_HPRT_PLSTS_Msk /*!< Port line status */ +#define USB_OTG_HPRT_PLSTS_0 (0x1UL << USB_OTG_HPRT_PLSTS_Pos) /*!< 0x00000400 */ +#define USB_OTG_HPRT_PLSTS_1 (0x2UL << USB_OTG_HPRT_PLSTS_Pos) /*!< 0x00000800 */ +#define USB_OTG_HPRT_PPWR_Pos (12U) +#define USB_OTG_HPRT_PPWR_Msk (0x1UL << USB_OTG_HPRT_PPWR_Pos) /*!< 0x00001000 */ +#define USB_OTG_HPRT_PPWR USB_OTG_HPRT_PPWR_Msk /*!< Port power */ + +#define USB_OTG_HPRT_PTCTL_Pos (13U) +#define USB_OTG_HPRT_PTCTL_Msk (0xFUL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x0001E000 */ +#define USB_OTG_HPRT_PTCTL USB_OTG_HPRT_PTCTL_Msk /*!< Port test control */ +#define USB_OTG_HPRT_PTCTL_0 (0x1UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00002000 */ +#define USB_OTG_HPRT_PTCTL_1 (0x2UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00004000 */ +#define USB_OTG_HPRT_PTCTL_2 (0x4UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00008000 */ +#define USB_OTG_HPRT_PTCTL_3 (0x8UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00010000 */ + +#define USB_OTG_HPRT_PSPD_Pos (17U) +#define USB_OTG_HPRT_PSPD_Msk (0x3UL << USB_OTG_HPRT_PSPD_Pos) /*!< 0x00060000 */ +#define USB_OTG_HPRT_PSPD USB_OTG_HPRT_PSPD_Msk /*!< Port speed */ +#define USB_OTG_HPRT_PSPD_0 (0x1UL << USB_OTG_HPRT_PSPD_Pos) /*!< 0x00020000 */ +#define USB_OTG_HPRT_PSPD_1 (0x2UL << USB_OTG_HPRT_PSPD_Pos) /*!< 0x00040000 */ + +/******************** Bit definition for USB_OTG_DOEPEACHMSK1 register ********************/ +#define USB_OTG_DOEPEACHMSK1_XFRCM_Pos (0U) +#define USB_OTG_DOEPEACHMSK1_XFRCM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_XFRCM_Pos) /*!< 0x00000001 */ +#define USB_OTG_DOEPEACHMSK1_XFRCM USB_OTG_DOEPEACHMSK1_XFRCM_Msk /*!< Transfer completed interrupt mask */ +#define USB_OTG_DOEPEACHMSK1_EPDM_Pos (1U) +#define USB_OTG_DOEPEACHMSK1_EPDM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_EPDM_Pos) /*!< 0x00000002 */ +#define USB_OTG_DOEPEACHMSK1_EPDM USB_OTG_DOEPEACHMSK1_EPDM_Msk /*!< Endpoint disabled interrupt mask */ +#define USB_OTG_DOEPEACHMSK1_TOM_Pos (3U) +#define USB_OTG_DOEPEACHMSK1_TOM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_TOM_Pos) /*!< 0x00000008 */ +#define USB_OTG_DOEPEACHMSK1_TOM USB_OTG_DOEPEACHMSK1_TOM_Msk /*!< Timeout condition mask */ +#define USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Pos (4U) +#define USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Pos) /*!< 0x00000010 */ +#define USB_OTG_DOEPEACHMSK1_ITTXFEMSK USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Msk /*!< IN token received when TxFIFO empty mask */ +#define USB_OTG_DOEPEACHMSK1_INEPNMM_Pos (5U) +#define USB_OTG_DOEPEACHMSK1_INEPNMM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_INEPNMM_Pos) /*!< 0x00000020 */ +#define USB_OTG_DOEPEACHMSK1_INEPNMM USB_OTG_DOEPEACHMSK1_INEPNMM_Msk /*!< IN token received with EP mismatch mask */ +#define USB_OTG_DOEPEACHMSK1_INEPNEM_Pos (6U) +#define USB_OTG_DOEPEACHMSK1_INEPNEM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_INEPNEM_Pos) /*!< 0x00000040 */ +#define USB_OTG_DOEPEACHMSK1_INEPNEM USB_OTG_DOEPEACHMSK1_INEPNEM_Msk /*!< IN endpoint NAK effective mask */ +#define USB_OTG_DOEPEACHMSK1_TXFURM_Pos (8U) +#define USB_OTG_DOEPEACHMSK1_TXFURM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_TXFURM_Pos) /*!< 0x00000100 */ +#define USB_OTG_DOEPEACHMSK1_TXFURM USB_OTG_DOEPEACHMSK1_TXFURM_Msk /*!< OUT packet error mask */ +#define USB_OTG_DOEPEACHMSK1_BIM_Pos (9U) +#define USB_OTG_DOEPEACHMSK1_BIM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_BIM_Pos) /*!< 0x00000200 */ +#define USB_OTG_DOEPEACHMSK1_BIM USB_OTG_DOEPEACHMSK1_BIM_Msk /*!< BNA interrupt mask */ +#define USB_OTG_DOEPEACHMSK1_BERRM_Pos (12U) +#define USB_OTG_DOEPEACHMSK1_BERRM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_BERRM_Pos) /*!< 0x00001000 */ +#define USB_OTG_DOEPEACHMSK1_BERRM USB_OTG_DOEPEACHMSK1_BERRM_Msk /*!< Bubble error interrupt mask */ +#define USB_OTG_DOEPEACHMSK1_NAKM_Pos (13U) +#define USB_OTG_DOEPEACHMSK1_NAKM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_NAKM_Pos) /*!< 0x00002000 */ +#define USB_OTG_DOEPEACHMSK1_NAKM USB_OTG_DOEPEACHMSK1_NAKM_Msk /*!< NAK interrupt mask */ +#define USB_OTG_DOEPEACHMSK1_NYETM_Pos (14U) +#define USB_OTG_DOEPEACHMSK1_NYETM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_NYETM_Pos) /*!< 0x00004000 */ +#define USB_OTG_DOEPEACHMSK1_NYETM USB_OTG_DOEPEACHMSK1_NYETM_Msk /*!< NYET interrupt mask */ + +/******************** Bit definition for USB_OTG_HPTXFSIZ register ********************/ +#define USB_OTG_HPTXFSIZ_PTXSA_Pos (0U) +#define USB_OTG_HPTXFSIZ_PTXSA_Msk (0xFFFFUL << USB_OTG_HPTXFSIZ_PTXSA_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_HPTXFSIZ_PTXSA USB_OTG_HPTXFSIZ_PTXSA_Msk /*!< Host periodic TxFIFO start address */ +#define USB_OTG_HPTXFSIZ_PTXFD_Pos (16U) +#define USB_OTG_HPTXFSIZ_PTXFD_Msk (0xFFFFUL << USB_OTG_HPTXFSIZ_PTXFD_Pos) /*!< 0xFFFF0000 */ +#define USB_OTG_HPTXFSIZ_PTXFD USB_OTG_HPTXFSIZ_PTXFD_Msk /*!< Host periodic TxFIFO depth */ + +/******************** Bit definition for USB_OTG_DIEPCTL register ********************/ +#define USB_OTG_DIEPCTL_MPSIZ_Pos (0U) +#define USB_OTG_DIEPCTL_MPSIZ_Msk (0x7FFUL << USB_OTG_DIEPCTL_MPSIZ_Pos) /*!< 0x000007FF */ +#define USB_OTG_DIEPCTL_MPSIZ USB_OTG_DIEPCTL_MPSIZ_Msk /*!< Maximum packet size */ +#define USB_OTG_DIEPCTL_USBAEP_Pos (15U) +#define USB_OTG_DIEPCTL_USBAEP_Msk (0x1UL << USB_OTG_DIEPCTL_USBAEP_Pos) /*!< 0x00008000 */ +#define USB_OTG_DIEPCTL_USBAEP USB_OTG_DIEPCTL_USBAEP_Msk /*!< USB active endpoint */ +#define USB_OTG_DIEPCTL_EONUM_DPID_Pos (16U) +#define USB_OTG_DIEPCTL_EONUM_DPID_Msk (0x1UL << USB_OTG_DIEPCTL_EONUM_DPID_Pos) /*!< 0x00010000 */ +#define USB_OTG_DIEPCTL_EONUM_DPID USB_OTG_DIEPCTL_EONUM_DPID_Msk /*!< Even/odd frame */ +#define USB_OTG_DIEPCTL_NAKSTS_Pos (17U) +#define USB_OTG_DIEPCTL_NAKSTS_Msk (0x1UL << USB_OTG_DIEPCTL_NAKSTS_Pos) /*!< 0x00020000 */ +#define USB_OTG_DIEPCTL_NAKSTS USB_OTG_DIEPCTL_NAKSTS_Msk /*!< NAK status */ + +#define USB_OTG_DIEPCTL_EPTYP_Pos (18U) +#define USB_OTG_DIEPCTL_EPTYP_Msk (0x3UL << USB_OTG_DIEPCTL_EPTYP_Pos) /*!< 0x000C0000 */ +#define USB_OTG_DIEPCTL_EPTYP USB_OTG_DIEPCTL_EPTYP_Msk /*!< Endpoint type */ +#define USB_OTG_DIEPCTL_EPTYP_0 (0x1UL << USB_OTG_DIEPCTL_EPTYP_Pos) /*!< 0x00040000 */ +#define USB_OTG_DIEPCTL_EPTYP_1 (0x2UL << USB_OTG_DIEPCTL_EPTYP_Pos) /*!< 0x00080000 */ +#define USB_OTG_DIEPCTL_STALL_Pos (21U) +#define USB_OTG_DIEPCTL_STALL_Msk (0x1UL << USB_OTG_DIEPCTL_STALL_Pos) /*!< 0x00200000 */ +#define USB_OTG_DIEPCTL_STALL USB_OTG_DIEPCTL_STALL_Msk /*!< STALL handshake */ + +#define USB_OTG_DIEPCTL_TXFNUM_Pos (22U) +#define USB_OTG_DIEPCTL_TXFNUM_Msk (0xFUL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x03C00000 */ +#define USB_OTG_DIEPCTL_TXFNUM USB_OTG_DIEPCTL_TXFNUM_Msk /*!< TxFIFO number */ +#define USB_OTG_DIEPCTL_TXFNUM_0 (0x1UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x00400000 */ +#define USB_OTG_DIEPCTL_TXFNUM_1 (0x2UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x00800000 */ +#define USB_OTG_DIEPCTL_TXFNUM_2 (0x4UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x01000000 */ +#define USB_OTG_DIEPCTL_TXFNUM_3 (0x8UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x02000000 */ +#define USB_OTG_DIEPCTL_CNAK_Pos (26U) +#define USB_OTG_DIEPCTL_CNAK_Msk (0x1UL << USB_OTG_DIEPCTL_CNAK_Pos) /*!< 0x04000000 */ +#define USB_OTG_DIEPCTL_CNAK USB_OTG_DIEPCTL_CNAK_Msk /*!< Clear NAK */ +#define USB_OTG_DIEPCTL_SNAK_Pos (27U) +#define USB_OTG_DIEPCTL_SNAK_Msk (0x1UL << USB_OTG_DIEPCTL_SNAK_Pos) /*!< 0x08000000 */ +#define USB_OTG_DIEPCTL_SNAK USB_OTG_DIEPCTL_SNAK_Msk /*!< Set NAK */ +#define USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Pos (28U) +#define USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Pos) /*!< 0x10000000 */ +#define USB_OTG_DIEPCTL_SD0PID_SEVNFRM USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Msk /*!< Set DATA0 PID */ +#define USB_OTG_DIEPCTL_SODDFRM_Pos (29U) +#define USB_OTG_DIEPCTL_SODDFRM_Msk (0x1UL << USB_OTG_DIEPCTL_SODDFRM_Pos) /*!< 0x20000000 */ +#define USB_OTG_DIEPCTL_SODDFRM USB_OTG_DIEPCTL_SODDFRM_Msk /*!< Set odd frame */ +#define USB_OTG_DIEPCTL_EPDIS_Pos (30U) +#define USB_OTG_DIEPCTL_EPDIS_Msk (0x1UL << USB_OTG_DIEPCTL_EPDIS_Pos) /*!< 0x40000000 */ +#define USB_OTG_DIEPCTL_EPDIS USB_OTG_DIEPCTL_EPDIS_Msk /*!< Endpoint disable */ +#define USB_OTG_DIEPCTL_EPENA_Pos (31U) +#define USB_OTG_DIEPCTL_EPENA_Msk (0x1UL << USB_OTG_DIEPCTL_EPENA_Pos) /*!< 0x80000000 */ +#define USB_OTG_DIEPCTL_EPENA USB_OTG_DIEPCTL_EPENA_Msk /*!< Endpoint enable */ + +/******************** Bit definition for USB_OTG_HCCHAR register ********************/ +#define USB_OTG_HCCHAR_MPSIZ_Pos (0U) +#define USB_OTG_HCCHAR_MPSIZ_Msk (0x7FFUL << USB_OTG_HCCHAR_MPSIZ_Pos) /*!< 0x000007FF */ +#define USB_OTG_HCCHAR_MPSIZ USB_OTG_HCCHAR_MPSIZ_Msk /*!< Maximum packet size */ + +#define USB_OTG_HCCHAR_EPNUM_Pos (11U) +#define USB_OTG_HCCHAR_EPNUM_Msk (0xFUL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00007800 */ +#define USB_OTG_HCCHAR_EPNUM USB_OTG_HCCHAR_EPNUM_Msk /*!< Endpoint number */ +#define USB_OTG_HCCHAR_EPNUM_0 (0x1UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00000800 */ +#define USB_OTG_HCCHAR_EPNUM_1 (0x2UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00001000 */ +#define USB_OTG_HCCHAR_EPNUM_2 (0x4UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00002000 */ +#define USB_OTG_HCCHAR_EPNUM_3 (0x8UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00004000 */ +#define USB_OTG_HCCHAR_EPDIR_Pos (15U) +#define USB_OTG_HCCHAR_EPDIR_Msk (0x1UL << USB_OTG_HCCHAR_EPDIR_Pos) /*!< 0x00008000 */ +#define USB_OTG_HCCHAR_EPDIR USB_OTG_HCCHAR_EPDIR_Msk /*!< Endpoint direction */ +#define USB_OTG_HCCHAR_LSDEV_Pos (17U) +#define USB_OTG_HCCHAR_LSDEV_Msk (0x1UL << USB_OTG_HCCHAR_LSDEV_Pos) /*!< 0x00020000 */ +#define USB_OTG_HCCHAR_LSDEV USB_OTG_HCCHAR_LSDEV_Msk /*!< Low-speed device */ + +#define USB_OTG_HCCHAR_EPTYP_Pos (18U) +#define USB_OTG_HCCHAR_EPTYP_Msk (0x3UL << USB_OTG_HCCHAR_EPTYP_Pos) /*!< 0x000C0000 */ +#define USB_OTG_HCCHAR_EPTYP USB_OTG_HCCHAR_EPTYP_Msk /*!< Endpoint type */ +#define USB_OTG_HCCHAR_EPTYP_0 (0x1UL << USB_OTG_HCCHAR_EPTYP_Pos) /*!< 0x00040000 */ +#define USB_OTG_HCCHAR_EPTYP_1 (0x2UL << USB_OTG_HCCHAR_EPTYP_Pos) /*!< 0x00080000 */ + +#define USB_OTG_HCCHAR_MC_Pos (20U) +#define USB_OTG_HCCHAR_MC_Msk (0x3UL << USB_OTG_HCCHAR_MC_Pos) /*!< 0x00300000 */ +#define USB_OTG_HCCHAR_MC USB_OTG_HCCHAR_MC_Msk /*!< Multi Count (MC) / Error Count (EC) */ +#define USB_OTG_HCCHAR_MC_0 (0x1UL << USB_OTG_HCCHAR_MC_Pos) /*!< 0x00100000 */ +#define USB_OTG_HCCHAR_MC_1 (0x2UL << USB_OTG_HCCHAR_MC_Pos) /*!< 0x00200000 */ + +#define USB_OTG_HCCHAR_DAD_Pos (22U) +#define USB_OTG_HCCHAR_DAD_Msk (0x7FUL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x1FC00000 */ +#define USB_OTG_HCCHAR_DAD USB_OTG_HCCHAR_DAD_Msk /*!< Device address */ +#define USB_OTG_HCCHAR_DAD_0 (0x01UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x00400000 */ +#define USB_OTG_HCCHAR_DAD_1 (0x02UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x00800000 */ +#define USB_OTG_HCCHAR_DAD_2 (0x04UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x01000000 */ +#define USB_OTG_HCCHAR_DAD_3 (0x08UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x02000000 */ +#define USB_OTG_HCCHAR_DAD_4 (0x10UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x04000000 */ +#define USB_OTG_HCCHAR_DAD_5 (0x20UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x08000000 */ +#define USB_OTG_HCCHAR_DAD_6 (0x40UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x10000000 */ +#define USB_OTG_HCCHAR_ODDFRM_Pos (29U) +#define USB_OTG_HCCHAR_ODDFRM_Msk (0x1UL << USB_OTG_HCCHAR_ODDFRM_Pos) /*!< 0x20000000 */ +#define USB_OTG_HCCHAR_ODDFRM USB_OTG_HCCHAR_ODDFRM_Msk /*!< Odd frame */ +#define USB_OTG_HCCHAR_CHDIS_Pos (30U) +#define USB_OTG_HCCHAR_CHDIS_Msk (0x1UL << USB_OTG_HCCHAR_CHDIS_Pos) /*!< 0x40000000 */ +#define USB_OTG_HCCHAR_CHDIS USB_OTG_HCCHAR_CHDIS_Msk /*!< Channel disable */ +#define USB_OTG_HCCHAR_CHENA_Pos (31U) +#define USB_OTG_HCCHAR_CHENA_Msk (0x1UL << USB_OTG_HCCHAR_CHENA_Pos) /*!< 0x80000000 */ +#define USB_OTG_HCCHAR_CHENA USB_OTG_HCCHAR_CHENA_Msk /*!< Channel enable */ + +/******************** Bit definition for USB_OTG_HCSPLT register ********************/ + +#define USB_OTG_HCSPLT_PRTADDR_Pos (0U) +#define USB_OTG_HCSPLT_PRTADDR_Msk (0x7FUL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x0000007F */ +#define USB_OTG_HCSPLT_PRTADDR USB_OTG_HCSPLT_PRTADDR_Msk /*!< Port address */ +#define USB_OTG_HCSPLT_PRTADDR_0 (0x01UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000001 */ +#define USB_OTG_HCSPLT_PRTADDR_1 (0x02UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000002 */ +#define USB_OTG_HCSPLT_PRTADDR_2 (0x04UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000004 */ +#define USB_OTG_HCSPLT_PRTADDR_3 (0x08UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000008 */ +#define USB_OTG_HCSPLT_PRTADDR_4 (0x10UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000010 */ +#define USB_OTG_HCSPLT_PRTADDR_5 (0x20UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000020 */ +#define USB_OTG_HCSPLT_PRTADDR_6 (0x40UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000040 */ + +#define USB_OTG_HCSPLT_HUBADDR_Pos (7U) +#define USB_OTG_HCSPLT_HUBADDR_Msk (0x7FUL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00003F80 */ +#define USB_OTG_HCSPLT_HUBADDR USB_OTG_HCSPLT_HUBADDR_Msk /*!< Hub address */ +#define USB_OTG_HCSPLT_HUBADDR_0 (0x01UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000080 */ +#define USB_OTG_HCSPLT_HUBADDR_1 (0x02UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000100 */ +#define USB_OTG_HCSPLT_HUBADDR_2 (0x04UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000200 */ +#define USB_OTG_HCSPLT_HUBADDR_3 (0x08UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000400 */ +#define USB_OTG_HCSPLT_HUBADDR_4 (0x10UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000800 */ +#define USB_OTG_HCSPLT_HUBADDR_5 (0x20UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00001000 */ +#define USB_OTG_HCSPLT_HUBADDR_6 (0x40UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00002000 */ + +#define USB_OTG_HCSPLT_XACTPOS_Pos (14U) +#define USB_OTG_HCSPLT_XACTPOS_Msk (0x3UL << USB_OTG_HCSPLT_XACTPOS_Pos) /*!< 0x0000C000 */ +#define USB_OTG_HCSPLT_XACTPOS USB_OTG_HCSPLT_XACTPOS_Msk /*!< XACTPOS */ +#define USB_OTG_HCSPLT_XACTPOS_0 (0x1UL << USB_OTG_HCSPLT_XACTPOS_Pos) /*!< 0x00004000 */ +#define USB_OTG_HCSPLT_XACTPOS_1 (0x2UL << USB_OTG_HCSPLT_XACTPOS_Pos) /*!< 0x00008000 */ +#define USB_OTG_HCSPLT_COMPLSPLT_Pos (16U) +#define USB_OTG_HCSPLT_COMPLSPLT_Msk (0x1UL << USB_OTG_HCSPLT_COMPLSPLT_Pos) /*!< 0x00010000 */ +#define USB_OTG_HCSPLT_COMPLSPLT USB_OTG_HCSPLT_COMPLSPLT_Msk /*!< Do complete split */ +#define USB_OTG_HCSPLT_SPLITEN_Pos (31U) +#define USB_OTG_HCSPLT_SPLITEN_Msk (0x1UL << USB_OTG_HCSPLT_SPLITEN_Pos) /*!< 0x80000000 */ +#define USB_OTG_HCSPLT_SPLITEN USB_OTG_HCSPLT_SPLITEN_Msk /*!< Split enable */ + +/******************** Bit definition for USB_OTG_HCINT register ********************/ +#define USB_OTG_HCINT_XFRC_Pos (0U) +#define USB_OTG_HCINT_XFRC_Msk (0x1UL << USB_OTG_HCINT_XFRC_Pos) /*!< 0x00000001 */ +#define USB_OTG_HCINT_XFRC USB_OTG_HCINT_XFRC_Msk /*!< Transfer completed */ +#define USB_OTG_HCINT_CHH_Pos (1U) +#define USB_OTG_HCINT_CHH_Msk (0x1UL << USB_OTG_HCINT_CHH_Pos) /*!< 0x00000002 */ +#define USB_OTG_HCINT_CHH USB_OTG_HCINT_CHH_Msk /*!< Channel halted */ +#define USB_OTG_HCINT_AHBERR_Pos (2U) +#define USB_OTG_HCINT_AHBERR_Msk (0x1UL << USB_OTG_HCINT_AHBERR_Pos) /*!< 0x00000004 */ +#define USB_OTG_HCINT_AHBERR USB_OTG_HCINT_AHBERR_Msk /*!< AHB error */ +#define USB_OTG_HCINT_STALL_Pos (3U) +#define USB_OTG_HCINT_STALL_Msk (0x1UL << USB_OTG_HCINT_STALL_Pos) /*!< 0x00000008 */ +#define USB_OTG_HCINT_STALL USB_OTG_HCINT_STALL_Msk /*!< STALL response received interrupt */ +#define USB_OTG_HCINT_NAK_Pos (4U) +#define USB_OTG_HCINT_NAK_Msk (0x1UL << USB_OTG_HCINT_NAK_Pos) /*!< 0x00000010 */ +#define USB_OTG_HCINT_NAK USB_OTG_HCINT_NAK_Msk /*!< NAK response received interrupt */ +#define USB_OTG_HCINT_ACK_Pos (5U) +#define USB_OTG_HCINT_ACK_Msk (0x1UL << USB_OTG_HCINT_ACK_Pos) /*!< 0x00000020 */ +#define USB_OTG_HCINT_ACK USB_OTG_HCINT_ACK_Msk /*!< ACK response received/transmitted interrupt */ +#define USB_OTG_HCINT_NYET_Pos (6U) +#define USB_OTG_HCINT_NYET_Msk (0x1UL << USB_OTG_HCINT_NYET_Pos) /*!< 0x00000040 */ +#define USB_OTG_HCINT_NYET USB_OTG_HCINT_NYET_Msk /*!< Response received interrupt */ +#define USB_OTG_HCINT_TXERR_Pos (7U) +#define USB_OTG_HCINT_TXERR_Msk (0x1UL << USB_OTG_HCINT_TXERR_Pos) /*!< 0x00000080 */ +#define USB_OTG_HCINT_TXERR USB_OTG_HCINT_TXERR_Msk /*!< Transaction error */ +#define USB_OTG_HCINT_BBERR_Pos (8U) +#define USB_OTG_HCINT_BBERR_Msk (0x1UL << USB_OTG_HCINT_BBERR_Pos) /*!< 0x00000100 */ +#define USB_OTG_HCINT_BBERR USB_OTG_HCINT_BBERR_Msk /*!< Babble error */ +#define USB_OTG_HCINT_FRMOR_Pos (9U) +#define USB_OTG_HCINT_FRMOR_Msk (0x1UL << USB_OTG_HCINT_FRMOR_Pos) /*!< 0x00000200 */ +#define USB_OTG_HCINT_FRMOR USB_OTG_HCINT_FRMOR_Msk /*!< Frame overrun */ +#define USB_OTG_HCINT_DTERR_Pos (10U) +#define USB_OTG_HCINT_DTERR_Msk (0x1UL << USB_OTG_HCINT_DTERR_Pos) /*!< 0x00000400 */ +#define USB_OTG_HCINT_DTERR USB_OTG_HCINT_DTERR_Msk /*!< Data toggle error */ + +/******************** Bit definition for USB_OTG_DIEPINT register ********************/ +#define USB_OTG_DIEPINT_XFRC_Pos (0U) +#define USB_OTG_DIEPINT_XFRC_Msk (0x1UL << USB_OTG_DIEPINT_XFRC_Pos) /*!< 0x00000001 */ +#define USB_OTG_DIEPINT_XFRC USB_OTG_DIEPINT_XFRC_Msk /*!< Transfer completed interrupt */ +#define USB_OTG_DIEPINT_EPDISD_Pos (1U) +#define USB_OTG_DIEPINT_EPDISD_Msk (0x1UL << USB_OTG_DIEPINT_EPDISD_Pos) /*!< 0x00000002 */ +#define USB_OTG_DIEPINT_EPDISD USB_OTG_DIEPINT_EPDISD_Msk /*!< Endpoint disabled interrupt */ +#define USB_OTG_DIEPINT_AHBERR_Pos (2U) +#define USB_OTG_DIEPINT_AHBERR_Msk (0x1UL << USB_OTG_DIEPINT_AHBERR_Pos) /*!< 0x00000004 */ +#define USB_OTG_DIEPINT_AHBERR USB_OTG_DIEPINT_AHBERR_Msk /*!< AHB Error (AHBErr) during an IN transaction */ +#define USB_OTG_DIEPINT_TOC_Pos (3U) +#define USB_OTG_DIEPINT_TOC_Msk (0x1UL << USB_OTG_DIEPINT_TOC_Pos) /*!< 0x00000008 */ +#define USB_OTG_DIEPINT_TOC USB_OTG_DIEPINT_TOC_Msk /*!< Timeout condition */ +#define USB_OTG_DIEPINT_ITTXFE_Pos (4U) +#define USB_OTG_DIEPINT_ITTXFE_Msk (0x1UL << USB_OTG_DIEPINT_ITTXFE_Pos) /*!< 0x00000010 */ +#define USB_OTG_DIEPINT_ITTXFE USB_OTG_DIEPINT_ITTXFE_Msk /*!< IN token received when TxFIFO is empty */ +#define USB_OTG_DIEPINT_INEPNM_Pos (5U) +#define USB_OTG_DIEPINT_INEPNM_Msk (0x1UL << USB_OTG_DIEPINT_INEPNM_Pos) /*!< 0x00000004 */ +#define USB_OTG_DIEPINT_INEPNM USB_OTG_DIEPINT_INEPNM_Msk /*!< IN token received with EP mismatch */ +#define USB_OTG_DIEPINT_INEPNE_Pos (6U) +#define USB_OTG_DIEPINT_INEPNE_Msk (0x1UL << USB_OTG_DIEPINT_INEPNE_Pos) /*!< 0x00000040 */ +#define USB_OTG_DIEPINT_INEPNE USB_OTG_DIEPINT_INEPNE_Msk /*!< IN endpoint NAK effective */ +#define USB_OTG_DIEPINT_TXFE_Pos (7U) +#define USB_OTG_DIEPINT_TXFE_Msk (0x1UL << USB_OTG_DIEPINT_TXFE_Pos) /*!< 0x00000080 */ +#define USB_OTG_DIEPINT_TXFE USB_OTG_DIEPINT_TXFE_Msk /*!< Transmit FIFO empty */ +#define USB_OTG_DIEPINT_TXFIFOUDRN_Pos (8U) +#define USB_OTG_DIEPINT_TXFIFOUDRN_Msk (0x1UL << USB_OTG_DIEPINT_TXFIFOUDRN_Pos) /*!< 0x00000100 */ +#define USB_OTG_DIEPINT_TXFIFOUDRN USB_OTG_DIEPINT_TXFIFOUDRN_Msk /*!< Transmit Fifo Underrun */ +#define USB_OTG_DIEPINT_BNA_Pos (9U) +#define USB_OTG_DIEPINT_BNA_Msk (0x1UL << USB_OTG_DIEPINT_BNA_Pos) /*!< 0x00000200 */ +#define USB_OTG_DIEPINT_BNA USB_OTG_DIEPINT_BNA_Msk /*!< Buffer not available interrupt */ +#define USB_OTG_DIEPINT_PKTDRPSTS_Pos (11U) +#define USB_OTG_DIEPINT_PKTDRPSTS_Msk (0x1UL << USB_OTG_DIEPINT_PKTDRPSTS_Pos) /*!< 0x00000800 */ +#define USB_OTG_DIEPINT_PKTDRPSTS USB_OTG_DIEPINT_PKTDRPSTS_Msk /*!< Packet dropped status */ +#define USB_OTG_DIEPINT_BERR_Pos (12U) +#define USB_OTG_DIEPINT_BERR_Msk (0x1UL << USB_OTG_DIEPINT_BERR_Pos) /*!< 0x00001000 */ +#define USB_OTG_DIEPINT_BERR USB_OTG_DIEPINT_BERR_Msk /*!< Babble error interrupt */ +#define USB_OTG_DIEPINT_NAK_Pos (13U) +#define USB_OTG_DIEPINT_NAK_Msk (0x1UL << USB_OTG_DIEPINT_NAK_Pos) /*!< 0x00002000 */ +#define USB_OTG_DIEPINT_NAK USB_OTG_DIEPINT_NAK_Msk /*!< NAK interrupt */ + +/******************** Bit definition for USB_OTG_HCINTMSK register ********************/ +#define USB_OTG_HCINTMSK_XFRCM_Pos (0U) +#define USB_OTG_HCINTMSK_XFRCM_Msk (0x1UL << USB_OTG_HCINTMSK_XFRCM_Pos) /*!< 0x00000001 */ +#define USB_OTG_HCINTMSK_XFRCM USB_OTG_HCINTMSK_XFRCM_Msk /*!< Transfer completed mask */ +#define USB_OTG_HCINTMSK_CHHM_Pos (1U) +#define USB_OTG_HCINTMSK_CHHM_Msk (0x1UL << USB_OTG_HCINTMSK_CHHM_Pos) /*!< 0x00000002 */ +#define USB_OTG_HCINTMSK_CHHM USB_OTG_HCINTMSK_CHHM_Msk /*!< Channel halted mask */ +#define USB_OTG_HCINTMSK_AHBERR_Pos (2U) +#define USB_OTG_HCINTMSK_AHBERR_Msk (0x1UL << USB_OTG_HCINTMSK_AHBERR_Pos) /*!< 0x00000004 */ +#define USB_OTG_HCINTMSK_AHBERR USB_OTG_HCINTMSK_AHBERR_Msk /*!< AHB error */ +#define USB_OTG_HCINTMSK_STALLM_Pos (3U) +#define USB_OTG_HCINTMSK_STALLM_Msk (0x1UL << USB_OTG_HCINTMSK_STALLM_Pos) /*!< 0x00000008 */ +#define USB_OTG_HCINTMSK_STALLM USB_OTG_HCINTMSK_STALLM_Msk /*!< STALL response received interrupt mask */ +#define USB_OTG_HCINTMSK_NAKM_Pos (4U) +#define USB_OTG_HCINTMSK_NAKM_Msk (0x1UL << USB_OTG_HCINTMSK_NAKM_Pos) /*!< 0x00000010 */ +#define USB_OTG_HCINTMSK_NAKM USB_OTG_HCINTMSK_NAKM_Msk /*!< NAK response received interrupt mask */ +#define USB_OTG_HCINTMSK_ACKM_Pos (5U) +#define USB_OTG_HCINTMSK_ACKM_Msk (0x1UL << USB_OTG_HCINTMSK_ACKM_Pos) /*!< 0x00000020 */ +#define USB_OTG_HCINTMSK_ACKM USB_OTG_HCINTMSK_ACKM_Msk /*!< ACK response received/transmitted interrupt mask */ +#define USB_OTG_HCINTMSK_NYET_Pos (6U) +#define USB_OTG_HCINTMSK_NYET_Msk (0x1UL << USB_OTG_HCINTMSK_NYET_Pos) /*!< 0x00000040 */ +#define USB_OTG_HCINTMSK_NYET USB_OTG_HCINTMSK_NYET_Msk /*!< response received interrupt mask */ +#define USB_OTG_HCINTMSK_TXERRM_Pos (7U) +#define USB_OTG_HCINTMSK_TXERRM_Msk (0x1UL << USB_OTG_HCINTMSK_TXERRM_Pos) /*!< 0x00000080 */ +#define USB_OTG_HCINTMSK_TXERRM USB_OTG_HCINTMSK_TXERRM_Msk /*!< Transaction error mask */ +#define USB_OTG_HCINTMSK_BBERRM_Pos (8U) +#define USB_OTG_HCINTMSK_BBERRM_Msk (0x1UL << USB_OTG_HCINTMSK_BBERRM_Pos) /*!< 0x00000100 */ +#define USB_OTG_HCINTMSK_BBERRM USB_OTG_HCINTMSK_BBERRM_Msk /*!< Babble error mask */ +#define USB_OTG_HCINTMSK_FRMORM_Pos (9U) +#define USB_OTG_HCINTMSK_FRMORM_Msk (0x1UL << USB_OTG_HCINTMSK_FRMORM_Pos) /*!< 0x00000200 */ +#define USB_OTG_HCINTMSK_FRMORM USB_OTG_HCINTMSK_FRMORM_Msk /*!< Frame overrun mask */ +#define USB_OTG_HCINTMSK_DTERRM_Pos (10U) +#define USB_OTG_HCINTMSK_DTERRM_Msk (0x1UL << USB_OTG_HCINTMSK_DTERRM_Pos) /*!< 0x00000400 */ +#define USB_OTG_HCINTMSK_DTERRM USB_OTG_HCINTMSK_DTERRM_Msk /*!< Data toggle error mask */ + +/******************** Bit definition for USB_OTG_DIEPTSIZ register ********************/ + +#define USB_OTG_DIEPTSIZ_XFRSIZ_Pos (0U) +#define USB_OTG_DIEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << USB_OTG_DIEPTSIZ_XFRSIZ_Pos) /*!< 0x0007FFFF */ +#define USB_OTG_DIEPTSIZ_XFRSIZ USB_OTG_DIEPTSIZ_XFRSIZ_Msk /*!< Transfer size */ +#define USB_OTG_DIEPTSIZ_PKTCNT_Pos (19U) +#define USB_OTG_DIEPTSIZ_PKTCNT_Msk (0x3FFUL << USB_OTG_DIEPTSIZ_PKTCNT_Pos) /*!< 0x1FF80000 */ +#define USB_OTG_DIEPTSIZ_PKTCNT USB_OTG_DIEPTSIZ_PKTCNT_Msk /*!< Packet count */ +#define USB_OTG_DIEPTSIZ_MULCNT_Pos (29U) +#define USB_OTG_DIEPTSIZ_MULCNT_Msk (0x3UL << USB_OTG_DIEPTSIZ_MULCNT_Pos) /*!< 0x60000000 */ +#define USB_OTG_DIEPTSIZ_MULCNT USB_OTG_DIEPTSIZ_MULCNT_Msk /*!< Packet count */ +/******************** Bit definition for USB_OTG_HCTSIZ register ********************/ +#define USB_OTG_HCTSIZ_XFRSIZ_Pos (0U) +#define USB_OTG_HCTSIZ_XFRSIZ_Msk (0x7FFFFUL << USB_OTG_HCTSIZ_XFRSIZ_Pos) /*!< 0x0007FFFF */ +#define USB_OTG_HCTSIZ_XFRSIZ USB_OTG_HCTSIZ_XFRSIZ_Msk /*!< Transfer size */ +#define USB_OTG_HCTSIZ_PKTCNT_Pos (19U) +#define USB_OTG_HCTSIZ_PKTCNT_Msk (0x3FFUL << USB_OTG_HCTSIZ_PKTCNT_Pos) /*!< 0x1FF80000 */ +#define USB_OTG_HCTSIZ_PKTCNT USB_OTG_HCTSIZ_PKTCNT_Msk /*!< Packet count */ +#define USB_OTG_HCTSIZ_DOPING_Pos (31U) +#define USB_OTG_HCTSIZ_DOPING_Msk (0x1UL << USB_OTG_HCTSIZ_DOPING_Pos) /*!< 0x80000000 */ +#define USB_OTG_HCTSIZ_DOPING USB_OTG_HCTSIZ_DOPING_Msk /*!< Do PING */ +#define USB_OTG_HCTSIZ_DPID_Pos (29U) +#define USB_OTG_HCTSIZ_DPID_Msk (0x3UL << USB_OTG_HCTSIZ_DPID_Pos) /*!< 0x60000000 */ +#define USB_OTG_HCTSIZ_DPID USB_OTG_HCTSIZ_DPID_Msk /*!< Data PID */ +#define USB_OTG_HCTSIZ_DPID_0 (0x1UL << USB_OTG_HCTSIZ_DPID_Pos) /*!< 0x20000000 */ +#define USB_OTG_HCTSIZ_DPID_1 (0x2UL << USB_OTG_HCTSIZ_DPID_Pos) /*!< 0x40000000 */ + +/******************** Bit definition for USB_OTG_DIEPDMA register ********************/ +#define USB_OTG_DIEPDMA_DMAADDR_Pos (0U) +#define USB_OTG_DIEPDMA_DMAADDR_Msk (0xFFFFFFFFUL << USB_OTG_DIEPDMA_DMAADDR_Pos) /*!< 0xFFFFFFFF */ +#define USB_OTG_DIEPDMA_DMAADDR USB_OTG_DIEPDMA_DMAADDR_Msk /*!< DMA address */ + +/******************** Bit definition for USB_OTG_HCDMA register ********************/ +#define USB_OTG_HCDMA_DMAADDR_Pos (0U) +#define USB_OTG_HCDMA_DMAADDR_Msk (0xFFFFFFFFUL << USB_OTG_HCDMA_DMAADDR_Pos) /*!< 0xFFFFFFFF */ +#define USB_OTG_HCDMA_DMAADDR USB_OTG_HCDMA_DMAADDR_Msk /*!< DMA address */ + +/******************** Bit definition for USB_OTG_DTXFSTS register ********************/ +#define USB_OTG_DTXFSTS_INEPTFSAV_Pos (0U) +#define USB_OTG_DTXFSTS_INEPTFSAV_Msk (0xFFFFUL << USB_OTG_DTXFSTS_INEPTFSAV_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_DTXFSTS_INEPTFSAV USB_OTG_DTXFSTS_INEPTFSAV_Msk /*!< IN endpoint TxFIFO space available */ + +/******************** Bit definition for USB_OTG_DIEPTXF register ********************/ +#define USB_OTG_DIEPTXF_INEPTXSA_Pos (0U) +#define USB_OTG_DIEPTXF_INEPTXSA_Msk (0xFFFFUL << USB_OTG_DIEPTXF_INEPTXSA_Pos) /*!< 0x0000FFFF */ +#define USB_OTG_DIEPTXF_INEPTXSA USB_OTG_DIEPTXF_INEPTXSA_Msk /*!< IN endpoint FIFOx transmit RAM start address */ +#define USB_OTG_DIEPTXF_INEPTXFD_Pos (16U) +#define USB_OTG_DIEPTXF_INEPTXFD_Msk (0xFFFFUL << USB_OTG_DIEPTXF_INEPTXFD_Pos) /*!< 0xFFFF0000 */ +#define USB_OTG_DIEPTXF_INEPTXFD USB_OTG_DIEPTXF_INEPTXFD_Msk /*!< IN endpoint TxFIFO depth */ + +/******************** Bit definition for USB_OTG_DOEPCTL register ********************/ + +#define USB_OTG_DOEPCTL_MPSIZ_Pos (0U) +#define USB_OTG_DOEPCTL_MPSIZ_Msk (0x7FFUL << USB_OTG_DOEPCTL_MPSIZ_Pos) /*!< 0x000007FF */ +#define USB_OTG_DOEPCTL_MPSIZ USB_OTG_DOEPCTL_MPSIZ_Msk /*!< Maximum packet size */ /*! Date: Tue, 3 Aug 2021 20:21:06 +0200 Subject: Add stm32 license header --- src/portable/st/synopsys/synopsys_common.h | 55 +++++++++++++++++++----------- 1 file changed, 36 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/synopsys_common.h b/src/portable/st/synopsys/synopsys_common.h index 4e71e8258..6f0602fe9 100644 --- a/src/portable/st/synopsys/synopsys_common.h +++ b/src/portable/st/synopsys/synopsys_common.h @@ -1,29 +1,45 @@ +/** + ****************************************************************************** + * @file synopsys_common.h + * @author MCD Application Team + * @brief CMSIS Cortex-M3 Device USB OTG peripheral Header File. + * This file contains the USB OTG peripheral register's definitions, bits + * definitions and memory mapping for STM32F1xx devices. + * + * This file contains: + * - Data structures and the address mapping for the USB OTG peripheral + * - The Peripheral's registers declarations and bits definition + * - Macros to access the peripheral's registers hardware + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + #include "stdint.h" #pragma once -/* IO definitions (access restrictions to peripheral registers) */ -/** - \defgroup CMSIS_glob_defs CMSIS Global Defines - - IO Type Qualifiers are used - \li to specify the access to peripheral variables. - \li for automatic generation of peripheral register debug information. -*/ #ifdef __cplusplus - #define __I volatile /*!< Defines 'read only' permissions */ + #define __I volatile #else - #define __I volatile const /*!< Defines 'read only' permissions */ + #define __I volatile const #endif -#define __O volatile /*!< Defines 'write only' permissions */ -#define __IO volatile /*!< Defines 'read / write' permissions */ - -/* following defines should be used for structure members */ -#define __IM volatile const /*! Defines 'read only' structure member permissions */ -#define __OM volatile /*! Defines 'write only' structure member permissions */ -#define __IOM volatile /*! Defines 'read / write' structure member permissions */ +#define __O volatile +#define __IO volatile +#define __IM volatile const +#define __OM volatile +#define __IOM volatile -/*@} end of group Cortex_M3 */ /** * @brief __USB_OTG_Core_register */ @@ -155,7 +171,6 @@ typedef struct #define USB_OTG_FIFO_BASE 0x00001000UL #define USB_OTG_FIFO_SIZE 0x00001000UL - /******************************************************************************/ /* */ /* USB_OTG */ @@ -1446,3 +1461,5 @@ typedef struct #define USB_OTG_FRMNUM_1 (0x2UL << USB_OTG_FRMNUM_Pos) /*!< 0x00400000 */ #define USB_OTG_FRMNUM_2 (0x4UL << USB_OTG_FRMNUM_Pos) /*!< 0x00800000 */ #define USB_OTG_FRMNUM_3 (0x8UL << USB_OTG_FRMNUM_Pos) /*!< 0x01000000 */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ -- cgit v1.3.1 From a698dda67ef9980a0b8eaf0ab9d3edc9adf1c2f4 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Thu, 5 Aug 2021 09:56:24 +0200 Subject: Minor fix. --- src/portable/microchip/samx7x/dcd_samx7x.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 419265723..0d9e184f6 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -77,9 +77,9 @@ static tusb_speed_t get_speed(void); static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); // DMA descriptors shouldn't be placed in ITCM ! -CFG_TUSB_MEM_SECTION dma_desc_t dma_desc[6]; +CFG_TUSB_MEM_SECTION static dma_desc_t dma_desc[6]; -xfer_ctl_t xfer_status[EP_MAX]; +static xfer_ctl_t xfer_status[EP_MAX]; static const tusb_desc_endpoint_t ep0_desc = { @@ -148,7 +148,7 @@ void dcd_connect(uint8_t rhport) dcd_int_disable(rhport); // Enable the USB controller in device mode USB_REG->CTRL = CTRL_UIMOD | CTRL_USBE; - while (SR_CLKUSABLE != (USB_REG->SR & SR_CLKUSABLE)); + while (!(USB_REG->SR & SR_CLKUSABLE)); #if TUD_OPT_HIGH_SPEED USB_REG->DEVCTRL &= ~DEVCTRL_SPDCONF; #else @@ -180,7 +180,7 @@ void dcd_disconnect(uint8_t rhport) USB_REG->DEVEPT &= ~(0x3FF << DEVEPT_EPEN0_Pos); // Unfreeze USB clock USB_REG->CTRL &= ~CTRL_FRZCLK; - while (SR_CLKUSABLE != (USB_REG->SR & SR_CLKUSABLE)); + while (!(USB_REG->SR & SR_CLKUSABLE)); // Clear all the pending interrupts USB_REG->DEVICR = DEVICR_Msk; // Disable all interrupts @@ -193,7 +193,7 @@ void dcd_disconnect(uint8_t rhport) static tusb_speed_t get_speed(void) { - switch ((USB_REG->SR & SR_SPEED) >> SR_SPEED_Pos) { + switch (USB_REG->SR & SR_SPEED) { case SR_SPEED_FULL_SPEED: default: return TUSB_SPEED_FULL; @@ -367,7 +367,7 @@ void dcd_int_handler(uint8_t rhport) { // Unfreeze USB clock USB_REG->CTRL &= ~CTRL_FRZCLK; - while(SR_CLKUSABLE != (USB_REG->SR & SR_CLKUSABLE)); + while(!(USB_REG->SR & SR_CLKUSABLE)); // Reset all endpoints for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) { @@ -386,7 +386,7 @@ void dcd_int_handler(uint8_t rhport) if (int_status & DEVISR_WAKEUP) { USB_REG->CTRL &= ~CTRL_FRZCLK; - while (SR_CLKUSABLE != (USB_REG->SR & SR_CLKUSABLE)); + while (!(USB_REG->SR & SR_CLKUSABLE)); USB_REG->DEVICR = DEVICR_WAKEUPC; USB_REG->DEVIDR = DEVIDR_WAKEUPEC; USB_REG->DEVIER = DEVIER_SUSPES; @@ -398,7 +398,7 @@ void dcd_int_handler(uint8_t rhport) { // Unfreeze USB clock USB_REG->CTRL &= ~CTRL_FRZCLK; - while (SR_CLKUSABLE != (USB_REG->SR & SR_CLKUSABLE)); + while (!(USB_REG->SR & SR_CLKUSABLE)); USB_REG->DEVICR = DEVICR_SUSPC; USB_REG->DEVIDR = DEVIDR_SUSPEC; USB_REG->DEVIER = DEVIER_WAKEUPES; -- cgit v1.3.1 From c6d495d6436c797b4efd029bd16ee8f19ff0a9f0 Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Sat, 7 Aug 2021 08:54:32 +0200 Subject: Remove dependencies to external libraries for the dcd driver The core of tinyusb must be as independent as possible, we previously relied on nuclei-sdk or the GD32VF103 firmware library for the synopsys driver to work with the GD32VF103. Fortunatly we needed very few parts from them so we implement them here. --- src/portable/st/synopsys/dcd_synopsys.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 4b39844a1..7545ef6f7 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -94,16 +94,28 @@ #define EP_FIFO_SIZE_FS 1280 #elif CFG_TUSB_MCU == OPT_MCU_GD32VF103 -#define STM32F1_SYNOPSYS -#include "gd32vf103.h" -#include "nmsis_core.h" -#include "core_feature_eclic.h" #include "synopsys_common.h" + +// These numbers are the same for the whole GD32VF103 family. +#define OTG_FS_IRQn 86 #define EP_MAX_FS 4 #define EP_FIFO_SIZE_FS 1280 -#define OTG_FS_IRQn USBFS_IRQn -#define NVIC_EnableIRQ ECLIC_EnableIRQ -#define NVIC_DisableIRQ ECLIC_DisableIRQ + +// The GD32VF103 is a RISC-V MCU, which implements the ECLIC Core-Local +// Interrupt Controller by Nuclei. It is nearly API compatible to the +// NVIC used by ARM MCUs. +#define ECLIC_INTERRUPT_ENABLE_BASE 0xD2001001UL + +#define NVIC_EnableIRQ __eclic_enable_interrupt +#define NVIC_DisableIRQ __eclic_disable_interrupt + +static inline void __eclic_enable_interrupt (uint32_t irq) { + *(volatile uint8_t*)(ECLIC_INTERRUPT_ENABLE_BASE + (irq * 4)) = 1; +} + +static inline void __eclic_disable_interrupt (uint32_t irq){ + *(volatile uint8_t*)(ECLIC_INTERRUPT_ENABLE_BASE + (irq * 4)) = 0; +} #else #error "Unsupported MCUs" -- cgit v1.3.1 From 768282982039001128cecfe125d88f58ce640713 Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Sat, 7 Aug 2021 09:01:01 +0200 Subject: Add correct endpoint count for GD32VF103 This controller family only supports USB FS with four endpoints --- src/device/dcd_attr.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 18f369332..7772a6d96 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -147,6 +147,10 @@ //#elif TU_CHECK_MCU(MM32F327X) // #define DCD_ATTR_ENDPOINT_MAX not known yet +//------------- GigaDevice -------------// +#elif TU_CHECK_MCU(GD32VF103) + #define DCD_ATTR_ENDPOINT_MAX 4 + #else #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" #define DCD_ATTR_ENDPOINT_MAX 8 -- cgit v1.3.1 From 4cebde65ec59f21f282c67a590c09bf982e99af5 Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Sat, 7 Aug 2021 12:00:13 +0200 Subject: Remove unnecessary define guard The GD32VF103 family only has USB-OTG peripherals. --- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 7545ef6f7..b8f6ceda2 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -34,7 +34,7 @@ #define USE_SOF 0 #if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ - defined (STM32F107xB) || defined (STM32F107xC) || defined (GD32VF103) + defined (STM32F107xB) || defined (STM32F107xC) #define STM32F1_SYNOPSYS #endif -- cgit v1.3.1 From 8b78067cc1142c5915ad5fa1275996e92f91a58d Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Sat, 7 Aug 2021 12:06:54 +0200 Subject: Use linear buffer for GD32VF103 As the peripheral is the same as on the STM32F1 and STM32F4 lines we do the same. --- src/class/audio/audio_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index de0bddcd3..ff4e312a7 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -89,7 +89,8 @@ (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) || \ CFG_TUSB_MCU == OPT_MCU_RX63X || \ CFG_TUSB_MCU == OPT_MCU_RX65X || \ - CFG_TUSB_MCU == OPT_MCU_RX72N + CFG_TUSB_MCU == OPT_MCU_RX72N || \ + CFG_TUSB_MCU == OPT_MCU_GD32VF103 #define USE_LINEAR_BUFFER 0 #else #define USE_LINEAR_BUFFER 1 -- cgit v1.3.1 From ea72d64992e7ec1453b1c449f72354aba2758ce8 Mon Sep 17 00:00:00 2001 From: Robert Manzke Date: Sun, 8 Aug 2021 08:30:52 +0200 Subject: STM32L151 portable driver adaptations --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 21 ++++++++++++++++++++- .../st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h | 4 ++++ 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 74c144107..eeba7204f 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -113,7 +113,8 @@ (CFG_TUSB_MCU == OPT_MCU_STM32F0 ) || \ (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_FSDEV)) || \ (CFG_TUSB_MCU == OPT_MCU_STM32F3 ) || \ - (CFG_TUSB_MCU == OPT_MCU_STM32L0 ) \ + (CFG_TUSB_MCU == OPT_MCU_STM32L0 ) || \ + (CFG_TUSB_MCU == OPT_MCU_STM32L1 ) \ ) // In order to reduce the dependance on HAL, we undefine this. @@ -273,6 +274,20 @@ void dcd_connect(uint8_t rhport) USB->BCDR |= USB_BCDR_DPPU; } +#elif defined(SYSCFG_PMC_USB_PU) // works e.g. on STM32L151 +// Disable internal D+ PU +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + SYSCFG->PMC &= ~(SYSCFG_PMC_USB_PU); +} + +// Enable internal D+ PU +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + SYSCFG->PMC |= SYSCFG_PMC_USB_PU; +} #endif // Enable device interrupt @@ -284,6 +299,8 @@ void dcd_int_enable (uint8_t rhport) __ISB(); #if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 NVIC_EnableIRQ(USB_IRQn); +#elif CFG_TUSB_MCU == OPT_MCU_STM32L1 + NVIC_EnableIRQ(USB_LP_IRQn); #elif CFG_TUSB_MCU == OPT_MCU_STM32F3 // Some STM32F302/F303 devices allow to remap the USB interrupt vectors from // shared USB/CAN IRQs to separate CAN and USB IRQs. @@ -318,6 +335,8 @@ void dcd_int_disable(uint8_t rhport) #if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 NVIC_DisableIRQ(USB_IRQn); +#elif CFG_TUSB_MCU == OPT_MCU_STM32L1 + NVIC_DisableIRQ(USB_LP_IRQn); #elif CFG_TUSB_MCU == OPT_MCU_STM32F3 // Some STM32F302/F303 devices allow to remap the USB interrupt vectors from // shared USB/CAN IRQs to separate CAN and USB IRQs. diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h index d26c700d2..eca8bf575 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h @@ -83,6 +83,10 @@ #include "stm32l0xx.h" #define PMA_LENGTH (1024u) +#elif CFG_TUSB_MCU == OPT_MCU_STM32L1 + #include "stm32l1xx.h" + #define PMA_LENGTH (512u) + #else #error You are using an untested or unimplemented STM32 variant. Please update the driver. // This includes L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4 -- cgit v1.3.1 From 2ea0ef4543ed8a3d127f6354ab3a5ae2a48ec245 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 10 Aug 2021 16:40:43 +0700 Subject: correct newline usage keycode (ENTER 0x28) --- src/class/hid/hid.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index ec14c9c7c..9265a2ede 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -871,10 +871,10 @@ enum {0, 0 }, /* 0x07 */ \ {0, HID_KEY_BACKSPACE }, /* 0x08 Backspace */ \ {0, HID_KEY_TAB }, /* 0x09 Tab */ \ - {0, HID_KEY_RETURN }, /* 0x0A Line Feed */ \ + {0, HID_KEY_ENTER }, /* 0x0A Line Feed */ \ {0, 0 }, /* 0x0B */ \ {0, 0 }, /* 0x0C */ \ - {0, HID_KEY_RETURN }, /* 0x0D CR */ \ + {0, HID_KEY_ENTER }, /* 0x0D CR */ \ {0, 0 }, /* 0x0E */ \ {0, 0 }, /* 0x0F */ \ {0, 0 }, /* 0x10 */ \ -- cgit v1.3.1 From 2c7bb540b41d3609d25cda44add46f5b685cdf7a Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 10 Aug 2021 20:26:51 +0200 Subject: dcd_da1469x: Use mcu.h instead of MCU specific header dcd_da1469x can work with broader range of MCUs that share same USB core. Specific header file that was used DA1469xAB.h now it is changed to mcu/mcu.h which includes actual MCU specific register file. --- src/portable/dialog/da146xx/dcd_da146xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 59f728d08..d209b152d 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -28,7 +28,7 @@ #if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_DA1469X -#include "DA1469xAB.h" +#include "mcu/mcu.h" #include "device/dcd.h" -- cgit v1.3.1 From f3a6e564ee9dfe3587d8d9dce051eae76bdb9d0c Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 11 Aug 2021 20:06:57 +0700 Subject: rp2040 enable suspend and resume interrupt --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 80 +++++++++++++++++----------- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 7 ++- src/portable/raspberrypi/rp2040/rp2040_usb.c | 6 +-- 3 files changed, 55 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index f78a932f1..f39cfab3e 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -37,6 +37,14 @@ #include "device/dcd.h" +// Current implementation force vbus detection as always present, causing device think it is always plugged into host. +// Therefore it cannot detect disconnect event, mistaken it as suspend. +// Note: won't work if change to 0 (for now) +// +// Note: Line state when disconnected is very sensitive, in actual testing, +// it can toggles between J-state (idle) and SE1 if cable still connected to rp2040 (not connected to host) +#define FORCE_VBUS_DETECT 1 + /*------------------------------------------------------------------*/ /* Low level controller *------------------------------------------------------------------*/ @@ -52,14 +60,14 @@ static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2] = {0}; static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, tusb_dir_t dir) { - return &hw_endpoints[num][dir]; + return &hw_endpoints[num][dir]; } static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr) { - uint8_t num = tu_edpt_number(ep_addr); - tusb_dir_t dir = tu_edpt_dir(ep_addr); - return hw_endpoint_get_by_num(num, dir); + uint8_t num = tu_edpt_number(ep_addr); + tusb_dir_t dir = tu_edpt_dir(ep_addr); + return hw_endpoint_get_by_num(num, dir); } static void _hw_endpoint_alloc(struct hw_endpoint *ep) @@ -290,7 +298,9 @@ static void dcd_rp2040_irq(void) hw_handle_buff_status(); } - // SE0 for 2 us or more, usually together with Bus Reset +#if FORCE_VBUS_DETECT == 0 + // Since we force VBUS detect On, device will always think it is connected and + // couldn't distinguish between disconnect and suspend if (status & USB_INTS_DEV_CONN_DIS_BITS) { handled |= USB_INTS_DEV_CONN_DIS_BITS; @@ -306,6 +316,7 @@ static void dcd_rp2040_irq(void) usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS; } +#endif // SE0 for 2.5 us or more if (status & USB_INTS_BUS_RESET_BITS) @@ -322,7 +333,7 @@ static void dcd_rp2040_irq(void) #endif } -#if 0 +#if 1 // TODO Enable SUSPEND & RESUME interrupt and test later on with/without VBUS detection /* Note from pico datasheet 4.1.2.6.4 (v1.2) @@ -364,36 +375,43 @@ static void dcd_rp2040_irq(void) /*------------------------------------------------------------------*/ /* Controller API *------------------------------------------------------------------*/ + void dcd_init (uint8_t rhport) { - pico_trace("dcd_init %d\n", rhport); - assert(rhport == 0); + pico_trace("dcd_init %d\n", rhport); + assert(rhport == 0); - // Reset hardware to default state - rp2040_usb_init(); + // Reset hardware to default state + rp2040_usb_init(); - irq_set_exclusive_handler(USBCTRL_IRQ, dcd_rp2040_irq); - memset(hw_endpoints, 0, sizeof(hw_endpoints)); - next_buffer_ptr = &usb_dpram->epx_data[0]; - - // EP0 always exists so init it now - // EP0 OUT - hw_endpoint_init(0x0, 64, TUSB_XFER_CONTROL); - // EP0 IN - hw_endpoint_init(0x80, 64, TUSB_XFER_CONTROL); - - // Initializes the USB peripheral for device mode and enables it. - // Don't need to enable the pull up here. Force VBUS - usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS; - - // Enable individual controller IRQS here. Processor interrupt enable will be used - // for the global interrupt enable... - // TODO Enable SUSPEND & RESUME interrupt - usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS; - usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS | - USB_INTS_DEV_CONN_DIS_BITS /* | USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS */ ; +#if FORCE_VBUS_DETECT + // Force VBUS detect so the device thinks it is plugged into a host + usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; +#endif - dcd_connect(rhport); + irq_set_exclusive_handler(USBCTRL_IRQ, dcd_rp2040_irq); + memset(hw_endpoints, 0, sizeof(hw_endpoints)); + next_buffer_ptr = &usb_dpram->epx_data[0]; + + // EP0 always exists so init it now + // EP0 OUT + hw_endpoint_init(0x0, 64, TUSB_XFER_CONTROL); + // EP0 IN + hw_endpoint_init(0x80, 64, TUSB_XFER_CONTROL); + + // Initializes the USB peripheral for device mode and enables it. + // Don't need to enable the pull up here. Force VBUS + usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS; + + // Enable individual controller IRQS here. Processor interrupt enable will be used + // for the global interrupt enable... + // Note: Force VBUS detect cause disconnection not detectable + usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS; + usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS | + USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS | + (FORCE_VBUS_DETECT ? 0 : USB_INTS_DEV_CONN_DIS_BITS); + + dcd_connect(rhport); } void dcd_int_enable(uint8_t rhport) diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 40a0805c6..2c007ddd3 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -61,8 +61,8 @@ static struct hw_endpoint ep_pool[1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS]; // Flags we set by default in sie_ctrl (we add other bits on top) enum { - SIE_CTRL_BASE = USB_SIE_CTRL_SOF_EN_BITS | USB_SIE_CTRL_KEEP_ALIVE_EN_BITS | - USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS + SIE_CTRL_BASE = USB_SIE_CTRL_SOF_EN_BITS | USB_SIE_CTRL_KEEP_ALIVE_EN_BITS | + USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS }; static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr) @@ -360,6 +360,9 @@ bool hcd_init(uint8_t rhport) // Reset any previous state rp2040_usb_init(); + // Force VBUS detect to always present, for now we assume vbus is always provided (without using VBUS En) + usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; + irq_set_exclusive_handler(USBCTRL_IRQ, hcd_rp2040_irq); // clear epx and interrupt eps diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index dc12e6d82..43554d28b 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -62,11 +62,7 @@ void rp2040_usb_init(void) memset(usb_dpram, 0, sizeof(*usb_dpram)); // Mux the controller to the onboard usb phy - usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; - - // Force VBUS detect so the device thinks it is plugged into a host - // TODO support VBUs detect - usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS; + usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; } void hw_endpoint_reset_transfer(struct hw_endpoint *ep) -- cgit v1.3.1 From 979af6c2a859a1e76930d429f37abff6a224599a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 11 Aug 2021 20:29:39 +0700 Subject: clean up endpoint set/clear stall --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 78 ++++++++++++---------------- src/portable/raspberrypi/rp2040/rp2040_usb.h | 2 +- 2 files changed, 35 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index f39cfab3e..6b1e79af4 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -230,7 +230,6 @@ static void reset_ep0(void) { struct hw_endpoint *ep = hw_endpoint_get_by_addr(addrs[i]); ep->next_pid = 1u; - ep->stalled = 0; } } @@ -241,39 +240,9 @@ static void ep0_0len_status(void) hw_endpoint_xfer(0x80, NULL, 0); } -static void _hw_endpoint_stall(struct hw_endpoint *ep) +static void bus_reset(void) { - assert(!ep->stalled); - if (tu_edpt_number(ep->ep_addr) == 0) - { - // A stall on EP0 has to be armed so it can be cleared on the next setup packet - usb_hw_set->ep_stall_arm = (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; - } - _hw_endpoint_buffer_control_set_mask32(ep, USB_BUF_CTRL_STALL); - ep->stalled = true; -} - -static void hw_endpoint_stall(uint8_t ep_addr) -{ - struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); - _hw_endpoint_stall(ep); -} - -static void _hw_endpoint_clear_stall(struct hw_endpoint *ep) -{ - if (tu_edpt_number(ep->ep_addr) == 0) - { - // Probably already been cleared but no harm - usb_hw_clear->ep_stall_arm = (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; - } - _hw_endpoint_buffer_control_clear_mask32(ep, USB_BUF_CTRL_STALL); - ep->stalled = false; -} -static void hw_endpoint_clear_stall(uint8_t ep_addr) -{ - struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); - _hw_endpoint_clear_stall(ep); } static void dcd_rp2040_irq(void) @@ -322,9 +291,13 @@ static void dcd_rp2040_irq(void) if (status & USB_INTS_BUS_RESET_BITS) { pico_trace("BUS RESET\n"); - usb_hw->dev_addr_ctrl = 0; + handled |= USB_INTS_BUS_RESET_BITS; + + usb_hw->dev_addr_ctrl = 0; + bus_reset(); dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); + usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; #if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX @@ -492,20 +465,37 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t return true; } -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { - pico_trace("dcd_edpt_stall %02x\n", ep_addr); - assert(rhport == 0); - hw_endpoint_stall(ep_addr); + pico_trace("dcd_edpt_stall %02x\n", ep_addr); + assert(rhport == 0); + + if ( tu_edpt_number(ep_addr) == 0 ) + { + // A stall on EP0 has to be armed so it can be cleared on the next setup packet + usb_hw_set->ep_stall_arm = (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS; + } + + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + + // TODO check with double buffered + _hw_endpoint_buffer_control_set_mask32(ep, USB_BUF_CTRL_STALL); } -void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { - pico_trace("dcd_edpt_clear_stall %02x\n", ep_addr); - assert(rhport == 0); - hw_endpoint_clear_stall(ep_addr); -} + pico_trace("dcd_edpt_clear_stall %02x\n", ep_addr); + assert(rhport == 0); + if (tu_edpt_number(ep_addr)) + { + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + + // clear stall also reset toggle to DATA0 + // TODO check with double buffered + _hw_endpoint_buffer_control_clear_mask32(ep, USB_BUF_CTRL_STALL | USB_BUF_CTRL_DATA1_PID); + } +} void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) { @@ -518,8 +508,8 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) void dcd_int_handler(uint8_t rhport) { - (void) rhport; - dcd_rp2040_irq(); + (void) rhport; + dcd_rp2040_irq(); } #endif diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index 514152cd9..5570a731a 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -42,7 +42,7 @@ struct hw_endpoint // Buffer pointer in usb dpram uint8_t *hw_data_buf; - // Have we been stalled + // Have we been stalled TODO remove later bool stalled; // Current transfer information -- cgit v1.3.1 From a2baf9427d62ecb49b8d0e58a7ddb12698ddf814 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 11 Aug 2021 20:36:23 +0700 Subject: more dcd clean up --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 6b1e79af4..0dabdd1d7 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -233,13 +233,6 @@ static void reset_ep0(void) } } -static void ep0_0len_status(void) -{ - // Send 0len complete response on EP0 IN - reset_ep0(); - hw_endpoint_xfer(0x80, NULL, 0); -} - static void bus_reset(void) { @@ -405,7 +398,9 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) assert(rhport == 0); // Can't set device address in hardware until status xfer has complete - ep0_0len_status(); + // Send 0len complete response on EP0 IN + reset_ep0(); + hw_endpoint_xfer(0x80, NULL, 0); } void dcd_remote_wakeup(uint8_t rhport) -- cgit v1.3.1 From 88d4cb402d5db6cb88ffa0aecb78fccfe3ab0afd Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Aug 2021 00:11:04 +0700 Subject: simplify hw_endpoint_init() --- src/device/dcd.h | 1 + src/portable/raspberrypi/rp2040/dcd_rp2040.c | 65 +++++++++++++--------------- 2 files changed, 31 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index 8bfad9b72..66767c1fe 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -152,6 +152,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); // clear stall, data toggle is also reset to DATA0 +// This API never calls with control endpoints, since it is auto cleared when receiving setup packet void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); //--------------------------------------------------------------------+ diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 0dabdd1d7..ca083d500 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -101,8 +101,29 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep) *ep->endpoint_control = reg; } -static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) +#if 0 // todo unused +static void _hw_endpoint_close(struct hw_endpoint *ep) +{ + // Clear hardware registers and then zero the struct + // Clears endpoint enable + *ep->endpoint_control = 0; + // Clears buffer available, etc + *ep->buffer_control = 0; + // Clear any endpoint state + memset(ep, 0, sizeof(struct hw_endpoint)); +} + +static void hw_endpoint_close(uint8_t ep_addr) +{ + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + _hw_endpoint_close(ep); +} +#endif + +static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + const uint8_t num = tu_edpt_number(ep_addr); const tusb_dir_t dir = tu_edpt_dir(ep_addr); @@ -112,7 +133,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t ep->rx = (dir == TUSB_DIR_OUT); // Response to a setup packet on EP0 starts with pid of 1 - ep->next_pid = num == 0 ? 1u : 0u; + ep->next_pid = (num == 0 ? 1u : 0u); ep->wMaxPacketSize = wMaxPacketSize; ep->transfer_type = transfer_type; @@ -152,7 +173,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t } // Now if it hasn't already been done - //alloc a buffer and fill in endpoint control register + // alloc a buffer and fill in endpoint control register // TODO device may change configuration (dynamic), should clear and reallocate if(!(ep->configured)) { @@ -163,31 +184,6 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t ep->configured = true; } -#if 0 // todo unused -static void _hw_endpoint_close(struct hw_endpoint *ep) -{ - // Clear hardware registers and then zero the struct - // Clears endpoint enable - *ep->endpoint_control = 0; - // Clears buffer available, etc - *ep->buffer_control = 0; - // Clear any endpoint state - memset(ep, 0, sizeof(struct hw_endpoint)); -} - -static void hw_endpoint_close(uint8_t ep_addr) -{ - struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); - _hw_endpoint_close(ep); -} -#endif - -static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t bmAttributes) -{ - struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); - _hw_endpoint_init(ep, ep_addr, wMaxPacketSize, bmAttributes); -} - static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); @@ -290,7 +286,6 @@ static void dcd_rp2040_irq(void) usb_hw->dev_addr_ctrl = 0; bus_reset(); dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); - usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; #if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX @@ -394,13 +389,13 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address (uint8_t rhport, uint8_t dev_addr) { - pico_trace("dcd_set_address %d %d\n", rhport, dev_addr); - assert(rhport == 0); + pico_trace("dcd_set_address %d %d\n", rhport, dev_addr); + assert(rhport == 0); - // Can't set device address in hardware until status xfer has complete - // Send 0len complete response on EP0 IN - reset_ep0(); - hw_endpoint_xfer(0x80, NULL, 0); + // Can't set device address in hardware until status xfer has complete + // Send 0len complete response on EP0 IN + reset_ep0(); + hw_endpoint_xfer(0x80, NULL, 0); } void dcd_remote_wakeup(uint8_t rhport) -- cgit v1.3.1 From 4f2999bc0488cf6bb9823ea315e0960888d1d593 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Aug 2021 00:12:15 +0700 Subject: white space --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 96 ++++++++++++++-------------- 1 file changed, 48 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index ca083d500..24c6c010e 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -70,13 +70,13 @@ static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr) return hw_endpoint_get_by_num(num, dir); } -static void _hw_endpoint_alloc(struct hw_endpoint *ep) +static void _hw_endpoint_alloc(struct hw_endpoint *ep, uint8_t transfer_type) { // size must be multiple of 64 uint16_t size = tu_div_ceil(ep->wMaxPacketSize, 64) * 64u; // double buffered for Control and Bulk endpoint - if ( ep->transfer_type == TUSB_XFER_CONTROL || ep->transfer_type == TUSB_XFER_BULK) + if ( transfer_type == TUSB_XFER_CONTROL || transfer_type == TUSB_XFER_BULK ) { size *= 2u; } @@ -96,7 +96,7 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep) ep_dir_string[tu_edpt_dir(ep->ep_addr)]); // Fill in endpoint control register with buffer offset - uint32_t const reg = EP_CTRL_ENABLE_BITS | (ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; + uint32_t const reg = EP_CTRL_ENABLE_BITS | (transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; *ep->endpoint_control = reg; } @@ -122,66 +122,66 @@ static void hw_endpoint_close(uint8_t ep_addr) static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) { - struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); + struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr); - const uint8_t num = tu_edpt_number(ep_addr); - const tusb_dir_t dir = tu_edpt_dir(ep_addr); + const uint8_t num = tu_edpt_number(ep_addr); + const tusb_dir_t dir = tu_edpt_dir(ep_addr); - ep->ep_addr = ep_addr; + ep->ep_addr = ep_addr; - // For device, IN is a tx transfer and OUT is an rx transfer - ep->rx = (dir == TUSB_DIR_OUT); + // For device, IN is a tx transfer and OUT is an rx transfer + ep->rx = (dir == TUSB_DIR_OUT); - // Response to a setup packet on EP0 starts with pid of 1 - ep->next_pid = (num == 0 ? 1u : 0u); + // Response to a setup packet on EP0 starts with pid of 1 + ep->next_pid = (num == 0 ? 1u : 0u); - ep->wMaxPacketSize = wMaxPacketSize; - ep->transfer_type = transfer_type; + ep->wMaxPacketSize = wMaxPacketSize; + ep->transfer_type = transfer_type; - // Every endpoint has a buffer control register in dpram - if (dir == TUSB_DIR_IN) - { - ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in; - } - else - { - ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].out; - } + // Every endpoint has a buffer control register in dpram + if ( dir == TUSB_DIR_IN ) + { + ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in; + } + else + { + ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].out; + } - // Clear existing buffer control state - *ep->buffer_control = 0; + // Clear existing buffer control state + *ep->buffer_control = 0; - if (num == 0) - { - // EP0 has no endpoint control register because - // the buffer offsets are fixed - ep->endpoint_control = NULL; + if ( num == 0 ) + { + // EP0 has no endpoint control register because + // the buffer offsets are fixed + ep->endpoint_control = NULL; - // Buffer offset is fixed - ep->hw_data_buf = (uint8_t*)&usb_dpram->ep0_buf_a[0]; + // Buffer offset is fixed + ep->hw_data_buf = (uint8_t*) &usb_dpram->ep0_buf_a[0]; + } + else + { + // Set the endpoint control register (starts at EP1, hence num-1) + if ( dir == TUSB_DIR_IN ) + { + ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].in; } else { - // Set the endpoint control register (starts at EP1, hence num-1) - if (dir == TUSB_DIR_IN) - { - ep->endpoint_control = &usb_dpram->ep_ctrl[num-1].in; - } - else - { - ep->endpoint_control = &usb_dpram->ep_ctrl[num-1].out; - } + ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].out; + } - // Now if it hasn't already been done - // alloc a buffer and fill in endpoint control register - // TODO device may change configuration (dynamic), should clear and reallocate - if(!(ep->configured)) - { - _hw_endpoint_alloc(ep); - } + // Now if it hasn't already been done + // alloc a buffer and fill in endpoint control register + // TODO device may change configuration (dynamic), should clear and reallocate + if ( !(ep->configured) ) + { + _hw_endpoint_alloc(ep, transfer_type); } + } - ep->configured = true; + ep->configured = true; } static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) -- cgit v1.3.1 From cde607338d723e3d62fba6cfb9ea4b07eb89a55d Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 11 Aug 2021 14:45:47 +0200 Subject: da1469x: Fix no VBUS startup For self powered device if device started without VBUS present it would not be correctly attached to USB bus even if tusb_vbus_changed() was later called. This modifies dcd_init() so it starts USB state machine without checking if VBUS is present or not, like all others drivers do. tusb_vbus_changed() function is also removed its content was moved to dcd_init. --- src/portable/dialog/da146xx/dcd_da146xx.c | 38 ++++++++----------------------- 1 file changed, 10 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index d209b152d..5fcf3bc5b 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -258,33 +258,6 @@ static const tusb_desc_endpoint_t ep0IN_desc = #define XFER_CTL_BASE(_ep, _dir) &_dcd.xfer_status[_ep][_dir] -// Function could be called when VBUS change was detected. -void tusb_vbus_changed(bool present) -{ - if (present != _dcd.vbus_present) - { - _dcd.vbus_present = present; - if (present) - { - USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk; - USB->USB_NFSR_REG = 0; - USB->USB_FAR_REG = 0x80; - USB->USB_NFSR_REG = NFSR_NODE_RESET; - USB->USB_TXMSK_REG = 0; - USB->USB_RXMSK_REG = 0; - - USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk | - USB_USB_MAMSK_REG_USB_M_ALT_Msk | - USB_USB_MAMSK_REG_USB_M_WARN_Msk; - USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk; - } - else - { - USB->USB_MCTRL_REG = 0; - } - } -} - static void fill_tx_fifo(xfer_ctl_t * xfer) { int left_to_send; @@ -763,7 +736,16 @@ static void handle_ep0_nak(void) void dcd_init(uint8_t rhport) { USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk; - tusb_vbus_changed((CRG_TOP->ANA_STATUS_REG & CRG_TOP_ANA_STATUS_REG_VBUS_AVAILABLE_Msk) != 0); + USB->USB_NFSR_REG = 0; + USB->USB_FAR_REG = 0x80; + USB->USB_NFSR_REG = NFSR_NODE_RESET; + USB->USB_TXMSK_REG = 0; + USB->USB_RXMSK_REG = 0; + + USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk | + USB_USB_MAMSK_REG_USB_M_ALT_Msk | + USB_USB_MAMSK_REG_USB_M_WARN_Msk; + USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk; dcd_connect(rhport); } -- cgit v1.3.1 From 4ad47d9e264a7119f5429a045a185ad0d448d998 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Aug 2021 15:40:26 +0700 Subject: bus_reset will reset all endpoints allow for dynamic configuration as well as state-less enumeration --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 50 ++++++++++------------------ 1 file changed, 17 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 24c6c010e..63d8278da 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -40,9 +40,6 @@ // Current implementation force vbus detection as always present, causing device think it is always plugged into host. // Therefore it cannot detect disconnect event, mistaken it as suspend. // Note: won't work if change to 0 (for now) -// -// Note: Line state when disconnected is very sensitive, in actual testing, -// it can toggles between J-state (idle) and SE1 if cable still connected to rp2040 (not connected to host) #define FORCE_VBUS_DETECT 1 /*------------------------------------------------------------------*/ @@ -56,7 +53,7 @@ static uint8_t *next_buffer_ptr; // USB_MAX_ENDPOINTS Endpoints, direction TUSB_DIR_OUT for out and TUSB_DIR_IN for in. -static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2] = {0}; +static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2]; static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, tusb_dir_t dir) { @@ -75,8 +72,8 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep, uint8_t transfer_type) // size must be multiple of 64 uint16_t size = tu_div_ceil(ep->wMaxPacketSize, 64) * 64u; - // double buffered for Control and Bulk endpoint - if ( transfer_type == TUSB_XFER_CONTROL || transfer_type == TUSB_XFER_BULK ) + // double buffered Bulk endpoint + if ( transfer_type == TUSB_XFER_BULK ) { size *= 2u; } @@ -88,12 +85,7 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep, uint8_t transfer_type) uint dpram_offset = hw_data_offset(ep->hw_data_buf); assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX); - pico_info("Alloced %d bytes at offset 0x%x (0x%p) for ep %d %s\n", - size, - dpram_offset, - ep->hw_data_buf, - tu_edpt_number(ep->ep_addr), - ep_dir_string[tu_edpt_dir(ep->ep_addr)]); + pico_info(" Alloced %d bytes at offset 0x%x (0x%p)\r\n", size, dpram_offset, ep->hw_data_buf); // Fill in endpoint control register with buffer offset uint32_t const reg = EP_CTRL_ENABLE_BITS | (transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset; @@ -157,7 +149,7 @@ static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t // the buffer offsets are fixed ep->endpoint_control = NULL; - // Buffer offset is fixed + // Buffer offset is fixed (also double buffered) ep->hw_data_buf = (uint8_t*) &usb_dpram->ep0_buf_a[0]; } else @@ -172,16 +164,9 @@ static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].out; } - // Now if it hasn't already been done // alloc a buffer and fill in endpoint control register - // TODO device may change configuration (dynamic), should clear and reallocate - if ( !(ep->configured) ) - { - _hw_endpoint_alloc(ep, transfer_type); - } + _hw_endpoint_alloc(ep, transfer_type); } - - ep->configured = true; } static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) @@ -229,14 +214,19 @@ static void reset_ep0(void) } } -static void bus_reset(void) +static void reset_all_endpoints(void) { + memset(hw_endpoints, 0, sizeof(hw_endpoints)); + next_buffer_ptr = &usb_dpram->epx_data[0]; + // Init Control endpoint out & in + hw_endpoint_init(0x0, 64, TUSB_XFER_CONTROL); + hw_endpoint_init(0x80, 64, TUSB_XFER_CONTROL); } static void dcd_rp2040_irq(void) { - uint32_t status = usb_hw->ints; + uint32_t const status = usb_hw->ints; uint32_t handled = 0; if (status & USB_INTS_SETUP_REQ_BITS) @@ -276,7 +266,7 @@ static void dcd_rp2040_irq(void) } #endif - // SE0 for 2.5 us or more + // SE0 for 2.5 us or more (will last at least 10ms) if (status & USB_INTS_BUS_RESET_BITS) { pico_trace("BUS RESET\n"); @@ -284,7 +274,7 @@ static void dcd_rp2040_irq(void) handled |= USB_INTS_BUS_RESET_BITS; usb_hw->dev_addr_ctrl = 0; - bus_reset(); + reset_all_endpoints(); dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; @@ -351,14 +341,9 @@ void dcd_init (uint8_t rhport) #endif irq_set_exclusive_handler(USBCTRL_IRQ, dcd_rp2040_irq); - memset(hw_endpoints, 0, sizeof(hw_endpoints)); - next_buffer_ptr = &usb_dpram->epx_data[0]; - // EP0 always exists so init it now - // EP0 OUT - hw_endpoint_init(0x0, 64, TUSB_XFER_CONTROL); - // EP0 IN - hw_endpoint_init(0x80, 64, TUSB_XFER_CONTROL); + // reset endpoints + reset_all_endpoints(); // Initializes the USB peripheral for device mode and enables it. // Don't need to enable the pull up here. Force VBUS @@ -442,7 +427,6 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { - pico_info("dcd_edpt_open %02x\n", desc_edpt->bEndpointAddress); assert(rhport == 0); hw_endpoint_init(desc_edpt->bEndpointAddress, desc_edpt->wMaxPacketSize.size, desc_edpt->bmAttributes.xfer); return true; -- cgit v1.3.1 From 17ef9f4843250e8c6b6b1fde53ed6a54a4f20470 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Aug 2021 15:46:33 +0700 Subject: add ready check for edpt claim --- src/device/usbd.c | 5 +++++ src/portable/raspberrypi/rp2040/dcd_rp2040.c | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index a30eab217..bef7725b5 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1191,6 +1191,8 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) { (void) rhport; + TU_VERIFY(tud_ready()); + uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -1244,6 +1246,9 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + // TODO skip ready() check for now since enumeration also use this API + // TU_VERIFY(tud_ready()); + TU_LOG2(" Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes); // Attempt to transfer on a busy endpoint, sound like an race condition ! diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 63d8278da..49284e92e 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -284,9 +284,6 @@ static void dcd_rp2040_irq(void) #endif } -#if 1 - // TODO Enable SUSPEND & RESUME interrupt and test later on with/without VBUS detection - /* Note from pico datasheet 4.1.2.6.4 (v1.2) * If you enable the suspend interrupt, it is likely you will see a suspend interrupt when * the device is first connected but the bus is idle. The bus can be idle for a few ms before @@ -308,7 +305,6 @@ static void dcd_rp2040_irq(void) dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS; } -#endif if (status ^ handled) { -- cgit v1.3.1 From d52b981c3af06233891e827edcd484ece244a5a8 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Aug 2021 17:07:39 +0700 Subject: revert ready() check in claim (do it later in separated PR) --- src/device/usbd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index bef7725b5..a15959710 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1191,7 +1191,8 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - TU_VERIFY(tud_ready()); + // TODO add this check later, also make sure we don't starve an out endpoint while suspending + // TU_VERIFY(tud_ready()); uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); -- cgit v1.3.1 From 0ec794376bdc28aea3def01cc9fcbb7bcc6d5201 Mon Sep 17 00:00:00 2001 From: Tobias Ringström Date: Fri, 13 Aug 2021 14:11:14 +0200 Subject: Fix dcd_set_address bug when called more than once with different addresses (e.g. after plugging the device into a different port). --- src/portable/st/synopsys/dcd_synopsys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index c15694eba..e36c2ba26 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -519,7 +519,7 @@ void dcd_int_disable (uint8_t rhport) void dcd_set_address (uint8_t rhport, uint8_t dev_addr) { USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport); - dev->DCFG |= (dev_addr << USB_OTG_DCFG_DAD_Pos) & USB_OTG_DCFG_DAD_Msk; + dev->DCFG = (dev->DCFG & ~USB_OTG_DCFG_DAD_Msk) | (dev_addr << USB_OTG_DCFG_DAD_Pos); // Response with status after changing device address dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); -- cgit v1.3.1 From 6af1950c8d90c41664b079ad78a0918b4821ea92 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 14 Aug 2021 01:51:13 +0700 Subject: synopsys clear DAD on bus_reset --- src/portable/st/synopsys/dcd_synopsys.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index e36c2ba26..5a5645dd4 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -192,6 +192,10 @@ static void bus_reset(uint8_t rhport) out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK; } + // clear device address + dev->DCFG &= ~USB_OTG_DCFG_DAD_Msk; + + // TODO should probably assign value when reset rather than OR dev->DAINTMSK |= (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos); dev->DOEPMSK |= USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM; dev->DIEPMSK |= USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM; -- cgit v1.3.1 From 09e4348adcdb0af74a15d8077edf610690dd55a4 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 15 Aug 2021 17:19:25 +0700 Subject: move gd32vf103 to its own family --- hw/bsp/fomu/family.mk | 2 +- hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.h | 20 + .../gd32vf103/boards/sipeed_longan_nano/board.mk | 13 + hw/bsp/gd32vf103/family.c | 197 ++++++ hw/bsp/gd32vf103/family.mk | 68 +++ hw/bsp/gd32vf103/system_gd32vf103.c | 668 +++++++++++++++++++++ hw/bsp/gd32vf103_longan_nano/board.mk | 69 --- .../gd32vf103_longan_nano/gd32vf103_longan_nano.c | 194 ------ hw/bsp/gd32vf103_longan_nano/nuclei_sdk_hal.h | 22 - hw/bsp/gd32vf103_longan_nano/system_gd32vf103.c | 668 --------------------- src/portable/st/synopsys/dcd_synopsys.c | 4 + 11 files changed, 971 insertions(+), 954 deletions(-) create mode 100644 hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.h create mode 100644 hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.mk create mode 100644 hw/bsp/gd32vf103/family.c create mode 100644 hw/bsp/gd32vf103/family.mk create mode 100644 hw/bsp/gd32vf103/system_gd32vf103.c delete mode 100644 hw/bsp/gd32vf103_longan_nano/board.mk delete mode 100644 hw/bsp/gd32vf103_longan_nano/gd32vf103_longan_nano.c delete mode 100644 hw/bsp/gd32vf103_longan_nano/nuclei_sdk_hal.h delete mode 100644 hw/bsp/gd32vf103_longan_nano/system_gd32vf103.c (limited to 'src') diff --git a/hw/bsp/fomu/family.mk b/hw/bsp/fomu/family.mk index 40cb5dd45..165535c6b 100644 --- a/hw/bsp/fomu/family.mk +++ b/hw/bsp/fomu/family.mk @@ -5,7 +5,7 @@ CFLAGS += \ -nostdlib \ -DCFG_TUSB_MCU=OPT_MCU_VALENTYUSB_EPTRI -# Cross Compiler for RISC-V +# Toolchain from https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack CROSS_COMPILE = riscv-none-embed- # All source paths should be relative to the top level. diff --git a/hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.h b/hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.h new file mode 100644 index 000000000..fae7c40b7 --- /dev/null +++ b/hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.h @@ -0,0 +1,20 @@ +#ifndef _NUCLEI_SDK_HAL_H +#define _NUCLEI_SDK_HAL_H + +#include "gd32vf103c_longan_nano.h" + +// 4 bits for interrupt level, 0 for priority. +// level 0 = lowest priority, level 15 = highest priority. +#define __ECLIC_INTCTLBITS 4 + +#define __SYSTEM_CLOCK 72000000 +#define HXTAL_VALUE ((uint32_t)8000000) + +#define SOC_DEBUG_UART GD32_COM0 + +#define DBG_KEY_UNLOCK 0x4B5A6978 +#define DBG_CMD_RESET 0x1 +#define DBG_KEY REG32(DBG + 0x0C) +#define DBG_CMD REG32(DBG + 0x08) + +#endif diff --git a/hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.mk b/hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.mk new file mode 100644 index 000000000..3b8944452 --- /dev/null +++ b/hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.mk @@ -0,0 +1,13 @@ +LONGAN_NANO_SDK_BSP = $(GD32VF103_SDK_SOC)/Board/gd32vf103c_longan_nano +LINKER_SCRIPTS = $(LONGAN_NANO_SDK_BSP)/Source/GCC + +# All source paths should be relative to the top level. +LD_FILE = $(LINKER_SCRIPTS)/gcc_gd32vf103xb_flashxip.ld # Longan Nano 128k ROM 32k RAM +#LD_FILE = $(LINKER_SCRIPTS)/gcc_gd32vf103x8_flashxip.ld # Longan Nano Lite 64k ROM 20k RAM + +SRC_C += $(LONGAN_NANO_SDK_BSP)/Source/gd32vf103c_longan_nano.c +INC += $(TOP)/$(LONGAN_NANO_SDK_BSP)/Include + +# Longan Nano 128k ROM 32k RAM +JLINK_DEVICE = gd32vf103cbt6 +#JLINK_DEVICE = gd32vf103c8t6 # Longan Nano Lite 64k ROM 20k RAM diff --git a/hw/bsp/gd32vf103/family.c b/hw/bsp/gd32vf103/family.c new file mode 100644 index 000000000..d76fb9a2a --- /dev/null +++ b/hw/bsp/gd32vf103/family.c @@ -0,0 +1,197 @@ +/* + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "board.h" +#include "drv_usb_hw.h" +#include "drv_usb_dev.h" + +#include "../board.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ + +void USBFS_IRQHandler(void) { tud_int_handler(0); } + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + +#define USB_NO_VBUS_PIN + +// According to GD32VF103 user manual clock tree: +// Systick clock = AHB clock / 4. +#define TIMER_TICKS ((SystemCoreClock / 4) / 1000) + +#define BUTTON_PORT GPIOA +#define BUTTON_PIN GPIO_PIN_0 +#define BUTTON_STATE_ACTIVE 1 + +#define UART_DEV SOC_DEBUG_UART + +#define LED_PIN LED_R + +void board_init(void) { + /* Disable interrupts during init */ + __disable_irq(); + +#if CFG_TUSB_OS == OPT_OS_NONE + SysTick_Config(TIMER_TICKS); +#endif + + rcu_periph_clock_enable(RCU_GPIOA); + rcu_periph_clock_enable(RCU_GPIOB); + rcu_periph_clock_enable(RCU_GPIOC); + rcu_periph_clock_enable(RCU_GPIOD); + rcu_periph_clock_enable(RCU_AF); + +#ifdef BUTTON_PIN + gpio_init(BUTTON_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, BUTTON_PIN); +#endif + +#ifdef LED_PIN + gd_led_init(LED_PIN); +#endif + +#if defined(UART_DEV) + gd_com_init(UART_DEV); +#endif + + /* USB D+ and D- pins don't need to be configured. */ + /* Configure VBUS Pin */ +#ifndef USB_NO_VBUS_PIN + gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_9); +#endif + + /* This for ID line debug */ + // gpio_init(GPIOA, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_10); + + /* Enable USB OTG clock */ + usb_rcu_config(); + + /* Reset USB OTG peripheral */ + rcu_periph_reset_enable(RCU_USBFSRST); + rcu_periph_reset_disable(RCU_USBFSRST); + + /* Configure USBFS IRQ */ + ECLIC_Register_IRQ(USBFS_IRQn, ECLIC_NON_VECTOR_INTERRUPT, + ECLIC_POSTIVE_EDGE_TRIGGER, 3, 0, NULL); + + /* Retrieve otg core registers */ + usb_gr* otg_core_regs = (usb_gr*)(USBFS_REG_BASE + USB_REG_OFFSET_CORE); + +#ifdef USB_NO_VBUS_PIN + /* Disable VBUS sense*/ + otg_core_regs->GCCFG |= GCCFG_VBUSIG | GCCFG_PWRON | GCCFG_VBUSBCEN; +#else + /* Enable VBUS sense via pin PA9 */ + otg_core_regs->GCCFG |= GCCFG_VBUSIG | GCCFG_PWRON | GCCFG_VBUSBCEN; + otg_core_regs->GCCFG &= ~GCCFG_VBUSIG; +#endif + + /* Enable interrupts globaly */ + __enable_irq(); +} + +void gd32vf103_reset(void) { + /* The MTIMER unit of the GD32VF103 doesn't have the MSFRST + * register to generate a software reset request. + * BUT instead two undocumented registers in the debug peripheral + * that allow issueing a software reset. + * https://github.com/esmil/gd32vf103inator/blob/master/include/gd32vf103/dbg.h + */ + DBG_KEY = DBG_KEY_UNLOCK; + DBG_CMD = DBG_CMD_RESET; +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) { + state ? gd_led_on(LED_PIN) : gd_led_off(LED_PIN); +} + +uint32_t board_button_read(void) { + return BUTTON_STATE_ACTIVE == gpio_input_bit_get(BUTTON_PORT, BUTTON_PIN); +} + +int board_uart_read(uint8_t* buf, int len) { +#if defined(UART_DEV) + int rxsize = len; + while (rxsize--) { + *(uint8_t*)buf = usart_read(UART_DEV); + buf++; + } + return len; +#else + (void)buf; + (void)len; + return 0; +#endif +} + +int board_uart_write(void const* buf, int len) { +#if defined(UART_DEV) + int txsize = len; + while (txsize--) { + usart_write(UART_DEV, *(uint8_t*)buf); + buf++; + } + return len; +#else + (void)buf; + (void)len; + return 0; +#endif +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void eclic_mtip_handler(void) { + system_ticks++; + SysTick_Reload(TIMER_TICKS); +} +uint32_t board_millis(void) { return system_ticks; } +#endif + +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(char* file, uint32_t line) { + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line + number, + tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) + */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/hw/bsp/gd32vf103/family.mk b/hw/bsp/gd32vf103/family.mk new file mode 100644 index 000000000..3479433e4 --- /dev/null +++ b/hw/bsp/gd32vf103/family.mk @@ -0,0 +1,68 @@ +# https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable +#CROSS_COMPILE ?= riscv32-unknown-elf- + +# Toolchain from https://nucleisys.com/download.php +CROSS_COMPILE ?= riscv-nuclei-elf- + +# Toolchain from https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack +#CROSS_COMPILE ?= riscv-none-embed- + +# Submodules +NUCLEI_SDK = hw/mcu/gd/nuclei-sdk +DEPS_SUBMODULES += $(NUCLEI_SDK) + +# Nuclei-SDK paths +GD32VF103_SDK_SOC = $(NUCLEI_SDK)/SoC/gd32vf103 +GD32VF103_SDK_DRIVER = $(GD32VF103_SDK_SOC)/Common/Source/Drivers +LIBC_STUBS = $(GD32VF103_SDK_SOC)/Common/Source/Stubs +STARTUP_ASM = $(GD32VF103_SDK_SOC)/Common/Source/GCC + +include $(TOP)/$(BOARD_PATH)/board.mk + +SKIP_NANOLIB = 1 + +CFLAGS += \ + -march=rv32imac \ + -mabi=ilp32 \ + -mcmodel=medlow \ + -mstrict-align \ + -nostdlib -nostartfiles \ + -DCFG_TUSB_MCU=OPT_MCU_GD32VF103 \ + -DDOWNLOAD_MODE=DOWNLOAD_MODE_FLASHXIP \ + -DGD32VF103 + +# mcu driver cause following warnings +CFLAGS += -Wno-error=unused-parameter + +SRC_C += \ + src/portable/st/synopsys/dcd_synopsys.c \ + $(GD32VF103_SDK_DRIVER)/gd32vf103_rcu.c \ + $(GD32VF103_SDK_DRIVER)/gd32vf103_gpio.c \ + $(GD32VF103_SDK_DRIVER)/Usb/gd32vf103_usb_hw.c \ + $(GD32VF103_SDK_DRIVER)/gd32vf103_usart.c \ + $(LIBC_STUBS)/sbrk.c \ + $(LIBC_STUBS)/close.c \ + $(LIBC_STUBS)/isatty.c \ + $(LIBC_STUBS)/fstat.c \ + $(LIBC_STUBS)/lseek.c \ + $(LIBC_STUBS)/read.c + +SRC_S += \ + $(STARTUP_ASM)/startup_gd32vf103.S \ + $(STARTUP_ASM)/intexc_gd32vf103.S + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/$(NUCLEI_SDK)/NMSIS/Core/Include \ + $(TOP)/$(GD32VF103_SDK_SOC)/Common/Include \ + $(TOP)/$(GD32VF103_SDK_SOC)/Common/Include/Usb + +# For freeRTOS port source +FREERTOS_PORT = RISC-V + +# For flash-jlink target +JLINK_IF = jtag + +# flash target ROM bootloader +flash: $(BUILD)/$(PROJECT).bin + dfu-util -R -a 0 --dfuse-address 0x08000000 -D $< diff --git a/hw/bsp/gd32vf103/system_gd32vf103.c b/hw/bsp/gd32vf103/system_gd32vf103.c new file mode 100644 index 000000000..29518a54a --- /dev/null +++ b/hw/bsp/gd32vf103/system_gd32vf103.c @@ -0,0 +1,668 @@ +/*! + \file system_gd32vf103.h +\brief RISC-V Device Peripheral Access Layer Source File for + GD32VF103 Device Series + +*/ + +/* + Copyright (c) 2020, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +/* This file refers the RISC-V standard, some adjustments are made according to GigaDevice chips */ +#include "board.h" + +/* system frequency define */ +#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */ +#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */ +#define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */ +#define __SYSTEM_CLOCK_HXTAL (HXTAL_VALUE) + +#if !defined(__SYSTEM_CLOCK) +#define __SYSTEM_CLOCK 72000000 +#endif + +#if __SYSTEM_CLOCK == 48000000 + #define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000) + uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_HXTAL; + static void system_clock_48m_hxtal(void); + +#elif __SYSTEM_CLOCK == 72000000 + #define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000) + uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL; + static void system_clock_72m_hxtal(void); + +#elif __SYSTEM_CLOCK == 96000000 + #define __SYSTEM_CLOCK_96M_PLL_HXTAL (uint32_t)(96000000) + uint32_t SystemCoreClock = __SYSTEM_CLOCK_96M_PLL_HXTAL; + static void system_clock_96m_hxtal(void); + +#else +#error No valid system clock configuration set! +#endif + +/* configure the system clock */ +static void system_clock_config(void); + +/*! + \brief configure the system clock + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_config(void) +{ +#if defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) + system_clock_48m_hxtal(); +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) + system_clock_72m_hxtal(); +#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) + system_clock_96m_hxtal(); +#endif /* __SYSTEM_CLOCK_HXTAL */ +} + +/*! + \brief setup the microcontroller system, initialize the system + \param[in] none + \param[out] none + \retval none +*/ +void SystemInit(void) +{ + /* reset the RCC clock configuration to the default reset state */ + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */ + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL); + + /* reset HXTALEN, CKMEN, PLLEN bits */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); + + /* Reset HXTALBPS bit */ + RCU_CTL &= ~(RCU_CTL_HXTALBPS); + + /* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */ + + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | + RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4); + RCU_CFG1 = 0x00000000U; + + /* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */ + RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN); + /* disable all interrupts */ + RCU_INT = 0x00FF0000U; + + /* Configure the System clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */ + system_clock_config(); +} + +/*! + \brief update the SystemCoreClock with current core clock retrieved from cpu registers + \param[in] none + \param[out] none + \retval none +*/ +void SystemCoreClockUpdate(void) +{ + uint32_t scss; + uint32_t pllsel, predv0sel, pllmf, ck_src; + uint32_t predv0, predv1, pll1mf; + + scss = GET_BITS(RCU_CFG0, 2, 3); + + switch (scss) + { + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + SystemCoreClock = IRC8M_VALUE; + break; + + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + SystemCoreClock = HXTAL_VALUE; + break; + + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection, HXTAL or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + + if(RCU_PLLSRC_IRC8M_DIV2 == pllsel){ + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE / 2U; + }else{ + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + + /* source clock use PLL1 */ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; + pll1mf = ((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; + if(17U == pll1mf){ + pll1mf = 20U; + } + ck_src = (ck_src / predv1) * pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + pllmf |= 0x10U; + } + + if(pllmf >= 15U){ + pllmf += 1U; + }else{ + pllmf += 2U; + } + + SystemCoreClock = ck_src * pllmf; + + if(15U == pllmf){ + /* PLL source clock multiply by 6.5 */ + SystemCoreClock = ck_src * 6U + ck_src / 2U; + } + + break; + + /* IRC8M is selected as CK_SYS */ + default: + SystemCoreClock = IRC8M_VALUE; + break; + } +} + +#if defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) +/*! + \brief configure the system clock to 48M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_48m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL12); + + if(HXTAL_VALUE==25000000){ + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + }else if(HXTAL_VALUE==8000000){ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 ); + } + + + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) +/*! + \brief configure the system clock to 72M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_72m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL18); + + + if(HXTAL_VALUE==25000000){ + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + }else if(HXTAL_VALUE==8000000){ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 ); + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) +/*! + \brief configure the system clock to 96M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_96m_hxtal(void) +{ + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ + do{ + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ + while(1){ + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + if(HXTAL_VALUE==25000000){ + + /* CK_PLL = (CK_PREDIV0) * 24 = 96 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL24); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + } + + }else if(HXTAL_VALUE==8000000){ + /* CK_PLL = (CK_PREDIV0) * 24 = 96 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL24); + + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 ); + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + } +} + +#endif + +/** + * \defgroup NMSIS_Core_IntExcNMI_Handling Interrupt and Exception and NMI Handling + * \brief Functions for interrupt, exception and nmi handle available in system_.c. + * \details + * Nuclei provide a template for interrupt, exception and NMI handling. Silicon Vendor could adapat according + * to their requirement. Silicon vendor could implement interface for different exception code and + * replace current implementation. + * + * @{ + */ +/** \brief Max exception handler number, don't include the NMI(0xFFF) one */ +#define MAX_SYSTEM_EXCEPTION_NUM 12 +/** + * \brief Store the exception handlers for each exception ID + * \note + * - This SystemExceptionHandlers are used to store all the handlers for all + * the exception codes Nuclei N/NX core provided. + * - Exception code 0 - 11, totally 12 exceptions are mapped to SystemExceptionHandlers[0:11] + * - Exception for NMI is also re-routed to exception handling(exception code 0xFFF) in startup code configuration, the handler itself is mapped to SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM] + */ +static unsigned long SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM + 1]; + +/** + * \brief Exception Handler Function Typedef + * \note + * This typedef is only used internal in this system_gd32vf103.c file. + * It is used to do type conversion for registered exception handler before calling it. + */ +typedef void (*EXC_HANDLER)(unsigned long mcause, unsigned long sp); + +/** + * \brief System Default Exception Handler + * \details + * This function provided a default exception and NMI handling code for all exception ids. + * By default, It will just print some information for debug, Vendor can customize it according to its requirements. + */ +static void system_default_exception_handler(unsigned long mcause, unsigned long sp) +{ + /* TODO: Uncomment this if you have implement printf function */ + /*printf("MCAUSE: 0x%lx\r\n", mcause); + printf("MEPC : 0x%lx\r\n", __RV_CSR_READ(CSR_MEPC)); + printf("MTVAL : 0x%lx\r\n", __RV_CSR_READ(CSR_MBADADDR));*/ + while (1); +} + +/** + * \brief Initialize all the default core exception handlers + * \details + * The core exception handler for each exception id will be initialized to \ref system_default_exception_handler. + * \note + * Called in \ref _init function, used to initialize default exception handlers for all exception IDs + */ +static void Exception_Init(void) +{ + for (int i = 0; i < MAX_SYSTEM_EXCEPTION_NUM + 1; i++) { + SystemExceptionHandlers[i] = (unsigned long)system_default_exception_handler; + } +} + +/** + * \brief Register an exception handler for exception code EXCn + * \details + * * For EXCn < \ref MAX_SYSTEM_EXCEPTION_NUM, it will be registered into SystemExceptionHandlers[EXCn-1]. + * * For EXCn == NMI_EXCn, it will be registered into SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM]. + * \param EXCn See \ref EXCn_Type + * \param exc_handler The exception handler for this exception code EXCn + */ +void Exception_Register_EXC(uint32_t EXCn, unsigned long exc_handler) +{ + if ((EXCn < MAX_SYSTEM_EXCEPTION_NUM) && (EXCn != 0)) { + SystemExceptionHandlers[EXCn] = exc_handler; + } else if (EXCn == NMI_EXCn) { + SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM] = exc_handler; + } +} + +/** + * \brief Get current exception handler for exception code EXCn + * \details + * * For EXCn < \ref MAX_SYSTEM_EXCEPTION_NUM, it will return SystemExceptionHandlers[EXCn-1]. + * * For EXCn == NMI_EXCn, it will return SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM]. + * \param EXCn See \ref EXCn_Type + * \return Current exception handler for exception code EXCn, if not found, return 0. + */ +unsigned long Exception_Get_EXC(uint32_t EXCn) +{ + if ((EXCn < MAX_SYSTEM_EXCEPTION_NUM) && (EXCn != 0)) { + return SystemExceptionHandlers[EXCn]; + } else if (EXCn == NMI_EXCn) { + return SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM]; + } else { + return 0; + } +} + +/** + * \brief Common NMI and Exception handler entry + * \details + * This function provided a command entry for NMI and exception. Silicon Vendor could modify + * this template implementation according to requirement. + * \remarks + * - RISCV provided common entry for all types of exception. This is proposed code template + * for exception entry function, Silicon Vendor could modify the implementation. + * - For the core_exception_handler template, we provided exception register function \ref Exception_Register_EXC + * which can help developer to register your exception handler for specific exception number. + */ +uint32_t core_exception_handler(unsigned long mcause, unsigned long sp) +{ + uint32_t EXCn = (uint32_t)(mcause & 0X00000fff); + EXC_HANDLER exc_handler; + + if ((EXCn < MAX_SYSTEM_EXCEPTION_NUM) && (EXCn > 0)) { + exc_handler = (EXC_HANDLER)SystemExceptionHandlers[EXCn]; + } else if (EXCn == NMI_EXCn) { + exc_handler = (EXC_HANDLER)SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM]; + } else { + exc_handler = (EXC_HANDLER)system_default_exception_handler; + } + if (exc_handler != NULL) { + exc_handler(mcause, sp); + } + return 0; +} +/** @} */ /* End of Doxygen Group NMSIS_Core_ExceptionAndNMI */ + +/** + * \brief initialize eclic config + * \details + * Eclic need initialize after boot up, Vendor could also change the initialization + * configuration. + */ +void ECLIC_Init(void) +{ + /* TODO: Add your own initialization code here. This function will be called by main */ + ECLIC_SetMth(0); + ECLIC_SetCfgNlbits(__ECLIC_INTCTLBITS); +} + +/** + * \brief Initialize a specific IRQ and register the handler + * \details + * This function set vector mode, trigger mode and polarity, interrupt level and priority, + * assign handler for specific IRQn. + * \param [in] IRQn NMI interrupt handler address + * \param [in] shv \ref ECLIC_NON_VECTOR_INTERRUPT means non-vector mode, and \ref ECLIC_VECTOR_INTERRUPT is vector mode + * \param [in] trig_mode see \ref ECLIC_TRIGGER_Type + * \param [in] lvl interupt level + * \param [in] priority interrupt priority + * \param [in] handler interrupt handler, if NULL, handler will not be installed + * \return -1 means invalid input parameter. 0 means successful. + * \remarks + * - This function use to configure specific eclic interrupt and register its interrupt handler and enable its interrupt. + * - If the vector table is placed in read-only section(FLASHXIP mode), handler could not be installed + */ +int32_t ECLIC_Register_IRQ(IRQn_Type IRQn, uint8_t shv, ECLIC_TRIGGER_Type trig_mode, uint8_t lvl, uint8_t priority, void* handler) +{ + if ((IRQn > SOC_INT_MAX) || (shv > ECLIC_VECTOR_INTERRUPT) \ + || (trig_mode > ECLIC_NEGTIVE_EDGE_TRIGGER)) { + return -1; + } + + /* set interrupt vector mode */ + ECLIC_SetShvIRQ(IRQn, shv); + /* set interrupt trigger mode and polarity */ + ECLIC_SetTrigIRQ(IRQn, trig_mode); + /* set interrupt level */ + ECLIC_SetLevelIRQ(IRQn, lvl); + /* set interrupt priority */ + ECLIC_SetPriorityIRQ(IRQn, priority); + if (handler != NULL) { + /* set interrupt handler entry to vector table */ + ECLIC_SetVector(IRQn, (rv_csr_t)handler); + } + /* enable interrupt */ + ECLIC_EnableIRQ(IRQn); + return 0; +} +/** @} */ /* End of Doxygen Group NMSIS_Core_ExceptionAndNMI */ + +/** + * \brief early init function before main + * \details + * This function is executed right before main function. + * For RISC-V gnu toolchain, _init function might not be called + * by __libc_init_array function, so we defined a new function + * to do initialization + */ +void _premain_init(void) +{ + /* Initialize exception default handlers */ + Exception_Init(); + /* ECLIC initialization, mainly MTH and NLBIT */ + ECLIC_Init(); +} + +/** + * \brief finish function after main + * \param [in] status status code return from main + * \details + * This function is executed right after main function. + * For RISC-V gnu toolchain, _fini function might not be called + * by __libc_fini_array function, so we defined a new function + * to do initialization + */ +void _postmain_fini(int status) +{ + /* TODO: Add your own finishing code here, called after main */ +} + +/** + * \brief _init function called in __libc_init_array() + * \details + * This `__libc_init_array()` function is called during startup code, + * user need to implement this function, otherwise when link it will + * error init.c:(.text.__libc_init_array+0x26): undefined reference to `_init' + * \note + * Please use \ref _premain_init function now + */ +void _init(void) +{ + /* Don't put any code here, please use _premain_init now */ +} + +/** + * \brief _fini function called in __libc_fini_array() + * \details + * This `__libc_fini_array()` function is called when exit main. + * user need to implement this function, otherwise when link it will + * error fini.c:(.text.__libc_fini_array+0x28): undefined reference to `_fini' + * \note + * Please use \ref _postmain_fini function now + */ +void _fini(void) +{ + /* Don't put any code here, please use _postmain_fini now */ +} + +/** @} */ /* End of Doxygen Group NMSIS_Core_SystemAndClock */ diff --git a/hw/bsp/gd32vf103_longan_nano/board.mk b/hw/bsp/gd32vf103_longan_nano/board.mk deleted file mode 100644 index 5ab275dbe..000000000 --- a/hw/bsp/gd32vf103_longan_nano/board.mk +++ /dev/null @@ -1,69 +0,0 @@ -CROSS_COMPILE = riscv32-unknown-elf- - -# Submodules -DEPS_SUBMODULES += hw/mcu/gd/nuclei-sdk -NUCLEI_SDK = hw/mcu/gd/nuclei-sdk - -# Nuclei-SDK paths -GD32VF103_SDK_SOC = $(NUCLEI_SDK)/SoC/gd32vf103 -GD32VF103_SDK_DRIVER = $(GD32VF103_SDK_SOC)/Common/Source/Drivers -LONGAN_NANO_SDK_BSP = $(GD32VF103_SDK_SOC)/Board/gd32vf103c_longan_nano -LINKER_SCRIPTS = $(LONGAN_NANO_SDK_BSP)/Source/GCC -LIBC_STUBS = $(GD32VF103_SDK_SOC)/Common/Source/Stubs -STARTUP_ASM = $(GD32VF103_SDK_SOC)/Common/Source/GCC - -SKIP_NANOLIB = 1 - -CFLAGS += \ - -march=rv32imac \ - -mabi=ilp32 \ - -mcmodel=medlow \ - -mstrict-align \ - -nostdlib -nostartfiles \ - -DCFG_TUSB_MCU=OPT_MCU_GD32VF103 \ - -DDOWNLOAD_MODE=DOWNLOAD_MODE_FLASHXIP \ - -DGD32VF103 - -# mcu driver cause following warnings -CFLAGS += -Wno-error=unused-parameter - -# All source paths should be relative to the top level. -LD_FILE = $(LINKER_SCRIPTS)/gcc_gd32vf103xb_flashxip.ld # Longan Nano 128k ROM 32k RAM -#LD_FILE = $(LINKER_SCRIPTS)/gcc_gd32vf103x8_flashxip.ld # Longan Nano Lite 64k ROM 20k RAM - -SRC_C += \ - src/portable/st/synopsys/dcd_synopsys.c \ - $(GD32VF103_SDK_DRIVER)/gd32vf103_rcu.c \ - $(GD32VF103_SDK_DRIVER)/gd32vf103_gpio.c \ - $(GD32VF103_SDK_DRIVER)/Usb/gd32vf103_usb_hw.c \ - $(GD32VF103_SDK_DRIVER)/gd32vf103_usart.c \ - $(LONGAN_NANO_SDK_BSP)/Source/gd32vf103c_longan_nano.c \ - $(LIBC_STUBS)/sbrk.c \ - $(LIBC_STUBS)/close.c \ - $(LIBC_STUBS)/isatty.c \ - $(LIBC_STUBS)/fstat.c \ - $(LIBC_STUBS)/lseek.c \ - $(LIBC_STUBS)/read.c - -SRC_S += \ - $(STARTUP_ASM)/startup_gd32vf103.S \ - $(STARTUP_ASM)/intexc_gd32vf103.S - -INC += \ - $(TOP)/hw/bsp/$(BOARD) \ - $(TOP)/$(NUCLEI_SDK)/NMSIS/Core/Include \ - $(TOP)/$(GD32VF103_SDK_SOC)/Common/Include \ - $(TOP)/$(GD32VF103_SDK_SOC)/Common/Include/Usb \ - $(TOP)/$(LONGAN_NANO_SDK_BSP)/Include - -# For freeRTOS port source -FREERTOS_PORT = RISC-V - -# For flash-jlink target -JLINK_IF = jtag -JLINK_DEVICE = gd32vf103cbt6 # Longan Nano 128k ROM 32k RAM -#JLINK_DEVICE = gd32vf103c8t6 # Longan Nano Lite 64k ROM 20k RAM - -# flash target ROM bootloader -flash: $(BUILD)/$(PROJECT).bin - dfu-util -R -a 0 --dfuse-address 0x08000000 -D $< diff --git a/hw/bsp/gd32vf103_longan_nano/gd32vf103_longan_nano.c b/hw/bsp/gd32vf103_longan_nano/gd32vf103_longan_nano.c deleted file mode 100644 index 951ab844c..000000000 --- a/hw/bsp/gd32vf103_longan_nano/gd32vf103_longan_nano.c +++ /dev/null @@ -1,194 +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. - * - * This file is part of the TinyUSB stack. - */ - -#include "../board.h" -#include "nuclei_sdk_hal.h" - -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ - -void USBFS_IRQHandler(void) { tud_int_handler(0); } - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM -//--------------------------------------------------------------------+ - -#define USB_NO_VBUS_PIN - -// According to GD32VF103 user manual clock tree: -// Systick clock = AHB clock / 4. -#define TIMER_TICKS ((SystemCoreClock / 4) / 1000) - -#define BUTTON_PORT GPIOA -#define BUTTON_PIN GPIO_PIN_0 -#define BUTTON_STATE_ACTIVE 1 - -#define UART_DEV SOC_DEBUG_UART - -#define LED_PIN LED_R - -void board_init(void) { - /* Disable interrupts during init */ - __disable_irq(); - -#if CFG_TUSB_OS == OPT_OS_NONE - SysTick_Config(TIMER_TICKS); -#endif - - rcu_periph_clock_enable(RCU_GPIOA); - rcu_periph_clock_enable(RCU_GPIOB); - rcu_periph_clock_enable(RCU_GPIOC); - rcu_periph_clock_enable(RCU_GPIOD); - rcu_periph_clock_enable(RCU_AF); - -#ifdef BUTTON_PIN - gpio_init(BUTTON_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, BUTTON_PIN); -#endif - -#ifdef LED_PIN - gd_led_init(LED_PIN); -#endif - -#if defined(UART_DEV) - gd_com_init(UART_DEV); -#endif - - /* USB D+ and D- pins don't need to be configured. */ - /* Configure VBUS Pin */ -#ifndef USB_NO_VBUS_PIN - gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_9); -#endif - - /* This for ID line debug */ - // gpio_init(GPIOA, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_10); - - /* Enable USB OTG clock */ - usb_rcu_config(); - - /* Reset USB OTG peripheral */ - rcu_periph_reset_enable(RCU_USBFSRST); - rcu_periph_reset_disable(RCU_USBFSRST); - - /* Configure USBFS IRQ */ - ECLIC_Register_IRQ(USBFS_IRQn, ECLIC_NON_VECTOR_INTERRUPT, - ECLIC_POSTIVE_EDGE_TRIGGER, 3, 0, NULL); - - /* Retrieve otg core registers */ - usb_gr* otg_core_regs = (usb_gr*)(USBFS_REG_BASE + USB_REG_OFFSET_CORE); - -#ifdef USB_NO_VBUS_PIN - /* Disable VBUS sense*/ - otg_core_regs->GCCFG |= GCCFG_VBUSIG | GCCFG_PWRON | GCCFG_VBUSBCEN; -#else - /* Enable VBUS sense via pin PA9 */ - otg_core_regs->GCCFG |= GCCFG_VBUSIG | GCCFG_PWRON | GCCFG_VBUSBCEN; - otg_core_regs->GCCFG &= ~GCCFG_VBUSIG; -#endif - - /* Enable interrupts globaly */ - __enable_irq(); -} - -void gd32vf103_reset(void) { - /* The MTIMER unit of the GD32VF103 doesn't have the MSFRST - * register to generate a software reset request. - * BUT instead two undocumented registers in the debug peripheral - * that allow issueing a software reset. - * https://github.com/esmil/gd32vf103inator/blob/master/include/gd32vf103/dbg.h - */ - DBG_KEY = DBG_KEY_UNLOCK; - DBG_CMD = DBG_CMD_RESET; -} - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) { - state ? gd_led_on(LED_PIN) : gd_led_off(LED_PIN); -} - -uint32_t board_button_read(void) { - return BUTTON_STATE_ACTIVE == gpio_input_bit_get(BUTTON_PORT, BUTTON_PIN); -} - -int board_uart_read(uint8_t* buf, int len) { -#if defined(UART_DEV) - int rxsize = len; - while (rxsize--) { - *(uint8_t*)buf = usart_read(UART_DEV); - buf++; - } - return len; -#else - (void)buf; - (void)len; - return 0; -#endif -} - -int board_uart_write(void const* buf, int len) { -#if defined(UART_DEV) - int txsize = len; - while (txsize--) { - usart_write(UART_DEV, *(uint8_t*)buf); - buf++; - } - return len; -#else - (void)buf; - (void)len; - return 0; -#endif -} - -#if CFG_TUSB_OS == OPT_OS_NONE -volatile uint32_t system_ticks = 0; -void eclic_mtip_handler(void) { - system_ticks++; - SysTick_Reload(TIMER_TICKS); -} -uint32_t board_millis(void) { return system_ticks; } -#endif - -#ifdef USE_FULL_ASSERT -/** - * @brief Reports the name of the source file and the source line number - * where the assert_param error has occurred. - * @param file: pointer to the source file name - * @param line: assert_param error line source number - * @retval None - */ -void assert_failed(char* file, uint32_t line) { - /* USER CODE BEGIN 6 */ - /* User can add his own implementation to report the file name and line - number, - tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) - */ - /* USER CODE END 6 */ -} -#endif /* USE_FULL_ASSERT */ diff --git a/hw/bsp/gd32vf103_longan_nano/nuclei_sdk_hal.h b/hw/bsp/gd32vf103_longan_nano/nuclei_sdk_hal.h deleted file mode 100644 index 9b2a616a8..000000000 --- a/hw/bsp/gd32vf103_longan_nano/nuclei_sdk_hal.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _NUCLEI_SDK_HAL_H -#define _NUCLEI_SDK_HAL_H - -#include "gd32vf103c_longan_nano.h" -#include "drv_usb_hw.h" -#include "drv_usb_dev.h" - -// 4 bits for interrupt level, 0 for priority. -// level 0 = lowest priority, level 15 = highest priority. -#define __ECLIC_INTCTLBITS 4 - -#define __SYSTEM_CLOCK 72000000 -#define HXTAL_VALUE ((uint32_t)8000000) - -#define SOC_DEBUG_UART GD32_COM0 - -#define DBG_KEY_UNLOCK 0x4B5A6978 -#define DBG_CMD_RESET 0x1 -#define DBG_KEY REG32(DBG + 0x0C) -#define DBG_CMD REG32(DBG + 0x08) - -#endif diff --git a/hw/bsp/gd32vf103_longan_nano/system_gd32vf103.c b/hw/bsp/gd32vf103_longan_nano/system_gd32vf103.c deleted file mode 100644 index 8019974d6..000000000 --- a/hw/bsp/gd32vf103_longan_nano/system_gd32vf103.c +++ /dev/null @@ -1,668 +0,0 @@ -/*! - \file system_gd32vf103.h -\brief RISC-V Device Peripheral Access Layer Source File for - GD32VF103 Device Series - -*/ - -/* - Copyright (c) 2020, GigaDevice Semiconductor Inc. - - Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - -/* This file refers the RISC-V standard, some adjustments are made according to GigaDevice chips */ -#include "nuclei_sdk_hal.h" - -/* system frequency define */ -#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */ -#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */ -#define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */ -#define __SYSTEM_CLOCK_HXTAL (HXTAL_VALUE) - -#if !defined(__SYSTEM_CLOCK) -#define __SYSTEM_CLOCK 72000000 -#endif - -#if __SYSTEM_CLOCK == 48000000 - #define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000) - uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_HXTAL; - static void system_clock_48m_hxtal(void); - -#elif __SYSTEM_CLOCK == 72000000 - #define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000) - uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL; - static void system_clock_72m_hxtal(void); - -#elif __SYSTEM_CLOCK == 96000000 - #define __SYSTEM_CLOCK_96M_PLL_HXTAL (uint32_t)(96000000) - uint32_t SystemCoreClock = __SYSTEM_CLOCK_96M_PLL_HXTAL; - static void system_clock_96m_hxtal(void); - -#else -#error No valid system clock configuration set! -#endif - -/* configure the system clock */ -static void system_clock_config(void); - -/*! - \brief configure the system clock - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_config(void) -{ -#if defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) - system_clock_48m_hxtal(); -#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) - system_clock_72m_hxtal(); -#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) - system_clock_96m_hxtal(); -#endif /* __SYSTEM_CLOCK_HXTAL */ -} - -/*! - \brief setup the microcontroller system, initialize the system - \param[in] none - \param[out] none - \retval none -*/ -void SystemInit(void) -{ - /* reset the RCC clock configuration to the default reset state */ - /* enable IRC8M */ - RCU_CTL |= RCU_CTL_IRC8MEN; - - /* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */ - RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | - RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL); - - /* reset HXTALEN, CKMEN, PLLEN bits */ - RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); - - /* Reset HXTALBPS bit */ - RCU_CTL &= ~(RCU_CTL_HXTALBPS); - - /* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */ - - RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | - RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4); - RCU_CFG1 = 0x00000000U; - - /* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */ - RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN); - /* disable all interrupts */ - RCU_INT = 0x00FF0000U; - - /* Configure the System clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */ - system_clock_config(); -} - -/*! - \brief update the SystemCoreClock with current core clock retrieved from cpu registers - \param[in] none - \param[out] none - \retval none -*/ -void SystemCoreClockUpdate(void) -{ - uint32_t scss; - uint32_t pllsel, predv0sel, pllmf, ck_src; - uint32_t predv0, predv1, pll1mf; - - scss = GET_BITS(RCU_CFG0, 2, 3); - - switch (scss) - { - /* IRC8M is selected as CK_SYS */ - case SEL_IRC8M: - SystemCoreClock = IRC8M_VALUE; - break; - - /* HXTAL is selected as CK_SYS */ - case SEL_HXTAL: - SystemCoreClock = HXTAL_VALUE; - break; - - /* PLL is selected as CK_SYS */ - case SEL_PLL: - /* PLL clock source selection, HXTAL or IRC8M/2 */ - pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); - - - if(RCU_PLLSRC_IRC8M_DIV2 == pllsel){ - /* PLL clock source is IRC8M/2 */ - ck_src = IRC8M_VALUE / 2U; - }else{ - /* PLL clock source is HXTAL */ - ck_src = HXTAL_VALUE; - - predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); - - /* source clock use PLL1 */ - if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ - predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; - pll1mf = ((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; - if(17U == pll1mf){ - pll1mf = 20U; - } - ck_src = (ck_src / predv1) * pll1mf; - } - predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; - ck_src /= predv0; - } - - /* PLL multiplication factor */ - pllmf = GET_BITS(RCU_CFG0, 18, 21); - - if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ - pllmf |= 0x10U; - } - - if(pllmf >= 15U){ - pllmf += 1U; - }else{ - pllmf += 2U; - } - - SystemCoreClock = ck_src * pllmf; - - if(15U == pllmf){ - /* PLL source clock multiply by 6.5 */ - SystemCoreClock = ck_src * 6U + ck_src / 2U; - } - - break; - - /* IRC8M is selected as CK_SYS */ - default: - SystemCoreClock = IRC8M_VALUE; - break; - } -} - -#if defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) -/*! - \brief configure the system clock to 48M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_48m_hxtal(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - - /* enable HXTAL */ - RCU_CTL |= RCU_CTL_HXTALEN; - - /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } - } - - /* HXTAL is stable */ - /* AHB = SYSCLK */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - /* CK_PLL = (CK_PREDIV0) * 12 = 48 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL12); - - if(HXTAL_VALUE==25000000){ - - /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ - } - - }else if(HXTAL_VALUE==8000000){ - RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 ); - } - - - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* select PLL as system clock */ - RCU_CFG0 &= ~RCU_CFG0_SCS; - RCU_CFG0 |= RCU_CKSYSSRC_PLL; - - /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ - } -} - -#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) -/*! - \brief configure the system clock to 72M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_72m_hxtal(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - - /* enable HXTAL */ - RCU_CTL |= RCU_CTL_HXTALEN; - - /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } - } - - /* HXTAL is stable */ - /* AHB = SYSCLK */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - /* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL18); - - - if(HXTAL_VALUE==25000000){ - - /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); - - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ - } - - }else if(HXTAL_VALUE==8000000){ - RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 ); - } - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* select PLL as system clock */ - RCU_CFG0 &= ~RCU_CFG0_SCS; - RCU_CFG0 |= RCU_CKSYSSRC_PLL; - - /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ - } -} - -#elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) -/*! - \brief configure the system clock to 96M by PLL which selects HXTAL(MD/HD/XD:8M; CL:25M) as its clock source - \param[in] none - \param[out] none - \retval none -*/ -static void system_clock_96m_hxtal(void) -{ - uint32_t timeout = 0U; - uint32_t stab_flag = 0U; - - /* enable HXTAL */ - RCU_CTL |= RCU_CTL_HXTALEN; - - /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ - timeout++; - stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - - /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ - } - } - - /* HXTAL is stable */ - /* AHB = SYSCLK */ - RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; - /* APB2 = AHB/1 */ - RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; - /* APB1 = AHB/2 */ - RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - - if(HXTAL_VALUE==25000000){ - - /* CK_PLL = (CK_PREDIV0) * 24 = 96 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL24); - - /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ - RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); - /* enable PLL1 */ - RCU_CTL |= RCU_CTL_PLL1EN; - /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ - } - - }else if(HXTAL_VALUE==8000000){ - /* CK_PLL = (CK_PREDIV0) * 24 = 96 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); - RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL24); - - RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0); - RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 ); - } - - /* enable PLL */ - RCU_CTL |= RCU_CTL_PLLEN; - - /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ - } - - /* select PLL as system clock */ - RCU_CFG0 &= ~RCU_CFG0_SCS; - RCU_CFG0 |= RCU_CKSYSSRC_PLL; - - /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ - } -} - -#endif - -/** - * \defgroup NMSIS_Core_IntExcNMI_Handling Interrupt and Exception and NMI Handling - * \brief Functions for interrupt, exception and nmi handle available in system_.c. - * \details - * Nuclei provide a template for interrupt, exception and NMI handling. Silicon Vendor could adapat according - * to their requirement. Silicon vendor could implement interface for different exception code and - * replace current implementation. - * - * @{ - */ -/** \brief Max exception handler number, don't include the NMI(0xFFF) one */ -#define MAX_SYSTEM_EXCEPTION_NUM 12 -/** - * \brief Store the exception handlers for each exception ID - * \note - * - This SystemExceptionHandlers are used to store all the handlers for all - * the exception codes Nuclei N/NX core provided. - * - Exception code 0 - 11, totally 12 exceptions are mapped to SystemExceptionHandlers[0:11] - * - Exception for NMI is also re-routed to exception handling(exception code 0xFFF) in startup code configuration, the handler itself is mapped to SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM] - */ -static unsigned long SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM + 1]; - -/** - * \brief Exception Handler Function Typedef - * \note - * This typedef is only used internal in this system_gd32vf103.c file. - * It is used to do type conversion for registered exception handler before calling it. - */ -typedef void (*EXC_HANDLER)(unsigned long mcause, unsigned long sp); - -/** - * \brief System Default Exception Handler - * \details - * This function provided a default exception and NMI handling code for all exception ids. - * By default, It will just print some information for debug, Vendor can customize it according to its requirements. - */ -static void system_default_exception_handler(unsigned long mcause, unsigned long sp) -{ - /* TODO: Uncomment this if you have implement printf function */ - /*printf("MCAUSE: 0x%lx\r\n", mcause); - printf("MEPC : 0x%lx\r\n", __RV_CSR_READ(CSR_MEPC)); - printf("MTVAL : 0x%lx\r\n", __RV_CSR_READ(CSR_MBADADDR));*/ - while (1); -} - -/** - * \brief Initialize all the default core exception handlers - * \details - * The core exception handler for each exception id will be initialized to \ref system_default_exception_handler. - * \note - * Called in \ref _init function, used to initialize default exception handlers for all exception IDs - */ -static void Exception_Init(void) -{ - for (int i = 0; i < MAX_SYSTEM_EXCEPTION_NUM + 1; i++) { - SystemExceptionHandlers[i] = (unsigned long)system_default_exception_handler; - } -} - -/** - * \brief Register an exception handler for exception code EXCn - * \details - * * For EXCn < \ref MAX_SYSTEM_EXCEPTION_NUM, it will be registered into SystemExceptionHandlers[EXCn-1]. - * * For EXCn == NMI_EXCn, it will be registered into SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM]. - * \param EXCn See \ref EXCn_Type - * \param exc_handler The exception handler for this exception code EXCn - */ -void Exception_Register_EXC(uint32_t EXCn, unsigned long exc_handler) -{ - if ((EXCn < MAX_SYSTEM_EXCEPTION_NUM) && (EXCn != 0)) { - SystemExceptionHandlers[EXCn] = exc_handler; - } else if (EXCn == NMI_EXCn) { - SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM] = exc_handler; - } -} - -/** - * \brief Get current exception handler for exception code EXCn - * \details - * * For EXCn < \ref MAX_SYSTEM_EXCEPTION_NUM, it will return SystemExceptionHandlers[EXCn-1]. - * * For EXCn == NMI_EXCn, it will return SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM]. - * \param EXCn See \ref EXCn_Type - * \return Current exception handler for exception code EXCn, if not found, return 0. - */ -unsigned long Exception_Get_EXC(uint32_t EXCn) -{ - if ((EXCn < MAX_SYSTEM_EXCEPTION_NUM) && (EXCn != 0)) { - return SystemExceptionHandlers[EXCn]; - } else if (EXCn == NMI_EXCn) { - return SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM]; - } else { - return 0; - } -} - -/** - * \brief Common NMI and Exception handler entry - * \details - * This function provided a command entry for NMI and exception. Silicon Vendor could modify - * this template implementation according to requirement. - * \remarks - * - RISCV provided common entry for all types of exception. This is proposed code template - * for exception entry function, Silicon Vendor could modify the implementation. - * - For the core_exception_handler template, we provided exception register function \ref Exception_Register_EXC - * which can help developer to register your exception handler for specific exception number. - */ -uint32_t core_exception_handler(unsigned long mcause, unsigned long sp) -{ - uint32_t EXCn = (uint32_t)(mcause & 0X00000fff); - EXC_HANDLER exc_handler; - - if ((EXCn < MAX_SYSTEM_EXCEPTION_NUM) && (EXCn > 0)) { - exc_handler = (EXC_HANDLER)SystemExceptionHandlers[EXCn]; - } else if (EXCn == NMI_EXCn) { - exc_handler = (EXC_HANDLER)SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM]; - } else { - exc_handler = (EXC_HANDLER)system_default_exception_handler; - } - if (exc_handler != NULL) { - exc_handler(mcause, sp); - } - return 0; -} -/** @} */ /* End of Doxygen Group NMSIS_Core_ExceptionAndNMI */ - -/** - * \brief initialize eclic config - * \details - * Eclic need initialize after boot up, Vendor could also change the initialization - * configuration. - */ -void ECLIC_Init(void) -{ - /* TODO: Add your own initialization code here. This function will be called by main */ - ECLIC_SetMth(0); - ECLIC_SetCfgNlbits(__ECLIC_INTCTLBITS); -} - -/** - * \brief Initialize a specific IRQ and register the handler - * \details - * This function set vector mode, trigger mode and polarity, interrupt level and priority, - * assign handler for specific IRQn. - * \param [in] IRQn NMI interrupt handler address - * \param [in] shv \ref ECLIC_NON_VECTOR_INTERRUPT means non-vector mode, and \ref ECLIC_VECTOR_INTERRUPT is vector mode - * \param [in] trig_mode see \ref ECLIC_TRIGGER_Type - * \param [in] lvl interupt level - * \param [in] priority interrupt priority - * \param [in] handler interrupt handler, if NULL, handler will not be installed - * \return -1 means invalid input parameter. 0 means successful. - * \remarks - * - This function use to configure specific eclic interrupt and register its interrupt handler and enable its interrupt. - * - If the vector table is placed in read-only section(FLASHXIP mode), handler could not be installed - */ -int32_t ECLIC_Register_IRQ(IRQn_Type IRQn, uint8_t shv, ECLIC_TRIGGER_Type trig_mode, uint8_t lvl, uint8_t priority, void* handler) -{ - if ((IRQn > SOC_INT_MAX) || (shv > ECLIC_VECTOR_INTERRUPT) \ - || (trig_mode > ECLIC_NEGTIVE_EDGE_TRIGGER)) { - return -1; - } - - /* set interrupt vector mode */ - ECLIC_SetShvIRQ(IRQn, shv); - /* set interrupt trigger mode and polarity */ - ECLIC_SetTrigIRQ(IRQn, trig_mode); - /* set interrupt level */ - ECLIC_SetLevelIRQ(IRQn, lvl); - /* set interrupt priority */ - ECLIC_SetPriorityIRQ(IRQn, priority); - if (handler != NULL) { - /* set interrupt handler entry to vector table */ - ECLIC_SetVector(IRQn, (rv_csr_t)handler); - } - /* enable interrupt */ - ECLIC_EnableIRQ(IRQn); - return 0; -} -/** @} */ /* End of Doxygen Group NMSIS_Core_ExceptionAndNMI */ - -/** - * \brief early init function before main - * \details - * This function is executed right before main function. - * For RISC-V gnu toolchain, _init function might not be called - * by __libc_init_array function, so we defined a new function - * to do initialization - */ -void _premain_init(void) -{ - /* Initialize exception default handlers */ - Exception_Init(); - /* ECLIC initialization, mainly MTH and NLBIT */ - ECLIC_Init(); -} - -/** - * \brief finish function after main - * \param [in] status status code return from main - * \details - * This function is executed right after main function. - * For RISC-V gnu toolchain, _fini function might not be called - * by __libc_fini_array function, so we defined a new function - * to do initialization - */ -void _postmain_fini(int status) -{ - /* TODO: Add your own finishing code here, called after main */ -} - -/** - * \brief _init function called in __libc_init_array() - * \details - * This `__libc_init_array()` function is called during startup code, - * user need to implement this function, otherwise when link it will - * error init.c:(.text.__libc_init_array+0x26): undefined reference to `_init' - * \note - * Please use \ref _premain_init function now - */ -void _init(void) -{ - /* Don't put any code here, please use _premain_init now */ -} - -/** - * \brief _fini function called in __libc_fini_array() - * \details - * This `__libc_fini_array()` function is called when exit main. - * user need to implement this function, otherwise when link it will - * error fini.c:(.text.__libc_fini_array+0x28): undefined reference to `_fini' - * \note - * Please use \ref _postmain_fini function now - */ -void _fini(void) -{ - /* Don't put any code here, please use _postmain_fini now */ -} - -/** @} */ /* End of Doxygen Group NMSIS_Core_SystemAndClock */ diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index b8f6ceda2..ea19080ae 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -303,6 +303,8 @@ static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, tusb_speed_t speed) // Turnaround timeout depends on the MCU clock uint32_t turnaround; + TU_LOG_INT(2, SystemCoreClock); + if ( SystemCoreClock >= 32000000U ) turnaround = 0x6U; else if ( SystemCoreClock >= 27500000U ) @@ -646,6 +648,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) _allocated_fifo_words_tx += fifo_size; + TU_LOG(2, " Allocated %u bytes at offset %u", fifo_size*4, EP_FIFO_SIZE-_allocated_fifo_words_tx*4); + // DIEPTXF starts at FIFO #1. // Both TXFD and TXSA are in unit of 32-bit words. usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | (EP_FIFO_SIZE/4 - _allocated_fifo_words_tx); -- cgit v1.3.1 From ab2eec77d46b0c4984ff0daa13467dde2dc4ad3c Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 16 Aug 2021 20:22:14 +0700 Subject: complete suspend, resume, remote wakeup for nrf52 --- src/device/usbd.c | 29 ++++++++-- src/portable/nordic/nrf5x/dcd_nrf5x.c | 103 ++++++++++++++++++++++++---------- 2 files changed, 97 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index a30eab217..538964a3d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -37,6 +37,9 @@ // USBD Configuration //--------------------------------------------------------------------+ +// Debug level of USBD +#define USBD_DBG_LVL 2 + #ifndef CFG_TUD_TASK_QUEUE_SZ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif @@ -556,7 +559,7 @@ void tud_task (void) break; case DCD_EVENT_SUSPEND: - TU_LOG2("\r\n"); + TU_LOG2(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en); if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); break; @@ -684,6 +687,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Only support remote wakeup for device feature TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); + TU_LOG(USBD_DBG_LVL, " Enable Remote Wakeup\r\n"); + // Host may enable remote wake up before suspending especially HID device _usbd_dev.remote_wakeup_en = true; tud_control_status(rhport, p_request); @@ -693,6 +698,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Only support remote wakeup for device feature TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); + TU_LOG(USBD_DBG_LVL, " Disable Remote Wakeup\r\n"); + // Host may disable remote wake up after resuming _usbd_dev.remote_wakeup_en = false; tud_control_status(rhport, p_request); @@ -1036,10 +1043,6 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) } break; - case DCD_EVENT_SOF: - return; // skip SOF event for now - break; - case DCD_EVENT_SUSPEND: // NOTE: When plugging/unplugging device, the D+/D- state are unstable and // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ). @@ -1061,6 +1064,17 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) } break; + case DCD_EVENT_SOF: + // Some MCUs after running dcd_remote_wakeup() does not have way to detect the end of remote wakeup + // which last 1-15 ms. DCD can use SOF as a clear indicator that bus is back to operational + if ( _usbd_dev.suspended ) + { + _usbd_dev.suspended = 0; + dcd_event_t const event_resume = { .rhport = event->rhport, .event_id = DCD_EVENT_RESUME }; + osal_queue_send(_usbd_q, &event_resume, in_isr); + } + break; + default: osal_queue_send(_usbd_q, event, in_isr); break; @@ -1312,6 +1326,8 @@ bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { + TU_LOG(USBD_DBG_LVL, " Stall EP %02X", ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -1322,9 +1338,12 @@ void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { + TU_LOG(USBD_DBG_LVL, " Clear Stall EP %02X", ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + dcd_edpt_clear_stall(rhport, ep_addr); _usbd_dev.ep_status[epnum][dir].stalled = false; _usbd_dev.ep_status[epnum][dir].busy = false; diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 5f4fe08ad..f6b64c986 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -85,7 +85,7 @@ static struct // Number of pending DMA that is started but not handled yet by dcd_int_handler(). // Since nRF can only carry one DMA can run at a time, this value is normally be either 0 or 1. // However, in critical section with interrupt disabled, the DMA can be finished and added up - // until handled by dcd_init_handler() when exiting critical section. + // until handled by dcd_int_handler() when exiting critical section. volatile uint8_t dma_pending; }_dcd; @@ -277,14 +277,8 @@ void dcd_remote_wakeup(uint8_t rhport) (void) rhport; // Bring controller out of low power mode + // will start wakeup when USBWUALLOWED is set NRF_USBD->LOWPOWER = 0; - - // Initiate RESUME signal - NRF_USBD->DPDMVALUE = USBD_DPDMVALUE_STATE_Resume; - NRF_USBD->TASKS_DPDMDRIVE = 1; - - // TODO There is no USBEVENT Resume interrupt - // We may manually raise DCD_EVENT_RESUME event here } // disconnect by disabling internal pull-up resistor on D+/D- @@ -339,10 +333,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { // SPLIT ISO buffer when ISO IN endpoint is already opened. if (_dcd.xfer[EP_ISO_NUM][TUSB_DIR_IN].mps) NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN; + // Clear old events NRF_USBD->EVENTS_ENDISOOUT = 0; + // Clear SOF event in case interrupt was not enabled yet. if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0) NRF_USBD->EVENTS_SOF = 0; + // Enable SOF and ISOOUT interrupts, and ISOOUT endpoint. NRF_USBD->INTENSET = USBD_INTENSET_ENDISOOUT_Msk | USBD_INTENSET_SOF_Msk; NRF_USBD->EPOUTEN |= USBD_EPOUTEN_ISOOUT_Msk; @@ -350,10 +347,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) else { NRF_USBD->EVENTS_ENDISOIN = 0; + // SPLIT ISO buffer when ISO OUT endpoint is already opened. if (_dcd.xfer[EP_ISO_NUM][TUSB_DIR_OUT].mps) NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN; + // Clear SOF event in case interrupt was not enabled yet. if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0) NRF_USBD->EVENTS_SOF = 0; + // Enable SOF and ISOIN interrupts, and ISOIN endpoint. NRF_USBD->INTENSET = USBD_INTENSET_ENDISOIN_Msk | USBD_INTENSET_SOF_Msk; NRF_USBD->EPINEN |= USBD_EPINEN_ISOIN_Msk; @@ -507,6 +507,8 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) *------------------------------------------------------------------*/ void bus_reset(void) { + // 6.35.6 USB controller automatically disabled all endpoints (except control) + // i.e EPOUTEN and EPINEN and reset USBADDR to 0 for(int i=0; i<8; i++) { NRF_USBD->TASKS_STARTEPIN[i] = 0; @@ -516,6 +518,15 @@ void bus_reset(void) NRF_USBD->TASKS_STARTISOIN = 0; NRF_USBD->TASKS_STARTISOOUT = 0; + // Clear USB Event Interrupt + NRF_USBD->EVENTS_USBEVENT = 0; + NRF_USBD->EVENTCAUSE |= NRF_USBD->EVENTCAUSE; + + // Reset interrupt + NRF_USBD->INTENCLR = NRF_USBD->INTEN; + NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_EPDATA_Msk | + USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk; + tu_varclr(&_dcd); _dcd.xfer[0][TUSB_DIR_IN].mps = MAX_PACKET_SIZE; _dcd.xfer[0][TUSB_DIR_OUT].mps = MAX_PACKET_SIZE; @@ -561,39 +572,71 @@ void dcd_int_handler(uint8_t rhport) if ( int_status & USBD_INTEN_SOF_Msk ) { + bool iso_enabled = false; + // ISOOUT: Transfer data gathered in previous frame from buffer to RAM if (NRF_USBD->EPOUTEN & USBD_EPOUTEN_ISOOUT_Msk) { + iso_enabled = true; xact_out_dma(EP_ISO_NUM); } + // ISOIN: Notify client that data was transferred - xfer_td_t* xfer = get_td(EP_ISO_NUM, TUSB_DIR_IN); - if ( xfer->iso_in_transfer_ready ) + if (NRF_USBD->EPINEN & USBD_EPINEN_ISOIN_Msk) { - xfer->iso_in_transfer_ready = false; - dcd_event_xfer_complete(0, EP_ISO_NUM | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true); + iso_enabled = true; + + xfer_td_t* xfer = get_td(EP_ISO_NUM, TUSB_DIR_IN); + if ( xfer->iso_in_transfer_ready ) + { + xfer->iso_in_transfer_ready = false; + dcd_event_xfer_complete(0, EP_ISO_NUM | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true); + } } + + if ( !iso_enabled ) + { + // ISO endpoint is not used, SOF is only enabled one-time for remote wakeup + // so we disable it now + NRF_USBD->INTENCLR = USBD_INTENSET_SOF_Msk; + } + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } if ( int_status & USBD_INTEN_USBEVENT_Msk ) { - uint32_t const evt_cause = NRF_USBD->EVENTCAUSE & (USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk); + TU_LOG(2, "EVENTCAUSE = 0x%04lX\r\n", NRF_USBD->EVENTCAUSE); + + enum { EVT_CAUSE_MASK = USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk | USBD_EVENTCAUSE_USBWUALLOWED_Msk }; + uint32_t const evt_cause = NRF_USBD->EVENTCAUSE & EVT_CAUSE_MASK; NRF_USBD->EVENTCAUSE = evt_cause; // clear interrupt if ( evt_cause & USBD_EVENTCAUSE_SUSPEND_Msk ) { - dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); - // Put controller into low power mode + // Leave HFXO disable to application, since it may be used by other peripherals NRF_USBD->LOWPOWER = 1; - // Leave HFXO disable to application, since it may be used by other + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } - if ( evt_cause & USBD_EVENTCAUSE_RESUME_Msk ) + if ( evt_cause & USBD_EVENTCAUSE_USBWUALLOWED_Msk ) { - dcd_event_bus_signal(0, DCD_EVENT_RESUME , true); + // USB is out of low power mode, and wakeup is allowed + // Initiate RESUME signal + NRF_USBD->DPDMVALUE = USBD_DPDMVALUE_STATE_Resume; + NRF_USBD->TASKS_DPDMDRIVE = 1; + + // There is no Resume interrupt for remote wakeup, enable SOF for to report bus ready state + // Clear SOF event in case interrupt was not enabled yet. + if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0) NRF_USBD->EVENTS_SOF = 0; + NRF_USBD->INTENSET = USBD_INTENSET_SOF_Msk; + } + + if ( evt_cause & USBD_EVENTCAUSE_RESUME_Msk ) + { + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } } @@ -845,18 +888,22 @@ void tusb_hal_nrf_power_event (uint32_t event) USB_EVT_READY = 2 }; +#if CFG_TUSB_DEBUG >= 2 + const char* const power_evt_str[] = { "Detected", "Removed", "Ready" }; + TU_LOG(2, "Power USB event: %s\r\n", power_evt_str[event]); +#endif + switch ( event ) { case USB_EVT_DETECTED: - TU_LOG2("Power USB Detect\r\n"); - if ( !NRF_USBD->ENABLE ) { - /* Prepare for READY event receiving */ + // Prepare for receiving READY event: disable interrupt since we will blocking wait + NRF_USBD->INTENCLR = USBD_INTEN_USBEVENT_Msk; NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk; __ISB(); __DSB(); // for sync -#ifdef NRF52_SERIES +#ifdef NRF52_SERIES // NRF53 does not need this errata // ERRATA 171, 187, 166 if ( nrfx_usbd_errata_187() ) { @@ -891,7 +938,7 @@ void tusb_hal_nrf_power_event (uint32_t event) } #endif - /* Enable the peripheral */ + // Enable the peripheral (will cause Ready event) NRF_USBD->ENABLE = 1; __ISB(); __DSB(); // for sync @@ -901,13 +948,11 @@ void tusb_hal_nrf_power_event (uint32_t event) break; case USB_EVT_READY: - TU_LOG2("Power USB Ready\r\n"); - // Skip if pull-up is enabled and HCLK is already running. // Application probably call this more than necessary. if ( NRF_USBD->USBPULLUP && hfclk_running() ) break; - /* Waiting for USBD peripheral enabled */ + // Waiting for USBD peripheral enabled while ( !(USBD_EVENTCAUSE_READY_Msk & NRF_USBD->EVENTCAUSE) ) { } NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk; @@ -959,9 +1004,8 @@ void tusb_hal_nrf_power_event (uint32_t event) // ISO buffer Lower half for IN, upper half for OUT NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN; - // Enable interrupt - NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_EPDATA_Msk | - USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk; + // Enable bus-reset interrupt + NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk; // Enable interrupt, priorities should be set by application NVIC_ClearPendingIRQ(USBD_IRQn); @@ -976,7 +1020,6 @@ void tusb_hal_nrf_power_event (uint32_t event) break; case USB_EVT_REMOVED: - TU_LOG2("Power USB Removed\r\n"); if ( NRF_USBD->ENABLE ) { // Abort all transfers -- cgit v1.3.1 From 26d347be17b68b4c4e22cb3af69bb9428d300c3a Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 16 Aug 2021 20:24:07 +0700 Subject: add note for renesas rx remote wakeup --- src/portable/renesas/usba/dcd_usba.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 739861413..1db1fdb32 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -824,6 +824,8 @@ void dcd_int_handler(uint8_t rhport) * Therefore we need to manually send resume event. * Of course, when USB host resumes on its own, * RESM interrupt rise properly, then this statements are ignored. */ + // TODO can be dropped since this logic is implemented by usbd + // USBD will exit suspended mode when SOF event is received dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); _dcd.suspended = 0; } -- cgit v1.3.1 From 7aff4b178ec415a5d5af2eaebc87e99098037cb8 Mon Sep 17 00:00:00 2001 From: Mengsk Date: Tue, 17 Aug 2021 00:19:24 +0200 Subject: use USBD_MemCopy. --- src/portable/nuvoton/nuc121/dcd_nuc121.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 37b7b0106..959c2eeb0 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -101,6 +101,11 @@ static void usb_detach(void) USBD->SE0 |= USBD_SE0_SE0_Msk; } +static void usb_memcpy(uint8_t *dest, uint8_t *src, uint16_t size) +{ + while(size--) *dest++ = *src++; +} + static void usb_control_send_zlp(void) { USBD->EP[PERIPH_EP0].CFG |= USBD_CFG_DSQSYNC_Msk; @@ -153,7 +158,7 @@ static void dcd_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) else #endif { - memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); + usb_memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); } ep->MXPLD = bytes_now; @@ -252,7 +257,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) /* mine the data for the information we need */ int const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); int const size = p_endpoint_desc->wMaxPacketSize.size; - tusb_xfer_type_t const type = p_endpoint_desc->bmAttributes.xfer; + tusb_xfer_type_t const type = (tusb_xfer_type_t)p_endpoint_desc->bmAttributes.xfer; struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; /* allocate buffer from USB RAM */ @@ -450,7 +455,7 @@ void dcd_int_handler(uint8_t rhport) else #endif { - memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); + usb_memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); xfer->data_ptr += available_bytes; } -- cgit v1.3.1 From a6d18c400ddc6b61f665baae5672ed46af17c99c Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 17 Aug 2021 13:29:26 +0700 Subject: fix keyboard report reserved is always 0 --- src/class/hid/hid_device.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index a10e3a5e3..2ee80750a 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -121,6 +121,7 @@ bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modi hid_keyboard_report_t report; report.modifier = modifier; + report.reserved = 0; if ( keycode ) { -- cgit v1.3.1 From 9b869463ddd7277befa30f8e781b9d72ae005c07 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 17 Aug 2021 17:00:53 +0700 Subject: skipped suspend/resume if not connected --- src/device/usbd.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 538964a3d..e8a50352c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -559,13 +559,28 @@ void tud_task (void) break; case DCD_EVENT_SUSPEND: - TU_LOG2(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en); - if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); + // NOTE: When plugging/unplugging device, the D+/D- state are unstable and + // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ), which result in a series of event + // e.g suspend -> resume -> unplug/plug. Skip suspend/resume if not connected + if ( _usbd_dev.connected ) + { + TU_LOG2(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en); + if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); + }else + { + TU_LOG2(" Skipped\r\n"); + } break; case DCD_EVENT_RESUME: - TU_LOG2("\r\n"); - if (tud_resume_cb) tud_resume_cb(); + if ( _usbd_dev.connected ) + { + TU_LOG2("\r\n"); + if (tud_resume_cb) tud_resume_cb(); + }else + { + TU_LOG2(" Skipped\r\n"); + } break; case DCD_EVENT_SOF: -- cgit v1.3.1 From 3e8276846ec4db204caf0e3136871b9f4e6b5c81 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 18 Aug 2021 16:38:13 +0700 Subject: correct usb memcpy for nuc120 as well --- src/portable/nuvoton/nuc120/dcd_nuc120.c | 13 ++++++++++--- src/portable/nuvoton/nuc121/dcd_nuc121.c | 6 ++++-- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 047fa3fa6..57cc76e81 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -99,6 +99,11 @@ static void usb_detach(void) USBD->DRVSE0 |= USBD_DRVSE0_DRVSE0_Msk; } +static inline void usb_memcpy(uint8_t *dest, uint8_t *src, uint16_t size) +{ + while(size--) *dest++ = *src++; +} + static void usb_control_send_zlp(void) { USBD->EP[PERIPH_EP0].CFG |= USBD_CFG_DSQ_SYNC_Msk; @@ -151,7 +156,8 @@ static void dcd_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) else #endif { - memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); + // USB SRAM seems to only support byte access and memcpy could possibly do it by words + usb_memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); } ep->MXPLD = bytes_now; @@ -246,7 +252,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) /* mine the data for the information we need */ int const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); int const size = p_endpoint_desc->wMaxPacketSize.size; - tusb_xfer_type_t const type = p_endpoint_desc->bmAttributes.xfer; + tusb_xfer_type_t const type = (tusb_xfer_type_t) p_endpoint_desc->bmAttributes.xfer; struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; /* allocate buffer from USB RAM */ @@ -439,7 +445,8 @@ void dcd_int_handler(uint8_t rhport) else #endif { - memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); + // USB SRAM seems to only support byte access and memcpy could possibly do it by words + usb_memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); xfer->data_ptr += available_bytes; } diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 959c2eeb0..20519ec28 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -101,7 +101,7 @@ static void usb_detach(void) USBD->SE0 |= USBD_SE0_SE0_Msk; } -static void usb_memcpy(uint8_t *dest, uint8_t *src, uint16_t size) +static inline void usb_memcpy(uint8_t *dest, uint8_t *src, uint16_t size) { while(size--) *dest++ = *src++; } @@ -158,6 +158,7 @@ static void dcd_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep) else #endif { + // USB SRAM seems to only support byte access and memcpy could possibly do it by words usb_memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); } @@ -257,7 +258,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) /* mine the data for the information we need */ int const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); int const size = p_endpoint_desc->wMaxPacketSize.size; - tusb_xfer_type_t const type = (tusb_xfer_type_t)p_endpoint_desc->bmAttributes.xfer; + tusb_xfer_type_t const type = (tusb_xfer_type_t) p_endpoint_desc->bmAttributes.xfer; struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP]; /* allocate buffer from USB RAM */ @@ -455,6 +456,7 @@ void dcd_int_handler(uint8_t rhport) else #endif { + // USB SRAM seems to only support byte access and memcpy could possibly do it by words usb_memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); xfer->data_ptr += available_bytes; } -- cgit v1.3.1 From 351581537f47a9cca84e1b4f13af704c0effaa78 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Tue, 17 Aug 2021 23:13:11 +0900 Subject: Removes redundant SOF processing from the Renesas RX family. The same logic regarding the resume signal was implemented by usbd. See also: #1023 --- src/portable/renesas/usba/dcd_usba.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index 1db1fdb32..cdc66079a 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -139,7 +139,6 @@ typedef struct { pipe_state_t pipe[10]; uint8_t ep[2][16]; /* a lookup table for a pipe index from an endpoint address */ - uint8_t suspended; } dcd_data_t; //--------------------------------------------------------------------+ @@ -815,20 +814,9 @@ void dcd_int_handler(uint8_t rhport) } if (is0 & USB_IS0_RESM) { dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); - _dcd.suspended = 0; } if (is0 & USB_IS0_SOFR) { - if (_dcd.suspended) { - /* When USB host resumes caused by `dcd_remote_wakeup()`, - * RESM interrupt does not rise. - * Therefore we need to manually send resume event. - * Of course, when USB host resumes on its own, - * RESM interrupt rise properly, then this statements are ignored. */ - // TODO can be dropped since this logic is implemented by usbd - // USBD will exit suspended mode when SOF event is received - dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); - _dcd.suspended = 0; - } + // USBD will exit suspended mode when SOF event is received dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); } if (is0 & USB_IS0_DVST) { @@ -844,7 +832,6 @@ void dcd_int_handler(uint8_t rhport) case USB_IS0_DVSQ_SUSP2: case USB_IS0_DVSQ_SUSP3: dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); - _dcd.suspended = 1; default: break; } -- cgit v1.3.1 From ff59e98a6ab29c70cdf743db7412ddb609e32730 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Thu, 19 Aug 2021 23:57:34 +0900 Subject: Add compile switch to enable SOF during suspend only --- src/portable/renesas/usba/dcd_usba.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c index cdc66079a..095dcc136 100644 --- a/src/portable/renesas/usba/dcd_usba.c +++ b/src/portable/renesas/usba/dcd_usba.c @@ -27,6 +27,10 @@ #include "tusb_option.h" +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#define USE_SOF 0 + #if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_RX63X || \ CFG_TUSB_MCU == OPT_MCU_RX65X || \ CFG_TUSB_MCU == OPT_MCU_RX72N ) @@ -626,7 +630,7 @@ void dcd_init(uint8_t rhport) /* Setup default control pipe */ USB0.DCPMAXP.BIT.MXPS = 64; USB0.INTENB0.WORD = USB_IS0_VBINT | USB_IS0_BRDY | USB_IS0_BEMP | - USB_IS0_DVST | USB_IS0_CTRT | USB_IS0_SOFR | USB_IS0_RESM; + USB_IS0_DVST | USB_IS0_CTRT | (USE_SOF ? USB_IS0_SOFR: 0) | USB_IS0_RESM; USB0.BEMPENB.WORD = 1; USB0.BRDYENB.WORD = 1; @@ -814,10 +818,16 @@ void dcd_int_handler(uint8_t rhport) } if (is0 & USB_IS0_RESM) { dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); +#if (0==USE_SOF) + USB0.INTENB0.BIT.SOFE = 0; +#endif } - if (is0 & USB_IS0_SOFR) { + if ((is0 & USB_IS0_SOFR) && USB0.INTENB0.BIT.SOFE) { // USBD will exit suspended mode when SOF event is received dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); +#if (0==USE_SOF) + USB0.INTENB0.BIT.SOFE = 0; +#endif } if (is0 & USB_IS0_DVST) { switch (is0 & USB_IS0_DVSQ) { @@ -832,6 +842,9 @@ void dcd_int_handler(uint8_t rhport) case USB_IS0_DVSQ_SUSP2: case USB_IS0_DVSQ_SUSP3: dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); +#if (0==USE_SOF) + USB0.INTENB0.BIT.SOFE = 1; +#endif default: break; } -- cgit v1.3.1 From 1cef2b6a42d93704847c1a6ab82617e5baf04f4a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Aug 2021 18:01:10 +0700 Subject: extra common edpt helper for device and host stack tu_edpt_validate() and tu_edpt_bind_driver() --- src/common/tusb_common.h | 14 ++ src/device/usbd.c | 58 +------- src/host/usbh.c | 338 ++++++++++++++++++++++++-------------------- src/host/usbh_classdriver.h | 2 + src/tusb.c | 62 ++++++++ 5 files changed, 265 insertions(+), 209 deletions(-) (limited to 'src') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index c8a66a879..302e75277 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -73,6 +73,20 @@ #include "tusb_error.h" // TODO remove #include "tusb_timeout.h" // TODO remove +//--------------------------------------------------------------------+ +// Internal Helper used by Host and Device Stack +//--------------------------------------------------------------------+ + +// Check if endpoint descriptor is valid per USB specs +bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed); + +// Bind all endpoint of a interface descriptor to class driver +void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id); + +//--------------------------------------------------------------------+ +// Internal Inline Functions +//--------------------------------------------------------------------+ + //------------- Mem -------------// #define tu_memclr(buffer, size) memset((buffer), 0, (size)) #define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) diff --git a/src/device/usbd.c b/src/device/usbd.c index 8b4f4e7e3..23f174dab 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -274,7 +274,6 @@ static osal_mutex_t _usbd_mutex; //--------------------------------------------------------------------+ // Prototypes //--------------------------------------------------------------------+ -static void mark_interface_endpoint(uint8_t ep2drv[][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); static bool process_set_config(uint8_t rhport, uint8_t cfg_num); static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); @@ -901,7 +900,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) } } - mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor + // bind all endpoints for this driver + tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id); p_desc += drv_len; // next interface @@ -919,25 +919,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) return true; } -// Helper marking endpoint of interface belongs to class driver -static void mark_interface_endpoint(uint8_t ep2drv[][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) -{ - uint16_t len = 0; - - while( len < desc_len ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - - ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; - } - - len = (uint16_t)(len + tu_desc_len(p_desc)); - p_desc = tu_desc_next(p_desc); - } -} - // return descriptor's buffer and update desc_len static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request) { @@ -1177,41 +1158,8 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { - uint16_t const max_packet_size = tu_le16toh(desc_ep->wMaxPacketSize.size); - - TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX); - - switch (desc_ep->bmAttributes.xfer) - { - case TUSB_XFER_ISOCHRONOUS: - { - uint16_t const spec_size = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023); - TU_ASSERT(max_packet_size <= spec_size); - } - break; - - case TUSB_XFER_BULK: - if (_usbd_dev.speed == TUSB_SPEED_HIGH) - { - // Bulk highspeed must be EXACTLY 512 - TU_ASSERT(max_packet_size == 512); - }else - { - // TODO Bulk fullspeed can only be 8, 16, 32, 64 - TU_ASSERT(max_packet_size <= 64); - } - break; - - case TUSB_XFER_INTERRUPT: - { - uint16_t const spec_size = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 64); - TU_ASSERT(max_packet_size <= spec_size); - } - break; - - default: return false; - } + TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed)); return dcd_edpt_open(rhport, desc_ep); } diff --git a/src/host/usbh.c b/src/host/usbh.c index 93621c42a..36c2ea7c8 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -28,16 +28,23 @@ #if TUSB_OPT_HOST_ENABLED -#ifndef CFG_TUH_TASK_QUEUE_SZ -#define CFG_TUH_TASK_QUEUE_SZ 16 -#endif - #include "tusb.h" #include "host/usbh.h" #include "host/usbh_classdriver.h" #include "hub.h" #include "usbh_hcd.h" +//--------------------------------------------------------------------+ +// USBH Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUH_TASK_QUEUE_SZ +#define CFG_TUH_TASK_QUEUE_SZ 16 +#endif + +// Debug level of USBD +#define USBH_DBG_LVL 2 + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -135,6 +142,7 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_EN //------------- Helper Function Prototypes -------------// static bool enum_new_device(hcd_event_t* event); static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); +static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); // from usbh_control.c extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); @@ -314,151 +322,6 @@ uint8_t* usbh_get_enum_buf(void) return _usbh_ctrl_buf; } -//--------------------------------------------------------------------+ -// Endpoint API -//--------------------------------------------------------------------+ - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = &_usbh_devices[dev_addr]; - -#if CFG_TUSB_OS != OPT_OS_NONE - // pre-check to help reducing mutex lock - TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0)); - osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif - - // can only claim the endpoint if it is not busy and not claimed yet. - bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0); - if (ret) - { - dev->ep_status[epnum][dir].claimed = 1; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(dev->mutex); -#endif - - return ret; -} - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = &_usbh_devices[dev_addr]; - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); -#endif - - // can only release the endpoint if it is claimed and not busy - bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1); - if (ret) - { - dev->ep_status[epnum][dir].claimed = 0; - } - -#if CFG_TUSB_OS != OPT_OS_NONE - osal_mutex_unlock(dev->mutex); -#endif - - return ret; -} - -// TODO has some duplication code with device, refactor later -bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = &_usbh_devices[dev_addr]; - - TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); - - // Attempt to transfer on a busy endpoint, sound like an race condition ! - TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); - - // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() - // could return and USBH task can preempt and clear the busy - dev->ep_status[epnum][dir].busy = true; - - if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) - { - TU_LOG2("OK\r\n"); - return true; - }else - { - // HCD error, mark endpoint as ready to allow next transfer - dev->ep_status[epnum][dir].busy = false; - dev->ep_status[epnum][dir].claimed = 0; - TU_LOG2("failed\r\n"); - TU_BREAKPOINT(); - return false; - } -} - -bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) -{ - TU_LOG2("Open EP Control with Size = %u\r\n", max_packet_size); - - tusb_desc_endpoint_t ep0_desc = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = 0, - .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, - .wMaxPacketSize = { .size = max_packet_size }, - .bInterval = 0 - }; - - return hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc); -} - -bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) -{ - TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size); - - bool ret = hcd_edpt_open(rhport, dev_addr, desc_ep); - - if (ret) - { - usbh_device_t* dev = &_usbh_devices[dev_addr]; - - // new endpoints belongs to latest interface (last valid value) - // TODO FIXME not true with ISO - uint8_t drvid = 0xff; - for(uint8_t i=0; i < sizeof(dev->itf2drv); i++) - { - if ( dev->itf2drv[i] == 0xff ) break; - drvid = dev->itf2drv[i]; - } - TU_ASSERT(drvid < USBH_CLASS_DRIVER_COUNT); - - uint8_t const ep_addr = desc_ep->bEndpointAddress; - dev->ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = drvid; - } - - return ret; -} - -bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - usbh_device_t* dev = &_usbh_devices[dev_addr]; - - return dev->ep_status[epnum][dir].busy; -} - - //--------------------------------------------------------------------+ // HCD Event Handler //--------------------------------------------------------------------+ @@ -841,7 +704,7 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c dev0->state = TUSB_DEVICE_STATE_UNPLUG; // open control pipe for new address - TU_ASSERT ( usbh_edpt_control_open(new_addr, new_dev->ep0_packet_size) ); + TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_packet_size) ); // Get full device descriptor TU_LOG2("Get Device Descriptor\r\n"); @@ -981,6 +844,34 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co return true; } +// Get total length of n interface (depending on IAD) +static uint16_t get_interface_length(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) +{ + uint8_t const* p_desc = (uint8_t const*) desc_itf; + uint16_t len = 0; + + while (itf_count--) + { + // Next on interface desc + len += tu_desc_len(desc_itf); + p_desc = tu_desc_next(p_desc); + + while (len < max_len) + { + // return on IAD regardless of itf count + if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; + + if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && + ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) break; + + len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + } + + return len; +} + static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) { usbh_device_t* dev = &_usbh_devices[dev_addr]; @@ -992,20 +883,25 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura while( p_desc < desc_end ) { // TODO Do we need to use IAD - // tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL; + tusb_desc_interface_assoc_t const * desc_iad = NULL; // Class will always starts with Interface Association (if any) and then Interface descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - // desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc; + desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; p_desc = tu_desc_next(p_desc); } + TU_LOG_INT(2, p_desc - (uint8_t*) desc_cfg); + TU_LOG_INT(2, tu_desc_type(p_desc)); TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; uint16_t const remaining_len = desc_end-p_desc; + uint16_t const drv_len = get_interface_length(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, remaining_len); + TU_ASSERT(drv_len); + // Check if class is supported TODO drop class_code uint8_t drv_id; for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) @@ -1015,8 +911,11 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura if( drv_id >= USBH_CLASS_DRIVER_COUNT ) { - // skip unsupported class - p_desc = tu_desc_next(p_desc); + TU_LOG(USBH_DBG_LVL, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", + desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); + + // skip unsupported class until next Interface or IAD descriptor + p_desc += drv_len; } else { @@ -1038,6 +937,10 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura uint16_t const itf_len = driver->open(dev->rhport, dev_addr, desc_itf, remaining_len); TU_ASSERT( sizeof(tusb_desc_interface_t) <= itf_len && itf_len <= remaining_len); + + // bind all endpoints for this driver + tu_edpt_bind_driver(dev->ep2drv, desc_itf, drv_len, drv_id); + p_desc += itf_len; } } @@ -1046,4 +949,131 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura return true; } +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + +#if CFG_TUSB_OS != OPT_OS_NONE + // pre-check to help reducing mutex lock + TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0)); + osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only claim the endpoint if it is not busy and not claimed yet. + bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0); + if (ret) + { + dev->ep_status[epnum][dir].claimed = 1; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(dev->mutex); +#endif + + return ret; +} + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only release the endpoint if it is claimed and not busy + bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1); + if (ret) + { + dev->ep_status[epnum][dir].claimed = 0; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(dev->mutex); +#endif + + return ret; +} + +// TODO has some duplication code with device, refactor later +bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes); + + // Attempt to transfer on a busy endpoint, sound like an race condition ! + TU_ASSERT(dev->ep_status[epnum][dir].busy == 0); + + // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() + // could return and USBH task can preempt and clear the busy + dev->ep_status[epnum][dir].busy = true; + + if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) ) + { + TU_LOG2("OK\r\n"); + return true; + }else + { + // HCD error, mark endpoint as ready to allow next transfer + dev->ep_status[epnum][dir].busy = false; + dev->ep_status[epnum][dir].claimed = 0; + TU_LOG2("failed\r\n"); + TU_BREAKPOINT(); + return false; + } +} + +static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) +{ + TU_LOG2("Open EP Control with Size = %u\r\n", max_packet_size); + + tusb_desc_endpoint_t ep0_desc = + { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + .bEndpointAddress = 0, + .bmAttributes = { .xfer = TUSB_XFER_CONTROL }, + .wMaxPacketSize = { .size = max_packet_size }, + .bInterval = 0 + }; + + return hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc); +} + +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep) +{ + usbh_device_t* dev = &_usbh_devices[dev_addr]; + TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) dev->speed)); + + return hcd_edpt_open(rhport, dev_addr, desc_ep); +} + +bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + return dev->ep_status[epnum][dir].busy; +} + + + #endif diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index 0736fefa1..b05a33580 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -73,6 +73,8 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_ // If caller does not make any transfer, it must release endpoint for others. bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); +bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr); + // Check if endpoint transferring is complete bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); diff --git a/src/tusb.c b/src/tusb.c index 0350fa1de..260a6506f 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -63,6 +63,68 @@ bool tusb_inited(void) return ret; } +//--------------------------------------------------------------------+ +// Internal Helper for both Host and Device stack +//--------------------------------------------------------------------+ + +bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed) +{ + uint16_t const max_packet_size = tu_le16toh(desc_ep->wMaxPacketSize.size); + TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); + + switch (desc_ep->bmAttributes.xfer) + { + case TUSB_XFER_ISOCHRONOUS: + { + uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 1023); + TU_ASSERT(max_packet_size <= spec_size); + } + break; + + case TUSB_XFER_BULK: + if (speed == TUSB_SPEED_HIGH) + { + // Bulk highspeed must be EXACTLY 512 + TU_ASSERT(max_packet_size == 512); + }else + { + // TODO Bulk fullspeed can only be 8, 16, 32, 64 + TU_ASSERT(max_packet_size <= 64); + } + break; + + case TUSB_XFER_INTERRUPT: + { + uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 64); + TU_ASSERT(max_packet_size <= spec_size); + } + break; + + default: return false; + } + + return true; +} + +void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, uint8_t driver_id) +{ + uint8_t const* p_desc = (uint8_t const*) desc_itf; + uint16_t len = 0; + + while( len < desc_len ) + { + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) + { + uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; + + ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; + } + + len = (uint16_t)(len + tu_desc_len(p_desc)); + p_desc = tu_desc_next(p_desc); + } +} + /*------------------------------------------------------------------*/ /* Debug *------------------------------------------------------------------*/ -- cgit v1.3.1 From 62f2efbe8cf1e61f70660abac28f4226bca93daf Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Aug 2021 18:26:56 +0700 Subject: hid host skip get report descriptor if too large instead of assert --- examples/host/cdc_msc_hid/src/hid_app.c | 2 ++ src/class/hid/hid_host.c | 58 +++++++++++++++++++++------------ src/class/hid/hid_host.h | 2 ++ src/host/usbh.c | 2 -- 4 files changed, 41 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 420600f9a..5e3ac6a72 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -61,6 +61,8 @@ void hid_app_task(void) // Invoked when device with hid interface is mounted // Report descriptor is also available for use. tuh_hid_parse_report_descriptor() // can be used to parse common/simple enough descriptor. +// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped +// therefore report_desc = NULL, desc_len = 0 void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) { printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 40b6f5631..a39ac8bec 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -247,6 +247,8 @@ static bool config_set_protocol (uint8_t dev_addr, tusb_control_requ static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); + uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { (void) max_len; @@ -367,26 +369,34 @@ static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t cons uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - // Get Report Descriptor + // Get Report Descriptor if possible // using usbh enumeration buffer since report descriptor can be very long - TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSIZE ); + if( hid_itf->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE ) + { + TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", hid_itf->report_desc_len); - TU_LOG2("HID Get Report Descriptor\r\n"); - tusb_control_request_t const new_request = + // Driver is mounted without report descriptor + config_driver_mount_complete(dev_addr, instance, NULL, 0); + }else { - .bmRequestType_bit = + TU_LOG2("HID Get Report Descriptor\r\n"); + tusb_control_request_t const new_request = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_IN - }, - .bRequest = TUSB_REQ_GET_DESCRIPTOR, - .wValue = tu_u16(hid_itf->report_desc_type, 0), - .wIndex = itf_num, - .wLength = hid_itf->report_desc_len - }; + .bmRequestType_bit = + { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_IN + }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = tu_u16(hid_itf->report_desc_type, 0), + .wIndex = itf_num, + .wLength = hid_itf->report_desc_len + }; + + TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete)); + } - TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete)); return true; } @@ -394,13 +404,21 @@ static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_reque { TU_ASSERT(XFER_RESULT_SUCCESS == result); - uint8_t const itf_num = (uint8_t) request->wIndex; - uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); - hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + uint8_t const itf_num = (uint8_t) request->wIndex; + uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); uint8_t const* desc_report = usbh_get_enum_buf(); uint16_t const desc_len = request->wLength; + config_driver_mount_complete(dev_addr, instance, desc_report, desc_len); + + return true; +} + +static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) +{ + hidh_interface_t* hid_itf = get_instance(dev_addr, instance); + // enumeration is complete tuh_hid_mount_cb(dev_addr, instance, desc_report, desc_len); @@ -408,9 +426,7 @@ static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_reque hidh_get_report(dev_addr, hid_itf); // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(dev_addr, itf_num); - - return true; + usbh_driver_set_config_complete(dev_addr, hid_itf->itf_num); } //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index ef203123d..bbef05e25 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -97,6 +97,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, // Invoked when device with hid interface is mounted // Report descriptor is also available for use. tuh_hid_parse_report_descriptor() // can be used to parse common/simple enough descriptor. +// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped +// therefore report_desc = NULL, desc_len = 0 void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len); // Invoked when device with hid interface is un-mounted diff --git a/src/host/usbh.c b/src/host/usbh.c index 36c2ea7c8..979fc5065 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -892,8 +892,6 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura p_desc = tu_desc_next(p_desc); } - TU_LOG_INT(2, p_desc - (uint8_t*) desc_cfg); - TU_LOG_INT(2, tu_desc_type(p_desc)); TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; -- cgit v1.3.1 From 97703587d9f306f01a9435c1515a585f1b8d0975 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Aug 2021 19:08:38 +0700 Subject: improve host configuration parsing - remove driver class code binding - fully support IAD - auto calculate total length for interface descriptor for driver --- src/common/tusb_common.h | 3 + src/host/usbh.c | 131 +++++++++++++++++++------------------------- src/host/usbh_classdriver.h | 2 - src/host/usbh_hcd.h | 4 +- src/tusb.c | 30 ++++++++++ 5 files changed, 91 insertions(+), 79 deletions(-) (limited to 'src') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 302e75277..c2356ffee 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -83,6 +83,9 @@ bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed); // Bind all endpoint of a interface descriptor to class driver void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id); +// Calculate total length of n interfaces (depending on IAD) +uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len); + //--------------------------------------------------------------------+ // Internal Inline Functions //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index 979fc5065..662ce2673 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -48,6 +48,10 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ + +// Invalid driver ID in itf2drv[] ep2drv[][] mapping +enum { DRVID_INVALID = 0xFFu }; + #if CFG_TUSB_DEBUG >= 2 #define DRIVER_NAME(_name) .name = _name, #else @@ -59,7 +63,6 @@ static usbh_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_CDC { DRIVER_NAME("CDC") - .class_code = TUSB_CLASS_CDC, .init = cdch_init, .open = cdch_open, .set_config = cdch_set_config, @@ -71,7 +74,6 @@ static usbh_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_MSC { DRIVER_NAME("MSC") - .class_code = TUSB_CLASS_MSC, .init = msch_init, .open = msch_open, .set_config = msch_set_config, @@ -83,7 +85,6 @@ static usbh_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_HID { DRIVER_NAME("HID") - .class_code = TUSB_CLASS_HID, .init = hidh_init, .open = hidh_open, .set_config = hidh_set_config, @@ -95,7 +96,6 @@ static usbh_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_HUB { DRIVER_NAME("HUB") - .class_code = TUSB_CLASS_HUB, .init = hub_init, .open = hub_open, .set_config = hub_set_config, @@ -107,7 +107,6 @@ static usbh_class_driver_t const usbh_class_drivers[] = #if CFG_TUH_VENDOR { DRIVER_NAME("VENDOR") - .class_code = TUSB_CLASS_VENDOR_SPECIFIC, .init = cush_init, .open = cush_open_subtask, .xfer_cb = cush_isr, @@ -203,8 +202,8 @@ bool tuh_init(uint8_t rhport) TU_ASSERT(dev->mutex); #endif - memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping - memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping + memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping + memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping } // Class drivers init @@ -336,7 +335,6 @@ void hcd_event_handler(hcd_event_t const* event, bool in_isr) } } -// interrupt caused by a TD (with IOC=1) in pipe of class class_code void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) { hcd_event_t event = @@ -409,8 +407,8 @@ void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port usbh_class_drivers[drv_id].close(dev_addr); } - memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping - memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping + memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping + memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping hcd_device_close(rhport, dev_addr); @@ -439,7 +437,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { // continue with next valid interface uint8_t const drv_id = dev->itf2drv[itf_num]; - if (drv_id != 0xff) + if (drv_id != DRVID_INVALID) { usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; TU_LOG2("%s set config: itf = %u\r\n", driver->name, itf_num); @@ -835,43 +833,15 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co dev->configured = 1; dev->state = TUSB_DEVICE_STATE_CONFIGURED; - // Start the Set Configuration process for interfaces (itf = 0xff) + // Start the Set Configuration process for interfaces (itf = DRVID_INVALID) // Since driver can perform control transfer within its set_config, this is done asynchronously. // The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete() - // TODO use separated API instead of usig 0xff - usbh_driver_set_config_complete(dev_addr, 0xff); + // TODO use separated API instead of using DRVID_INVALID + usbh_driver_set_config_complete(dev_addr, DRVID_INVALID); return true; } -// Get total length of n interface (depending on IAD) -static uint16_t get_interface_length(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) -{ - uint8_t const* p_desc = (uint8_t const*) desc_itf; - uint16_t len = 0; - - while (itf_count--) - { - // Next on interface desc - len += tu_desc_len(desc_itf); - p_desc = tu_desc_next(p_desc); - - while (len < max_len) - { - // return on IAD regardless of itf count - if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; - - if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && - ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) break; - - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - } - - return len; -} - static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) { usbh_device_t* dev = &_usbh_devices[dev_addr]; @@ -895,53 +865,64 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; - uint16_t const remaining_len = desc_end-p_desc; - uint16_t const drv_len = get_interface_length(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, remaining_len); - TU_ASSERT(drv_len); + // Interface number must not be used already + TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == DRVID_INVALID ); - // Check if class is supported TODO drop class_code - uint8_t drv_id; - for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) - { - if ( usbh_class_drivers[drv_id].class_code == desc_itf->bInterfaceClass ) break; - } + uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, desc_end-p_desc); + TU_ASSERT(drv_len); - if( drv_id >= USBH_CLASS_DRIVER_COUNT ) + if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) { - TU_LOG(USBH_DBG_LVL, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", - desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); - - // skip unsupported class until next Interface or IAD descriptor - p_desc += drv_len; + // TODO Attach hub to Hub is not currently supported + // skip this interface + TU_LOG(USBH_DBG_LVL, "Only 1 level of HUB is supported\r\n"); } else { - usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; + // Find driver for this interface + uint8_t drv_id; + for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) + { + usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; - // Interface number must not be used already TODO alternate interface - TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff ); - dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; + if ( driver->open(dev->rhport, dev_addr, desc_itf, drv_len) ) + { + // open successfully + TU_LOG2("%s opened\r\n", driver->name); - if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0) - { - // TODO Attach hub to Hub is not currently supported - // skip this interface - p_desc = tu_desc_next(p_desc); - } - else - { - TU_LOG2("%s open\r\n", driver->name); + // bind interface to found driver + dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; + + // If using IAD, bind all interfaces to the same driver + if (desc_iad) + { + // IAD's first interface number and class should match with opened interface + TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && + desc_iad->bFunctionClass == desc_itf->bInterfaceClass); + + for(uint8_t i=1; ibInterfaceCount; i++) + { + dev->itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; + } + } - uint16_t const itf_len = driver->open(dev->rhport, dev_addr, desc_itf, remaining_len); - TU_ASSERT( sizeof(tusb_desc_interface_t) <= itf_len && itf_len <= remaining_len); + // bind all endpoints to found driver + tu_edpt_bind_driver(dev->ep2drv, desc_itf, drv_len, drv_id); - // bind all endpoints for this driver - tu_edpt_bind_driver(dev->ep2drv, desc_itf, drv_len, drv_id); + break; // exit driver find loop + } + } - p_desc += itf_len; + if( drv_id >= USBH_CLASS_DRIVER_COUNT ) + { + TU_LOG(USBH_DBG_LVL, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", + desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); } } + + // next Interface or IAD descriptor + p_desc += drv_len; } return true; diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index b05a33580..fccb30253 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -43,8 +43,6 @@ typedef struct { char const* name; #endif - uint8_t class_code; - void (* const init )(void); uint16_t (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index b3856d6b7..450b3e447 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -73,9 +73,9 @@ typedef struct { uint8_t suspended : 1; }; - volatile uint8_t state; // device state, value from enum tusbh_device_state_t + volatile uint8_t state; // device state, value from enum tusbh_device_state_t - uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) + uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) struct TU_ATTR_PACKED diff --git a/src/tusb.c b/src/tusb.c index 260a6506f..1fc775399 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -125,6 +125,36 @@ void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_ } } +uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) +{ + uint8_t const* p_desc = (uint8_t const*) desc_itf; + uint16_t len = 0; + + while (itf_count--) + { + // Next on interface desc + len += tu_desc_len(desc_itf); + p_desc = tu_desc_next(p_desc); + + while (len < max_len) + { + // return on IAD regardless of itf count + if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; + + if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && + ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) + { + break; + } + + len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + } + + return len; +} + /*------------------------------------------------------------------*/ /* Debug *------------------------------------------------------------------*/ -- cgit v1.3.1 From 22a5b1608c0949d46f8e346878bff730712858e4 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Aug 2021 19:31:38 +0700 Subject: change host driver open return type to bool the descriptor len used by driver will be calculated by usbh --- src/class/cdc/cdc_host.c | 12 ++++++------ src/class/cdc/cdc_host.h | 10 +++++----- src/class/hid/hid_host.c | 20 ++++++++++---------- src/class/hid/hid_host.h | 10 +++++----- src/class/msc/msc_host.c | 10 +++++----- src/class/msc/msc_host.h | 10 +++++----- src/host/hub.c | 13 +++++++------ src/host/hub.h | 10 +++++----- src/host/usbh_classdriver.h | 10 +++++----- 9 files changed, 53 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index fc7100e81..35b8de3b1 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -149,7 +149,7 @@ void cdch_init(void) tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX); } -uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) max_len; @@ -157,7 +157,7 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const // Protocol 0xFF can be RNDIS device for windows XP TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass && - 0xFF != itf_desc->bInterfaceProtocol, 0); + 0xFF != itf_desc->bInterfaceProtocol); cdch_data_t * p_cdc = get_itf(dev_addr); @@ -186,7 +186,7 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const // notification endpoint tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); p_cdc->ep_notif = desc_ep->bEndpointAddress; drv_len += tu_desc_len(p_desc); @@ -205,9 +205,9 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const for(uint32_t i=0; i<2; i++) { tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer, 0); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep), 0); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep)); if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) { @@ -222,7 +222,7 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const } } - return drv_len; + return true; } bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index edcd258a8..0d435138b 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -121,11 +121,11 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void cdch_init (void); -uint16_t cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); -bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void cdch_close (uint8_t dev_addr); +void cdch_init (void); +bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); +bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void cdch_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index a39ac8bec..4dd198369 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -249,19 +249,22 @@ static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_requ static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); -uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) +bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { (void) max_len; - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + + // len = interface + hid + n*endpoints + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + TU_ASSERT(max_len >= drv_len); - uint16_t drv_len = sizeof(tusb_desc_interface_t); uint8_t const *p_desc = (uint8_t const *) desc_itf; //------------- HID descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, 0); + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); // not enough interface, try to increase CFG_TUH_HID // TODO multiple devices @@ -269,13 +272,12 @@ uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID, 0); //------------- Endpoint Descriptor -------------// - drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, 0); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); // TODO also open endpoint OUT - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); hid_dev->inst_count++; @@ -292,9 +294,7 @@ uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const hid_itf->protocol_mode = HID_PROTOCOL_BOOT; if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; - drv_len += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - - return drv_len; + return true; } bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index bbef05e25..9a498afec 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -121,11 +121,11 @@ TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t ins //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hidh_init (void); -uint16_t hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num); -bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void hidh_close (uint8_t dev_addr); +void hidh_init (void); +bool hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); +bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num); +bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void hidh_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 2c027deff..f02f4550a 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -360,22 +360,22 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) +bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); // msc driver length is fixed uint16_t const drv_len = sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - TU_ASSERT(drv_len <= max_len, 0); + TU_ASSERT(drv_len <= max_len); msch_interface_t* p_msc = get_itf(dev_addr); tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); for(uint32_t i=0; i<2; i++) { - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer, 0); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc), 0); + TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { @@ -390,7 +390,7 @@ uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_msc->itf_num = desc_itf->bInterfaceNumber; - return drv_len; + return true; } bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 9e4217ba5..7718ad4fe 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -106,11 +106,11 @@ TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); // Internal Class Driver API //--------------------------------------------------------------------+ -void msch_init (void); -uint16_t msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool msch_set_config (uint8_t dev_addr, uint8_t itf_num); -bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void msch_close (uint8_t dev_addr); +void msch_init (void); +bool msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); +bool msch_set_config (uint8_t dev_addr, uint8_t itf_num); +void msch_close (uint8_t dev_addr); +bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus } diff --git a/src/host/hub.c b/src/host/hub.c index 2ead5bed1..00dce4e65 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -147,16 +147,17 @@ void hub_init(void) tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof(hub_interface_t)); } -uint16_t hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) +bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { - // hub driver does not support multiple TT yet TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass && - 0 == itf_desc->bInterfaceSubClass && - 1 <= itf_desc->bInterfaceProtocol, 0); + 0 == itf_desc->bInterfaceSubClass); + + // hub driver does not support multiple TT yet + TU_VERIFY(itf_desc->bInterfaceProtocol <= 1); // msc driver length is fixed uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); - TU_ASSERT(drv_len <= max_len, 0); + TU_ASSERT(drv_len <= max_len); //------------- Interrupt Status endpoint -------------// tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); @@ -169,7 +170,7 @@ uint16_t hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const hub_data[dev_addr-1].itf_num = itf_desc->bInterfaceNumber; hub_data[dev_addr-1].ep_in = desc_ep->bEndpointAddress; - return drv_len; + return true; } void hub_close(uint8_t dev_addr) diff --git a/src/host/hub.h b/src/host/hub.h index c9ffe4985..c4d544193 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -181,11 +181,11 @@ bool hub_status_pipe_queue(uint8_t dev_addr); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hub_init (void); -uint16_t hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -bool hub_set_config (uint8_t dev_addr, uint8_t itf_num); -bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void hub_close (uint8_t dev_addr); +void hub_init (void); +bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +bool hub_set_config (uint8_t dev_addr, uint8_t itf_num); +bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hub_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h index fccb30253..8bc2622aa 100644 --- a/src/host/usbh_classdriver.h +++ b/src/host/usbh_classdriver.h @@ -43,11 +43,11 @@ typedef struct { char const* name; #endif - void (* const init )(void); - uint16_t (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); - bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); - bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* const close )(uint8_t dev_addr); + void (* const init )(void); + bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); + bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); + bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + void (* const close )(uint8_t dev_addr); } usbh_class_driver_t; // Call by class driver to tell USBH that it has complete the enumeration -- cgit v1.3.1 From beb1a5c678dd50c3142d2c74a29e92affa0b06c9 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Aug 2021 19:39:33 +0700 Subject: minor clean up --- src/device/usbd.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 23f174dab..e12dafcfd 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -856,12 +856,12 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) while( p_desc < desc_end ) { - tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL; + tusb_desc_interface_assoc_t const * desc_iad = NULL; // Class will always starts with Interface Association (if any) and then Interface descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc; + desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; p_desc = tu_desc_next(p_desc); // next to Interface } @@ -870,6 +870,13 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc; uint16_t const remaining_len = desc_end-p_desc; + // Interface number must not be used already + TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber]); + + // TODO usbd can calculate the total length used for driver --> driver open() does not need to calculate it + // uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, desc_end-p_desc); + + // Find driver for this interface uint8_t drv_id; for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { @@ -881,31 +888,30 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // Open successfully, check if length is correct TU_ASSERT( sizeof(tusb_desc_interface_t) <= drv_len && drv_len <= remaining_len); - // Interface number must not be used already - TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber]); - TU_LOG2(" %s opened\r\n", driver->name); + + // bind interface to found driver _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; - // If IAD exist, assign all interfaces to the same driver - if (desc_itf_assoc) + // If using IAD, bind all interfaces to the same driver + if (desc_iad) { // IAD's first interface number and class should match with opened interface - TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber && - desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass); + TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && + desc_iad->bFunctionClass == desc_itf->bInterfaceClass); - for(uint8_t i=1; ibInterfaceCount; i++) + for(uint8_t i=1; ibInterfaceCount; i++) { _usbd_dev.itf2drv[desc_itf->bInterfaceNumber+i] = drv_id; } } - // bind all endpoints for this driver + // bind all endpoints to found driver tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id); p_desc += drv_len; // next interface - break; + break; // exit driver find loop } } -- cgit v1.3.1 From e20755442a3fe2141c9be8d54bee2aa4e092cdfc Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 21 Aug 2021 12:02:20 +0200 Subject: nuc126: fix set_address & disable sof --- src/portable/nuvoton/nuc121/dcd_nuc121.c | 37 ++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 20519ec28..80a19eb17 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -40,6 +40,12 @@ #include "device/dcd.h" #include "NuMicro.h" +// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) +// We disable SOF for now until needed later on +#ifndef USE_SOF +# define USE_SOF 0 +#endif + /* allocation of USBD RAM for Setup, EP0_IN, and and EP_OUT */ #define PERIPH_SETUP_BUF_BASE 0 #define PERIPH_SETUP_BUF_LEN 8 @@ -65,9 +71,6 @@ enum ep_enum PERIPH_MAX_EP, }; -/* set by dcd_set_address() */ -static volatile uint8_t assigned_address; - /* reset by dcd_init(), this is used by dcd_edpt_open() to assign USBD peripheral buffer addresses */ static uint32_t bufseg_addr; @@ -197,7 +200,11 @@ static void bus_reset(void) } /* centralized location for USBD interrupt enable bit mask */ +#if USE_SOF static const uint32_t enabled_irqs = USBD_INTSTS_VBDETIF_Msk | USBD_INTSTS_BUSIF_Msk | USBD_INTSTS_SETUP_Msk | USBD_INTSTS_USBIF_Msk | USBD_INTSTS_SOFIF_Msk; +#else +static const uint32_t enabled_irqs = USBD_INTSTS_VBDETIF_Msk | USBD_INTSTS_BUSIF_Msk | USBD_INTSTS_SETUP_Msk | USBD_INTSTS_USBIF_Msk; +#endif /* NUC121/NUC125/NUC126 TinyUSB API driver implementation @@ -239,7 +246,9 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { (void) rhport; usb_control_send_zlp(); /* SET_ADDRESS is the one exception where TinyUSB doesn't use dcd_edpt_xfer() to generate a ZLP */ - assigned_address = dev_addr; + + // DCD can only set address after status for this request is complete. + // do it at dcd_edpt0_status_complete() } void dcd_remote_wakeup(uint8_t rhport) @@ -420,9 +429,6 @@ void dcd_int_handler(uint8_t rhport) { if (status & USBD_INTSTS_EPEVT0_Msk) /* PERIPH_EP0 (EP0_IN) event: this is treated separately from the rest */ { - /* 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; - uint16_t const available_bytes = USBD->EP[PERIPH_EP0].MXPLD; active_ep0_xfer = (available_bytes == xfer_table[PERIPH_EP0].max_packet_size); @@ -495,6 +501,23 @@ void dcd_int_handler(uint8_t rhport) USBD->INTSTS = status & enabled_irqs; } +// Invoked when a control transfer's status stage is complete. +// May help DCD to prepare for next control transfer, this API is optional. +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) +{ + (void) rhport; + + if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && + request->bRequest == TUSB_REQ_SET_ADDRESS ) + { + uint8_t const dev_addr = (uint8_t) request->wValue; + + // Setting new address after the whole request is complete + USBD->FADDR = dev_addr; + } +} + void dcd_disconnect(uint8_t rhport) { (void) rhport; -- cgit v1.3.1 From 69e539fda4c72a2f3177b3944f83632ef6752c11 Mon Sep 17 00:00:00 2001 From: MasterPhi Date: Sat, 21 Aug 2021 12:11:35 +0200 Subject: Fix CI. --- src/portable/nuvoton/nuc121/dcd_nuc121.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 80a19eb17..a776e46f5 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -245,6 +245,7 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { (void) rhport; + (void) dev_addr; usb_control_send_zlp(); /* SET_ADDRESS is the one exception where TinyUSB doesn't use dcd_edpt_xfer() to generate a ZLP */ // DCD can only set address after status for this request is complete. -- cgit v1.3.1