From 9538ca7d74fbf5644c1e3a9747f0ad0c3e1a28d2 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 3 May 2020 14:50:12 +0700 Subject: [PATCH 001/167] add uart for mcb1800 --- hw/bsp/ea4357/ea4357.c | 61 +++++++++++++++++++++++----------------- hw/bsp/mcb1800/mcb1800.c | 36 ++++++++++++++---------- 2 files changed, 56 insertions(+), 41 deletions(-) diff --git a/hw/bsp/ea4357/ea4357.c b/hw/bsp/ea4357/ea4357.c index b7e7f7a5c..30d899f69 100644 --- a/hw/bsp/ea4357/ea4357.c +++ b/hw/bsp/ea4357/ea4357.c @@ -30,8 +30,8 @@ #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 +#define UART_PIN_TX 10 +#define UART_PIN_RX 11 // P9_1 joystick down #define BUTTON_PORT 4 @@ -66,6 +66,10 @@ static const PINMUX_GRP_T pinmuxing[] = // Button {0x9, 1, (SCU_MODE_INBUFF_EN | SCU_MODE_INACT | SCU_MODE_FUNC0 | SCU_MODE_PULLUP)}, + // UART + {UART_PORT, UART_PIN_TX, SCU_MODE_PULLDOWN | SCU_MODE_FUNC1}, + {UART_PORT, UART_PIN_RX, SCU_MODE_INACT | SCU_MODE_INBUFF_EN | SCU_MODE_ZIF_DIS | SCU_MODE_FUNC1}, + // USB }; @@ -119,9 +123,6 @@ void board_init(void) Chip_GPIO_SetPinDIRInput(LPC_GPIO_PORT, BUTTON_PORT, BUTTON_PIN); //------------- UART -------------// - 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)); - 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); @@ -139,15 +140,20 @@ void board_init(void) }; /* USB0 - * For USB Device operation; insert jumpers in position 1-2 in JP17/JP18/JP19. GPIO28 controls USB - * connect functionality and 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 + * For 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 USB 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 + * + * For 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 */ #if CFG_TUSB_RHPORT0_MODE Chip_USB0_Init(); @@ -168,22 +174,25 @@ void board_init(void) #endif /* USB1 - * When USB channel #1 is used as USB Host, 15Kohm pull-down resistors are needed on the USB data - * signals. These are activated inside the USB OTG chip (U31), and this has to be done via the I2C - * interface of GPIO52/GPIO53. - * J20 is the connector to use when USB Host is used. In order to provide +5V to the external USB - * device connected to this connector (J20), channel A of U20 must be enabled. It is enabled by default - * since SJ5 is normally connected between pin 1-2. LED34 lights green when +5V is available on J20. - * JP15 shall not be inserted. JP16 has no effect * - * When USB channel #1 is used as USB Device, a 1.5Kohm pull-up resistor is needed on the USB DP - * data signal. There are two methods to create this. JP15 is inserted and the pull-up resistor is always - * enabled. Alternatively, the pull-up resistor is activated inside the USB OTG chip (U31), and this has to - * be done via the I2C interface of GPIO52/GPIO53. In the latter case, JP15 shall not be inserted. - * J19 is the connector to use when USB Device is used. Normally it should be a USB-B connector for + * For USB Device: + * - a 1.5Kohm pull-up resistor is needed on the USB DP data signal. There are two methods to create this. + * JP15 is inserted and the pull-up resistor is always enabled. Alternatively, the pull-up resistor is activated + * inside the USB OTG chip (U31), and this has to be done via the I2C interface of GPIO52/GPIO53. In the latter case, + * JP15 shall not be inserted. + * - J19 is the connector to use when USB Device is used. Normally it should be a USB-B connector for * creating a USB Device interface, but the mini-AB connector can also be used in this case. The status * of VBUS can be read via U31. - * JP16 shall not be inserted. + * - JP16 shall not be inserted. + * + * For USB Host: + * - 15Kohm pull-down resistors are needed on the USB data signals. These are activated inside the USB OTG chip (U31), + * and this has to be done via the I2C interface of GPIO52/GPIO53. + * - J20 is the connector to use when USB Host is used. In order to provide +5V to the external USB + * device connected to this connector (J20), channel A of U20 must be enabled. It is enabled by default + * since SJ5 is normally connected between pin 1-2. + * - LED34 lights green when +5V is available on J20. + * - JP15 shall not be inserted. JP16 has no effect */ #if CFG_TUSB_RHPORT1_MODE Chip_USB1_Init(); diff --git a/hw/bsp/mcb1800/mcb1800.c b/hw/bsp/mcb1800/mcb1800.c index ae9f1b62f..075210c85 100644 --- a/hw/bsp/mcb1800/mcb1800.c +++ b/hw/bsp/mcb1800/mcb1800.c @@ -64,6 +64,11 @@ void USB1_IRQHandler(void) #define BUTTON_PORT 2 #define BUTTON_PIN 0 +#define UART_DEV LPC_USART3 +#define UART_PORT 0x02 +#define UART_PIN_TX 3 +#define UART_PIN_RX 4 + /* System configuration variables used by chip driver */ const uint32_t OscRateIn = 12000000; @@ -84,6 +89,10 @@ static const PINMUX_GRP_T pinmuxing[] = // 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)}, @@ -137,19 +146,11 @@ 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); - - 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 { @@ -223,9 +224,14 @@ int board_uart_read(uint8_t* buf, int len) 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 Date: Mon, 4 May 2020 00:29:52 +0700 Subject: [PATCH 002/167] clean up things, add makefile for host example --- examples/host/cdc_msc_hid/Makefile | 22 ++++++ .../cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject | 21 +++--- .../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 | 71 +++++++++---------- src/class/cdc/cdc_host.c | 1 - src/host/ehci/ehci.c | 6 +- test/test/support/tusb_config.h | 10 +-- 10 files changed, 104 insertions(+), 78 deletions(-) create mode 100644 examples/host/cdc_msc_hid/Makefile 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)}, + // 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)}, + // 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 }, + // 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)}, + // 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 From 905a80d1b2de5e8ad67b3687ffd0543d90ac904e Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 4 May 2020 14:11:58 +0700 Subject: [PATCH 003/167] 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(-) 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 From 58cedf4c061fbf9f95cd88cafb6e581fc04549ff Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 19 May 2020 00:55:43 +0700 Subject: [PATCH 004/167] usb0 host on mcb1800 work with fullspeed mode. use usbh_edpt_open() to correctly map ep2drv[] --- examples/host/cdc_msc_hid/Makefile | 3 +- .../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(-) 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 From 9be2f1bf3dc2c89bc23eed1e95c06de41ebb0946 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 22 May 2020 12:09:34 +0200 Subject: [PATCH 005/167] 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 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_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_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_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 From 4c01099a3d6e92404c645e5c906968955a6c9b1a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 22 May 2020 20:57:52 +0700 Subject: [PATCH 006/167] update makefile to build with ohci host update ses project for lpc1769 with rtt --- examples/host/cdc_msc_hid/Makefile | 6 +++-- .../ses/lpc175x_6x/lpc175x_6x.emProject | 23 ++++++++++++------- hw/bsp/board.c | 3 +++ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index 373dbbf9e..29a323957 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -9,15 +9,17 @@ INC += \ EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +CFLAGS += -Wno-error=cast-align # TinyUSB Host Stack source SRC_C += \ src/host/usbh.c \ src/host/hub.c \ src/host/ehci/ehci.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/lpc18_43/hcd_lpc18_43.c \ + src/portable/nxp/lpc17_40/hcd_lpc17_40.c include ../../rules.mk diff --git a/examples/host/cdc_msc_hid/ses/lpc175x_6x/lpc175x_6x.emProject b/examples/host/cdc_msc_hid/ses/lpc175x_6x/lpc175x_6x.emProject index ba5a9cea7..8a2c36390 100644 --- a/examples/host/cdc_msc_hid/ses/lpc175x_6x/lpc175x_6x.emProject +++ b/examples/host/cdc_msc_hid/ses/lpc175x_6x/lpc175x_6x.emProject @@ -19,8 +19,8 @@ arm_target_device_name="LPC1769" arm_target_interface_type="SWD" build_treat_warnings_as_errors="Yes" - c_preprocessor_definitions="LPC175x_6x;__LPC1700_FAMILY;__LPC176x_SUBFAMILY;ARM_MATH_CM3;FLASH_PLACEMENT=1;CORE_M3;BOARD_LPCXPRESSO1769;CFG_TUSB_MCU=OPT_MCU_LPC175X_6X" - c_user_include_directories="../../src;$(rootDir)/hw;$(rootDir)/src;$(lpcDir)/inc" + c_preprocessor_definitions="LPC175x_6x;__LPC1700_FAMILY;__LPC176x_SUBFAMILY;ARM_MATH_CM3;FLASH_PLACEMENT=1;CORE_M3;BOARD_LPCXPRESSO1769;CFG_TUSB_MCU=OPT_MCU_LPC175X_6X;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="LPC176x5x_Registers.xml" debug_target_connection="J-Link" gcc_enable_all_warnings="Yes" @@ -101,12 +101,19 @@ - + + + + + + + + + + + + + diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 56f407326..383a02ef4 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -40,6 +40,8 @@ #if defined(LOGGER_RTT) // Logging with RTT +// If using SES IDE, use the Syscalls/SEGGER_RTT_Syscalls_SES.c instead +#if !(defined __SES_ARM) && !(defined __SES_RISCV) && !(defined __CROSSWORKS_ARM) #include "SEGGER_RTT.h" TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) @@ -54,6 +56,7 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) (void) fhdl; return SEGGER_RTT_Read(0, buf, count); } +#endif #elif defined(LOGGER_SWO) // Logging with SWO for ARM Cortex From d108ea4326d824da73da0a4f9632c5da6aa2e3ec Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 22 May 2020 21:45:34 +0700 Subject: [PATCH 007/167] implement hcd_uframe_number for ohci able to get 8 byte descriptors using LPC1769 + base, but failed to reset and set address. --- .../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(-) 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; //--------------------------------------------------------------------+ From 4362665fb3ec1ef0d749bbcdaabe161ce1c06614 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 13 Jun 2020 12:36:05 +0200 Subject: [PATCH 008/167] 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(-) 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_ */ From 862d1667f0c7e94af29f92d575a7d14dbe126a66 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 14 Jun 2020 12:55:52 +0200 Subject: [PATCH 009/167] Fix alignment. --- src/device/usbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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++) { From ada82b840f642681f8012cb2a46aa7577393dd30 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 20 Jun 2020 10:51:21 +0200 Subject: [PATCH 010/167] 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(-) 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); From d0f3d039332cf22637d191cc62bed620c4f14dce Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 17 Jul 2020 08:40:10 +0200 Subject: [PATCH 011/167] 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(-) 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 +/// A.6 - Audio Interface Protocol Codes typedef enum { - AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, -} audio_function_subclass_type_t; + AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +} audio_interface_protocol_code_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_type_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) { - case TUSB_REQ_GET_INTERFACE: - return audiod_get_interface(rhport, p_request); + 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); + case TUSB_REQ_SET_INTERFACE: + return audiod_set_interface(rhport, p_request); - default: + // Unknown/Unsupported request + default: TU_BREAKPOINT(); return false; + } + } + + // Handle class requests + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) + { + // 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); + + // 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)); + + // 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 From 47bcedc0b4744d3554f385906414005b511e9ae4 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 18 Jul 2020 19:27:00 +0200 Subject: [PATCH 012/167] Add A.17.4 - Terminal Control Selectors --- src/class/audio/audio.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 { From 077e881c92c0704c53ede854f50701c3ba6dd921 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 19 Jul 2020 11:53:35 +0200 Subject: [PATCH 013/167] Implement all missing A.17 control selectors --- src/class/audio/audio.h | 253 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 241 insertions(+), 12 deletions(-) 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 From fdb156a3bb1eb4bc223dbca1dd287c7eff7a8e7c Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 20 Jul 2020 20:18:45 +0200 Subject: [PATCH 014/167] 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 | 49 ++++++++++----------- 2 files changed, 64 insertions(+), 63 deletions(-) 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). -// 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 +// 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 -#ifndef CFG_TUD_AUDIO_USE_TX_FIFO -#define CFG_TUD_AUDIO_USE_TX_FIFO 0 +// 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 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_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); From 141db1278aabd9a5d508450752fd5df79759747c Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 20 Jul 2020 20:24:05 +0200 Subject: [PATCH 015/167] Make definition of CFG_TUD_AUDIO_CTRL_BUF_SIZE mandatory --- src/class/audio/audio_device.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From d91843bcd21262658b43480240e5dfc2b7d7bd20 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 25 Jul 2020 11:18:50 +0200 Subject: [PATCH 016/167] 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(-) 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)); + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &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; - - // 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)); + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &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; - - // 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) + // 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_ep_cb(rhport, p_request); + 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 + } } - 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; + // 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); From 1269bb440a62120108ebe9a6d5436b88b28b4de3 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 25 Jul 2020 14:31:25 +0200 Subject: [PATCH 017/167] 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(-) 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; From 5e3f90cd6eabbeb664d523184338d7f4df46cef4 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 26 Jul 2020 19:21:30 +0200 Subject: [PATCH 018/167] 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(-) 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); } From 01903a4a6d0eb8a7260029133cc94a62d969092e Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 27 Jul 2020 21:03:20 +0200 Subject: [PATCH 019/167] 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(-) 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 From c557bf7b2e35482e8743eebfca7b5ff28b0b6d86 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 3 Aug 2020 19:48:05 +0200 Subject: [PATCH 020/167] Implement dynamic FIFO RAM allocation according to configuration desc. --- src/portable/st/synopsys/dcd_synopsys.c | 231 ++++++++++++++++++++---- 1 file changed, 196 insertions(+), 35 deletions(-) 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; } From 444e4d282137953e6834360a9fb866331d21d954 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 16 Aug 2020 13:48:25 +0200 Subject: [PATCH 021/167] Add EP close. Fix bug in set_interface within audio. --- src/class/audio/audio_device.c | 1483 ++++++++++++----------- src/portable/st/synopsys/dcd_synopsys.c | 37 + 2 files changed, 781 insertions(+), 739 deletions(-) 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; + break; - default: - // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! - asm("nop"); - break; - } - 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; - } + 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; + // 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; - } + 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; - } - } + 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; + break; - default: - // YOUR ENCODING AND SENDING IS REQUIRED HERE! - asm("nop"); - break; - } - 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; - } + 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; + // 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)); + // 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; + // 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; - } - } + 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; - } + // 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; - } + // 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; + // 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); + // 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); + // 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; - } - } + // 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; + // 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); + 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 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); - } + // 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); + // 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; - } - } + // 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 ); + // 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) + // 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 + // 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; + 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]; + // 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) + // 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); - } - - // We are done - abort loop - break; - } - - // Increase index, bytes read, and pointer - p_desc = tu_desc_next(p_desc); + foundEPs += 1; } + 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); + TU_VERIFY(foundEPs == nEps); - // Save current alternative interface setting - _audiod_itf[idxDriver].altSetting[idxItf] = alt; + // We are done - abort loop + break; + } - // Invoke callback - if (tud_audio_set_itf_cb) - { - if (!tud_audio_set_itf_cb(rhport, p_request)) return false; - } + // Moving forward + p_desc = tu_desc_next(p_desc); + } - tud_control_status(rhport, p_request); +// // 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); - return true; + // 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; } // 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; + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &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; - } + // Invoke callback + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_itf[idxDriver].ctrl_buf); } - return true; + 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; + } + } + 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; + (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) + // 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) { - 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; - } + 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)); - // 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) { - 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; + 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; - // There went something wrong - unsupported control request type - TU_BREAKPOINT(); - return false; + 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; + } + + // 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 ??? + // 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)); + // 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); - } - } + 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. + // 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! + // 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)); + // 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); - } + if (*n_bytes_copied == 0) + { + // Load with ZLP + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + } - return true; - } + 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); - } + // 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; - } + 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++) - { - // 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 + 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 - { - *idxDriver = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } + while (p_desc < p_desc_end) + { + if (p_desc[3] == entityID) // Entity IDs are always at offset 3 + { + *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++) - { - 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]; + 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) - { - *idxDriver = i; - return true; - } - p_desc = tu_desc_next(p_desc); - } - } + 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; } - 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); From c14f68e2c1db7ce82fb8e05d40d8b0b9a83aced6 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 19 Aug 2020 21:07:43 +0200 Subject: [PATCH 022/167] 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 ++ .../device/audio_test/src/usb_descriptors.c | 167 ++ src/class/audio/audio.h | 1615 +++++++++-------- 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, 1497 insertions(+), 876 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 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 From 37be0ca73238a40a2387c2e2566ae39f5cae6e08 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 20 Aug 2020 20:09:44 +0200 Subject: [PATCH 023/167] Fix formatting, get rid of all tabs. --- src/class/audio/audio.h | 1576 +++++++++++------------ src/class/audio/audio_device.c | 646 +++------- src/class/audio/audio_device.h | 88 +- src/portable/st/synopsys/dcd_synopsys.c | 103 +- 4 files changed, 1082 insertions(+), 1331 deletions(-) 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 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 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 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 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 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; + 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)); + // 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)); - } + 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)); + 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 - } + // 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)); + 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 - } + // 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)); + // 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 - } - } + // 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)); + // 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 - } - } + // 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; - } + // 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); + // 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; From c61e9fb96def7b77b4001374b362141a29dcba5b Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 24 Aug 2020 09:01:03 +0200 Subject: [PATCH 024/167] 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(-) 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) { From a4c096be377dd57554a67db92dd3d3167475c142 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 25 Aug 2020 13:15:43 +0200 Subject: [PATCH 025/167] 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(-) 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; } From a3eff0c51a8b5ad58fa7111e770e3b5b3d959351 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 25 Aug 2020 14:30:02 +0200 Subject: [PATCH 026/167] 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(-) 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); From b1f0d6f57eb14aec8c5d83bd54a70a56558d24e8 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 25 Aug 2020 14:41:50 +0200 Subject: [PATCH 027/167] 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(-) 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) From b9c9cfdbac66b38faacdff6b5b2629c332d328a9 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 29 Aug 2020 13:22:21 +0200 Subject: [PATCH 028/167] Change min to tu_min16. --- src/class/audio/audio_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 43c4b536356fdb9cb54a79f59fa0524cd14dc28c Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 29 Aug 2020 13:24:10 +0200 Subject: [PATCH 029/167] Fix CFG_TUD_AUDIO_RX_FIFO_SIZE defines. --- src/class/audio/audio_device.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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); From 83bd21420375d42f3788b3d3abd5e20ae00cd5b2 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 29 Aug 2020 13:26:41 +0200 Subject: [PATCH 030/167] Fix comment. --- src/class/audio/audio_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 8f0693346cf4cba4ea9ea5755a7690b9ee4dc28f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 1 Sep 2020 11:26:16 +0200 Subject: [PATCH 031/167] 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 | 122 ++++++++++++++++++++++++++------- src/class/audio/audio_device.h | 13 +++- 2 files changed, 108 insertions(+), 27 deletions(-) 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 //--------------------------------------------------------------------+ -#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) +/** + * \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; } - return tu_fifo_write_n(&audio->tx_ff[channelId], buffer, bufsize); + // 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, 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], 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 From f4e3c6fd8ee125123e2cfa704d61dab34be576c5 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 1 Sep 2020 17:12:31 +0700 Subject: [PATCH 032/167] clean up --- examples/host/cdc_msc_hid/src/main.c | 16 ++++++++-------- hw/bsp/mcb1800/board.mk | 4 ++-- test/test/support/tusb_config.h | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 273c95c77..9ec213090 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -75,7 +75,7 @@ CFG_TUSB_MEM_SECTION static char serial_in_buffer[64] = { 0 }; void tuh_mount_cb(uint8_t dev_addr) { // application set-up - printf("\na device with address %d is mounted\n", dev_addr); + printf("A device with address %d is mounted\r\n", dev_addr); tuh_cdc_receive(dev_addr, serial_in_buffer, sizeof(serial_in_buffer), true); // schedule first transfer } @@ -83,7 +83,7 @@ void tuh_mount_cb(uint8_t dev_addr) void tuh_umount_cb(uint8_t dev_addr) { // application tear-down - printf("\na device with address %d is unmounted \n", dev_addr); + printf("A device with address %d is unmounted \r\n", dev_addr); } // invoked ISR context @@ -187,14 +187,14 @@ void print_greeting(void) [OPT_OS_FREERTOS] = "FreeRTOS", }; - printf("\n--------------------------------------------------------------------\n"); - printf("- Host example\n"); - printf("- if you find any bugs or get any questions, feel free to file an\n"); - printf("- issue at https://github.com/hathach/tinyusb\n"); - printf("--------------------------------------------------------------------\n\n"); + printf("--------------------------------------------------------------------\r\n"); + printf("- Host example\r\n"); + printf("- if you find any bugs or get any questions, feel free to file an\r\n"); + printf("- issue at https://github.com/hathach/tinyusb\r\n"); + printf("--------------------------------------------------------------------\r\n\r\n"); printf("This Host demo is configured to support:\r\n"); - printf(" - RTOS = %s\n", rtos_name[CFG_TUSB_OS]); + printf(" - RTOS = %s\r\n", rtos_name[CFG_TUSB_OS]); #if CFG_TUH_CDC printf(" - Communication Device Class\r\n"); diff --git a/hw/bsp/mcb1800/board.mk b/hw/bsp/mcb1800/board.mk index 6037310a6..7ff17dae3 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_LPCOPEN \ -DCFG_TUSB_MCU=OPT_MCU_LPC18XX \ # mcu driver cause following warnings @@ -37,7 +37,7 @@ FREERTOS_PORT = ARM_CM3 # For flash-jlink target JLINK_DEVICE = LPC1857 -JLINK_IF = jtag +JLINK_IF = swd # flash using jlink flash: flash-jlink diff --git a/test/test/support/tusb_config.h b/test/test/support/tusb_config.h index 80ea0a1ea..a18d86598 100644 --- a/test/test/support/tusb_config.h +++ b/test/test/support/tusb_config.h @@ -43,7 +43,7 @@ #define CFG_TUSB_MCU OPT_MCU_NRF5X #endif -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HOST | OPT_MODE_HIGH_SPEED) #define CFG_TUSB_OS OPT_OS_NONE // CFG_TUSB_DEBUG is defined by compiler in DEBUG build From 84425c50b3bb5c892bfab9d094cc3da6a9c04da5 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 1 Sep 2020 19:16:50 +0700 Subject: [PATCH 033/167] 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(-) 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) From f17d6f15e0a63c74376e029822193cbac3e45d7e Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 1 Sep 2020 23:38:46 +0700 Subject: [PATCH 034/167] fix unit test --- test/test/support/tusb_config.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/test/support/tusb_config.h b/test/test/support/tusb_config.h index a18d86598..8cd99eaae 100644 --- a/test/test/support/tusb_config.h +++ b/test/test/support/tusb_config.h @@ -43,7 +43,10 @@ #define CFG_TUSB_MCU OPT_MCU_NRF5X #endif -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HOST | OPT_MODE_HIGH_SPEED) +#ifndef CFG_TUSB_RHPORT0_MODE +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#endif + #define CFG_TUSB_OS OPT_OS_NONE // CFG_TUSB_DEBUG is defined by compiler in DEBUG build From c492aef4c7b4dd6ee7b24c30176a570ae6eae043 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Sep 2020 00:46:08 +0700 Subject: [PATCH 035/167] 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(-) 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 ) From 52b5748e8d9dc8b3e32108f6fdae431ca1dbc71d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Sep 2020 00:56:43 +0700 Subject: [PATCH 036/167] fix ci build --- hw/bsp/ngx4330/board.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/ngx4330/board.mk b/hw/bsp/ngx4330/board.mk index 08a877229..23d53bd18 100644 --- a/hw/bsp/ngx4330/board.mk +++ b/hw/bsp/ngx4330/board.mk @@ -4,7 +4,7 @@ CFLAGS += \ -mabi=aapcs \ -mcpu=cortex-m4 \ -mfloat-abi=hard \ - -mfpu=fpv4-sp-d16 \ + -mfpu=fpv4-sp-d16 \ -nostdlib \ -DCORE_M4 \ -D__USE_CMSIS \ From c7d2d0ae294ca2c93920c86d6cd10a3e74e2b010 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Sep 2020 01:40:04 +0700 Subject: [PATCH 037/167] ohci work, tested with lpc1769 --- hw/bsp/lpcxpresso1769/lpcxpresso1769.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c index cc6fd95ae..f002e8cdc 100644 --- a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c +++ b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c @@ -78,21 +78,26 @@ static const PINMUX_GRP_T pin_usb_mux[] = { {0, 29, IOCON_MODE_INACT | IOCON_FUNC1}, // D+ {0, 30, IOCON_MODE_INACT | IOCON_FUNC1}, // D- - {2, 9, IOCON_MODE_INACT | IOCON_FUNC1}, // Connect + {2, 9, IOCON_MODE_INACT | IOCON_FUNC1}, // Soft Connect - {1, 19, IOCON_MODE_INACT | IOCON_FUNC2}, // USB_PPWR - {1, 22, IOCON_MODE_INACT | IOCON_FUNC2}, // USB_PWRD + {1, 19, IOCON_MODE_INACT | IOCON_FUNC2}, // USB_PPWR (Host mode) - /* VBUS is not connected on this board, so leave the pin at default setting. */ - /*Chip_IOCON_PinMux(LPC_IOCON, 1, 30, IOCON_MODE_INACT, IOCON_FUNC2);*/ /* USB VBUS */ + // VBUS is not connected on this board, so leave the pin at default setting. + /// Chip_IOCON_PinMux(LPC_IOCON, 1, 30, IOCON_MODE_INACT, IOCON_FUNC2); // USB VBUS }; // Invoked by startup code void SystemInit(void) { + extern void (* const g_pfnVectors[])(void); + unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; + *pSCB_VTOR = (unsigned int) &g_pfnVectors; + Chip_IOCON_Init(LPC_IOCON); Chip_IOCON_SetPinMuxing(LPC_IOCON, pinmuxing, sizeof(pinmuxing) / sizeof(PINMUX_GRP_T)); Chip_SetupXtalClocking(); + + Chip_SYSCTL_SetFLASHAccess(FLASHTIM_100MHZ_CPU); } void board_init(void) From 1cee2da7b920288202f651a4b970e50e05b8786f Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Sep 2020 12:58:09 +0700 Subject: [PATCH 038/167] revert to use __USE_LPCOPEN properly init fpu on LPC M4 --- hw/bsp/ea4088qs/board.mk | 9 ++++++--- hw/bsp/ea4088qs/ea4088qs.c | 10 ++++++++++ hw/bsp/ea4357/board.mk | 5 +++-- hw/bsp/ea4357/ea4357.c | 10 ++++++++++ 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/lpcxpresso1769/lpcxpresso1769.c | 2 ++ hw/bsp/mbed1768/board.mk | 2 +- hw/bsp/mbed1768/mbed1768.c | 6 ++++++ hw/bsp/mcb1800/board.mk | 2 +- hw/bsp/mcb1800/mcb1800.c | 6 ++++++ hw/bsp/ngx4330/board.mk | 5 +++-- hw/bsp/ngx4330/ngx4330.c | 12 +++++++++--- 16 files changed, 62 insertions(+), 17 deletions(-) diff --git a/hw/bsp/ea4088qs/board.mk b/hw/bsp/ea4088qs/board.mk index 2a63d8af2..51a6009a0 100644 --- a/hw/bsp/ea4088qs/board.mk +++ b/hw/bsp/ea4088qs/board.mk @@ -3,9 +3,11 @@ CFLAGS += \ -mthumb \ -mabi=aapcs \ -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ -nostdlib \ -DCORE_M4 \ - -D__USE_CMSIS \ + -D__USE_LPCOPEN \ -DCFG_TUSB_MEM_SECTION='__attribute__((section(".data.$$RAM2")))' \ -DCFG_TUSB_MCU=OPT_MCU_LPC40XX @@ -25,7 +27,8 @@ SRC_C += \ $(MCU_DIR)/src/iocon_17xx_40xx.c \ $(MCU_DIR)/src/sysctl_17xx_40xx.c \ $(MCU_DIR)/src/sysinit_17xx_40xx.c \ - $(MCU_DIR)/src/uart_17xx_40xx.c + $(MCU_DIR)/src/uart_17xx_40xx.c \ + $(MCU_DIR)/src/fpu_init.c INC += \ $(TOP)/$(MCU_DIR)/inc @@ -35,7 +38,7 @@ VENDOR = nxp CHIP_FAMILY = lpc17_40 # For freeRTOS port source -FREERTOS_PORT = ARM_CM3 +FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = LPC4088 diff --git a/hw/bsp/ea4088qs/ea4088qs.c b/hw/bsp/ea4088qs/ea4088qs.c index 7fc047490..00db1a299 100644 --- a/hw/bsp/ea4088qs/ea4088qs.c +++ b/hw/bsp/ea4088qs/ea4088qs.c @@ -86,6 +86,16 @@ static const PINMUX_GRP_T pin_usb_mux[] = // Invoked by startup code void SystemInit(void) { +#ifdef __USE_LPCOPEN + extern void (* const g_pfnVectors[])(void); + unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; + *pSCB_VTOR = (unsigned int) &g_pfnVectors; + +#if __FPU_USED == 1 + fpuInit(); +#endif +#endif // __USE_LPCOPEN + Chip_IOCON_Init(LPC_IOCON); Chip_IOCON_SetPinMuxing(LPC_IOCON, pinmuxing, sizeof(pinmuxing) / sizeof(PINMUX_GRP_T)); Chip_SetupXtalClocking(); diff --git a/hw/bsp/ea4357/board.mk b/hw/bsp/ea4357/board.mk index 44481118d..3ebe107e2 100644 --- a/hw/bsp/ea4357/board.mk +++ b/hw/bsp/ea4357/board.mk @@ -7,7 +7,7 @@ CFLAGS += \ -mfpu=fpv4-sp-d16 \ -nostdlib \ -DCORE_M4 \ - -D__USE_CMSIS \ + -D__USE_LPCOPEN \ -DCFG_TUSB_MCU=OPT_MCU_LPC43XX # mcu driver cause following warnings @@ -26,7 +26,8 @@ SRC_C += \ $(MCU_DIR)/src/sysinit_18xx_43xx.c \ $(MCU_DIR)/src/i2c_18xx_43xx.c \ $(MCU_DIR)/src/i2cm_18xx_43xx.c \ - $(MCU_DIR)/src/uart_18xx_43xx.c + $(MCU_DIR)/src/uart_18xx_43xx.c \ + $(MCU_DIR)/src/fpu_init.c INC += \ $(TOP)/$(MCU_DIR)/inc \ diff --git a/hw/bsp/ea4357/ea4357.c b/hw/bsp/ea4357/ea4357.c index daa3a6bd0..f41ba5ab9 100644 --- a/hw/bsp/ea4357/ea4357.c +++ b/hw/bsp/ea4357/ea4357.c @@ -85,6 +85,16 @@ static const PINMUX_GRP_T pinclockmuxing[] = // Invoked by startup code void SystemInit(void) { +#ifdef __USE_LPCOPEN + extern void (* const g_pfnVectors[])(void); + unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; + *pSCB_VTOR = (unsigned int) &g_pfnVectors; + +#if __FPU_USED == 1 + fpuInit(); +#endif +#endif // __USE_LPCOPEN + /* Setup system level pin muxing */ Chip_SCU_SetPinMuxing(pinmuxing, sizeof(pinmuxing) / sizeof(PINMUX_GRP_T)); diff --git a/hw/bsp/lpcxpresso11u37/board.mk b/hw/bsp/lpcxpresso11u37/board.mk index 27019ff8b..d1c48a2e5 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_CMSIS \ + -D__USE_LPCOPEN \ -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 1c1660367..d9017ae1a 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_CMSIS \ + -D__USE_LPCOPEN \ -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 5befc3aee..6dc3937f6 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_CMSIS \ + -D__USE_LPCOPEN \ -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 c603e4b30..18325c5f7 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_CMSIS \ + -D__USE_LPCOPEN \ -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 6886ef749..a345e5a27 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_CMSIS \ + -D__USE_LPCOPEN \ -DCFG_TUSB_MCU=OPT_MCU_LPC175X_6X \ -DRTC_EV_SUPPORT=0 diff --git a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c index f002e8cdc..5ec4fac23 100644 --- a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c +++ b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c @@ -89,9 +89,11 @@ static const PINMUX_GRP_T pin_usb_mux[] = // Invoked by startup code void SystemInit(void) { +#ifdef __USE_LPCOPEN extern void (* const g_pfnVectors[])(void); unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; *pSCB_VTOR = (unsigned int) &g_pfnVectors; +#endif Chip_IOCON_Init(LPC_IOCON); Chip_IOCON_SetPinMuxing(LPC_IOCON, pinmuxing, sizeof(pinmuxing) / sizeof(PINMUX_GRP_T)); diff --git a/hw/bsp/mbed1768/board.mk b/hw/bsp/mbed1768/board.mk index 5b23900ff..3bdc8a27a 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_CMSIS \ + -D__USE_LPCOPEN \ -DCFG_TUSB_MCU=OPT_MCU_LPC175X_6X \ -DRTC_EV_SUPPORT=0 diff --git a/hw/bsp/mbed1768/mbed1768.c b/hw/bsp/mbed1768/mbed1768.c index 5963ad8ec..0dfd05c81 100644 --- a/hw/bsp/mbed1768/mbed1768.c +++ b/hw/bsp/mbed1768/mbed1768.c @@ -65,6 +65,12 @@ static const PINMUX_GRP_T pin_usb_mux[] = // Invoked by startup code void SystemInit(void) { +#ifdef __USE_LPCOPEN + extern void (* const g_pfnVectors[])(void); + unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; + *pSCB_VTOR = (unsigned int) &g_pfnVectors; +#endif + Chip_IOCON_Init(LPC_IOCON); Chip_IOCON_SetPinMuxing(LPC_IOCON, pinmuxing, sizeof(pinmuxing) / sizeof(PINMUX_GRP_T)); Chip_SetupXtalClocking(); diff --git a/hw/bsp/mcb1800/board.mk b/hw/bsp/mcb1800/board.mk index 3d3bb2371..e3f07d0d0 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_CMSIS \ + -D__USE_LPCOPEN \ -DCFG_TUSB_MCU=OPT_MCU_LPC18XX # mcu driver cause following warnings diff --git a/hw/bsp/mcb1800/mcb1800.c b/hw/bsp/mcb1800/mcb1800.c index 1d7ffb35f..b57385985 100644 --- a/hw/bsp/mcb1800/mcb1800.c +++ b/hw/bsp/mcb1800/mcb1800.c @@ -112,6 +112,12 @@ static const PINMUX_GRP_T pinclockmuxing[] = // Invoked by startup code void SystemInit(void) { +#ifdef __USE_LPCOPEN + extern void (* const g_pfnVectors[])(void); + unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; + *pSCB_VTOR = (unsigned int) &g_pfnVectors; +#endif + /* Setup system level pin muxing */ Chip_SCU_SetPinMuxing(pinmuxing, sizeof(pinmuxing) / sizeof(PINMUX_GRP_T)); diff --git a/hw/bsp/ngx4330/board.mk b/hw/bsp/ngx4330/board.mk index 23d53bd18..fe66fceb5 100644 --- a/hw/bsp/ngx4330/board.mk +++ b/hw/bsp/ngx4330/board.mk @@ -7,7 +7,7 @@ CFLAGS += \ -mfpu=fpv4-sp-d16 \ -nostdlib \ -DCORE_M4 \ - -D__USE_CMSIS \ + -D__USE_LPCOPEN \ -DCFG_TUSB_MCU=OPT_MCU_LPC43XX # mcu driver cause following warnings @@ -24,7 +24,8 @@ SRC_C += \ $(MCU_DIR)/src/clock_18xx_43xx.c \ $(MCU_DIR)/src/gpio_18xx_43xx.c \ $(MCU_DIR)/src/sysinit_18xx_43xx.c \ - $(MCU_DIR)/src/uart_18xx_43xx.c + $(MCU_DIR)/src/uart_18xx_43xx.c \ + $(MCU_DIR)/src/fpu_init.c INC += \ $(TOP)/$(MCU_DIR)/inc \ diff --git a/hw/bsp/ngx4330/ngx4330.c b/hw/bsp/ngx4330/ngx4330.c index 5296ddcb3..b1908fc38 100644 --- a/hw/bsp/ngx4330/ngx4330.c +++ b/hw/bsp/ngx4330/ngx4330.c @@ -71,11 +71,17 @@ static const PINMUX_GRP_T pinmuxing[] = }; // Invoked by startup code -extern void (* const g_pfnVectors[])(void); void SystemInit(void) { - // Remap isr vector - *((uint32_t *) 0xE000ED08) = (uint32_t) &g_pfnVectors; +#ifdef __USE_LPCOPEN + extern void (* const g_pfnVectors[])(void); + unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; + *pSCB_VTOR = (unsigned int) &g_pfnVectors; + +#if __FPU_USED == 1 + fpuInit(); +#endif +#endif // __USE_LPCOPEN // Set up pinmux Chip_SCU_SetPinMuxing(pinmuxing, sizeof(pinmuxing) / sizeof(PINMUX_GRP_T)); From 1d83ad0ebb6c263736b0dadec80c9406563a5199 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Sep 2020 13:12:09 +0700 Subject: [PATCH 039/167] 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(-) 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) From ef651e073409bac1a9793d97bf5a25220913f32e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Sep 2020 17:07:29 +0700 Subject: [PATCH 040/167] 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(-) 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; From 338e96fa826b2e2bbb6fb489456202e9e4ec4fe2 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 3 Sep 2020 18:09:46 +0200 Subject: [PATCH 041/167] 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(+) 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); From 4ecedc70c8cbec366c7eb6dc90c99c7cce27407e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Sep 2020 23:48:56 +0700 Subject: [PATCH 042/167] fix vector assign --- hw/bsp/ea4088qs/ea4088qs.c | 2 +- hw/bsp/ea4357/ea4357.c | 2 +- hw/bsp/lpcxpresso1769/lpcxpresso1769.c | 2 +- hw/bsp/mbed1768/mbed1768.c | 2 +- hw/bsp/mcb1800/mcb1800.c | 2 +- hw/bsp/ngx4330/ngx4330.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/bsp/ea4088qs/ea4088qs.c b/hw/bsp/ea4088qs/ea4088qs.c index df76bb92a..f164526d7 100644 --- a/hw/bsp/ea4088qs/ea4088qs.c +++ b/hw/bsp/ea4088qs/ea4088qs.c @@ -89,7 +89,7 @@ void SystemInit(void) #ifdef __USE_LPCOPEN extern void (* const g_pfnVectors[])(void); unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; - *pSCB_VTOR = (unsigned int) &g_pfnVectors; + *pSCB_VTOR = (unsigned int) g_pfnVectors; #if __FPU_USED == 1 fpuInit(); diff --git a/hw/bsp/ea4357/ea4357.c b/hw/bsp/ea4357/ea4357.c index 69d2c3cc1..56653bd1b 100644 --- a/hw/bsp/ea4357/ea4357.c +++ b/hw/bsp/ea4357/ea4357.c @@ -88,7 +88,7 @@ void SystemInit(void) #ifdef __USE_LPCOPEN extern void (* const g_pfnVectors[])(void); unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; - *pSCB_VTOR = (unsigned int) &g_pfnVectors; + *pSCB_VTOR = (unsigned int) g_pfnVectors; #if __FPU_USED == 1 fpuInit(); diff --git a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c index 0d5e98e9e..101cc8a4c 100644 --- a/hw/bsp/lpcxpresso1769/lpcxpresso1769.c +++ b/hw/bsp/lpcxpresso1769/lpcxpresso1769.c @@ -92,7 +92,7 @@ void SystemInit(void) #ifdef __USE_LPCOPEN extern void (* const g_pfnVectors[])(void); unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; - *pSCB_VTOR = (unsigned int) &g_pfnVectors; + *pSCB_VTOR = (unsigned int) g_pfnVectors; #endif Chip_IOCON_Init(LPC_IOCON); diff --git a/hw/bsp/mbed1768/mbed1768.c b/hw/bsp/mbed1768/mbed1768.c index 17004cfe0..5495ed166 100644 --- a/hw/bsp/mbed1768/mbed1768.c +++ b/hw/bsp/mbed1768/mbed1768.c @@ -68,7 +68,7 @@ void SystemInit(void) #ifdef __USE_LPCOPEN extern void (* const g_pfnVectors[])(void); unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; - *pSCB_VTOR = (unsigned int) &g_pfnVectors; + *pSCB_VTOR = (unsigned int) g_pfnVectors; #endif Chip_IOCON_Init(LPC_IOCON); diff --git a/hw/bsp/mcb1800/mcb1800.c b/hw/bsp/mcb1800/mcb1800.c index a17ac5c3b..569d33834 100644 --- a/hw/bsp/mcb1800/mcb1800.c +++ b/hw/bsp/mcb1800/mcb1800.c @@ -115,7 +115,7 @@ void SystemInit(void) #ifdef __USE_LPCOPEN extern void (* const g_pfnVectors[])(void); unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; - *pSCB_VTOR = (unsigned int) &g_pfnVectors; + *pSCB_VTOR = (unsigned int) g_pfnVectors; #endif /* Setup system level pin muxing */ diff --git a/hw/bsp/ngx4330/ngx4330.c b/hw/bsp/ngx4330/ngx4330.c index dda3bc092..2e4ff9af9 100644 --- a/hw/bsp/ngx4330/ngx4330.c +++ b/hw/bsp/ngx4330/ngx4330.c @@ -76,7 +76,7 @@ void SystemInit(void) #ifdef __USE_LPCOPEN extern void (* const g_pfnVectors[])(void); unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; - *pSCB_VTOR = (unsigned int) &g_pfnVectors; + *pSCB_VTOR = (unsigned int) g_pfnVectors; #if __FPU_USED == 1 fpuInit(); From 35aee4a6af40c7c8befb5dfe81bbf7e26dc01ca8 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Sep 2020 23:57:51 +0700 Subject: [PATCH 043/167] 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(-) 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 + +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 From 7828c396dbc287f9d9a0aa6af63a32108f139b94 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Sep 2020 00:23:57 +0700 Subject: [PATCH 044/167] keyboard host work as proof of concept --- examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject | 1 + examples/host/cdc_msc_hid/src/main.c | 2 +- examples/host/cdc_msc_hid/src/tusb_config.h | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject index e0a2f6f97..2b5538957 100644 --- a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject +++ b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject @@ -53,6 +53,7 @@ + diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 8f61310d5..209379b37 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -58,7 +58,7 @@ int main(void) cdc_task(); #endif -#if CFG_TUD_HID +#if CFG_TUH_HID_KEYBOARD || CFG_TUH_HID_MOUSE hid_task(); #endif } diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index dd50c7050..6604623b1 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -71,8 +71,8 @@ #define CFG_TUH_HUB 0 #define CFG_TUH_CDC 1 -#define CFG_TUH_HID_KEYBOARD 0 -#define CFG_TUH_HID_MOUSE 0 +#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 From 865ebf7c5db98ccc3f8f5f4fead9d8bba0e57c18 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Sep 2020 00:50:10 +0700 Subject: [PATCH 045/167] fflush(stdout) for keyboard host example --- examples/host/cdc_msc_hid/src/main.c | 2 ++ examples/host/cdc_msc_hid/src/msc_app.c | 4 ++-- examples/make.mk | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 209379b37..34503499f 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -143,6 +143,8 @@ static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report) 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 diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 93dc6d3fe..62bd961c1 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -35,7 +35,7 @@ //------------- IMPLEMENTATION -------------// void tuh_msc_mounted_cb(uint8_t dev_addr) { - printf("a MassStorage device is mounted\r\n"); + printf("A MassStorage device is mounted\r\n"); //------------- Disk Information -------------// // SCSI VendorID[8] & ProductID[16] from Inquiry Command @@ -83,7 +83,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr) void tuh_msc_unmounted_cb(uint8_t dev_addr) { (void) dev_addr; - printf("a MassStorage device is unmounted\r\n"); + printf("A MassStorage device is unmounted\r\n"); // uint8_t phy_disk = dev_addr-1; // diff --git a/examples/make.mk b/examples/make.mk index b7917987e..6743044fd 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -84,7 +84,6 @@ ifeq ($(LOGGER),rtt) 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 From 5fb3d439b3e415bae5edbc556ea20f7211ac4bb5 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Sep 2020 01:32:30 +0700 Subject: [PATCH 046/167] update ci to also build host example --- .github/workflows/build.yml | 19 +++++++-- .../host/cdc_msc_hid/.only.MCU_LPC175X_6X | 0 .../host/cdc_msc_hid/.only.MCU_LPC177X_8X | 0 examples/host/cdc_msc_hid/.only.MCU_LPC18XX | 0 examples/host/cdc_msc_hid/.only.MCU_LPC40XX | 0 examples/host/cdc_msc_hid/.only.MCU_LPC43XX | 0 examples/host/cdc_msc_hid/src/main.c | 5 ++- tools/build_all.py | 41 +++++++++++++------ 8 files changed, 49 insertions(+), 16 deletions(-) create mode 100644 examples/host/cdc_msc_hid/.only.MCU_LPC175X_6X create mode 100644 examples/host/cdc_msc_hid/.only.MCU_LPC177X_8X create mode 100644 examples/host/cdc_msc_hid/.only.MCU_LPC18XX create mode 100644 examples/host/cdc_msc_hid/.only.MCU_LPC40XX create mode 100644 examples/host/cdc_msc_hid/.only.MCU_LPC43XX diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2ad274928..da1f9e5e0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,9 +26,22 @@ jobs: strategy: fail-fast: false matrix: - example: ['board_test', 'cdc_dual_ports', 'cdc_msc', 'cdc_msc_freertos', 'dfu_rt', - 'hid_composite', 'hid_composite_freertos', 'hid_generic_inout', 'midi_test', 'msc_dual_lun', 'net_lwip_webserver', - 'usbtmc', 'webusb_serial'] + example: + - 'device/board_test' + - 'device/cdc_dual_ports' + - 'device/cdc_msc' + - 'device/cdc_msc_freertos' + - 'device/dfu_rt' + - 'device/hid_composite' + - 'device/hid_composite_freertos' + - 'device/hid_generic_inout' + - 'device/midi_test' + - 'device/msc_dual_lun' + - 'device/net_lwip_webserver' + - 'device/usbtmc' + - 'device/webusb_serial' + - 'host/cdc_msc_hid' + steps: - name: Setup Python uses: actions/setup-python@v1 diff --git a/examples/host/cdc_msc_hid/.only.MCU_LPC175X_6X b/examples/host/cdc_msc_hid/.only.MCU_LPC175X_6X new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/cdc_msc_hid/.only.MCU_LPC177X_8X b/examples/host/cdc_msc_hid/.only.MCU_LPC177X_8X new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/cdc_msc_hid/.only.MCU_LPC18XX b/examples/host/cdc_msc_hid/.only.MCU_LPC18XX new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/cdc_msc_hid/.only.MCU_LPC40XX b/examples/host/cdc_msc_hid/.only.MCU_LPC40XX new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/cdc_msc_hid/.only.MCU_LPC43XX b/examples/host/cdc_msc_hid/.only.MCU_LPC43XX new file mode 100644 index 000000000..e69de29bb diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 34503499f..4200cc5e0 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -185,7 +185,8 @@ void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr) // invoked ISR context void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event) { - + (void) dev_addr; + (void) event; } #endif @@ -206,6 +207,8 @@ void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr) // invoked ISR context void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event) { + (void) dev_addr; + (void) event; } #endif diff --git a/tools/build_all.py b/tools/build_all.py index 9581104e1..0dc555d2f 100644 --- a/tools/build_all.py +++ b/tools/build_all.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,15 +15,19 @@ exit_status = 0 total_time = time.monotonic() -build_format = '| {:23} | {:30} | {:9} | {:7} | {:6} | {:6} |' -build_separator = '-' * 100 +build_format = '| {:29} | {:30} | {:18} | {:7} | {:6} | {:6} |' +build_separator = '-' * 106 # If examples are not specified in arguments, build all all_examples = [] for entry in os.scandir("examples/device"): if entry.is_dir(): - all_examples.append(entry.name) + all_examples.append("device/" + entry.name) + +for entry in os.scandir("examples/host"): + if entry.is_dir(): + all_examples.append("host/" + entry.name) if len(sys.argv) > 1: input_examples = list(set(all_examples).intersection(sys.argv)) @@ -43,14 +51,14 @@ if len(sys.argv) > 1: all_boards.sort() def build_example(example, board): - subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, + subprocess.run("make -C examples/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - return subprocess.run("make -j -C examples/device/{} BOARD={} all".format(example, board), shell=True, + return subprocess.run("make -j -C examples/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) def build_size(example, board): #elf_file = 'examples/device/{}/_build/build-{}/{}-firmware.elf'.format(example, board, board) - elf_file = 'examples/device/{}/_build/build-{}/*.elf'.format(example, board) + elf_file = 'examples/{}/_build/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]) @@ -58,7 +66,7 @@ def build_size(example, board): return (flash_size, sram_size) def skip_example(example, board): - ex_dir = 'examples/device/' + example + ex_dir = 'examples/' + example board_mk = 'hw/bsp/{}/board.mk'.format(board) with open(board_mk) as mk: @@ -74,10 +82,19 @@ def skip_example(example, board): if mcu_cflag in mk_contents: return 1 + # Build only list, if exists only these MCU are built + only_list = list(glob.iglob(ex_dir + '/.only.MCU_*')) + if len(only_list) > 0: + for only_file in only_list: + mcu_cflag = '-DCFG_TUSB_MCU=OPT_' + os.path.basename(only_file).split('.')[2] + if mcu_cflag in mk_contents: + return 0 + return 1 + 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')) for example in all_examples: print(build_separator) @@ -89,19 +106,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 @@ -114,7 +131,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) From a8e538efe7d11291e32e016fad5910ebaf9eac43 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Sep 2020 01:35:32 +0700 Subject: [PATCH 047/167] clean up --- src/class/hid/hid_host.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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; } From 10d5dac9137adfd6c14d96e1079f08447eacd9d8 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 4 Sep 2020 11:20:09 +0700 Subject: [PATCH 048/167] update doc --- docs/boards.md | 7 ++++--- hw/bsp/samg55xplained/board.mk | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/boards.md b/docs/boards.md index 1b3de29e9..309f5e5d9 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -19,7 +19,7 @@ This code base already had supported for a handful of following boards (sorted a - [DA14695 Development Kit – USB](https://www.dialog-semiconductor.com/products/da14695-development-kit-usb) - [DA1469x Development Kit – Pro](https://www.dialog-semiconductor.com/products/da14695-development-kit-pro) -### MicroChip SAMD +### MicroChip SAM - [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333) - [Adafruit Feather M0 Express](https://www.adafruit.com/product/3403) @@ -28,9 +28,10 @@ This code base already had supported for a handful of following boards (sorted a - [Adafruit ItsyBitsy M4 Express](https://www.adafruit.com/product/3800) - [Adafruit Metro M0 Express](https://www.adafruit.com/product/3505) - [Adafruit Metro M4 Express](https://www.adafruit.com/product/3382) -- [Microchip SAMD11 Xplained](https://www.microchip.com/developmenttools/ProductDetails/atsamd11-xpro) -- [Seeeduino Xiao](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html) - [Great Scott Gadgets LUNA](https://greatscottgadgets.com/luna/) +- [Microchip SAMD11 Xplained](https://www.microchip.com/developmenttools/ProductDetails/atsamd11-xpro) +- [Microchip SAMG55 Xplained Pro Evaluation Kit](https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/ATSAMG55-XPRO) +- [Seeeduino Xiao](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html) ### Nordic nRF5x diff --git a/hw/bsp/samg55xplained/board.mk b/hw/bsp/samg55xplained/board.mk index b53757dff..a58a7b41d 100644 --- a/hw/bsp/samg55xplained/board.mk +++ b/hw/bsp/samg55xplained/board.mk @@ -46,7 +46,7 @@ CHIP_FAMILY = samg FREERTOS_PORT = ARM_CM4F # For flash-jlink target -JLINK_DEVICE = ATSAMD51J19 +JLINK_DEVICE = ATSAMG55J19 JLINK_IF = swd # flash using edbg from https://github.com/ataradov/edbg From 4e789b240deb0b124b65fd3a177674f562f0b3c1 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sun, 6 Sep 2020 11:37:59 +0200 Subject: [PATCH 049/167] 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(-) 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. From 8b9893cadab88fa4abd17d5b9856e0d08ef03796 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Sep 2020 15:48:11 +0700 Subject: [PATCH 050/167] 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(-) 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); From 33f0a18523accfcdebf186f33271dd92f8681b56 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Sep 2020 16:25:31 +0700 Subject: [PATCH 051/167] update cdc edpt read --- src/class/cdc/cdc_device.c | 12 +++++------- src/device/usbd.c | 2 ++ 2 files changed, 7 insertions(+), 7 deletions(-) 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; From fe1b5dfa235550cc4eb63e237da50689fe407bf4 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Sep 2020 16:29:45 +0700 Subject: [PATCH 052/167] clean up --- src/class/cdc/cdc_device.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) 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) ) From ed6d48b81e8a5d1ed8b518921b30b87c7daecee5 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 9 Sep 2020 16:45:54 +0700 Subject: [PATCH 053/167] typo --- src/class/cdc/cdc_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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)); From 801f8b5b38b90cb3e15d0a1bb2accae58cde6130 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 10 Sep 2020 23:32:08 +0700 Subject: [PATCH 054/167] 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(-) 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 From ce4a9b9c3ad15a8a714959c89c7a39ba67970cfd Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 11 Sep 2020 00:14:07 +0700 Subject: [PATCH 055/167] clean up --- src/device/usbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 1804dba615653591a754c9221028c94a32e50495 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 12 Sep 2020 08:48:49 +0700 Subject: [PATCH 056/167] typo --- src/class/cdc/cdc_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); From 25bb8830c5db7985906d2540da2a35e49edddb75 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 12 Sep 2020 09:26:41 +0700 Subject: [PATCH 057/167] doc: merge example/readme.md into docs/getting_started.md --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- docs/getting_started.md | 114 ++++++++++++++++++++++++--- examples/readme.md | 104 ------------------------ 3 files changed, 103 insertions(+), 117 deletions(-) delete mode 100644 examples/readme.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 5160e9f84..9f956f9d8 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -26,4 +26,4 @@ Steps to reproduce the behavior: If applicable, add screenshots, bus capture to help explain your problem. **Log** -Please provide the stack's log (uart/rtt/swo) where the issue occurred, best with comments to explain the actual events. To enable logging, add `LOG=2` to to the make command if building with stock examples or set `CFG_TUSB_DEBUG=2` in your tusb_config.h. More information can be found at [example's readme](/examples/readme.md) +Please provide the stack's log (uart/rtt/swo) where the issue occurred, best with comments to explain the actual events. To enable logging, add `LOG=2` to to the make command if building with stock examples or set `CFG_TUSB_DEBUG=2` in your tusb_config.h. More information can be found at [example's readme](/docs/getting_started.md) diff --git a/docs/getting_started.md b/docs/getting_started.md index e282b4171..8d22a3127 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -1,14 +1,6 @@ # Getting Started # -## Get - -``` -git clone git@github.com:hathach/tinyusb.git tinyusb -``` - -*examples* is the folder where all the application & project files are located. There are demos for both device and hosts. For each, there are different projects for each of supported RTOS. Click to have more information on how to [build](../examples/readme.md) and run [device](../examples/device/readme.md) demos. - -## Add tinyusb to your project +## Add TinyUSB to your project It is relatively simple to incorporate tinyusb to your (existing) project @@ -37,6 +29,104 @@ int main(void) } ~~~ -[//]: # "\subpage md_boards_readme" -[//]: # "\subpage md_doxygen_started_demo" -[//]: # "\subpage md_tools_readme" +## Examples + +For your convenience, TinyUSB contains a handful of examples for both host and device with/without RTOS to quickly test the functionality as well as demonstrate how API() should be used. Most examples will work on most of [the supported Boards](boards.md). Firstly we need to `git clone` if not already + +``` +$ git clone https://github.com/hathach/tinyusb tinyusb +$ cd tinyusb +``` + +TinyUSB examples includes external repos aka submodules to provide low-level MCU peripheral's driver as well as external libraries such as FreeRTOS to compile with. Therefore we will firstly fetch those mcu driver repo by running this command in the top folder repo + +``` +$ git submodule update --init --recursive +``` + +It will takes a bit of time due to the number of supported MCUs, luckily we only need to do this once. Or if you only want to test with a specific mcu, you could only fetch its driver submodule. + +### Build + +To build example, first change directory to an example folder. + +``` +$ cd examples/device/cdc_msc +``` + +Then compile with `make BOARD=[board_name] all`, for example + +``` +$ make BOARD=feather_nrf52840_express all +``` + +#### Port Selection + +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=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 SPEED=full all +``` + +### Debug + +To compile for debugging add `DEBUG=1`, for example + +``` +$ make BOARD=feather_nrf52840_express DEBUG=1 all +``` + +#### 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 BOARD=feather_nrf52840_express LOG=2 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 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: should be compatible with more debugger that support SWO. + - Software viewer should be provided along with your debugger driver. + +``` +$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=rtt all +$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=swo all +``` + +### Flash + +`flash` target will use the default on-board debugger (jlink/cmsisdap/stlink/dfu) to flash the binary, please install those support software in advance. Some board use bootloader/DFU via serial which is required to pass to make command + +``` +$ make BOARD=feather_nrf52840_express flash +$ make SERIAL=/dev/ttyACM0 BOARD=feather_nrf52840_express flash +``` + +Since jlink can be used with most of the boards, there is also `flash-jlink` target for your convenience. + +``` +$ make BOARD=feather_nrf52840_express flash-jlink +``` + +Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can be generated with `uf2` target + +``` +$ make BOARD=feather_nrf52840_express all uf2 +``` diff --git a/examples/readme.md b/examples/readme.md deleted file mode 100644 index f6cd380b6..000000000 --- a/examples/readme.md +++ /dev/null @@ -1,104 +0,0 @@ -# Examples - -## Clone this repo - -``` -$ git clone https://github.com/hathach/tinyusb tinyusb -$ cd tinyusb -``` - -## Fetch submodule MCUs drivers - -TinyUSB examples includes external repos aka submodules to provide low-level MCU peripheral's driver to compile with. Therefore we will firstly fetch those mcu driver repo by running this command in the top folder repo - -``` -$ git submodule update --init --recursive -``` - -It will takes a bit of time due to the number of supported MCUs, luckily we only need to do this once. Or if you only want to test with a specific mcu, you could only update its driver submodule - -## Build - -[Here is the list of supported Boards](docs/boards.md) that should work out of the box with provided examples (hopefully). -To build example, first change directory to example folder. - -``` -$ cd examples/device/cdc_msc -``` - -Then compile with `make BOARD=[your_board] all`, for example - -``` -$ make BOARD=feather_nrf52840_express all -``` - -**Port Selection** - -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=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 SPEED=full all -``` - -### Debug - -To compile for debugging with debug symbols add `DEBUG=1`, for example - -``` -$ make BOARD=feather_nrf52840_express DEBUG=1 all -``` - -#### 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 BOARD=feather_nrf52840_express LOG=2 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 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: should be compatible with more debugger that support SWO. - - Software viewer should be provided along with your debugger driver. - -``` -$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=rtt all -$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=swo all -``` - -## Flash - -`flash` target will use the default on-board debugger (jlink/cmsisdap/stlink/dfu) to flash the binary, please install those support software in advance. Some board use bootloader/DFU via serial which is required to pass to make command - -``` -$ make BOARD=feather_nrf52840_express flash -$ make SERIAL=/dev/ttyACM0 BOARD=feather_nrf52840_express flash -``` - -Since jlink can be used with most of the boards, there is also `flash-jlink` target for your convenience. - -``` -$ make BOARD=feather_nrf52840_express flash-jlink -``` - -Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can be generated with `uf2` target - -``` -$ make BOARD=feather_nrf52840_express all uf2 -``` From 5931d19666667e9a5b2b99082fb24392e3983399 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 13 Sep 2020 15:01:20 +0700 Subject: [PATCH 058/167] correct the TUD_HID_REPORT_DESC_GAMEPAD --- src/class/hid/hid_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ) ,\ From 3b0216d3bfe568e949fe1ea7c2c9f3f3a8dc6a4b Mon Sep 17 00:00:00 2001 From: Mark Lentczner Date: Sun, 13 Sep 2020 15:05:18 -0700 Subject: [PATCH 059/167] 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(-) 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; From 23e6ee2ea2e69f09b43c9f7736b95560a6e9ef7b Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 14 Sep 2020 22:14:31 +0700 Subject: [PATCH 060/167] 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 | 25 +++++++++++++++++++------ src/device/usbd.c | 5 ++++- 2 files changed, 23 insertions(+), 7 deletions(-) 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) { - // 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), ); + uint8_t const rhport = TUD_OPT_RHPORT; + uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); - // claim endpoint and submit transfer - if ( 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. + // 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), ); + + // 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; From 9c0d15fc43818282b6a92432e675dd214e51735e Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 14 Sep 2020 22:23:59 +0700 Subject: [PATCH 061/167] more const --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From 349c0f640e7d4532cc96fd28dea2dd11a5d43bde Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 14 Sep 2020 18:24:08 +0200 Subject: [PATCH 062/167] Implementation done, yet to be tested. --- src/common/tusb_fifo.c | 421 ++++++++++++++++++++++++++++++++--------- src/common/tusb_fifo.h | 71 ++++--- 2 files changed, 362 insertions(+), 130 deletions(-) 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(buffer, - f->buffer + (f->rd_idx * f->item_size), - f->item_size*n); - - f->rd_idx = _ff_mod(f->rd_idx + n, f->depth); - f->count -= n; + memcpy(f->buffer + (wRel * f->item_size), data, n*f->item_size); } -// send data to fifo -static inline void _ff_push(tu_fifo_t* f, void const * data, uint16_t n) +// 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(f->buffer + (f->wr_idx * f->item_size), - data, - f->item_size*n); - - f->wr_idx = _ff_mod(f->wr_idx + n, f->depth); - - if (tu_fifo_full(f)) + if(wRel + n <= f->depth) // Linear mode only { - f->rd_idx = f->wr_idx; // keep the full state (rd == wr && count = depth) + 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); + } +} + +// 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); +} + +// 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) +{ + 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; + + // 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); + } +} + +// 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)) + { + 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); + + // Advance pointer + f->rd_idx = advance_pointer(f, r, ret); tu_fifo_unlock(f); - - return true; + 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); - - // 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); - - tu_fifo_unlock(f); - - return true; + return _tu_fifo_peek_at(f, pos, p_buffer, f->wr_idx, f->rd_idx); } /******************************************************************************/ /*! - @brief Write one element into the RX buffer. + @brief Read n items without removing it from the FIFO + + @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 + + @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 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; + + // 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; } - if (count + f->wr_idx <= f->depth ) - { - _ff_push(f, buf8, count); - } - else - { - uint16_t const part1 = f->depth - f->wr_idx; + uint16_t wRel = get_relative_pointer(f, w, 0); - // Part 1: from wr_idx to end - _ff_push(f, buf8, part1); - buf8 += part1*f->item_size; + // 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); +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_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; From 62a76c0e049998c6fda2f349503bee2fafd12bad Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 15 Sep 2020 16:08:23 +0200 Subject: [PATCH 063/167] 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(-) 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; From 9dfb78e9d82d0386de555aa291242ddfe835cd18 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 15 Sep 2020 20:40:41 +0200 Subject: [PATCH 064/167] Tested, working. --- src/common/tusb_fifo.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) 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; } From 21299f90faf501422706ce36b6d3bb7c55bb3ecb Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 19 Sep 2020 11:46:43 +0200 Subject: [PATCH 065/167] Final cleanup. --- src/common/tusb_fifo.c | 148 ++++++++++++++++++++++++++++++++--------- src/common/tusb_fifo.h | 19 +++++- 2 files changed, 131 insertions(+), 36 deletions(-) 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); From 9bdeafb29503b65d2c46e71a4c7e80b753bad55a Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 23 Sep 2020 20:48:03 +0200 Subject: [PATCH 066/167] 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(-) 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_ */ From 52c9a467b42c4448251753a295343496a9265b4f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 23 Sep 2020 21:36:30 +0200 Subject: [PATCH 067/167] Fix bug in modulo substitute. --- src/common/tusb_fifo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 9ddcfc09d7c0f076248307f76222d5b1db9e0882 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 25 Sep 2020 15:58:28 +0200 Subject: [PATCH 068/167] 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(-) 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. From 8dcb10493330513b5b017306634a936413f1ecd5 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 26 Sep 2020 11:00:31 +0200 Subject: [PATCH 069/167] Change modulo substitute to while ( idx >= depth) idx -= depth; --- src/common/tusb_fifo.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 From 6f3d0af1e65f9741cd9a735fea596e466645e234 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 26 Aug 2020 16:08:33 +0200 Subject: [PATCH 070/167] 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(-) 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; } } From 5ad2f8efc6ce77d3f58f3292838367dea8c41826 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 26 Aug 2020 16:34:56 +0200 Subject: [PATCH 071/167] 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(-) 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); } From f4a44ee06337366680958013143657aa693c80ef Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 10:56:17 +0200 Subject: [PATCH 072/167] 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(-) 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 From e67fc808aada31a549399a0b0337b43ec45535d1 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:13:25 +0200 Subject: [PATCH 073/167] 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(+) 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; } } From 66b091282f31275fff859c4cf61c3026215a3db7 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:16:41 +0200 Subject: [PATCH 074/167] 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(-) 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 From ca4a42156ceeb8dd6b70edc02b2b762645c62c66 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:18:11 +0200 Subject: [PATCH 075/167] 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(-) 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; } From 28cf63c7dbe08677d614d16a435487ae03b3cce6 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:24:41 +0200 Subject: [PATCH 076/167] 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(-) 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]); } From 759d5305062e5261d580fa64e40fc755db34c436 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 11 Sep 2020 13:42:52 +0200 Subject: [PATCH 077/167] 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(-) 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, bufsize); + 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 +{ +#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 From 6b5233096978305f1d6a87ef83393ba50e8b0bd2 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 14 Sep 2020 10:22:54 +0200 Subject: [PATCH 078/167] 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(-) 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) From 2ace98e943831784e6c9d81258babce2b7b3221c Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 14 Sep 2020 11:28:05 +0200 Subject: [PATCH 079/167] 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(-) 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 From 642a8b00c8bb733ddf84efbfbb6b3451bb747485 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 14 Sep 2020 12:31:00 +0200 Subject: [PATCH 080/167] 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(-) 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) { From f55437d8898f46e6deee273306179c2a7f3f9b5d Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 14 Sep 2020 14:32:38 +0200 Subject: [PATCH 081/167] 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(+) 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 From 529622710ca6a234fa385402e4a298759a04ad72 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 28 Sep 2020 18:10:57 +0200 Subject: [PATCH 082/167] 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(-) 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); From 9c837300f1d01593457f75b6e2a07a775ed3c5e1 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 28 Sep 2020 19:23:38 +0200 Subject: [PATCH 083/167] 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(-) 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); From da1c3c226b84faf2547a71fb7ed4acdb544d758b Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Mon, 28 Sep 2020 22:44:09 +0200 Subject: [PATCH 084/167] 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(-) 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; From 13a9cbde7957de2d87731a85dcc0c7ea756e71b7 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Tue, 29 Sep 2020 23:30:35 +0200 Subject: [PATCH 085/167] Change AUDIO_FUNC_PROTOCOL_CODE_UNDEF for midi in usbd.h --- src/device/usbd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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) From b2ce7a39b0d0b941ad7edb63f527b223568caa47 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 21 Sep 2020 15:23:56 +0200 Subject: [PATCH 086/167] 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(-) 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; From fceb8853c7e125d74fc4e13ca6ea6934248dbd21 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 21 Sep 2020 15:45:17 +0200 Subject: [PATCH 087/167] 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(+) 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; From 6f5ee09511a84aa2614af95a13963b8419ee8926 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 21 Sep 2020 15:49:41 +0200 Subject: [PATCH 088/167] 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(-) 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; From 96da1ca4b86f58074b741c8a2437c2fd8be2b867 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 21 Sep 2020 15:53:15 +0200 Subject: [PATCH 089/167] 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(-) 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); From 603ce17696dfb930f93649d82a87702fd89f303f Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Thu, 1 Oct 2020 17:49:30 +0200 Subject: [PATCH 090/167] Change AUDIO_CS_INTERFACE_HEADER to AUDIO_CS_AC_INTERFACE_HEADER --- src/device/usbd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 */\ From 849681724af698c77b01a615595418ba2efd543e Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Thu, 1 Oct 2020 11:51:33 -0500 Subject: [PATCH 091/167] 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(-) 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_ */ - From b7208d6f7e97e724853eb5d0e512a23005cc8790 Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Thu, 1 Oct 2020 12:51:48 -0500 Subject: [PATCH 092/167] 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(-) 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. From e21ab8d4a97ee909511cd096b440bf6255ca2c74 Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Thu, 1 Oct 2020 13:15:37 -0500 Subject: [PATCH 093/167] create hid multiple interface example --- .../device/hid_multipleinterface/Makefile | 12 + .../device/hid_multipleinterface/src/main.c | 208 ++++++++++++++++++ .../hid_multipleinterface/src/tusb_config.h | 110 +++++++++ .../src/usb_descriptors.c | 189 ++++++++++++++++ .../src/usb_descriptors.h | 34 +++ 5 files changed, 553 insertions(+) create mode 100644 examples/device/hid_multipleinterface/Makefile create mode 100644 examples/device/hid_multipleinterface/src/main.c create mode 100644 examples/device/hid_multipleinterface/src/tusb_config.h create mode 100644 examples/device/hid_multipleinterface/src/usb_descriptors.c create mode 100644 examples/device/hid_multipleinterface/src/usb_descriptors.h diff --git a/examples/device/hid_multipleinterface/Makefile b/examples/device/hid_multipleinterface/Makefile new file mode 100644 index 000000000..69b633fea --- /dev/null +++ b/examples/device/hid_multipleinterface/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/hid_multipleinterface/src/main.c b/examples/device/hid_multipleinterface/src/main.c new file mode 100644 index 000000000..985d87246 --- /dev/null +++ b/examples/device/hid_multipleinterface/src/main.c @@ -0,0 +1,208 @@ +/* + * 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 +#include +#include + +#include "bsp/board.h" +#include "tusb.h" + +#include "usb_descriptors.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; + +void led_blinking_task(void); +void hid_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + tusb_init(); + + while (1) + { + tud_task(); // tinyusb device task + led_blinking_task(); + + hid_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; +} + +//--------------------------------------------------------------------+ +// USB HID +//--------------------------------------------------------------------+ + +void hid_task(void) +{ + //Set up interfaces + const uint8_t keyboard_interface = 0; + const uint8_t mouse_interface = 1; + + // 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; + + uint32_t const btn = board_button_read(); + + // Remote wakeup + if ( tud_suspended() && btn ) + { + // Wake up host if we are in suspend mode + // and REMOTE_WAKEUP feature is enabled by host + tud_remote_wakeup(); + } + + /*------------- Keyboard -------------*/ + if ( tud_hid_n_ready(keyboard_interface) ) + { + // use to avoid send multiple consecutive zero report for keyboard + static bool has_key = false; + + if ( btn ) + { + uint8_t keycode[6] = { 0 }; + keycode[0] = HID_KEY_A; + + tud_hid_n_keyboard_report(keyboard_interface, REPORT_ID_KEYBOARD, 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); + has_key = false; + } + } + + /*------------- Mouse -------------*/ + if ( tud_hid_n_ready(mouse_interface) ) + { + if ( btn ) + { + 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); + + // delay a bit before attempt to send keyboard report + board_delay(10); + } + } +} + + +// 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) +{ + // TODO not Implemented + (void) report_id; + (void) report_type; + (void) buffer; + (void) reqlen; + + return 0; +} + +// 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) +{ + // TODO set LED based on CAPLOCK, NUMLOCK etc... + (void) report_id; + (void) report_type; + (void) buffer; + (void) bufsize; +} + +//--------------------------------------------------------------------+ +// 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/hid_multipleinterface/src/tusb_config.h b/examples/device/hid_multipleinterface/src/tusb_config.h new file mode 100644 index 000000000..9056d5173 --- /dev/null +++ b/examples/device/hid_multipleinterface/src/tusb_config.h @@ -0,0 +1,110 @@ +/* + * 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 board.mk +#ifndef CFG_TUSB_MCU + #error CFG_TUSB_MCU must be defined +#endif + +// 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 + +// 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 +#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 + +// This example doesn't use an RTOS +#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_HID 2 +#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_EP_BUFSIZE 16 + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/hid_multipleinterface/src/usb_descriptors.c b/examples/device/hid_multipleinterface/src/usb_descriptors.c new file mode 100644 index 000000000..f8423bdd1 --- /dev/null +++ b/examples/device/hid_multipleinterface/src/usb_descriptors.c @@ -0,0 +1,189 @@ +/* + * 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] 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) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + .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; +} + +//--------------------------------------------------------------------+ +// HID Report Descriptor +//--------------------------------------------------------------------+ + +uint8_t const desc_hid_report1[] = +{ + TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD) ) +}; + +uint8_t desc_hid_report2[] = +{ + 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(uint8_t desc_index) +{ + if (desc_index == 0) + { + return desc_hid_report1; + } + else if (desc_index == 1) + { + return desc_hid_report2; + } + + return 0; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ + +enum +{ + ITF_NUM_HID1, + ITF_NUM_HID2, + ITF_NUM_TOTAL +}; + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN + TUD_HID_DESC_LEN) + +#define EPNUM_HID1 0x81 +#define EPNUM_HID2 0x82 + +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, protocol, report descriptor len, EP In & Out 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) +}; + +// 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) + "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]; + +// 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 + { + // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors + + 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; + + // Convert ASCII string into UTF-16 + for(uint8_t i=0; i Date: Thu, 1 Oct 2020 13:37:54 -0500 Subject: [PATCH 094/167] Add pipeline task for example --- .github/workflows/build.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index da1f9e5e0..e2db8f775 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ jobs: steps: - name: Setup Ruby uses: actions/setup-ruby@v1 - + - name: Checkout TinyUSB uses: actions/checkout@v2 @@ -35,13 +35,14 @@ jobs: - 'device/hid_composite' - 'device/hid_composite_freertos' - 'device/hid_generic_inout' + - 'device/hid_multipleinterface' - 'device/midi_test' - 'device/msc_dual_lun' - 'device/net_lwip_webserver' - 'device/usbtmc' - 'device/webusb_serial' - 'host/cdc_msc_hid' - + steps: - name: Setup Python uses: actions/setup-python@v1 @@ -79,7 +80,7 @@ jobs: with: # Cannot do submodule checkout here since LWIP's git server cannot checkout unadventised commits (it must use tags) submodules: 'false' - + - name: Checkout Submodules run: | git submodule sync --recursive From 081af79009dc40ab41be9976d22629c7d251a50d Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Fri, 2 Oct 2020 16:02:00 -0500 Subject: [PATCH 095/167] fix simple pull request comments. Implement descriptor index hack. --- .../device/hid_multipleinterface/src/main.c | 8 ++--- .../src/usb_descriptors.c | 5 ++- .../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 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. From 2050dc0dc743294b07d0534278027da689bc6813 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Sat, 3 Oct 2020 09:46:22 +0200 Subject: [PATCH 096/167] 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(-) 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 From 78477077b418a25efa58ef0fb426d0cacb24d902 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sat, 26 Sep 2020 04:24:30 +0200 Subject: [PATCH 097/167] Use C++11 static_assert when available --- src/common/tusb_compiler.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 From 51fb659533c4c417b6771a801756ccc02d2b85f7 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sat, 26 Sep 2020 04:26:59 +0200 Subject: [PATCH 098/167] Use tu_printf instead of printf --- src/common/tusb_verify.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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) From e41d9202b81b0f3357c2feec2bca0c0a20b5478b Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sat, 26 Sep 2020 04:30:22 +0200 Subject: [PATCH 099/167] Allow overwriting TU_ASSERT etc macros --- src/common/tusb_verify.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) 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 From 788dcc200de76c965208c428ab1e1de0e72c98c1 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sat, 26 Sep 2020 05:40:24 +0200 Subject: [PATCH 100/167] Change CFG_TUSB_CONFIG_FILE mechanism to improve header file scanning --- src/tusb_option.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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 * @{ */ From 61aacf07d62a0d927e500bf2f39acae4609b9fc4 Mon Sep 17 00:00:00 2001 From: Jean Gressmann Date: Mon, 5 Oct 2020 18:35:35 +0200 Subject: [PATCH 101/167] Adds files for the open source D5035-01 hardware The board's files are here: https://github.com/RudolphRiedel/USB_CAN-FD --- hw/bsp/board_mcu.h | 10 +- hw/bsp/d5035-01/board.mk | 61 +++++ hw/bsp/d5035-01/d5035_01.c | 353 +++++++++++++++++++++++++ hw/bsp/d5035-01/same51j19a_flash.ld | 163 ++++++++++++ hw/mcu/microchip | 2 +- src/portable/microchip/samd/dcd_samd.c | 6 +- src/tusb_option.h | 1 + 7 files changed, 591 insertions(+), 5 deletions(-) create mode 100644 hw/bsp/d5035-01/board.mk create mode 100644 hw/bsp/d5035-01/d5035_01.c create mode 100644 hw/bsp/d5035-01/same51j19a_flash.ld diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index 3382d465d..6585ef9a6 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2020, Ha Thach (tinyusb.org) @@ -52,9 +52,15 @@ #elif CFG_TUSB_MCU == OPT_MCU_NRF5X #include "nrf.h" -#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || 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 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \ + CFG_TUSB_MCU == OPT_MCU_SAME51 #include "sam.h" + #if CFG_TUSB_MCU == OPT_MCU_SAME51 + #define SVC_Handler SVCall_Handler + #endif + #elif CFG_TUSB_MCU == OPT_MCU_SAMG #undef LITTLE_ENDIAN // hack to suppress "LITTLE_ENDIAN" redefined #include "sam.h" diff --git a/hw/bsp/d5035-01/board.mk b/hw/bsp/d5035-01/board.mk new file mode 100644 index 000000000..cbc653d19 --- /dev/null +++ b/hw/bsp/d5035-01/board.mk @@ -0,0 +1,61 @@ +CFLAGS += \ + -mthumb \ + -mabi=aapcs \ + -mlong-calls \ + -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -nostdlib -nostartfiles \ + -D__SAME51J19A__ \ + -DCONF_CPU_FREQUENCY=80000000 \ + -DCONF_GCLK_USB_FREQUENCY=48000000 \ + -DCFG_TUSB_MCU=OPT_MCU_SAME51 \ + -DD5035_01=1 \ + -DBOARD_NAME="\"D5035-01\"" + +ifdef HWREV + CFLAGS += -DHWREV=$(HWREV) +endif + +# All source paths should be relative to the top level. +LD_FILE = hw/bsp/$(BOARD)/same51j19a_flash.ld + +SRC_C += \ + hw/mcu/microchip/same/asf4/same51/gcc/gcc/startup_same51.c \ + hw/mcu/microchip/same/asf4/same51/gcc/system_same51.c \ + +ifdef SYSCALLS +ifneq ($(SYSCALLS),0) + SRC_C += hw/mcu/microchip/same/asf4/same51/hal/utils/src/utils_syscalls.c +endif +endif + +ifdef LOG +ifneq ($(LOG),0) + SRC_C += hw/mcu/microchip/same/asf4/same51/hal/utils/src/utils_syscalls.c +endif +endif + +INC += \ + $(TOP)/hw/mcu/microchip/same/asf4/same51/ \ + $(TOP)/hw/mcu/microchip/same/asf4/same51/config \ + $(TOP)/hw/mcu/microchip/same/asf4/same51/include \ + $(TOP)/hw/mcu/microchip/same/asf4/same51/hal/include \ + $(TOP)/hw/mcu/microchip/same/asf4/same51/hal/utils/include \ + $(TOP)/hw/mcu/microchip/same/asf4/same51/hpl/port \ + $(TOP)/hw/mcu/microchip/same/asf4/same51/hri \ + $(TOP)/hw/mcu/microchip/same/asf4/same51/CMSIS/Core/Include + +# For TinyUSB port source +VENDOR = microchip +CHIP_FAMILY = samd + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM4F + +# For flash-jlink target +JLINK_DEVICE = ATSAME51J19 +JLINK_IF = swd + +# flash using jlink +flash: flash-jlink diff --git a/hw/bsp/d5035-01/d5035_01.c b/hw/bsp/d5035-01/d5035_01.c new file mode 100644 index 000000000..5685ff16f --- /dev/null +++ b/hw/bsp/d5035-01/d5035_01.c @@ -0,0 +1,353 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jean Gressmann + * + * 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 "bsp/board.h" + +#include + +#if CONF_CPU_FREQUENCY != 80000000 +# error "CONF_CPU_FREQUENCY" must 80000000 +#endif + +#if CONF_GCLK_USB_FREQUENCY != 48000000 +# error "CONF_GCLK_USB_FREQUENCY" must 48000000 +#endif + +#if !defined(HWREV) +# error Define "HWREV" +#endif + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_0_Handler (void) +{ + tud_int_handler(0); +} + +void USB_1_Handler (void) +{ + tud_int_handler(0); +} + +void USB_2_Handler (void) +{ + tud_int_handler(0); +} + +void USB_3_Handler (void) +{ + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ +#define LED_PIN PIN_PA02 + +#if HWREV < 3 +# define BOARD_SERCOM SERCOM5 +#else +# define BOARD_SERCOM SERCOM0 +#endif + +static inline void init_clock(void) +{ + /* AUTOWS is enabled by default in REG_NVMCTRL_CTRLA - no need to change the number of wait states when changing the core clock */ +#if HWREV == 1 + /* configure XOSC1 for a 16MHz crystal connected to XIN1/XOUT1 */ + OSCCTRL->XOSCCTRL[1].reg = + OSCCTRL_XOSCCTRL_STARTUP(6) | // 1,953 ms + OSCCTRL_XOSCCTRL_RUNSTDBY | + OSCCTRL_XOSCCTRL_ENALC | + OSCCTRL_XOSCCTRL_IMULT(4) | + OSCCTRL_XOSCCTRL_IPTAT(3) | + OSCCTRL_XOSCCTRL_XTALEN | + OSCCTRL_XOSCCTRL_ENABLE; + while(0 == OSCCTRL->STATUS.bit.XOSCRDY1); + + OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(3) | OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC1_Val); /* pre-scaler = 8, input = XOSC1 */ + OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(39); /* multiply by 40 -> 80 MHz */ + OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE; + while(0 == OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL0 to be ready */ + + OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(7) | OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC1_Val); /* pre-scaler = 16, input = XOSC1 */ + OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(47); /* multiply by 48 -> 48 MHz */ + OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE; + while(0 == OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL1 to be ready */ +#else // HWREV >= 1 + /* configure XOSC0 for a 16MHz crystal connected to XIN0/XOUT0 */ + OSCCTRL->XOSCCTRL[0].reg = + OSCCTRL_XOSCCTRL_STARTUP(6) | // 1,953 ms + OSCCTRL_XOSCCTRL_RUNSTDBY | + OSCCTRL_XOSCCTRL_ENALC | + OSCCTRL_XOSCCTRL_IMULT(4) | + OSCCTRL_XOSCCTRL_IPTAT(3) | + OSCCTRL_XOSCCTRL_XTALEN | + OSCCTRL_XOSCCTRL_ENABLE; + while(0 == OSCCTRL->STATUS.bit.XOSCRDY0); + + OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(3) | OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC0_Val); /* pre-scaler = 8, input = XOSC1 */ + OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(39); /* multiply by 40 -> 80 MHz */ + OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE; + while(0 == OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL0 to be ready */ + + OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(7) | OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC0_Val); /* pre-scaler = 16, input = XOSC1 */ + OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(47); /* multiply by 48 -> 48 MHz */ + OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE; + while(0 == OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL1 to be ready */ +#endif // HWREV + + /* configure clock-generator 0 to use DPLL0 as source -> GCLK0 is used for the core */ + GCLK->GENCTRL[0].reg = + GCLK_GENCTRL_DIV(0) | + GCLK_GENCTRL_RUNSTDBY | + GCLK_GENCTRL_GENEN | + GCLK_GENCTRL_SRC_DPLL0 | /* DPLL0 */ + GCLK_GENCTRL_IDC ; + while(1 == GCLK->SYNCBUSY.bit.GENCTRL0); /* wait for the synchronization between clock domains to be complete */ + + /* configure clock-generator 1 to use DPLL1 as source -> for use with some peripheral */ + GCLK->GENCTRL[1].reg = + GCLK_GENCTRL_DIV(0) | + GCLK_GENCTRL_RUNSTDBY | + GCLK_GENCTRL_GENEN | + GCLK_GENCTRL_SRC_DPLL1 | + GCLK_GENCTRL_IDC ; + while(1 == GCLK->SYNCBUSY.bit.GENCTRL1); /* wait for the synchronization between clock domains to be complete */ + + /* configure clock-generator 2 to use DPLL0 as source -> for use with SERCOM */ + GCLK->GENCTRL[2].reg = + GCLK_GENCTRL_DIV(1) | /* 80MHz */ + GCLK_GENCTRL_RUNSTDBY | + GCLK_GENCTRL_GENEN | + GCLK_GENCTRL_SRC_DPLL0 | + GCLK_GENCTRL_IDC ; + while(1 == GCLK->SYNCBUSY.bit.GENCTRL2); /* wait for the synchronization between clock domains to be complete */ +} + +static inline void uart_init(void) +{ +#if HWREV < 3 + /* configure SERCOM5 on PB02 */ + PORT->Group[1].WRCONFIG.reg = + PORT_WRCONFIG_WRPINCFG | + PORT_WRCONFIG_WRPMUX | + PORT_WRCONFIG_PMUX(3) | /* function D */ + PORT_WRCONFIG_DRVSTR | + PORT_WRCONFIG_PINMASK(0x0004) | /* PB02 */ + PORT_WRCONFIG_PMUXEN; + + MCLK->APBDMASK.bit.SERCOM5_ = 1; + GCLK->PCHCTRL[SERCOM5_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK2 | GCLK_PCHCTRL_CHEN; /* setup SERCOM to use GLCK2 -> 80MHz */ + + SERCOM5->USART.CTRLA.reg = 0x00; /* disable SERCOM -> enable config */ + while(SERCOM5->USART.SYNCBUSY.bit.ENABLE); + + SERCOM5->USART.CTRLA.reg = /* CMODE = 0 -> async, SAMPA = 0, FORM = 0 -> USART frame, SMPR = 0 -> arithmetic baud rate */ + SERCOM_USART_CTRLA_SAMPR(1) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */ +// SERCOM_USART_CTRLA_FORM(0) | /* 0 = USART Frame, 2 = LIN Master */ + SERCOM_USART_CTRLA_DORD | /* LSB first */ + SERCOM_USART_CTRLA_MODE(1) | /* 0 = Asynchronous, 1 = USART with internal clock */ + SERCOM_USART_CTRLA_RXPO(1) | /* SERCOM PAD[1] is used for data reception */ + SERCOM_USART_CTRLA_TXPO(0); /* SERCOM PAD[0] is used for data transmission */ + + SERCOM5->USART.CTRLB.reg = /* RXEM = 0 -> receiver disabled, LINCMD = 0 -> normal USART transmission, SFDE = 0 -> start-of-frame detection disabled, SBMODE = 0 -> one stop bit, CHSIZE = 0 -> 8 bits */ + SERCOM_USART_CTRLB_TXEN; /* transmitter enabled */ + SERCOM5->USART.CTRLC.reg = 0x00; + // 21.701388889 @ baud rate of 230400 bit/s, table 33-2, p 918 of DS60001507E + SERCOM5->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(7) | SERCOM_USART_BAUD_FRAC_BAUD(21); + +// SERCOM5->USART.INTENSET.reg = SERCOM_USART_INTENSET_TXC; + SERCOM5->SPI.CTRLA.bit.ENABLE = 1; /* activate SERCOM */ + while(SERCOM5->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */ +#else +/* configure SERCOM0 on PA08 */ + PORT->Group[0].WRCONFIG.reg = + PORT_WRCONFIG_WRPINCFG | + PORT_WRCONFIG_WRPMUX | + PORT_WRCONFIG_PMUX(2) | /* function C */ + PORT_WRCONFIG_DRVSTR | + PORT_WRCONFIG_PINMASK(0x0100) | /* PA08 */ + PORT_WRCONFIG_PMUXEN; + + MCLK->APBAMASK.bit.SERCOM0_ = 1; + GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK2 | GCLK_PCHCTRL_CHEN; /* setup SERCOM to use GLCK2 -> 80MHz */ + + SERCOM0->USART.CTRLA.reg = 0x00; /* disable SERCOM -> enable config */ + while(SERCOM0->USART.SYNCBUSY.bit.ENABLE); + + SERCOM0->USART.CTRLA.reg = /* CMODE = 0 -> async, SAMPA = 0, FORM = 0 -> USART frame, SMPR = 0 -> arithmetic baud rate */ + SERCOM_USART_CTRLA_SAMPR(1) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */ +// SERCOM_USART_CTRLA_FORM(0) | /* 0 = USART Frame, 2 = LIN Master */ + SERCOM_USART_CTRLA_DORD | /* LSB first */ + SERCOM_USART_CTRLA_MODE(1) | /* 0 = Asynchronous, 1 = USART with internal clock */ + SERCOM_USART_CTRLA_RXPO(1) | /* SERCOM PAD[1] is used for data reception */ + SERCOM_USART_CTRLA_TXPO(0); /* SERCOM PAD[0] is used for data transmission */ + + SERCOM0->USART.CTRLB.reg = /* RXEM = 0 -> receiver disabled, LINCMD = 0 -> normal USART transmission, SFDE = 0 -> start-of-frame detection disabled, SBMODE = 0 -> one stop bit, CHSIZE = 0 -> 8 bits */ + SERCOM_USART_CTRLB_TXEN; /* transmitter enabled */ + SERCOM0->USART.CTRLC.reg = 0x00; + // 21.701388889 @ baud rate of 230400 bit/s, table 33-2, p 918 of DS60001507E + SERCOM0->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(7) | SERCOM_USART_BAUD_FRAC_BAUD(21); + +// SERCOM0->USART.INTENSET.reg = SERCOM_USART_INTENSET_TXC; + SERCOM0->SPI.CTRLA.bit.ENABLE = 1; /* activate SERCOM */ + while(SERCOM0->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */ +#endif +} + +static inline void uart_send_buffer(uint8_t const *text, size_t len) +{ + for (size_t i = 0; i < len; ++i) { + BOARD_SERCOM->USART.DATA.reg = text[i]; + while((BOARD_SERCOM->USART.INTFLAG.reg & SERCOM_SPI_INTFLAG_TXC) == 0); + } +} + +static inline void uart_send_str(const char* text) +{ + while (*text) { + BOARD_SERCOM->USART.DATA.reg = *text++; + while((BOARD_SERCOM->USART.INTFLAG.reg & SERCOM_SPI_INTFLAG_TXC) == 0); + } +} + + +void board_init(void) +{ + init_clock(); + + SystemCoreClock = CONF_CPU_FREQUENCY; + +#if CFG_TUSB_OS == OPT_OS_NONE + SysTick_Config(CONF_CPU_FREQUENCY / 1000); +#endif + + uart_init(); +#if CFG_TUSB_DEBUG >= 2 + uart_send_str(BOARD_NAME " UART initialized\n"); + tu_printf(BOARD_NAME " reset cause %#02x\n", RSTC->RCAUSE.reg); +#endif + + // Led init + gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_level(LED_PIN, 0); + +#if CFG_TUSB_DEBUG >= 2 + uart_send_str(BOARD_NAME " LED pin configured\n"); +#endif + +#if CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(USB_0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + NVIC_SetPriority(USB_1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + NVIC_SetPriority(USB_2_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + NVIC_SetPriority(USB_3_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); +#endif + + +#if TUSB_OPT_DEVICE_ENABLED +#if CFG_TUSB_DEBUG >= 2 + uart_send_str(BOARD_NAME " USB device enabled\n"); +#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_PA24H_USB_DM); + gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP); + + +#if CFG_TUSB_DEBUG >= 2 + uart_send_str(BOARD_NAME " USB device configured\n"); +#endif +#endif +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) +{ + gpio_set_pin_level(LED_PIN, state); +} + +uint32_t board_button_read(void) +{ + // this board has no button + 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) +{ + if (len < 0) { + uart_send_str(buf); + } else { + uart_send_buffer(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 + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) +{ + +} diff --git a/hw/bsp/d5035-01/same51j19a_flash.ld b/hw/bsp/d5035-01/same51j19a_flash.ld new file mode 100644 index 000000000..328d1c72f --- /dev/null +++ b/hw/bsp/d5035-01/same51j19a_flash.ld @@ -0,0 +1,163 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAME51J19A + * + * Copyright (c) 2019 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 = 0x00080000 + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000 + bkupram (rwx) : ORIGIN = 0x47000000, LENGTH = 0x00002000 + qspi (rwx) : ORIGIN = 0x04000000, LENGTH = 0x01000000 +} + +/* 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__ : 0x1000; + +/* 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 + + .bkupram (NOLOAD): + { + . = ALIGN(8); + _sbkupram = .; + *(.bkupram .bkupram.*); + . = ALIGN(8); + _ebkupram = .; + } > bkupram + + .qspi (NOLOAD): + { + . = ALIGN(8); + _sqspi = .; + *(.qspi .qspi.*); + . = ALIGN(8); + _eqspi = .; + } > qspi + + /* .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/mcu/microchip b/hw/mcu/microchip index 168322aa7..c5dc8b65d 160000 --- a/hw/mcu/microchip +++ b/hw/mcu/microchip @@ -1 +1 @@ -Subproject commit 168322aa7100f60d6837505f5705fd61454dac27 +Subproject commit c5dc8b65d4ab37b0ec8b2bc7fbd46a6aecc0ff43 diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index f1dca88a5..460be3ac2 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_SAME51) #include "sam.h" #include "device/dcd.h" @@ -94,7 +95,8 @@ 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 || CFG_TUSB_MCU == OPT_MCU_SAME5X +#if CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \ + CFG_TUSB_MCU == OPT_MCU_SAME51 void dcd_int_enable(uint8_t rhport) { diff --git a/src/tusb_option.h b/src/tusb_option.h index 7e486bff0..70ef4de8c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -59,6 +59,7 @@ #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_SAME51 205 ///< MicroChip SAME51 #define OPT_MCU_SAMG 202 ///< MicroChip SAMDG series // STM32 From 862f6ac81ec3ff5bc7708204268e535f7f3d7732 Mon Sep 17 00:00:00 2001 From: Jean Gressmann Date: Mon, 5 Oct 2020 20:06:39 +0200 Subject: [PATCH 102/167] Update Microchip submodule commit --- hw/mcu/microchip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/mcu/microchip b/hw/mcu/microchip index c5dc8b65d..df9970f6c 160000 --- a/hw/mcu/microchip +++ b/hw/mcu/microchip @@ -1 +1 @@ -Subproject commit c5dc8b65d4ab37b0ec8b2bc7fbd46a6aecc0ff43 +Subproject commit df9970f6c26967ace144a83219cf7378831f6181 From 1730a5dcba522600a046837c0aafbf7bd5508dba Mon Sep 17 00:00:00 2001 From: Jean Gressmann Date: Mon, 5 Oct 2020 20:30:04 +0200 Subject: [PATCH 103/167] D5035-01 bsp: fix paths, default to hw rev 1 (automated build) --- hw/bsp/d5035-01/board.mk | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/hw/bsp/d5035-01/board.mk b/hw/bsp/d5035-01/board.mk index cbc653d19..20ce0fac3 100644 --- a/hw/bsp/d5035-01/board.mk +++ b/hw/bsp/d5035-01/board.mk @@ -15,36 +15,38 @@ CFLAGS += \ ifdef HWREV CFLAGS += -DHWREV=$(HWREV) +else + CFLAGS += -DHWREV=1 endif # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/same51j19a_flash.ld SRC_C += \ - hw/mcu/microchip/same/asf4/same51/gcc/gcc/startup_same51.c \ - hw/mcu/microchip/same/asf4/same51/gcc/system_same51.c \ + hw/mcu/microchip/same51/gcc/gcc/startup_same51.c \ + hw/mcu/microchip/same51/gcc/system_same51.c \ ifdef SYSCALLS ifneq ($(SYSCALLS),0) - SRC_C += hw/mcu/microchip/same/asf4/same51/hal/utils/src/utils_syscalls.c + SRC_C += hw/mcu/microchip/same51/hal/utils/src/utils_syscalls.c endif endif ifdef LOG ifneq ($(LOG),0) - SRC_C += hw/mcu/microchip/same/asf4/same51/hal/utils/src/utils_syscalls.c + SRC_C += hw/mcu/microchip/same51/hal/utils/src/utils_syscalls.c endif endif INC += \ - $(TOP)/hw/mcu/microchip/same/asf4/same51/ \ - $(TOP)/hw/mcu/microchip/same/asf4/same51/config \ - $(TOP)/hw/mcu/microchip/same/asf4/same51/include \ - $(TOP)/hw/mcu/microchip/same/asf4/same51/hal/include \ - $(TOP)/hw/mcu/microchip/same/asf4/same51/hal/utils/include \ - $(TOP)/hw/mcu/microchip/same/asf4/same51/hpl/port \ - $(TOP)/hw/mcu/microchip/same/asf4/same51/hri \ - $(TOP)/hw/mcu/microchip/same/asf4/same51/CMSIS/Core/Include + $(TOP)/hw/mcu/microchip/same51/ \ + $(TOP)/hw/mcu/microchip/same51/config \ + $(TOP)/hw/mcu/microchip/same51/include \ + $(TOP)/hw/mcu/microchip/same51/hal/include \ + $(TOP)/hw/mcu/microchip/same51/hal/utils/include \ + $(TOP)/hw/mcu/microchip/same51/hpl/port \ + $(TOP)/hw/mcu/microchip/same51/hri \ + $(TOP)/hw/mcu/microchip/same51/CMSIS/Core/Include # For TinyUSB port source VENDOR = microchip From a2379060b6d47eec6d5e9499258bc62eb5a015d7 Mon Sep 17 00:00:00 2001 From: Jean Gressmann Date: Tue, 6 Oct 2020 17:36:11 +0200 Subject: [PATCH 104/167] Adds D5035-01 to the list of supported boards --- docs/boards.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/boards.md b/docs/boards.md index 309f5e5d9..f49b247ac 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -4,7 +4,7 @@ The board support code is only used for self-contained examples and testing. It - One LED : for status - One Button : to get input from user - One UART : optional for device, but required for host examples - + ## Supported Boards This code base already had supported for a handful of following boards (sorted alphabetically) @@ -28,6 +28,7 @@ This code base already had supported for a handful of following boards (sorted a - [Adafruit ItsyBitsy M4 Express](https://www.adafruit.com/product/3800) - [Adafruit Metro M0 Express](https://www.adafruit.com/product/3505) - [Adafruit Metro M4 Express](https://www.adafruit.com/product/3382) +- [D5035-01](https://github.com/RudolphRiedel/USB_CAN-FD) - [Great Scott Gadgets LUNA](https://greatscottgadgets.com/luna/) - [Microchip SAMD11 Xplained](https://www.microchip.com/developmenttools/ProductDetails/atsamd11-xpro) - [Microchip SAMG55 Xplained Pro Evaluation Kit](https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/ATSAMG55-XPRO) @@ -114,7 +115,7 @@ This code base already had supported for a handful of following boards (sorted a ### TI - [MSP430F5529 USB LaunchPad Evaluation Kit](http://www.ti.com/tool/MSP-EXP430F5529LP) - + ### Tomu - [Fomu](https://www.crowdsupply.com/sutajio-kosagi/fomu) From f92fe1e23e3e8689b6f001c5232a5960acdb3b7f Mon Sep 17 00:00:00 2001 From: Jean Gressmann Date: Tue, 6 Oct 2020 17:39:36 +0200 Subject: [PATCH 105/167] D5035-01: more natural Makefile variable use --- hw/bsp/d5035-01/board.mk | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hw/bsp/d5035-01/board.mk b/hw/bsp/d5035-01/board.mk index 20ce0fac3..ac2146475 100644 --- a/hw/bsp/d5035-01/board.mk +++ b/hw/bsp/d5035-01/board.mk @@ -13,11 +13,9 @@ CFLAGS += \ -DD5035_01=1 \ -DBOARD_NAME="\"D5035-01\"" -ifdef HWREV - CFLAGS += -DHWREV=$(HWREV) -else - CFLAGS += -DHWREV=1 -endif +HWREV ?= 1 + +CFLAGS += -DHWREV=$(HWREV) # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/same51j19a_flash.ld From 020ad47bb004cb01e2c7834a34d74da66cef3532 Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Mon, 5 Oct 2020 22:40:00 -0700 Subject: [PATCH 106/167] stm32: fix ISTR and CTR_RX/TX race conditions --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 18 +++++++++++------- .../st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h | 8 ++++++-- 2 files changed, 17 insertions(+), 9 deletions(-) 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); } /** From 3f54c27afa39a3b9f2e5911b566416be460389fb Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Oct 2020 13:36:03 +0700 Subject: [PATCH 107/167] 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 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) From 74a1404bea4a2cf4fd8ecb4ce227f19ba9fbe1a0 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Oct 2020 13:36:27 +0700 Subject: [PATCH 108/167] tab -> spaces --- src/device/usbd.h | 506 +++++++++++++++++++++++----------------------- 1 file changed, 253 insertions(+), 253 deletions(-) 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 } From f700c08aeddd14ab5ae0a02a9eff330c5ae99dea Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Wed, 7 Oct 2020 10:57:12 +0200 Subject: [PATCH 109/167] 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(-) 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 From d407341d1e45d586b14dd35107675b7160c542cb Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Oct 2020 19:15:53 +0700 Subject: [PATCH 110/167] fix usb pin config with idf latest --- hw/bsp/esp32s2_kaluga_1/esp32s2_kaluga_1.c | 38 +++++++++++++++++----- hw/bsp/esp32s2_saola_1/esp32s2_saola_1.c | 37 +++++++++++++++++---- hw/bsp/samd11_xplained/board.mk | 8 +---- 3 files changed, 61 insertions(+), 22 deletions(-) diff --git a/hw/bsp/esp32s2_kaluga_1/esp32s2_kaluga_1.c b/hw/bsp/esp32s2_kaluga_1/esp32s2_kaluga_1.c index 3bf7a5b8a..47f9c2d47 100644 --- a/hw/bsp/esp32s2_kaluga_1/esp32s2_kaluga_1.c +++ b/hw/bsp/esp32s2_kaluga_1/esp32s2_kaluga_1.c @@ -25,11 +25,11 @@ */ #include "../board.h" -#include "driver/gpio.h" -#include "driver/periph_ctrl.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" #include "led_strip/include/led_strip.h" @@ -38,11 +38,10 @@ //--------------------------------------------------------------------+ #define LED_PIN 45 - #define BUTTON_PIN 0 #define BUTTON_STATE_ACTIVE 0 - +static void configure_pins(usb_hal_context_t *usb); static led_strip_t *strip; // Initialize on-board peripherals : led, button, uart and USB @@ -72,10 +71,33 @@ void board_init(void) .use_external_phy = false // use built-in PHY }; usb_hal_init(&hal); + configure_pins(&hal); +} - // Pin drive strength - gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); - gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); +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 diff --git a/hw/bsp/esp32s2_saola_1/esp32s2_saola_1.c b/hw/bsp/esp32s2_saola_1/esp32s2_saola_1.c index a30d3c81e..5795c4b68 100644 --- a/hw/bsp/esp32s2_saola_1/esp32s2_saola_1.c +++ b/hw/bsp/esp32s2_saola_1/esp32s2_saola_1.c @@ -25,11 +25,12 @@ */ #include "../board.h" -#include "driver/gpio.h" -#include "driver/periph_ctrl.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" #include "led_strip/include/led_strip.h" @@ -41,11 +42,10 @@ // however earlier revision v1.1 WS2812 is connected to GPIO 17 //#define LED_PIN 17 // v1.1 #define LED_PIN 18 // v1.2 and later - #define BUTTON_PIN 0 #define BUTTON_STATE_ACTIVE 0 - +static void configure_pins(usb_hal_context_t *usb); static led_strip_t *strip; // Initialize on-board peripherals : led, button, uart and USB @@ -75,10 +75,33 @@ void board_init(void) .use_external_phy = false // use built-in PHY }; usb_hal_init(&hal); + configure_pins(&hal); +} - // Pin drive strength - gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); - gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); +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 diff --git a/hw/bsp/samd11_xplained/board.mk b/hw/bsp/samd11_xplained/board.mk index 5b1a42157..6aec6509c 100644 --- a/hw/bsp/samd11_xplained/board.mk +++ b/hw/bsp/samd11_xplained/board.mk @@ -1,7 +1,4 @@ CFLAGS += \ - -ffunction-sections \ - -fdata-sections \ - -Wl,--gc-sections \ -mthumb \ -mabi=aapcs-linux \ -mcpu=cortex-m0plus \ @@ -9,9 +6,7 @@ CFLAGS += \ -D__SAMD11D14AM__ \ -DCONF_DFLL_OVERWRITE_CALIBRATION=0 \ -DOSC32K_OVERWRITE_CALIBRATION=0 \ - -DCFG_TUSB_MCU=OPT_MCU_SAMD11 \ - -fshort-enums \ - -Os + -DCFG_TUSB_MCU=OPT_MCU_SAMD11 # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/samd11d14am_flash.ld @@ -50,4 +45,3 @@ JLINK_IF = swd # flash using edbg flash: $(BUILD)/$(BOARD)-firmware.bin edbg -b -t samd11 -e -pv -f $< - From f02b5bfdfaf20a76054dc2f57d37c46de4be6534 Mon Sep 17 00:00:00 2001 From: Jean Gressmann Date: Wed, 7 Oct 2020 19:12:34 +0200 Subject: [PATCH 111/167] Address various issues raised by TinyUSB maintainers - remove OPT_MCU_SAME51 in favor of OPT_MCU_SAME5X and working around differences in the Atmel bsp locally in the D5035-01 bsp. - rename board folder to d5035_01 for consistency with other boards --- hw/bsp/board_mcu.h | 7 +------ hw/bsp/{d5035-01 => d5035_01}/board.mk | 8 +++++--- hw/bsp/{d5035-01 => d5035_01}/d5035_01.c | 0 hw/bsp/{d5035-01 => d5035_01}/same51j19a_flash.ld | 0 src/portable/microchip/samd/dcd_samd.c | 6 ++---- src/tusb_option.h | 1 - 6 files changed, 8 insertions(+), 14 deletions(-) rename hw/bsp/{d5035-01 => d5035_01}/board.mk (92%) rename hw/bsp/{d5035-01 => d5035_01}/d5035_01.c (100%) rename hw/bsp/{d5035-01 => d5035_01}/same51j19a_flash.ld (100%) diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index 6585ef9a6..eedae43f7 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -53,14 +53,9 @@ #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_SAME51 + CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X #include "sam.h" - #if CFG_TUSB_MCU == OPT_MCU_SAME51 - #define SVC_Handler SVCall_Handler - #endif - #elif CFG_TUSB_MCU == OPT_MCU_SAMG #undef LITTLE_ENDIAN // hack to suppress "LITTLE_ENDIAN" redefined #include "sam.h" diff --git a/hw/bsp/d5035-01/board.mk b/hw/bsp/d5035_01/board.mk similarity index 92% rename from hw/bsp/d5035-01/board.mk rename to hw/bsp/d5035_01/board.mk index ac2146475..1f2b467a0 100644 --- a/hw/bsp/d5035-01/board.mk +++ b/hw/bsp/d5035_01/board.mk @@ -9,14 +9,16 @@ CFLAGS += \ -D__SAME51J19A__ \ -DCONF_CPU_FREQUENCY=80000000 \ -DCONF_GCLK_USB_FREQUENCY=48000000 \ - -DCFG_TUSB_MCU=OPT_MCU_SAME51 \ + -DCFG_TUSB_MCU=OPT_MCU_SAME5X \ -DD5035_01=1 \ - -DBOARD_NAME="\"D5035-01\"" + -DBOARD_NAME="\"D5035-01\"" \ + -DSVC_Handler=SVCall_Handler -HWREV ?= 1 +HWRED ?= 1 CFLAGS += -DHWREV=$(HWREV) + # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/same51j19a_flash.ld diff --git a/hw/bsp/d5035-01/d5035_01.c b/hw/bsp/d5035_01/d5035_01.c similarity index 100% rename from hw/bsp/d5035-01/d5035_01.c rename to hw/bsp/d5035_01/d5035_01.c diff --git a/hw/bsp/d5035-01/same51j19a_flash.ld b/hw/bsp/d5035_01/same51j19a_flash.ld similarity index 100% rename from hw/bsp/d5035-01/same51j19a_flash.ld rename to hw/bsp/d5035_01/same51j19a_flash.ld diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 460be3ac2..f1dca88a5 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -28,8 +28,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_SAME51) + CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X) #include "sam.h" #include "device/dcd.h" @@ -95,8 +94,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 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \ - CFG_TUSB_MCU == OPT_MCU_SAME51 +#if CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X void dcd_int_enable(uint8_t rhport) { diff --git a/src/tusb_option.h b/src/tusb_option.h index 70ef4de8c..7e486bff0 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -59,7 +59,6 @@ #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_SAME51 205 ///< MicroChip SAME51 #define OPT_MCU_SAMG 202 ///< MicroChip SAMDG series // STM32 From 3295b5692b9a5e90c4798b1b72f5e83a7b9a7618 Mon Sep 17 00:00:00 2001 From: Jean Gressmann Date: Wed, 7 Oct 2020 19:26:13 +0200 Subject: [PATCH 112/167] D5035-01 bsp: fix typo --- hw/bsp/d5035_01/board.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/d5035_01/board.mk b/hw/bsp/d5035_01/board.mk index 1f2b467a0..cbc9ca5bb 100644 --- a/hw/bsp/d5035_01/board.mk +++ b/hw/bsp/d5035_01/board.mk @@ -14,7 +14,7 @@ CFLAGS += \ -DBOARD_NAME="\"D5035-01\"" \ -DSVC_Handler=SVCall_Handler -HWRED ?= 1 +HWREV ?= 1 CFLAGS += -DHWREV=$(HWREV) From ed94e944c98d0f0318233a1fda01d947baa72ca9 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Wed, 7 Oct 2020 13:15:58 -0500 Subject: [PATCH 113/167] mimxrt1010_evk: double stack size to allow net_lwip_webserver to run --- hw/bsp/mimxrt1010_evk/board.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/bsp/mimxrt1010_evk/board.mk b/hw/bsp/mimxrt1010_evk/board.mk index 4dc11693a..db4ab249b 100644 --- a/hw/bsp/mimxrt1010_evk/board.mk +++ b/hw/bsp/mimxrt1010_evk/board.mk @@ -19,6 +19,9 @@ MCU_DIR = hw/mcu/nxp/sdk/devices/MIMXRT1011 # All source paths should be relative to the top level. LD_FILE = $(MCU_DIR)/gcc/MIMXRT1011xxxxx_flexspi_nor.ld +LDFLAGS += \ + -Wl,--defsym,__stack_size__=0x800 \ + SRC_C += \ $(MCU_DIR)/system_MIMXRT1011.c \ $(MCU_DIR)/xip/fsl_flexspi_nor_boot.c \ From db3fe97f62f22747df2c79a841bc1fb235f2f89e Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Wed, 7 Oct 2020 20:36:00 -0500 Subject: [PATCH 114/167] fix variable names. add itf n callbacks to multihid --- .../device/hid_multipleinterface/src/main.c | 6 +++-- .../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(-) 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); From ec018fbf4ed30b014b82f993246f8730687e649a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 8 Oct 2020 17:17:37 +0700 Subject: [PATCH 115/167] clean up jlink default interface --- examples/rules.mk | 2 ++ hw/bsp/adafruit_clue/board.mk | 1 - hw/bsp/arduino_nano33_ble/board.mk | 1 - hw/bsp/circuitplayground_bluefruit/board.mk | 1 - hw/bsp/circuitplayground_express/board.mk | 1 - hw/bsp/d5035_01/board.mk | 1 - hw/bsp/da14695_dk_usb/board.mk | 1 - hw/bsp/da1469x_dk_pro/board.mk | 1 - hw/bsp/ea4088qs/board.mk | 1 - hw/bsp/ea4357/board.mk | 1 - hw/bsp/feather_m0_express/board.mk | 1 - hw/bsp/feather_m4_express/board.mk | 1 - hw/bsp/feather_nrf52840_express/board.mk | 1 - hw/bsp/feather_nrf52840_sense/board.mk | 1 - hw/bsp/feather_stm32f405/board.mk | 1 - hw/bsp/itsybitsy_m0/board.mk | 1 - hw/bsp/itsybitsy_m4/board.mk | 1 - hw/bsp/itsybitsy_nrf52840/board.mk | 1 - hw/bsp/lpcxpresso11u37/board.mk | 1 - hw/bsp/lpcxpresso11u68/board.mk | 1 - hw/bsp/lpcxpresso1347/board.mk | 1 - hw/bsp/lpcxpresso1549/board.mk | 1 - hw/bsp/lpcxpresso1769/board.mk | 1 - hw/bsp/lpcxpresso51u68/board.mk | 1 - hw/bsp/lpcxpresso54114/board.mk | 1 - hw/bsp/lpcxpresso55s69/board.mk | 1 - hw/bsp/luna/board.mk | 1 - hw/bsp/mbed1768/board.mk | 1 - hw/bsp/mcb1800/board.mk | 1 - hw/bsp/metro_m0_express/board.mk | 1 - hw/bsp/metro_m4_express/board.mk | 1 - hw/bsp/mimxrt1010_evk/board.mk | 1 - hw/bsp/mimxrt1020_evk/board.mk | 1 - hw/bsp/mimxrt1050_evkb/board.mk | 1 - hw/bsp/mimxrt1060_evk/board.mk | 1 - hw/bsp/mimxrt1064_evk/board.mk | 1 - hw/bsp/nrf52840_mdk_dongle/board.mk | 1 - hw/bsp/nutiny_nuc121s/board.mk | 1 - hw/bsp/nutiny_nuc125s/board.mk | 1 - hw/bsp/nutiny_nuc126v/board.mk | 1 - hw/bsp/nutiny_sdk_nuc120/board.mk | 1 - hw/bsp/nutiny_sdk_nuc505/board.mk | 1 - hw/bsp/pca10056/board.mk | 1 - hw/bsp/pca10059/board.mk | 1 - hw/bsp/pca10100/board.mk | 1 - hw/bsp/pyboardv11/board.mk | 1 - hw/bsp/raytac_mdbt50q_rx/board.mk | 1 - hw/bsp/samd11_xplained/board.mk | 1 - hw/bsp/samg55xplained/board.mk | 1 - hw/bsp/seeeduino_xiao/board.mk | 1 - hw/bsp/stm32f070rbnucleo/board.mk | 1 - hw/bsp/stm32f072disco/board.mk | 1 - hw/bsp/stm32f103bluepill/board.mk | 1 - hw/bsp/stm32f207nucleo/board.mk | 1 - hw/bsp/stm32f303disco/board.mk | 1 - hw/bsp/stm32f401blackpill/board.mk | 1 - hw/bsp/stm32f407disco/board.mk | 1 - hw/bsp/stm32f411blackpill/board.mk | 1 - hw/bsp/stm32f411disco/board.mk | 1 - hw/bsp/stm32f412disco/board.mk | 1 - hw/bsp/stm32h743eval/board.mk | 1 - hw/bsp/stm32h745disco/board.mk | 1 - hw/bsp/stm32l0538disco/board.mk | 1 - hw/bsp/stm32l476disco/board.mk | 1 - hw/bsp/teensy_40/board.mk | 1 - 65 files changed, 2 insertions(+), 64 deletions(-) diff --git a/examples/rules.mk b/examples/rules.mk index dacb81363..e972ce735 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -147,6 +147,8 @@ else JLINKEXE = JLinkExe endif +JLINK_IF ?= swd + # Flash using jlink flash-jlink: $(BUILD)/$(BOARD)-firmware.hex @echo halt > $(BUILD)/$(BOARD).jlink diff --git a/hw/bsp/adafruit_clue/board.mk b/hw/bsp/adafruit_clue/board.mk index 5290455cc..d5f7c7cd4 100644 --- a/hw/bsp/adafruit_clue/board.mk +++ b/hw/bsp/adafruit_clue/board.mk @@ -49,7 +49,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = nRF52840_xxAA -JLINK_IF = swd # For uf2 conversion UF2_FAMILY = 0xADA52840 diff --git a/hw/bsp/arduino_nano33_ble/board.mk b/hw/bsp/arduino_nano33_ble/board.mk index 0a25d0b19..d1d62bdf2 100644 --- a/hw/bsp/arduino_nano33_ble/board.mk +++ b/hw/bsp/arduino_nano33_ble/board.mk @@ -51,7 +51,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = nRF52840_xxAA -JLINK_IF = swd # flash using bossac (as part of Nano33 BSP tools) # can be found in arduino15/packages/arduino/tools/bossac/ diff --git a/hw/bsp/circuitplayground_bluefruit/board.mk b/hw/bsp/circuitplayground_bluefruit/board.mk index 5290455cc..d5f7c7cd4 100644 --- a/hw/bsp/circuitplayground_bluefruit/board.mk +++ b/hw/bsp/circuitplayground_bluefruit/board.mk @@ -49,7 +49,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = nRF52840_xxAA -JLINK_IF = swd # For uf2 conversion UF2_FAMILY = 0xADA52840 diff --git a/hw/bsp/circuitplayground_express/board.mk b/hw/bsp/circuitplayground_express/board.mk index e20272ad1..09b7b53a5 100644 --- a/hw/bsp/circuitplayground_express/board.mk +++ b/hw/bsp/circuitplayground_express/board.mk @@ -38,7 +38,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = ATSAMD21G18 -JLINK_IF = swd # flash using jlink flash: $(BUILD)/$(BOARD)-firmware.uf2 diff --git a/hw/bsp/d5035_01/board.mk b/hw/bsp/d5035_01/board.mk index cbc9ca5bb..0a7db6403 100644 --- a/hw/bsp/d5035_01/board.mk +++ b/hw/bsp/d5035_01/board.mk @@ -57,7 +57,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = ATSAME51J19 -JLINK_IF = swd # flash using jlink flash: flash-jlink diff --git a/hw/bsp/da14695_dk_usb/board.mk b/hw/bsp/da14695_dk_usb/board.mk index f5b8873f9..8fef7d10f 100644 --- a/hw/bsp/da14695_dk_usb/board.mk +++ b/hw/bsp/da14695_dk_usb/board.mk @@ -38,7 +38,6 @@ FREERTOS_PORT = ARM_CM33_NTZ/non_secure # For flash-jlink target JLINK_DEVICE = DA14695 -JLINK_IF = swd # flash using jlink but with some twists flash: flash-dialog diff --git a/hw/bsp/da1469x_dk_pro/board.mk b/hw/bsp/da1469x_dk_pro/board.mk index 6708955f2..60a62378c 100644 --- a/hw/bsp/da1469x_dk_pro/board.mk +++ b/hw/bsp/da1469x_dk_pro/board.mk @@ -38,7 +38,6 @@ FREERTOS_PORT = ARM_CM33_NTZ/non_secure # For flash-jlink target JLINK_DEVICE = DA14699 -JLINK_IF = swd # flash using jlink but with some twists flash: flash-dialog diff --git a/hw/bsp/ea4088qs/board.mk b/hw/bsp/ea4088qs/board.mk index 51a6009a0..15e0bfb86 100644 --- a/hw/bsp/ea4088qs/board.mk +++ b/hw/bsp/ea4088qs/board.mk @@ -42,7 +42,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = LPC4088 -JLINK_IF = swd # flash using jlink flash: flash-jlink diff --git a/hw/bsp/ea4357/board.mk b/hw/bsp/ea4357/board.mk index 3ebe107e2..f6c42e0cf 100644 --- a/hw/bsp/ea4357/board.mk +++ b/hw/bsp/ea4357/board.mk @@ -42,7 +42,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = LPC4357_M4 -JLINK_IF = swd # flash using jlink flash: flash-jlink diff --git a/hw/bsp/feather_m0_express/board.mk b/hw/bsp/feather_m0_express/board.mk index 7b6891e03..4128ed264 100644 --- a/hw/bsp/feather_m0_express/board.mk +++ b/hw/bsp/feather_m0_express/board.mk @@ -39,7 +39,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = ATSAMD21G18 -JLINK_IF = swd # flash using bossac at least version 1.8 # can be found in arduino15/packages/arduino/tools/bossac/ diff --git a/hw/bsp/feather_m4_express/board.mk b/hw/bsp/feather_m4_express/board.mk index 34c98597c..fadf65307 100644 --- a/hw/bsp/feather_m4_express/board.mk +++ b/hw/bsp/feather_m4_express/board.mk @@ -42,7 +42,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = ATSAMD51J19 -JLINK_IF = swd # flash using bossac at least version 1.8 # can be found in arduino15/packages/arduino/tools/bossac/ diff --git a/hw/bsp/feather_nrf52840_express/board.mk b/hw/bsp/feather_nrf52840_express/board.mk index 7b2625cd4..6cc972835 100644 --- a/hw/bsp/feather_nrf52840_express/board.mk +++ b/hw/bsp/feather_nrf52840_express/board.mk @@ -50,7 +50,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = nRF52840_xxAA -JLINK_IF = swd # For uf2 conversion UF2_FAMILY = 0xADA52840 diff --git a/hw/bsp/feather_nrf52840_sense/board.mk b/hw/bsp/feather_nrf52840_sense/board.mk index 5290455cc..d5f7c7cd4 100644 --- a/hw/bsp/feather_nrf52840_sense/board.mk +++ b/hw/bsp/feather_nrf52840_sense/board.mk @@ -49,7 +49,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = nRF52840_xxAA -JLINK_IF = swd # For uf2 conversion UF2_FAMILY = 0xADA52840 diff --git a/hw/bsp/feather_stm32f405/board.mk b/hw/bsp/feather_stm32f405/board.mk index 8233c6608..1988fa46e 100644 --- a/hw/bsp/feather_stm32f405/board.mk +++ b/hw/bsp/feather_stm32f405/board.mk @@ -44,7 +44,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = stm32f405rg -JLINK_IF = swd # Path to STM32 Cube Programmer CLI, should be added into system path STM32Prog = STM32_Programmer_CLI diff --git a/hw/bsp/itsybitsy_m0/board.mk b/hw/bsp/itsybitsy_m0/board.mk index 7b6891e03..4128ed264 100644 --- a/hw/bsp/itsybitsy_m0/board.mk +++ b/hw/bsp/itsybitsy_m0/board.mk @@ -39,7 +39,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = ATSAMD21G18 -JLINK_IF = swd # flash using bossac at least version 1.8 # can be found in arduino15/packages/arduino/tools/bossac/ diff --git a/hw/bsp/itsybitsy_m4/board.mk b/hw/bsp/itsybitsy_m4/board.mk index 34c98597c..fadf65307 100644 --- a/hw/bsp/itsybitsy_m4/board.mk +++ b/hw/bsp/itsybitsy_m4/board.mk @@ -42,7 +42,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = ATSAMD51J19 -JLINK_IF = swd # flash using bossac at least version 1.8 # can be found in arduino15/packages/arduino/tools/bossac/ diff --git a/hw/bsp/itsybitsy_nrf52840/board.mk b/hw/bsp/itsybitsy_nrf52840/board.mk index 7b2625cd4..6cc972835 100644 --- a/hw/bsp/itsybitsy_nrf52840/board.mk +++ b/hw/bsp/itsybitsy_nrf52840/board.mk @@ -50,7 +50,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = nRF52840_xxAA -JLINK_IF = swd # For uf2 conversion UF2_FAMILY = 0xADA52840 diff --git a/hw/bsp/lpcxpresso11u37/board.mk b/hw/bsp/lpcxpresso11u37/board.mk index d1c48a2e5..d34125ac7 100644 --- a/hw/bsp/lpcxpresso11u37/board.mk +++ b/hw/bsp/lpcxpresso11u37/board.mk @@ -40,7 +40,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = LPC11U37/401 -JLINK_IF = swd # flash using pyocd flash: $(BUILD)/$(BOARD)-firmware.hex diff --git a/hw/bsp/lpcxpresso11u68/board.mk b/hw/bsp/lpcxpresso11u68/board.mk index d9017ae1a..67124ab90 100644 --- a/hw/bsp/lpcxpresso11u68/board.mk +++ b/hw/bsp/lpcxpresso11u68/board.mk @@ -37,7 +37,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = LPC11U68 -JLINK_IF = swd # flash using pyocd flash: $(BUILD)/$(BOARD)-firmware.hex diff --git a/hw/bsp/lpcxpresso1347/board.mk b/hw/bsp/lpcxpresso1347/board.mk index 6dc3937f6..915834ddf 100644 --- a/hw/bsp/lpcxpresso1347/board.mk +++ b/hw/bsp/lpcxpresso1347/board.mk @@ -40,7 +40,6 @@ FREERTOS_PORT = ARM_CM3 # For flash-jlink target JLINK_DEVICE = LPC1347 -JLINK_IF = swd # flash using jlink flash: flash-jlink diff --git a/hw/bsp/lpcxpresso1549/board.mk b/hw/bsp/lpcxpresso1549/board.mk index 18325c5f7..27c3ca8d6 100644 --- a/hw/bsp/lpcxpresso1549/board.mk +++ b/hw/bsp/lpcxpresso1549/board.mk @@ -40,7 +40,6 @@ FREERTOS_PORT = ARM_CM3 # For flash-jlink target JLINK_DEVICE = LPC1549 -JLINK_IF = swd # flash using jlink flash: flash-jlink diff --git a/hw/bsp/lpcxpresso1769/board.mk b/hw/bsp/lpcxpresso1769/board.mk index a345e5a27..11da5f722 100644 --- a/hw/bsp/lpcxpresso1769/board.mk +++ b/hw/bsp/lpcxpresso1769/board.mk @@ -39,7 +39,6 @@ FREERTOS_PORT = ARM_CM3 # For flash-jlink target JLINK_DEVICE = LPC1769 -JLINK_IF = swd # flash using jlink flash: flash-jlink diff --git a/hw/bsp/lpcxpresso51u68/board.mk b/hw/bsp/lpcxpresso51u68/board.mk index 7dc7de341..cb36b3409 100644 --- a/hw/bsp/lpcxpresso51u68/board.mk +++ b/hw/bsp/lpcxpresso51u68/board.mk @@ -41,7 +41,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = LPC51U68 -JLINK_IF = swd # flash using pyocd (51u68 is not supported yet) flash: $(BUILD)/$(BOARD)-firmware.hex diff --git a/hw/bsp/lpcxpresso54114/board.mk b/hw/bsp/lpcxpresso54114/board.mk index 2bab0340f..cc0f6cd43 100644 --- a/hw/bsp/lpcxpresso54114/board.mk +++ b/hw/bsp/lpcxpresso54114/board.mk @@ -43,7 +43,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = LPC54114J256_M4 -JLINK_IF = swd # flash using pyocd flash: $(BUILD)/$(BOARD)-firmware.hex diff --git a/hw/bsp/lpcxpresso55s69/board.mk b/hw/bsp/lpcxpresso55s69/board.mk index 24c5ae89c..f98144cc5 100644 --- a/hw/bsp/lpcxpresso55s69/board.mk +++ b/hw/bsp/lpcxpresso55s69/board.mk @@ -43,7 +43,6 @@ FREERTOS_PORT = ARM_CM33_NTZ/non_secure # For flash-jlink target JLINK_DEVICE = LPC55S69 -JLINK_IF = swd # flash using pyocd flash: $(BUILD)/$(BOARD)-firmware.hex diff --git a/hw/bsp/luna/board.mk b/hw/bsp/luna/board.mk index 44f6fd75b..9969b97fe 100644 --- a/hw/bsp/luna/board.mk +++ b/hw/bsp/luna/board.mk @@ -39,7 +39,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = ATSAMD21G18 -JLINK_IF = swd # flash using jlink flash: $(BUILD)/$(BOARD)-firmware.bin diff --git a/hw/bsp/mbed1768/board.mk b/hw/bsp/mbed1768/board.mk index 3bdc8a27a..54a8357cc 100644 --- a/hw/bsp/mbed1768/board.mk +++ b/hw/bsp/mbed1768/board.mk @@ -39,7 +39,6 @@ FREERTOS_PORT = ARM_CM3 # For flash-jlink target JLINK_DEVICE = LPC1768 -JLINK_IF = swd # flash using pyocd flash: $(BUILD)/$(BOARD)-firmware.hex diff --git a/hw/bsp/mcb1800/board.mk b/hw/bsp/mcb1800/board.mk index e3f07d0d0..f8fd25800 100644 --- a/hw/bsp/mcb1800/board.mk +++ b/hw/bsp/mcb1800/board.mk @@ -37,7 +37,6 @@ FREERTOS_PORT = ARM_CM3 # For flash-jlink target JLINK_DEVICE = LPC1857 -JLINK_IF = swd # flash using jlink flash: flash-jlink diff --git a/hw/bsp/metro_m0_express/board.mk b/hw/bsp/metro_m0_express/board.mk index 7b6891e03..4128ed264 100644 --- a/hw/bsp/metro_m0_express/board.mk +++ b/hw/bsp/metro_m0_express/board.mk @@ -39,7 +39,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = ATSAMD21G18 -JLINK_IF = swd # flash using bossac at least version 1.8 # can be found in arduino15/packages/arduino/tools/bossac/ diff --git a/hw/bsp/metro_m4_express/board.mk b/hw/bsp/metro_m4_express/board.mk index 34c98597c..fadf65307 100644 --- a/hw/bsp/metro_m4_express/board.mk +++ b/hw/bsp/metro_m4_express/board.mk @@ -42,7 +42,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = ATSAMD51J19 -JLINK_IF = swd # flash using bossac at least version 1.8 # can be found in arduino15/packages/arduino/tools/bossac/ diff --git a/hw/bsp/mimxrt1010_evk/board.mk b/hw/bsp/mimxrt1010_evk/board.mk index 4dc11693a..6197c5365 100644 --- a/hw/bsp/mimxrt1010_evk/board.mk +++ b/hw/bsp/mimxrt1010_evk/board.mk @@ -46,7 +46,6 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = MIMXRT1011DAE5A -JLINK_IF = swd # flash by copying bin file to DAP Mass Storage flash: $(BUILD)/$(BOARD)-firmware.bin diff --git a/hw/bsp/mimxrt1020_evk/board.mk b/hw/bsp/mimxrt1020_evk/board.mk index 52148b684..c5b285b47 100644 --- a/hw/bsp/mimxrt1020_evk/board.mk +++ b/hw/bsp/mimxrt1020_evk/board.mk @@ -45,7 +45,6 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = MIMXRT1021DAG5A -JLINK_IF = swd # flash by copying bin file to DAP Mass Storage flash: $(BUILD)/$(BOARD)-firmware.bin diff --git a/hw/bsp/mimxrt1050_evkb/board.mk b/hw/bsp/mimxrt1050_evkb/board.mk index 4b642085d..2148f8298 100644 --- a/hw/bsp/mimxrt1050_evkb/board.mk +++ b/hw/bsp/mimxrt1050_evkb/board.mk @@ -45,7 +45,6 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = MIMXRT1052xxx6B -JLINK_IF = swd # flash by copying bin file to DAP Mass Storage flash: $(BUILD)/$(BOARD)-firmware.bin diff --git a/hw/bsp/mimxrt1060_evk/board.mk b/hw/bsp/mimxrt1060_evk/board.mk index fae0ad0ae..cf4007914 100644 --- a/hw/bsp/mimxrt1060_evk/board.mk +++ b/hw/bsp/mimxrt1060_evk/board.mk @@ -45,7 +45,6 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = MIMXRT1062xxx6A -JLINK_IF = swd # flash by copying bin file to DAP Mass Storage flash: $(BUILD)/$(BOARD)-firmware.bin diff --git a/hw/bsp/mimxrt1064_evk/board.mk b/hw/bsp/mimxrt1064_evk/board.mk index d8a892442..5f230d687 100644 --- a/hw/bsp/mimxrt1064_evk/board.mk +++ b/hw/bsp/mimxrt1064_evk/board.mk @@ -45,7 +45,6 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = MIMXRT1064xxx6A -JLINK_IF = swd # flash by copying bin file to DAP Mass Storage flash: $(BUILD)/$(BOARD)-firmware.bin diff --git a/hw/bsp/nrf52840_mdk_dongle/board.mk b/hw/bsp/nrf52840_mdk_dongle/board.mk index 9ba04ba1f..8ce8929b8 100644 --- a/hw/bsp/nrf52840_mdk_dongle/board.mk +++ b/hw/bsp/nrf52840_mdk_dongle/board.mk @@ -48,7 +48,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = nRF52840_xxAA -JLINK_IF = swd # flash using Nordic nrfutil (pip2 install nrfutil) # make BOARD=nrf52840_mdk_dongle SERIAL=/dev/ttyACM0 all flash diff --git a/hw/bsp/nutiny_nuc121s/board.mk b/hw/bsp/nutiny_nuc121s/board.mk index e89877820..0a8b6e048 100644 --- a/hw/bsp/nutiny_nuc121s/board.mk +++ b/hw/bsp/nutiny_nuc121s/board.mk @@ -49,7 +49,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = NUC121SC2AE -JLINK_IF = swd # Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton # Please compile and install it from github source diff --git a/hw/bsp/nutiny_nuc125s/board.mk b/hw/bsp/nutiny_nuc125s/board.mk index 5bba8dee3..31577d800 100644 --- a/hw/bsp/nutiny_nuc125s/board.mk +++ b/hw/bsp/nutiny_nuc125s/board.mk @@ -33,7 +33,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = NUC125SC2AE -JLINK_IF = swd # Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton # Please compile and install it from github source diff --git a/hw/bsp/nutiny_nuc126v/board.mk b/hw/bsp/nutiny_nuc126v/board.mk index 21f2c9c53..7bf3989fc 100644 --- a/hw/bsp/nutiny_nuc126v/board.mk +++ b/hw/bsp/nutiny_nuc126v/board.mk @@ -53,7 +53,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = NUC126VG4AE -JLINK_IF = swd # Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton # Please compile and install it from github source diff --git a/hw/bsp/nutiny_sdk_nuc120/board.mk b/hw/bsp/nutiny_sdk_nuc120/board.mk index 95acdb5f2..51841643a 100644 --- a/hw/bsp/nutiny_sdk_nuc120/board.mk +++ b/hw/bsp/nutiny_sdk_nuc120/board.mk @@ -49,7 +49,6 @@ 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 diff --git a/hw/bsp/nutiny_sdk_nuc505/board.mk b/hw/bsp/nutiny_sdk_nuc505/board.mk index 8752ef8ea..2d00cd9be 100644 --- a/hw/bsp/nutiny_sdk_nuc505/board.mk +++ b/hw/bsp/nutiny_sdk_nuc505/board.mk @@ -44,7 +44,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = NUC505YO13Y -JLINK_IF = swd # Note # To be able to program the SPI flash, it need to boot with ICP mode "1011". diff --git a/hw/bsp/pca10056/board.mk b/hw/bsp/pca10056/board.mk index 0971e64c8..8f4887dcb 100644 --- a/hw/bsp/pca10056/board.mk +++ b/hw/bsp/pca10056/board.mk @@ -50,7 +50,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = nRF52840_xxAA -JLINK_IF = swd # flash using jlink flash: flash-jlink diff --git a/hw/bsp/pca10059/board.mk b/hw/bsp/pca10059/board.mk index 72dfefdcb..bd7a80c0e 100644 --- a/hw/bsp/pca10059/board.mk +++ b/hw/bsp/pca10059/board.mk @@ -49,7 +49,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = nRF52840_xxAA -JLINK_IF = swd # flash using Nordic nrfutil (pip2 install nrfutil) # make BOARD=pca10059 SERIAL=/dev/ttyACM0 all flash diff --git a/hw/bsp/pca10100/board.mk b/hw/bsp/pca10100/board.mk index 5231aaf63..4b5be082e 100644 --- a/hw/bsp/pca10100/board.mk +++ b/hw/bsp/pca10100/board.mk @@ -50,7 +50,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = nRF52833_XXAA -JLINK_IF = swd # flash using jlink flash: flash-jlink diff --git a/hw/bsp/pyboardv11/board.mk b/hw/bsp/pyboardv11/board.mk index 9da0541ec..3be06e844 100644 --- a/hw/bsp/pyboardv11/board.mk +++ b/hw/bsp/pyboardv11/board.mk @@ -40,7 +40,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = stm32f405rg -JLINK_IF = swd # flash target using on-board stlink flash: flash-stlink diff --git a/hw/bsp/raytac_mdbt50q_rx/board.mk b/hw/bsp/raytac_mdbt50q_rx/board.mk index 47bb430fc..e153aab0b 100644 --- a/hw/bsp/raytac_mdbt50q_rx/board.mk +++ b/hw/bsp/raytac_mdbt50q_rx/board.mk @@ -48,7 +48,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = nRF52840_xxAA -JLINK_IF = swd # flash using jlink flash: flash-jlink diff --git a/hw/bsp/samd11_xplained/board.mk b/hw/bsp/samd11_xplained/board.mk index 6aec6509c..c80ece4a6 100644 --- a/hw/bsp/samd11_xplained/board.mk +++ b/hw/bsp/samd11_xplained/board.mk @@ -40,7 +40,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = ATSAMD11D14 -JLINK_IF = swd # flash using edbg flash: $(BUILD)/$(BOARD)-firmware.bin diff --git a/hw/bsp/samg55xplained/board.mk b/hw/bsp/samg55xplained/board.mk index a58a7b41d..79716d36d 100644 --- a/hw/bsp/samg55xplained/board.mk +++ b/hw/bsp/samg55xplained/board.mk @@ -47,7 +47,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = ATSAMG55J19 -JLINK_IF = swd # flash using edbg from https://github.com/ataradov/edbg flash: $(BUILD)/$(BOARD)-firmware.bin diff --git a/hw/bsp/seeeduino_xiao/board.mk b/hw/bsp/seeeduino_xiao/board.mk index d762c4eca..172f6f537 100644 --- a/hw/bsp/seeeduino_xiao/board.mk +++ b/hw/bsp/seeeduino_xiao/board.mk @@ -39,7 +39,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = ATSAMD21G18 -JLINK_IF = swd # flash using jlink flash: flash-jlink diff --git a/hw/bsp/stm32f070rbnucleo/board.mk b/hw/bsp/stm32f070rbnucleo/board.mk index 8ae75dd96..eec479bb4 100644 --- a/hw/bsp/stm32f070rbnucleo/board.mk +++ b/hw/bsp/stm32f070rbnucleo/board.mk @@ -44,7 +44,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = stm32f070rb -JLINK_IF = swd # flash target using on-board stlink flash: flash-stlink diff --git a/hw/bsp/stm32f072disco/board.mk b/hw/bsp/stm32f072disco/board.mk index e6787b266..4155acf84 100644 --- a/hw/bsp/stm32f072disco/board.mk +++ b/hw/bsp/stm32f072disco/board.mk @@ -45,7 +45,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = stm32f072rb -JLINK_IF = swd # flash target using on-board stlink flash: flash-stlink diff --git a/hw/bsp/stm32f103bluepill/board.mk b/hw/bsp/stm32f103bluepill/board.mk index 028c567b1..124b16021 100644 --- a/hw/bsp/stm32f103bluepill/board.mk +++ b/hw/bsp/stm32f103bluepill/board.mk @@ -43,7 +43,6 @@ FREERTOS_PORT = ARM_CM3 # For flash-jlink target JLINK_DEVICE = stm32f103c8 -JLINK_IF = swd # flash target ROM bootloader flash: $(BUILD)/$(BOARD)-firmware.bin diff --git a/hw/bsp/stm32f207nucleo/board.mk b/hw/bsp/stm32f207nucleo/board.mk index 9eaff8548..27d8638d3 100644 --- a/hw/bsp/stm32f207nucleo/board.mk +++ b/hw/bsp/stm32f207nucleo/board.mk @@ -43,7 +43,6 @@ FREERTOS_PORT = ARM_CM3 # For flash-jlink target JLINK_DEVICE = stm32f207zg -JLINK_IF = swd # flash target using on-board stlink flash: flash-stlink diff --git a/hw/bsp/stm32f303disco/board.mk b/hw/bsp/stm32f303disco/board.mk index 07312ac82..cb94dac3b 100644 --- a/hw/bsp/stm32f303disco/board.mk +++ b/hw/bsp/stm32f303disco/board.mk @@ -44,7 +44,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = stm32f303vc -JLINK_IF = swd # flash target using on-board stlink flash: flash-stlink diff --git a/hw/bsp/stm32f401blackpill/board.mk b/hw/bsp/stm32f401blackpill/board.mk index 38cabcc5a..993e29c5f 100644 --- a/hw/bsp/stm32f401blackpill/board.mk +++ b/hw/bsp/stm32f401blackpill/board.mk @@ -40,7 +40,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = stm32f401cc -JLINK_IF = swd # flash target ROM bootloader flash: $(BUILD)/$(BOARD)-firmware.bin diff --git a/hw/bsp/stm32f407disco/board.mk b/hw/bsp/stm32f407disco/board.mk index df2ee4ba5..87b7bea10 100644 --- a/hw/bsp/stm32f407disco/board.mk +++ b/hw/bsp/stm32f407disco/board.mk @@ -44,7 +44,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = stm32f407vg -JLINK_IF = swd # flash target using on-board stlink flash: flash-stlink diff --git a/hw/bsp/stm32f411blackpill/board.mk b/hw/bsp/stm32f411blackpill/board.mk index 36897607f..3441dbb52 100644 --- a/hw/bsp/stm32f411blackpill/board.mk +++ b/hw/bsp/stm32f411blackpill/board.mk @@ -40,7 +40,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = stm32f411ce -JLINK_IF = swd # flash target ROM bootloader flash: $(BUILD)/$(BOARD)-firmware.bin diff --git a/hw/bsp/stm32f411disco/board.mk b/hw/bsp/stm32f411disco/board.mk index 5e0d6c3a0..f15d802ab 100644 --- a/hw/bsp/stm32f411disco/board.mk +++ b/hw/bsp/stm32f411disco/board.mk @@ -44,7 +44,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = stm32f411ve -JLINK_IF = swd # flash target using on-board stlink flash: flash-stlink diff --git a/hw/bsp/stm32f412disco/board.mk b/hw/bsp/stm32f412disco/board.mk index 5cf5e9b7a..0cc32da20 100644 --- a/hw/bsp/stm32f412disco/board.mk +++ b/hw/bsp/stm32f412disco/board.mk @@ -45,7 +45,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = stm32f41zx -JLINK_IF = swd # flash target using on-board stlink flash: flash-stlink diff --git a/hw/bsp/stm32h743eval/board.mk b/hw/bsp/stm32h743eval/board.mk index 47d592c58..543b40a30 100644 --- a/hw/bsp/stm32h743eval/board.mk +++ b/hw/bsp/stm32h743eval/board.mk @@ -57,7 +57,6 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = stm32h743xi -JLINK_IF = swd # flash target using on-board stlink flash: flash-stlink diff --git a/hw/bsp/stm32h745disco/board.mk b/hw/bsp/stm32h745disco/board.mk index b3477b1e6..eb87e7461 100644 --- a/hw/bsp/stm32h745disco/board.mk +++ b/hw/bsp/stm32h745disco/board.mk @@ -52,7 +52,6 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = stm32h745xi -JLINK_IF = swd # flash target using on-board stlink flash: flash-stlink diff --git a/hw/bsp/stm32l0538disco/board.mk b/hw/bsp/stm32l0538disco/board.mk index 241ad5d28..bcfaee7ac 100644 --- a/hw/bsp/stm32l0538disco/board.mk +++ b/hw/bsp/stm32l0538disco/board.mk @@ -44,7 +44,6 @@ FREERTOS_PORT = ARM_CM0 # For flash-jlink target JLINK_DEVICE = STM32L053R8 -JLINK_IF = swd # Path to STM32 Cube Programmer CLI, should be added into system path STM32Prog = STM32_Programmer_CLI diff --git a/hw/bsp/stm32l476disco/board.mk b/hw/bsp/stm32l476disco/board.mk index dc6b886db..e2fc010dc 100644 --- a/hw/bsp/stm32l476disco/board.mk +++ b/hw/bsp/stm32l476disco/board.mk @@ -43,7 +43,6 @@ FREERTOS_PORT = ARM_CM4F # For flash-jlink target JLINK_DEVICE = stm32l476vg -JLINK_IF = swd # Path to STM32 Cube Programmer CLI, should be added into system path STM32Prog = STM32_Programmer_CLI diff --git a/hw/bsp/teensy_40/board.mk b/hw/bsp/teensy_40/board.mk index 0a19fe63a..e49f13a1f 100644 --- a/hw/bsp/teensy_40/board.mk +++ b/hw/bsp/teensy_40/board.mk @@ -45,7 +45,6 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = MIMXRT1062xxx6A -JLINK_IF = swd # flash by using teensy_loader_cli https://github.com/PaulStoffregen/teensy_loader_cli # Make sure it is in your PATH From e8b3af038edf2195a8b65e3f66f7097445f07ff2 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 8 Oct 2020 17:19:48 +0700 Subject: [PATCH 116/167] add flash-pyocd support --- examples/rules.mk | 4 ++++ hw/bsp/mimxrt1015_evk/board.mk | 9 +++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/examples/rules.mk b/examples/rules.mk index e972ce735..a062c29c5 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -163,4 +163,8 @@ flash-jlink: $(BUILD)/$(BOARD)-firmware.hex flash-stlink: $(BUILD)/$(BOARD)-firmware.elf STM32_Programmer_CLI --connect port=swd --write $< --go +# flash with pyocd +flash-pyocd: $(BUILD)/$(BOARD)-firmware.hex + pyocd flash -t $(PYOCD_TARGET) $< + endif # Make target diff --git a/hw/bsp/mimxrt1015_evk/board.mk b/hw/bsp/mimxrt1015_evk/board.mk index 7df60c2c6..3ce7c2f82 100644 --- a/hw/bsp/mimxrt1015_evk/board.mk +++ b/hw/bsp/mimxrt1015_evk/board.mk @@ -45,12 +45,9 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = MIMXRT1015DAF5A -JLINK_IF = swd -# flash by copying bin file to DAP Mass Storage -flash: $(BUILD)/$(BOARD)-firmware.bin - cp $< /media/$(USER)/RT1015-EVK/ +# For flash-pyocd target +PYOCD_TARGET = mimxrt1015 # flash using pyocd -#flash: $(BUILD)/$(BOARD)-firmware.hex -# pyocd flash -b MIMXRT1015-EVK $< +flash: flash-pyocd From 9edf4334c441afbcb24b723411c5cdef1fac56ec Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Thu, 1 Oct 2020 11:49:14 +0200 Subject: [PATCH 117/167] 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(-) 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) +{ + // 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; + 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; + 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 - { + 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; + do + { + 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_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 { From 6615dd90622ab72649c3a87cbcdc74038f5c412c Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 2 Oct 2020 12:38:43 +0200 Subject: [PATCH 118/167] 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(+) 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); From 33a5081bd1c712726f879ba65fee973b23480c27 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 2 Oct 2020 12:41:18 +0200 Subject: [PATCH 119/167] 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(-) 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) { From d36bfddc301daf9993c24c75597d04c1c39347a8 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 7 Oct 2020 09:32:17 +0200 Subject: [PATCH 120/167] 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(-) 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; From 298aa1b669a5c77f991c8161ba4c7d84f7a2b674 Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Thu, 8 Oct 2020 11:59:12 -0500 Subject: [PATCH 121/167] Cleanup per review on PR --- .../hid_multipleinterface/src/tusb_config.h | 2 +- .../src/usb_descriptors.c | 18 +++++++++--------- src/class/hid/hid_device.c | 4 +++- 3 files changed, 13 insertions(+), 11 deletions(-) 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 desc_hid_report1; + } + else if (itf == 1) + { + return desc_hid_report2; + } - return 0; + 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); From a4ba1f08275bc6fe8ce1f73d24f353861839cce7 Mon Sep 17 00:00:00 2001 From: Zachery Littell Date: Thu, 8 Oct 2020 12:08:13 -0500 Subject: [PATCH 122/167] Fix tu_verify args --- src/class/hid/hid_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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); From 344d589a354ec719333c10d315f4f186b178d2d7 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Oct 2020 13:48:08 +0700 Subject: [PATCH 123/167] use pyocd for iMXRT boards --- examples/rules.mk | 1 + hw/bsp/mimxrt1010_evk/board.mk | 8 +++++--- hw/bsp/mimxrt1020_evk/board.mk | 8 +++++--- hw/bsp/mimxrt1050_evkb/board.mk | 9 ++++----- hw/bsp/mimxrt1060_evk/board.mk | 8 +++++--- hw/bsp/mimxrt1064_evk/board.mk | 8 +++++--- 6 files changed, 25 insertions(+), 17 deletions(-) diff --git a/examples/rules.mk b/examples/rules.mk index a062c29c5..7ed648a8b 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -166,5 +166,6 @@ flash-stlink: $(BUILD)/$(BOARD)-firmware.elf # flash with pyocd flash-pyocd: $(BUILD)/$(BOARD)-firmware.hex pyocd flash -t $(PYOCD_TARGET) $< + pyocd reset -t $(PYOCD_TARGET) endif # Make target diff --git a/hw/bsp/mimxrt1010_evk/board.mk b/hw/bsp/mimxrt1010_evk/board.mk index 6197c5365..3ff916624 100644 --- a/hw/bsp/mimxrt1010_evk/board.mk +++ b/hw/bsp/mimxrt1010_evk/board.mk @@ -47,6 +47,8 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = MIMXRT1011DAE5A -# flash by copying bin file to DAP Mass Storage -flash: $(BUILD)/$(BOARD)-firmware.bin - cp $< /media/$(USER)/RT1010-EVK/ +# For flash-pyocd target +PYOCD_TARGET = mimxrt1010 + +# flash using pyocd +flash: flash-pyocd diff --git a/hw/bsp/mimxrt1020_evk/board.mk b/hw/bsp/mimxrt1020_evk/board.mk index c5b285b47..66bcdf89b 100644 --- a/hw/bsp/mimxrt1020_evk/board.mk +++ b/hw/bsp/mimxrt1020_evk/board.mk @@ -46,6 +46,8 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = MIMXRT1021DAG5A -# flash by copying bin file to DAP Mass Storage -flash: $(BUILD)/$(BOARD)-firmware.bin - cp $< /media/$(USER)/RT1020-EVK/ +# For flash-pyocd target +PYOCD_TARGET = mimxrt1020 + +# flash using pyocd +flash: flash-pyocd diff --git a/hw/bsp/mimxrt1050_evkb/board.mk b/hw/bsp/mimxrt1050_evkb/board.mk index 2148f8298..123e2ea82 100644 --- a/hw/bsp/mimxrt1050_evkb/board.mk +++ b/hw/bsp/mimxrt1050_evkb/board.mk @@ -43,9 +43,8 @@ CHIP_FAMILY = transdimension # For freeRTOS port source FREERTOS_PORT = ARM_CM7/r0p1 -# For flash-jlink target -JLINK_DEVICE = MIMXRT1052xxx6B +# For flash-pyocd target +PYOCD_TARGET = mimxrt1050 -# flash by copying bin file to DAP Mass Storage -flash: $(BUILD)/$(BOARD)-firmware.bin - cp $< /media/$(USER)/RT1050-EVK/ +# flash using pyocd +flash: flash-pyocd diff --git a/hw/bsp/mimxrt1060_evk/board.mk b/hw/bsp/mimxrt1060_evk/board.mk index cf4007914..5c93e1cdf 100644 --- a/hw/bsp/mimxrt1060_evk/board.mk +++ b/hw/bsp/mimxrt1060_evk/board.mk @@ -46,6 +46,8 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = MIMXRT1062xxx6A -# flash by copying bin file to DAP Mass Storage -flash: $(BUILD)/$(BOARD)-firmware.bin - cp $< /media/$(USER)/RT1060-EVK/ +# For flash-pyocd target +PYOCD_TARGET = mimxrt1060 + +# flash using pyocd +flash: flash-pyocd diff --git a/hw/bsp/mimxrt1064_evk/board.mk b/hw/bsp/mimxrt1064_evk/board.mk index 5f230d687..f6a277497 100644 --- a/hw/bsp/mimxrt1064_evk/board.mk +++ b/hw/bsp/mimxrt1064_evk/board.mk @@ -46,6 +46,8 @@ FREERTOS_PORT = ARM_CM7/r0p1 # For flash-jlink target JLINK_DEVICE = MIMXRT1064xxx6A -# flash by copying bin file to DAP Mass Storage -flash: $(BUILD)/$(BOARD)-firmware.bin - cp $< /media/$(USER)/RT1064-EVK/ +# For flash-pyocd target +PYOCD_TARGET = mimxrt1064 + +# flash using pyocd +flash: flash-pyocd From 2219068371fa514e320ddf1c6059c3f6ed901ae7 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Oct 2020 13:50:55 +0700 Subject: [PATCH 124/167] rename hid multiple interface --- .github/workflows/build.yml | 2 +- .../{hid_multipleinterface => hid_multiple_interface}/Makefile | 0 .../src/main.c | 0 .../src/tusb_config.h | 0 .../src/usb_descriptors.c | 0 5 files changed, 1 insertion(+), 1 deletion(-) rename examples/device/{hid_multipleinterface => hid_multiple_interface}/Makefile (100%) rename examples/device/{hid_multipleinterface => hid_multiple_interface}/src/main.c (100%) rename examples/device/{hid_multipleinterface => hid_multiple_interface}/src/tusb_config.h (100%) rename examples/device/{hid_multipleinterface => hid_multiple_interface}/src/usb_descriptors.c (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e2db8f775..fd48eef1b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,7 +35,7 @@ jobs: - 'device/hid_composite' - 'device/hid_composite_freertos' - 'device/hid_generic_inout' - - 'device/hid_multipleinterface' + - 'device/hid_multiple_interface' - 'device/midi_test' - 'device/msc_dual_lun' - 'device/net_lwip_webserver' diff --git a/examples/device/hid_multipleinterface/Makefile b/examples/device/hid_multiple_interface/Makefile similarity index 100% rename from examples/device/hid_multipleinterface/Makefile rename to examples/device/hid_multiple_interface/Makefile diff --git a/examples/device/hid_multipleinterface/src/main.c b/examples/device/hid_multiple_interface/src/main.c similarity index 100% rename from examples/device/hid_multipleinterface/src/main.c rename to examples/device/hid_multiple_interface/src/main.c diff --git a/examples/device/hid_multipleinterface/src/tusb_config.h b/examples/device/hid_multiple_interface/src/tusb_config.h similarity index 100% rename from examples/device/hid_multipleinterface/src/tusb_config.h rename to examples/device/hid_multiple_interface/src/tusb_config.h diff --git a/examples/device/hid_multipleinterface/src/usb_descriptors.c b/examples/device/hid_multiple_interface/src/usb_descriptors.c similarity index 100% rename from examples/device/hid_multipleinterface/src/usb_descriptors.c rename to examples/device/hid_multiple_interface/src/usb_descriptors.c From 2e464c5015f83ee52465e61160def7662b6541bc Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Oct 2020 13:57:23 +0700 Subject: [PATCH 125/167] clean up example --- .../device/hid_multiple_interface/src/main.c | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/examples/device/hid_multiple_interface/src/main.c b/examples/device/hid_multiple_interface/src/main.c index b1957b9fc..3599683c5 100644 --- a/examples/device/hid_multiple_interface/src/main.c +++ b/examples/device/hid_multiple_interface/src/main.c @@ -34,6 +34,12 @@ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ +// Interface index depends on the order in configuration descriptor +enum { + ITF_KEYBOARD = 0, + ITF_MOUSE = 1 +}; + /* Blink pattern * - 250 ms : device not mounted * - 1000 ms : device mounted @@ -104,10 +110,6 @@ void tud_resume_cb(void) void hid_task(void) { - //Set up interfaces - const uint8_t keyboard_interface = 0; - const uint8_t mouse_interface = 1; - // Poll every 10ms const uint32_t interval_ms = 10; static uint32_t start_ms = 0; @@ -126,7 +128,7 @@ void hid_task(void) } /*------------- Keyboard -------------*/ - if ( tud_hid_n_ready(keyboard_interface) ) + if ( tud_hid_n_ready(ITF_KEYBOARD) ) { // use to avoid send multiple consecutive zero report for keyboard static bool has_key = false; @@ -136,29 +138,26 @@ void hid_task(void) uint8_t keycode[6] = { 0 }; keycode[0] = HID_KEY_A; - tud_hid_n_keyboard_report(keyboard_interface, 0, 0, keycode); + tud_hid_n_keyboard_report(ITF_KEYBOARD, 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, 0, 0, NULL); + if (has_key) tud_hid_n_keyboard_report(ITF_KEYBOARD, 0, 0, NULL); has_key = false; } } /*------------- Mouse -------------*/ - if ( tud_hid_n_ready(mouse_interface) ) + if ( tud_hid_n_ready(ITF_MOUSE) ) { if ( btn ) { int8_t const delta = 5; // no button, right + down, no scroll pan - 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); + tud_hid_n_mouse_report(ITF_MOUSE, 0, 0x00, delta, delta, 0, 0); } } } From 13abcb953fcd3d51983e9768619adde776af257e Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Oct 2020 20:24:10 +0700 Subject: [PATCH 126/167] rename multiple hid callback --- .../device/hid_multiple_interface/src/main.c | 4 +-- .../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(-) 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 //--------------------------------------------------------------------+ From 8ba0c362ccb72a04ec101610f4b7f9c8577a26da Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Oct 2020 20:51:20 +0700 Subject: [PATCH 127/167] 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(-) 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); From 8cf1ed6e4ee385dbfb7ef7dd1446c52eab67f503 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Oct 2020 21:01:52 +0700 Subject: [PATCH 128/167] try GITHUB_PATH for ci --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fd48eef1b..227593e8a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -66,14 +66,14 @@ jobs: npm install --global xpm xpm install --global @xpack-dev-tools/arm-none-eabi-gcc@latest xpm install --global @xpack-dev-tools/riscv-none-embed-gcc@latest - echo "::add-path::`echo $HOME/opt/xPacks/@xpack-dev-tools/arm-none-eabi-gcc/*/.content/bin`" - echo "::add-path::`echo $HOME/opt/xPacks/@xpack-dev-tools/riscv-none-embed-gcc/*/.content/bin`" + echo `$HOME/opt/xPacks/@xpack-dev-tools/arm-none-eabi-gcc/*/.content/bin` >> $GITHUB_PATH + echo `echo $HOME/opt/xPacks/@xpack-dev-tools/riscv-none-embed-gcc/*/.content/bin` >> $GITHUB_PATH # TI MSP430 GCC mkdir -p /tmp/dl/ [ -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`" + echo `echo $HOME/msp430-gcc-*_linux64/bin` >> $GITHUB_PATH - name: Checkout TinyUSB uses: actions/checkout@v2 From 3fd38ddf0493f84eb3124aacf9ccd7c76643a2c9 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 9 Oct 2020 21:10:59 +0700 Subject: [PATCH 129/167] fix ci build --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 227593e8a..8bb382a8d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -66,7 +66,7 @@ jobs: npm install --global xpm xpm install --global @xpack-dev-tools/arm-none-eabi-gcc@latest xpm install --global @xpack-dev-tools/riscv-none-embed-gcc@latest - echo `$HOME/opt/xPacks/@xpack-dev-tools/arm-none-eabi-gcc/*/.content/bin` >> $GITHUB_PATH + echo `echo $HOME/opt/xPacks/@xpack-dev-tools/arm-none-eabi-gcc/*/.content/bin` >> $GITHUB_PATH echo `echo $HOME/opt/xPacks/@xpack-dev-tools/riscv-none-embed-gcc/*/.content/bin` >> $GITHUB_PATH # TI MSP430 GCC From 032e84c9befa0797f6a6faf86fbfdff13ec77bbe Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 9 Oct 2020 19:50:05 +0200 Subject: [PATCH 130/167] 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(-) 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; + + // 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 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; - - 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; - } } // 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 From 63f18cef1990ba5cc99667475766ecdef7988aac Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 9 Oct 2020 20:15:57 +0200 Subject: [PATCH 131/167] Extend example s.t. a saw tooth is sent. --- examples/device/audio_test/src/main.c | 44 +++++++++++++++++++ examples/device/audio_test/src/tusb_config.h | 10 +++-- .../device/audio_test/src/usb_descriptors.c | 2 +- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 2ea1d36c6..4ef03fa27 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -58,6 +58,10 @@ uint8_t clkValid; 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 +// Audio test data +uint8_t test_buffer_audio[CFG_TUD_AUDIO_TX_FIFO_SIZE]; +uint16_t startVal = 0; + void led_blinking_task(void); void audio_task(void); @@ -364,6 +368,46 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * return false; // Yet not implemented } +bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) +{ + (void) rhport; + (void) itf; + (void) ep_in; + (void) cur_alt_setting; + + tud_audio_write (test_buffer_audio, CFG_TUD_AUDIO_TX_FIFO_SIZE); + + return true; +} + +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) +{ + (void) rhport; + (void) rhport; + (void) itf; + (void) ep_in; + (void) cur_alt_setting; + + uint8_t * pBuffer = test_buffer_audio; + + for (size_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_SIZE/2; cnt++) + { + *(uint16_t *)pBuffer = startVal++; + pBuffer += 2; + } + + return true; +} + +bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + (void) p_request; + startVal = 0; + + return true; +} + //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index 6cd6882bc..16f88a4da 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -93,18 +93,20 @@ extern "C" { // 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 +#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 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) +#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) // 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_TUSB_DEBUG 0 + #ifdef __cplusplus } #endif diff --git a/examples/device/audio_test/src/usb_descriptors.c b/examples/device/audio_test/src/usb_descriptors.c index 0b4f9b62c..02d018823 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*/ 45*3) + TUD_AUDIO_MIC_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ 3, /*_nBitsUsedPerSample*/ 24, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ 48*4) }; // Invoked when received GET CONFIGURATION DESCRIPTOR From 14ff7313ee0e40c157bc24b83c25a8939929a450 Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 9 Oct 2020 20:36:35 +0200 Subject: [PATCH 132/167] Fix minor issue in audio example. --- examples/device/audio_test/src/main.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 4ef03fa27..c3c32b533 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 -uint8_t test_buffer_audio[CFG_TUD_AUDIO_TX_FIFO_SIZE]; +uint16_t test_buffer_audio[CFG_TUD_AUDIO_TX_FIFO_SIZE/2]; uint16_t startVal = 0; void led_blinking_task(void); @@ -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 (test_buffer_audio, CFG_TUD_AUDIO_TX_FIFO_SIZE); + tud_audio_write ((uint8_t *)test_buffer_audio, CFG_TUD_AUDIO_TX_FIFO_SIZE); return true; } @@ -388,12 +388,9 @@ bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uin (void) ep_in; (void) cur_alt_setting; - uint8_t * pBuffer = test_buffer_audio; - for (size_t cnt = 0; cnt < CFG_TUD_AUDIO_TX_FIFO_SIZE/2; cnt++) { - *(uint16_t *)pBuffer = startVal++; - pBuffer += 2; + test_buffer_audio[cnt] = startVal++; } return true; From a85c4ee11ddb33522fb40937dfa09faea6c9132a Mon Sep 17 00:00:00 2001 From: Reinhard Panhuber Date: Fri, 9 Oct 2020 21:59:52 +0200 Subject: [PATCH 133/167] Fix unused parameter in audio test. --- examples/device/audio_test/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index c3c32b533..7f0ce3652 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -383,7 +383,7 @@ bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, u 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) { (void) rhport; - (void) rhport; + (void) n_bytes_copied; (void) itf; (void) ep_in; (void) cur_alt_setting; From f914e48d25cae6d5cda34d3193f46b74826e0e1a Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sat, 10 Oct 2020 05:00:55 +0200 Subject: [PATCH 134/167] Dynamically check STM32F3 IRQ remap option --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) 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); From 35fae201fb35b5eb78f654fe94acd5f2c0f44912 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sat, 10 Oct 2020 16:49:45 -0500 Subject: [PATCH 135/167] net_lwip_webserver: tweak main.c comments with smartphone suggestions --- examples/device/net_lwip_webserver/src/main.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index b672ca3bb..508f57857 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -32,6 +32,16 @@ RNDIS should be valid on Linux and Windows hosts, and CDC-ECM should be valid on The MCU appears to the host as IP address 192.168.7.1, and provides a DHCP server, DNS server, and web server. */ +/* +Some smartphones *may* work with this implementation as well, but likely have limited (broken) drivers, +and likely their manufacturer has not tested such functionality. Some code workarounds could be tried: + +The smartphone may only have an ECM driver, but refuse to automatically pick ECM (unlike the OSes above); +try modifying ./examples/devices/net_lwip_webserver/usb_descriptors.c so that CONFIG_ID_ECM is default. + +The smartphone may be artificially picky about which Ethernet MAC address to recognize; if this happens, +try changing the first byte of tud_network_mac_address[] below from 0x02 to 0x00 (clearing bit 1). +*/ #include "bsp/board.h" #include "tusb.h" @@ -50,7 +60,7 @@ 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) */ -/* it is suggested that the first two bytes are 0x02,0x02 to indicate a link-local address */ +/* it is suggested that the first byte is 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 */ From b8e7e2b7c9dda007772a2da17c73fc93a8722c92 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 11 Oct 2020 13:33:06 +0700 Subject: [PATCH 136/167] update microchip driver also skip audio_test for same5x for now due to assert() macro conflict --- examples/device/audio_test/.skip.MCU_SAME5X | 0 hw/mcu/microchip | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 examples/device/audio_test/.skip.MCU_SAME5X diff --git a/examples/device/audio_test/.skip.MCU_SAME5X b/examples/device/audio_test/.skip.MCU_SAME5X new file mode 100644 index 000000000..e69de29bb diff --git a/hw/mcu/microchip b/hw/mcu/microchip index df9970f6c..434e384e8 160000 --- a/hw/mcu/microchip +++ b/hw/mcu/microchip @@ -1 +1 @@ -Subproject commit df9970f6c26967ace144a83219cf7378831f6181 +Subproject commit 434e384e8f1c6a05377f82e1f0796467a2267ad5 From 7fda95f508ee1548da4bc9296aa160b98f2bd8c2 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sun, 11 Oct 2020 09:27:43 +0200 Subject: [PATCH 137/167] Remap USB IRQs on STM32F303 BSP --- hw/bsp/stm32f303disco/stm32f303disco.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/hw/bsp/stm32f303disco/stm32f303disco.c b/hw/bsp/stm32f303disco/stm32f303disco.c index 1fe908bc3..33552bc07 100644 --- a/hw/bsp/stm32f303disco/stm32f303disco.c +++ b/hw/bsp/stm32f303disco/stm32f303disco.c @@ -31,27 +31,29 @@ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -// USB defaults to using interrupts 19, 20, and 42 (based on SYSCFG_CFGR1.USB_IT_RMP) +// USB defaults to using interrupts 19, 20 and 42, however, this BSP sets the +// SYSCFG_CFGR1.USB_IT_RMP bit remapping interrupts to 74, 75 and 76. + // FIXME: Do all three need to be handled, or just the LP one? -// USB high-priority interrupt (Channel 19): Triggered only by a correct +// USB high-priority interrupt (Channel 74): 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) +void USB_HP_IRQHandler(void) { tud_int_handler(0); } -// USB low-priority interrupt (Channel 20): Triggered by all USB events +// USB low-priority interrupt (Channel 75): 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) +void USB_LP_IRQHandler(void) { tud_int_handler(0); } -// USB wakeup interrupt (Channel 42): Triggered by the wakeup event from the USB +// USB wakeup interrupt (Channel 76): Triggered by the wakeup event from the USB // Suspend mode. -void USBWakeUp_IRQHandler(void) +void USBWakeUp_RMP_IRQHandler(void) { tud_int_handler(0); } @@ -127,6 +129,10 @@ void board_init(void) SysTick_Config(SystemCoreClock / 1000); #endif + // Remap the USB interrupts + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_REMAPINTERRUPT_USB_ENABLE(); + // LED __HAL_RCC_GPIOE_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct; From e10358bfaba5a2818e3f21ac93a9cc32a7b9bf33 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sat, 10 Oct 2020 17:36:37 -0500 Subject: [PATCH 138/167] bsp: add ATSAMD21-XPRO eval board --- hw/bsp/atsamd21_xpro/atsamd21_xpro.c | 142 ++++++++++++++++++++++ hw/bsp/atsamd21_xpro/board.mk | 45 +++++++ hw/bsp/atsamd21_xpro/samd21j18a_flash.ld | 144 +++++++++++++++++++++++ 3 files changed, 331 insertions(+) create mode 100644 hw/bsp/atsamd21_xpro/atsamd21_xpro.c create mode 100644 hw/bsp/atsamd21_xpro/board.mk create mode 100644 hw/bsp/atsamd21_xpro/samd21j18a_flash.ld diff --git a/hw/bsp/atsamd21_xpro/atsamd21_xpro.c b/hw/bsp/atsamd21_xpro/atsamd21_xpro.c new file mode 100644 index 000000000..aa962b127 --- /dev/null +++ b/hw/bsp/atsamd21_xpro/atsamd21_xpro.c @@ -0,0 +1,142 @@ +/* + * 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" + +#undef LITTLE_ENDIAN /* workaround for buggy SAMD submodule: compile error for ATSAMD21J18 (J, not G) */ +#include "sam.h" + +#include "hal/include/hal_gpio.h" +#include "hal/include/hal_init.h" +#include "hri/hri_nvmctrl_d21.h" + +#include "hpl/gclk/hpl_gclk_base.h" +#include "hpl_pm_config.h" +#include "hpl/pm/hpl_pm_base.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ +#define LED_PIN (32+30) // pin PB30 +#define BUTTON_PIN (0+15) // pin PA15 + +/* Referenced GCLKs, should be initialized firstly */ +#define _GCLK_INIT_1ST (1 << 0 | 1 << 1) + +/* Not referenced GCLKs, initialized last */ +#define _GCLK_INIT_LAST (~_GCLK_INIT_1ST) + +void board_init(void) +{ + // Clock init ( follow hpl_init.c ) + hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, 2); + + _pm_init(); + _sysctrl_init_sources(); +#if _GCLK_INIT_1ST + _gclk_init_generators_by_fref(_GCLK_INIT_1ST); +#endif + _sysctrl_init_referenced_generators(); + _gclk_init_generators_by_fref(_GCLK_INIT_LAST); + + // Led init + gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_level(LED_PIN, 1); + + // Button init + gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(BUTTON_PIN, GPIO_PULL_UP); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer (samd SystemCoreClock may not correct) + SysTick_Config(CONF_CPU_FREQUENCY / 1000); +#endif + + /* USB Clock init + * The USB module requires a GCLK_USB of 48 MHz ~ 0.25% clock + * for low speed and full speed operation. */ + _pm_enable_bus_clock(PM_BUS_APBB, USB); + _pm_enable_bus_clock(PM_BUS_AHB, USB); + _gclk_enable_channel(USB_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); + + // 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); +} + +//--------------------------------------------------------------------+ +// 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 asf_assert(const bool condition, const char *const file, const int line) {} + +void USB_Handler(void) +{ + tud_int_handler(0); +} diff --git a/hw/bsp/atsamd21_xpro/board.mk b/hw/bsp/atsamd21_xpro/board.mk new file mode 100644 index 000000000..a00bceda2 --- /dev/null +++ b/hw/bsp/atsamd21_xpro/board.mk @@ -0,0 +1,45 @@ +CFLAGS += \ + -flto \ + -mthumb \ + -mabi=aapcs-linux \ + -mcpu=cortex-m0plus \ + -nostdlib -nostartfiles \ + -D__SAMD21J18A__ \ + -DCONF_DFLL_OVERWRITE_CALIBRATION=0 \ + -DCFG_TUSB_MCU=OPT_MCU_SAMD21 + +# All source paths should be relative to the top level. +LD_FILE = hw/bsp/atsamd21_xpro/samd21j18a_flash.ld + +SRC_C += \ + hw/mcu/microchip/samd/asf4/samd21/gcc/gcc/startup_samd21.c \ + hw/mcu/microchip/samd/asf4/samd21/gcc/system_samd21.c \ + hw/mcu/microchip/samd/asf4/samd21/hpl/gclk/hpl_gclk.c \ + hw/mcu/microchip/samd/asf4/samd21/hpl/pm/hpl_pm.c \ + hw/mcu/microchip/samd/asf4/samd21/hpl/sysctrl/hpl_sysctrl.c \ + hw/mcu/microchip/samd/asf4/samd21/hal/src/hal_atomic.c + +INC += \ + $(TOP)/hw/mcu/microchip/samd/asf4/samd21/ \ + $(TOP)/hw/mcu/microchip/samd/asf4/samd21/config \ + $(TOP)/hw/mcu/microchip/samd/asf4/samd21/include \ + $(TOP)/hw/mcu/microchip/samd/asf4/samd21/hal/include \ + $(TOP)/hw/mcu/microchip/samd/asf4/samd21/hal/utils/include \ + $(TOP)/hw/mcu/microchip/samd/asf4/samd21/hpl/pm/ \ + $(TOP)/hw/mcu/microchip/samd/asf4/samd21/hpl/port \ + $(TOP)/hw/mcu/microchip/samd/asf4/samd21/hri \ + $(TOP)/hw/mcu/microchip/samd/asf4/samd21/CMSIS/Include + +# For TinyUSB port source +VENDOR = microchip +CHIP_FAMILY = samd + +# For freeRTOS port source +FREERTOS_PORT = ARM_CM0 + +# For flash-jlink target +JLINK_DEVICE = ATSAMD21J18 +JLINK_IF = swd + +# flash using jlink +flash: flash-jlink diff --git a/hw/bsp/atsamd21_xpro/samd21j18a_flash.ld b/hw/bsp/atsamd21_xpro/samd21j18a_flash.ld new file mode 100644 index 000000000..e2f93416d --- /dev/null +++ b/hw/bsp/atsamd21_xpro/samd21j18a_flash.ld @@ -0,0 +1,144 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21J18A + * + * Copyright (c) 2017 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; + +/* 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 = .; + end = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} From db70a35044bdec7092e89f269429cf87bbce6afe Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 13 Oct 2020 16:25:51 +0200 Subject: [PATCH 139/167] 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(+) 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),\ }\ } From 042ca2375e826e2b3c78c88a3c91d4ddbc128cb9 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Wed, 14 Oct 2020 09:15:26 -0500 Subject: [PATCH 140/167] bsp: atsamd21_xpro: removed no longer needed workaround --- hw/bsp/atsamd21_xpro/atsamd21_xpro.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/bsp/atsamd21_xpro/atsamd21_xpro.c b/hw/bsp/atsamd21_xpro/atsamd21_xpro.c index aa962b127..26d3e93bd 100644 --- a/hw/bsp/atsamd21_xpro/atsamd21_xpro.c +++ b/hw/bsp/atsamd21_xpro/atsamd21_xpro.c @@ -25,8 +25,6 @@ */ #include "bsp/board.h" - -#undef LITTLE_ENDIAN /* workaround for buggy SAMD submodule: compile error for ATSAMD21J18 (J, not G) */ #include "sam.h" #include "hal/include/hal_gpio.h" From 56277ce21639a1e3ed608e73d67367d2b21c1764 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Wed, 14 Oct 2020 20:26:40 -0500 Subject: [PATCH 141/167] net_lwip_webserver: efficiency tweaks --- .../device/net_lwip_webserver/src/lwipopts.h | 4 +- examples/device/net_lwip_webserver/src/main.c | 21 +++++---- lib/networking/dhserver.c | 43 ++++++++++--------- lib/networking/dhserver.h | 7 ++- 4 files changed, 38 insertions(+), 37 deletions(-) diff --git a/examples/device/net_lwip_webserver/src/lwipopts.h b/examples/device/net_lwip_webserver/src/lwipopts.h index 23319592d..5a8096f50 100644 --- a/examples/device/net_lwip_webserver/src/lwipopts.h +++ b/examples/device/net_lwip_webserver/src/lwipopts.h @@ -35,7 +35,7 @@ /* 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_RAW 0 #define LWIP_NETCONN 0 #define LWIP_SOCKET 0 #define LWIP_DHCP 0 @@ -54,4 +54,6 @@ #define LWIP_HTTPD_SSI 0 #define LWIP_HTTPD_SSI_INCLUDE_TAG 0 +#define LWIP_SINGLE_NETIF 1 + #endif /* __LWIPOPTS_H__ */ diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index 508f57857..020f4e4d6 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -71,22 +71,21 @@ 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 } + /* mac ip address lease time */ + { {0}, IPADDR4_INIT_BYTES(192, 168, 7, 2), 24 * 60 * 60 }, + { {0}, IPADDR4_INIT_BYTES(192, 168, 7, 3), 24 * 60 * 60 }, + { {0}, IPADDR4_INIT_BYTES(192, 168, 7, 4), 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 */ + .router = IPADDR4_INIT_BYTES(0, 0, 0, 0), /* router address (if any) */ + .port = 67, /* listen port */ + .dns = IPADDR4_INIT_BYTES(192, 168, 7, 1), /* dns server (if any) */ + "usb", /* dns suffix */ + TU_ARRAY_SIZE(entries), /* num entry */ + entries /* entries */ }; - static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) { (void)netif; diff --git a/lib/networking/dhserver.c b/lib/networking/dhserver.c index a1a570f93..9287858ea 100644 --- a/lib/networking/dhserver.c +++ b/lib/networking/dhserver.c @@ -96,23 +96,23 @@ static const dhcp_config_t *config = NULL; char magic_cookie[] = {0x63,0x82,0x53,0x63}; -static uint32_t get_ip(const uint8_t *pnt) +static ip_addr_t get_ip(const uint8_t *pnt) { - uint32_t result; + ip_addr_t result; memcpy(&result, pnt, sizeof(result)); return result; } -static void set_ip(uint8_t *pnt, uint32_t value) +static void set_ip(uint8_t *pnt, ip_addr_t value) { - memcpy(pnt, &value, sizeof(value)); + memcpy(pnt, &value.addr, sizeof(value.addr)); } -static dhcp_entry_t *entry_by_ip(uint32_t ip) +static dhcp_entry_t *entry_by_ip(ip_addr_t ip) { int i; for (i = 0; i < config->num_entry; i++) - if (get_ip(config->entries[i].addr) == ip) + if (config->entries[i].addr.addr == ip.addr) return &config->entries[i]; return NULL; } @@ -162,11 +162,11 @@ uint8_t *find_dhcp_option(uint8_t *attrs, int size, uint8_t attr) int fill_options(void *dest, uint8_t msg_type, const char *domain, - uint32_t dns, + ip_addr_t dns, int lease_time, - uint32_t serverid, - uint32_t router, - uint32_t subnet) + ip_addr_t serverid, + ip_addr_t router, + ip_addr_t subnet) { uint8_t *ptr = (uint8_t *)dest; /* ACK message type */ @@ -195,7 +195,7 @@ int fill_options(void *dest, ptr += 4; /* router */ - if (router != 0) + if (router.addr != 0) { *ptr++ = DHCP_ROUTER; *ptr++ = 4; @@ -214,7 +214,7 @@ int fill_options(void *dest, } /* domain name server (DNS) */ - if (dns != 0) + if (dns.addr != 0) { *ptr++ = DHCP_DNSSERVER; *ptr++ = 4; @@ -232,6 +232,7 @@ static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const uint8_t *ptr; dhcp_entry_t *entry; struct pbuf *pp; + struct netif *netif = netif_get_by_index(p->if_idx); (void)arg; (void)addr; @@ -249,7 +250,7 @@ static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const 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)); + set_ip(dhcp_data.dp_yiaddr, entry->addr); memcpy(dhcp_data.dp_magic, magic_cookie, 4); memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); @@ -257,11 +258,11 @@ static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const fill_options(dhcp_data.dp_options, DHCP_OFFER, config->domain, - get_ip(config->dns), + config->dns, entry->lease, - get_ip(config->addr), - get_ip(config->addr), - get_ip(entry->subnet)); + *netif_ip4_addr(netif), + config->router, + *netif_ip4_netmask(netif)); pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); if (pp == NULL) break; @@ -299,11 +300,11 @@ static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const fill_options(dhcp_data.dp_options, DHCP_ACK, config->domain, - get_ip(config->dns), + config->dns, entry->lease, - get_ip(config->addr), - get_ip(config->addr), - get_ip(entry->subnet)); + *netif_ip4_addr(netif), + config->router, + *netif_ip4_netmask(netif)); /* 6. send ACK */ pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); diff --git a/lib/networking/dhserver.h b/lib/networking/dhserver.h index 901f6e351..0d22461c7 100644 --- a/lib/networking/dhserver.h +++ b/lib/networking/dhserver.h @@ -42,16 +42,15 @@ typedef struct dhcp_entry { uint8_t mac[6]; - uint8_t addr[4]; - uint8_t subnet[4]; + ip_addr_t addr; uint32_t lease; } dhcp_entry_t; typedef struct dhcp_config { - uint8_t addr[4]; + ip_addr_t router; uint16_t port; - uint8_t dns[4]; + ip_addr_t dns; const char *domain; int num_entry; dhcp_entry_t *entries; From 4e4aa26fb6155e409f8bea17515bc7b6ceb9b8cb Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 Oct 2020 11:57:30 +0700 Subject: [PATCH 142/167] add samd21 xplained pro to boards.md doc --- docs/boards.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/boards.md b/docs/boards.md index f49b247ac..59f6905ea 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -30,8 +30,9 @@ This code base already had supported for a handful of following boards (sorted a - [Adafruit Metro M4 Express](https://www.adafruit.com/product/3382) - [D5035-01](https://github.com/RudolphRiedel/USB_CAN-FD) - [Great Scott Gadgets LUNA](https://greatscottgadgets.com/luna/) -- [Microchip SAMD11 Xplained](https://www.microchip.com/developmenttools/ProductDetails/atsamd11-xpro) -- [Microchip SAMG55 Xplained Pro Evaluation Kit](https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/ATSAMG55-XPRO) +- [Microchip SAMD11 Xplained Pro](https://www.microchip.com/developmenttools/ProductDetails/atsamd11-xpro) +- [Microchip SAMD21 Xplained Pro](https://www.microchip.com/DevelopmentTools/ProductDetails/ATSAMD21-XPRO) +- [Microchip SAMG55 Xplained Pro](https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/ATSAMG55-XPRO) - [Seeeduino Xiao](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html) ### Nordic nRF5x From 8669fd738313e296c376312ba22945a003d81a4f Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Thu, 15 Oct 2020 15:34:12 +0200 Subject: [PATCH 143/167] 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(+) 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) */ From a5581b10df1484ffa263fdb456149511a41df69a Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 14 Oct 2020 16:53:55 +0200 Subject: [PATCH 144/167] audio: Add headset example This example code creates USB Audio 2.0 headset device. Device has two audio interfaces first stereo speaker with 48kHz stereo stream. Second interface for microphone with 48kHz mono stream. This example can be used to start working on audio device. It can be also used to verify ISO endpoints for boards. Speaker adaptive clock (bound to SOF). Microphone for now has asynchronous clock. Volume and mute control while present are not used for data stream modification. --- examples/device/uac2_headset/Makefile | 12 + examples/device/uac2_headset/src/main.c | 391 ++++++++++++++++++ .../device/uac2_headset/src/tusb_config.h | 134 ++++++ .../device/uac2_headset/src/usb_descriptors.c | 165 ++++++++ .../device/uac2_headset/src/usb_descriptors.h | 120 ++++++ 5 files changed, 822 insertions(+) create mode 100644 examples/device/uac2_headset/Makefile create mode 100644 examples/device/uac2_headset/src/main.c create mode 100644 examples/device/uac2_headset/src/tusb_config.h create mode 100644 examples/device/uac2_headset/src/usb_descriptors.c create mode 100644 examples/device/uac2_headset/src/usb_descriptors.h diff --git a/examples/device/uac2_headset/Makefile b/examples/device/uac2_headset/Makefile new file mode 100644 index 000000000..5a455078e --- /dev/null +++ b/examples/device/uac2_headset/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/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c new file mode 100644 index 000000000..cdb29f3f4 --- /dev/null +++ b/examples/device/uac2_headset/src/main.c @@ -0,0 +1,391 @@ +/* + * 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. + * + */ + +#include +#include + +#include "bsp/board.h" +#include "tusb.h" +#include "usb_descriptors.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTOTYPES +//--------------------------------------------------------------------+ + +/* Blink pattern + * - 25 ms : streaming data + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum +{ + BLINK_STREAMING = 25, + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +enum +{ + VOLUME_CTRL_0_DB = 0, + VOLUME_CTRL_10_DB = 2560, + VOLUME_CTRL_20_DB = 5120, + VOLUME_CTRL_30_DB = 7680, + VOLUME_CTRL_40_DB = 10240, + VOLUME_CTRL_50_DB = 12800, + VOLUME_CTRL_60_DB = 15360, + VOLUME_CTRL_70_DB = 17920, + VOLUME_CTRL_80_DB = 20480, + VOLUME_CTRL_90_DB = 23040, + VOLUME_CTRL_100_DB = 25600, + VOLUME_CTRL_SILENCE = 0x8000, +}; + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +// Audio controls +// Current states +int8_t mute[CFG_TUD_AUDIO_N_CHANNELS_TX + 1]; // +1 for master channel 0 +int16_t volume[CFG_TUD_AUDIO_N_CHANNELS_TX + 1]; // +1 for master channel 0 + +// Buffer for microphone data +int16_t mic_buf[1000]; +// Buffer for speaker data +int16_t spk_buf[1000]; +// Speaker data size received in the last frame +int spk_data_size; + +void led_blinking_task(void); +void audio_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + tusb_init(); + + TU_LOG1("Headset running\r\n"); + + while (1) + { + tud_task(); // TinyUSB device task + audio_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; +} + +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; + }; + + audio_cs_req_t bRequest; + 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) +{ + 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); + + audio_control_cur_4_t curf = { tu_htole32(AUDIO_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 = + { + .wNumSubRanges = tu_htole16(1), + .subrange[0] = { tu_htole32(AUDIO_SAMPLE_RATE), tu_htole32(AUDIO_SAMPLE_RATE), 0} + }; + 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); + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &rangef, sizeof(rangef)); + } + } + else if (request->bControlSelector == AUDIO_CS_CTRL_CLK_VALID && + 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); + 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", + 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) +{ + TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT); + + 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); + 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) + { + if (request->bRequest == AUDIO_CS_REQ_RANGE) + { + audio_control_range_2_n_t(1) range_vol = { + .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, + 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); + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_vol, sizeof(cur_vol)); + } + } + TU_LOG1("Feature unit get request not supported, entity = %u, selector = %u, request = %u\r\n", + request->bEntityID, request->bControlSelector, request->bRequest); + + return false; +} + +// Helper for feature unit set requests +static bool tud_audio_feature_unit_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_FU_CTRL_MUTE) + { + TU_VERIFY(request->wLength == sizeof(audio_control_cur_1_t)); + + mute[request->bChannelNumber] = ((audio_control_cur_1_t *)buf)->bCur; + + TU_LOG2("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]); + + return true; + } + else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) + { + TU_VERIFY(request->wLength == sizeof(audio_control_cur_2_t)); + + 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); + + return true; + } + else + { + TU_LOG1("Feature unit set request not supported, entity = %u, selector = %u, request = %u\r\n", + request->bEntityID, request->bControlSelector, request->bRequest); + return false; + } +} + +//--------------------------------------------------------------------+ +// Application Callback API Implementations +//--------------------------------------------------------------------+ + +// 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) +{ + audio_control_request_t *request = (audio_control_request_t *)p_request; + + if (request->bEntityID == UAC2_ENTITY_CLOCK) + return tud_audio_clock_get_request(rhport, request); + if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) + return tud_audio_feature_unit_get_request(rhport, request); + else + { + TU_LOG1("Get request not handled, entity = %d, selector = %d, request = %d\r\n", + request->bEntityID, request->bControlSelector, request->bRequest); + } + return false; +} + +// 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 *buf) +{ + audio_control_request_t const *request = (audio_control_request_t const *)p_request; + + if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) + return tud_audio_feature_unit_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); + + return false; +} + +bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void)rhport; + + uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex)); + uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue)); + + if (ITF_NUM_AUDIO_STREAMING_SPK == itf && alt == 0) + blink_interval_ms = BLINK_MOUNTED; + + return true; +} + +bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void)rhport; + uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex)); + uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue)); + + TU_LOG2("Set interface %d alt %d\r\n", itf, alt); + if (ITF_NUM_AUDIO_STREAMING_SPK == itf && alt != 0) + blink_interval_ms = BLINK_STREAMING; + + return true; +} + +bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t *buffer, uint16_t buf_size) +{ + (void)rhport; + + spk_data_size = buf_size; + memcpy(spk_buf, buffer, buf_size); + + return true; +} + +bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) +{ + (void)rhport; + (void)itf; + (void)ep_in; + (void)cur_alt_setting; + + // This callback could be used to fill microphone data separately + return true; +} + +//--------------------------------------------------------------------+ +// AUDIO Task +//--------------------------------------------------------------------+ + +void audio_task(void) +{ + // When new data arrived, copy data from speaker buffer, to microphone buffer + // and send it over + if (spk_data_size) + { + int16_t *src = spk_buf; + int16_t *limit = spk_buf + spk_data_size / 2; + int16_t *dst = mic_buf; + while (src < limit) + { + // Combine two channels into one + int32_t left = *src++; + int32_t right = *src++; + *dst++ = (int16_t)((left + right) / 2); + } + tud_audio_write((uint8_t *)mic_buf, spk_data_size / 2); + spk_data_size = 0; + } +} + +//--------------------------------------------------------------------+ +// 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; + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; +} diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h new file mode 100644 index 000000000..d19feeb86 --- /dev/null +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -0,0 +1,134 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ha Thach (tinyusb.org) + * 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. + * + */ + +#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 + +#ifndef CFG_TUSB_DEBUG +// Can be set during compilation i.e.: make LOG= BOARD= +// Keep in mind that enabling logs when data is streaming can disrupt data flow. +// It can be very helpful though when audio unit requests are tested/debugged. +#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 + * 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 +//-------------------------------------------------------------------- + +#ifndef AUDIO_SAMPLE_RATE +#define AUDIO_SAMPLE_RATE 48000 +#endif + +#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 + +// 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_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) +#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) + +// 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) + +// 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/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c new file mode 100644 index 000000000..940f0fe2b --- /dev/null +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -0,0 +1,165 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ha Thach (tinyusb.org) + * 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. + * + */ + +#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] 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 +//--------------------------------------------------------------------+ +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_HEADSET_STEREO_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 +#elif CFG_TUSB_MCU == OPT_MCU_NRF5X +// ISO endpoints for NRF5x are fixed to 0x08 (0x88) +#define EPNUM_AUDIO 0x08 +#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 +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 + 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) +}; + +// 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) + "TinyUSB", // 1: Manufacturer + "TinyUSB headset", // 2: Product + "000001", // 3: Serials, should use chip ID + "TinyUSB Speakers", // 4: Audio Interface + "TinyUSB Microphone", // 5: 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 < chr_count; i++) + { + _desc_str[1 + i] = str[i]; + } + } + + // first byte is length (including header), second byte is string type + _desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2 * chr_count + 2); + + return _desc_str; +} diff --git a/examples/device/uac2_headset/src/usb_descriptors.h b/examples/device/uac2_headset/src/usb_descriptors.h new file mode 100644 index 000000000..6651897b0 --- /dev/null +++ b/examples/device/uac2_headset/src/usb_descriptors.h @@ -0,0 +1,120 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jerzy Kasenbreg + * + * 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_ + +#include "tusb.h" + +// Unit numbers are arbitrary selected +#define UAC2_ENTITY_CLOCK 0x04 +// Speaker path +#define UAC2_ENTITY_SPK_INPUT_TERMINAL 0x01 +#define UAC2_ENTITY_SPK_FEATURE_UNIT 0x02 +#define UAC2_ENTITY_SPK_OUTPUT_TERMINAL 0x03 +// Microphone path +#define UAC2_ENTITY_MIC_INPUT_TERMINAL 0x11 +#define UAC2_ENTITY_MIC_OUTPUT_TERMINAL 0x13 + +enum +{ + ITF_NUM_AUDIO_CONTROL = 0, + ITF_NUM_AUDIO_STREAMING_SPK, + ITF_NUM_AUDIO_STREAMING_MIC, + ITF_NUM_TOTAL +}; + +#define TUD_AUDIO_HEADSET_STEREO_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_FEATURE_UNIT_TWO_CHANNEL_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO_DESC_OUTPUT_TERM_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_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_HEADSET_STEREO_DESCRIPTOR(_stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epoutsize, _epin, _epinsize) \ + /* Standard Interface Association Descriptor (IAD) */\ + TUD_AUDIO_DESC_IAD(/*_firstitfs*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ ITF_NUM_TOTAL, /*_stridx*/ 0x00),\ + /* Standard AC Interface Descriptor(4.7.1) */\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* 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), \ + /* 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) */\ + TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(/*_unitid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_srcid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_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), /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.7.2.5) */\ + TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Input Terminal Descriptor(4.7.2.4) */\ + TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_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*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_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)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x05),\ + /* 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)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x05),\ + /* Class-Specific AS Interface Descriptor(4.9.2) */\ + TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x02, /*_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_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_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_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 */\ + 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),\ + /* 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)\ + +#endif From c87ed8eff1ac1305f69dd83144890f5a6f752a6f Mon Sep 17 00:00:00 2001 From: Jacob Potter Date: Sun, 18 Oct 2020 16:55:14 -0600 Subject: [PATCH 145/167] 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(-) 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 | 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: [PATCH 146/167] net_device: tweak 'pbuf chain' implementation --- src/class/net/net_device.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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) From 01996457c8974de5fcb02dab32210ddb99f0134a Mon Sep 17 00:00:00 2001 From: Jacob Potter Date: Sat, 24 Oct 2020 17:11:32 -0600 Subject: [PATCH 147/167] 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(-) 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 From 229be75a98af03bdbcfabb29b8a3ddd106ba5f30 Mon Sep 17 00:00:00 2001 From: Jacob Potter Date: Sat, 24 Oct 2020 17:16:05 -0600 Subject: [PATCH 148/167] Move into if statement --- src/portable/st/synopsys/dcd_synopsys.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) 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 | 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: [PATCH 149/167] 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(-) 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 From e4eb2de4018572ecdab8e0e738447e5929021519 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 30 Oct 2020 12:15:04 +0700 Subject: [PATCH 150/167] f4 use offical st driver repo --- .gitmodules | 6 ++++++ hw/bsp/feather_stm32f405/board.mk | 17 +++++++++-------- hw/bsp/pyboardv11/board.mk | 15 ++++++++------- hw/bsp/stm32f401blackpill/board.mk | 15 ++++++++------- hw/bsp/stm32f407disco/board.mk | 17 +++++++++-------- hw/bsp/stm32f411blackpill/board.mk | 15 ++++++++------- hw/bsp/stm32f411disco/board.mk | 17 +++++++++-------- hw/bsp/stm32f412disco/board.mk | 19 ++++++++++--------- hw/mcu/st/cmsis_device_f4 | 1 + hw/mcu/st/stm32f4xx_hal_driver | 1 + 10 files changed, 69 insertions(+), 54 deletions(-) create mode 160000 hw/mcu/st/cmsis_device_f4 create mode 160000 hw/mcu/st/stm32f4xx_hal_driver diff --git a/.gitmodules b/.gitmodules index c8f8eea97..f15d00f8b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,3 +31,9 @@ [submodule "lib/CMSIS_4"] path = lib/CMSIS_4 url = https://github.com/ARM-software/CMSIS.git +[submodule "hw/mcu/st/cmsis_device_f4"] + path = hw/mcu/st/cmsis_device_f4 + url = https://github.com/STMicroelectronics/cmsis_device_f4.git +[submodule "hw/mcu/st/stm32f4xx_hal_driver"] + path = hw/mcu/st/stm32f4xx_hal_driver + url = https://github.com/STMicroelectronics/stm32f4xx_hal_driver.git diff --git a/hw/bsp/feather_stm32f405/board.mk b/hw/bsp/feather_stm32f405/board.mk index 1988fa46e..fdba8cd0d 100644 --- a/hw/bsp/feather_stm32f405/board.mk +++ b/hw/bsp/feather_stm32f405/board.mk @@ -12,19 +12,20 @@ CFLAGS += \ # 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 +ST_FAMILY = f4 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F405RGTx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f4xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_uart.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f405xx.s diff --git a/hw/bsp/pyboardv11/board.mk b/hw/bsp/pyboardv11/board.mk index 3be06e844..aa185ae3c 100644 --- a/hw/bsp/pyboardv11/board.mk +++ b/hw/bsp/pyboardv11/board.mk @@ -9,18 +9,19 @@ CFLAGS += \ -DSTM32F405xx \ -DCFG_TUSB_MCU=OPT_MCU_STM32F4 -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F4xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F4xx +ST_FAMILY = f4 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F405RGTx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f4xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_gpio.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f405xx.s diff --git a/hw/bsp/stm32f401blackpill/board.mk b/hw/bsp/stm32f401blackpill/board.mk index 993e29c5f..3d52a79ed 100644 --- a/hw/bsp/stm32f401blackpill/board.mk +++ b/hw/bsp/stm32f401blackpill/board.mk @@ -9,18 +9,19 @@ CFLAGS += \ -DSTM32F401xC \ -DCFG_TUSB_MCU=OPT_MCU_STM32F4 -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F4xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F4xx +ST_FAMILY = f4 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F401VCTx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f4xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_gpio.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f401xc.s diff --git a/hw/bsp/stm32f407disco/board.mk b/hw/bsp/stm32f407disco/board.mk index 87b7bea10..542588fc2 100644 --- a/hw/bsp/stm32f407disco/board.mk +++ b/hw/bsp/stm32f407disco/board.mk @@ -12,19 +12,20 @@ CFLAGS += \ # 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 +ST_FAMILY = f4 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F407VGTx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f4xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_uart.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_gpio.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f407xx.s diff --git a/hw/bsp/stm32f411blackpill/board.mk b/hw/bsp/stm32f411blackpill/board.mk index 3441dbb52..5b7a70017 100644 --- a/hw/bsp/stm32f411blackpill/board.mk +++ b/hw/bsp/stm32f411blackpill/board.mk @@ -9,18 +9,19 @@ CFLAGS += \ -DSTM32F411xE \ -DCFG_TUSB_MCU=OPT_MCU_STM32F4 -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F4xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F4xx +ST_FAMILY = f4 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F411CEUx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f4xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_gpio.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f411xe.s diff --git a/hw/bsp/stm32f411disco/board.mk b/hw/bsp/stm32f411disco/board.mk index f15d802ab..cea8d2cdb 100644 --- a/hw/bsp/stm32f411disco/board.mk +++ b/hw/bsp/stm32f411disco/board.mk @@ -12,19 +12,20 @@ CFLAGS += \ # 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 +ST_FAMILY = f4 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F411VETx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f4xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_uart.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_gpio.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f411xe.s diff --git a/hw/bsp/stm32f412disco/board.mk b/hw/bsp/stm32f412disco/board.mk index 0cc32da20..d991c4b75 100644 --- a/hw/bsp/stm32f412disco/board.mk +++ b/hw/bsp/stm32f412disco/board.mk @@ -12,20 +12,21 @@ CFLAGS += \ # 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 +ST_FAMILY = f4 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F412ZGTx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f4xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_uart.c \ - $(ST_HAL_DRIVER)/Src/stm32f4xx_hal_gpio.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f412zx.s diff --git a/hw/mcu/st/cmsis_device_f4 b/hw/mcu/st/cmsis_device_f4 new file mode 160000 index 000000000..2615e866f --- /dev/null +++ b/hw/mcu/st/cmsis_device_f4 @@ -0,0 +1 @@ +Subproject commit 2615e866fa48fe1ff1af9e31c348813f2b19e7ec diff --git a/hw/mcu/st/stm32f4xx_hal_driver b/hw/mcu/st/stm32f4xx_hal_driver new file mode 160000 index 000000000..04e99fbda --- /dev/null +++ b/hw/mcu/st/stm32f4xx_hal_driver @@ -0,0 +1 @@ +Subproject commit 04e99fbdabd00ab8f370f377c66b0a4570365b58 From 41a36b125661a57551124f3908fea8e682dfbc4c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 30 Oct 2020 12:48:34 +0700 Subject: [PATCH 151/167] f0 use offical st driver repo --- .gitmodules | 6 ++++++ hw/bsp/stm32f070rbnucleo/board.mk | 20 +++++++++++--------- hw/bsp/stm32f072disco/board.mk | 19 ++++++++++--------- hw/mcu/st/cmsis_device_f0 | 1 + hw/mcu/st/stm32f0xx_hal_driver | 1 + 5 files changed, 29 insertions(+), 18 deletions(-) create mode 160000 hw/mcu/st/cmsis_device_f0 create mode 160000 hw/mcu/st/stm32f0xx_hal_driver diff --git a/.gitmodules b/.gitmodules index f15d00f8b..b2b706160 100644 --- a/.gitmodules +++ b/.gitmodules @@ -37,3 +37,9 @@ [submodule "hw/mcu/st/stm32f4xx_hal_driver"] path = hw/mcu/st/stm32f4xx_hal_driver url = https://github.com/STMicroelectronics/stm32f4xx_hal_driver.git +[submodule "hw/mcu/st/cmsis_device_f0"] + path = hw/mcu/st/cmsis_device_f0 + url = https://github.com/STMicroelectronics/cmsis_device_f0.git +[submodule "hw/mcu/st/stm32f0xx_hal_driver"] + path = hw/mcu/st/stm32f0xx_hal_driver + url = https://github.com/STMicroelectronics/stm32f0xx_hal_driver.git diff --git a/hw/bsp/stm32f070rbnucleo/board.mk b/hw/bsp/stm32f070rbnucleo/board.mk index eec479bb4..70aeccc0b 100644 --- a/hw/bsp/stm32f070rbnucleo/board.mk +++ b/hw/bsp/stm32f070rbnucleo/board.mk @@ -12,20 +12,22 @@ CFLAGS += \ # 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 +ST_FAMILY = f0 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/stm32F070rbtx_flash.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f0xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f0xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_uart.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c + SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f070xb.s diff --git a/hw/bsp/stm32f072disco/board.mk b/hw/bsp/stm32f072disco/board.mk index 4155acf84..4b73b570b 100644 --- a/hw/bsp/stm32f072disco/board.mk +++ b/hw/bsp/stm32f072disco/board.mk @@ -12,20 +12,21 @@ CFLAGS += \ # 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 +ST_FAMILY = f0 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F072RBTx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f0xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f0xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32f0xx_hal_uart.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f072xb.s diff --git a/hw/mcu/st/cmsis_device_f0 b/hw/mcu/st/cmsis_device_f0 new file mode 160000 index 000000000..2fc25ee22 --- /dev/null +++ b/hw/mcu/st/cmsis_device_f0 @@ -0,0 +1 @@ +Subproject commit 2fc25ee22264bc27034358be0bd400b893ef837e diff --git a/hw/mcu/st/stm32f0xx_hal_driver b/hw/mcu/st/stm32f0xx_hal_driver new file mode 160000 index 000000000..0e95cd886 --- /dev/null +++ b/hw/mcu/st/stm32f0xx_hal_driver @@ -0,0 +1 @@ +Subproject commit 0e95cd88657030f640a11e690a8a5186c7712ea5 From 092f7baec02f8008d4d1f579c5094e7096db2183 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 30 Oct 2020 12:49:43 +0700 Subject: [PATCH 152/167] random clean up --- hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c | 1 + hw/bsp/teensy_40/teensy40.c | 1 + 2 files changed, 2 insertions(+) diff --git a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c index 1042bcfe7..6fb00b9b7 100644 --- a/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c +++ b/hw/bsp/mimxrt1060_evk/mimxrt1060_evk.c @@ -49,6 +49,7 @@ #define UART_RX_PINMUX IOMUXC_GPIO_AD_B0_13_LPUART1_RX #define UART_TX_PINMUX IOMUXC_GPIO_AD_B0_12_LPUART1_TX +// needed by fsl_flexspi_nor_boot const uint8_t dcd_data[] = { 0x00 }; void board_init(void) diff --git a/hw/bsp/teensy_40/teensy40.c b/hw/bsp/teensy_40/teensy40.c index 30fdedd27..85501df11 100644 --- a/hw/bsp/teensy_40/teensy40.c +++ b/hw/bsp/teensy_40/teensy40.c @@ -49,6 +49,7 @@ #define UART_RX_PINMUX IOMUXC_GPIO_AD_B0_03_LPUART6_RX // D0 #define UART_TX_PINMUX IOMUXC_GPIO_AD_B0_02_LPUART6_TX // D1 +// needed by fsl_flexspi_nor_boot const uint8_t dcd_data[] = { 0x00 }; void board_init(void) From 8850ea90b4b94611901602e99a7bd0952327db8d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 30 Oct 2020 12:55:54 +0700 Subject: [PATCH 153/167] f1 use offical st driver repo --- .gitmodules | 6 ++++++ hw/bsp/stm32f103bluepill/board.mk | 17 +++++++++-------- hw/mcu/st/cmsis_device_f1 | 1 + hw/mcu/st/stm32f1xx_hal_driver | 1 + 4 files changed, 17 insertions(+), 8 deletions(-) create mode 160000 hw/mcu/st/cmsis_device_f1 create mode 160000 hw/mcu/st/stm32f1xx_hal_driver diff --git a/.gitmodules b/.gitmodules index b2b706160..89dbed9fe 100644 --- a/.gitmodules +++ b/.gitmodules @@ -43,3 +43,9 @@ [submodule "hw/mcu/st/stm32f0xx_hal_driver"] path = hw/mcu/st/stm32f0xx_hal_driver url = https://github.com/STMicroelectronics/stm32f0xx_hal_driver.git +[submodule "hw/mcu/st/cmsis_device_f1"] + path = hw/mcu/st/cmsis_device_f1 + url = https://github.com/STMicroelectronics/cmsis_device_f1.git +[submodule "hw/mcu/st/stm32f1xx_hal_driver"] + path = hw/mcu/st/stm32f1xx_hal_driver + url = https://github.com/STMicroelectronics/stm32f1xx_hal_driver.git diff --git a/hw/bsp/stm32f103bluepill/board.mk b/hw/bsp/stm32f103bluepill/board.mk index 124b16021..8ab973776 100644 --- a/hw/bsp/stm32f103bluepill/board.mk +++ b/hw/bsp/stm32f103bluepill/board.mk @@ -11,19 +11,20 @@ CFLAGS += \ # mcu driver cause following warnings #CFLAGS += -Wno-error=unused-parameter -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F1xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F1xx +ST_FAMILY = f1 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F103XB_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f1xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f1xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f1xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f1xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f1xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32f1xx_hal_gpio.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f103xb.s diff --git a/hw/mcu/st/cmsis_device_f1 b/hw/mcu/st/cmsis_device_f1 new file mode 160000 index 000000000..6601104a6 --- /dev/null +++ b/hw/mcu/st/cmsis_device_f1 @@ -0,0 +1 @@ +Subproject commit 6601104a6397299b7304fd5bcd9a491f56cb23a6 diff --git a/hw/mcu/st/stm32f1xx_hal_driver b/hw/mcu/st/stm32f1xx_hal_driver new file mode 160000 index 000000000..1dd9d3662 --- /dev/null +++ b/hw/mcu/st/stm32f1xx_hal_driver @@ -0,0 +1 @@ +Subproject commit 1dd9d3662fb7eb2a7f7d3bc0a4c1dc7537915a29 From bbcf2d7e01cbd13b9065f622a898a0e5b4c01b08 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 30 Oct 2020 13:01:01 +0700 Subject: [PATCH 154/167] f2 use offical st driver repo --- .gitmodules | 6 ++++++ hw/bsp/stm32f207nucleo/board.mk | 18 ++++++++++-------- hw/mcu/st/cmsis_device_f2 | 1 + hw/mcu/st/stm32f2xx_hal_driver | 1 + 4 files changed, 18 insertions(+), 8 deletions(-) create mode 160000 hw/mcu/st/cmsis_device_f2 create mode 160000 hw/mcu/st/stm32f2xx_hal_driver diff --git a/.gitmodules b/.gitmodules index 89dbed9fe..ee7372aef 100644 --- a/.gitmodules +++ b/.gitmodules @@ -49,3 +49,9 @@ [submodule "hw/mcu/st/stm32f1xx_hal_driver"] path = hw/mcu/st/stm32f1xx_hal_driver url = https://github.com/STMicroelectronics/stm32f1xx_hal_driver.git +[submodule "hw/mcu/st/cmsis_device_f2"] + path = hw/mcu/st/cmsis_device_f2 + url = https://github.com/STMicroelectronics/cmsis_device_f2.git +[submodule "hw/mcu/st/stm32f2xx_hal_driver"] + path = hw/mcu/st/stm32f2xx_hal_driver + url = https://github.com/STMicroelectronics/stm32f2xx_hal_driver.git diff --git a/hw/bsp/stm32f207nucleo/board.mk b/hw/bsp/stm32f207nucleo/board.mk index 27d8638d3..cad816d9f 100644 --- a/hw/bsp/stm32f207nucleo/board.mk +++ b/hw/bsp/stm32f207nucleo/board.mk @@ -11,19 +11,21 @@ CFLAGS += \ # mcu driver cause following warnings CFLAGS += -Wno-error=sign-compare -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F2xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F2xx +ST_FAMILY = f2 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver + # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F207ZGTx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f2xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f2xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f2xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f2xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f2xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32f2xx_hal_gpio.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f207xx.s diff --git a/hw/mcu/st/cmsis_device_f2 b/hw/mcu/st/cmsis_device_f2 new file mode 160000 index 000000000..182fcb368 --- /dev/null +++ b/hw/mcu/st/cmsis_device_f2 @@ -0,0 +1 @@ +Subproject commit 182fcb3681ce116816feb41b7764f1b019ce796f diff --git a/hw/mcu/st/stm32f2xx_hal_driver b/hw/mcu/st/stm32f2xx_hal_driver new file mode 160000 index 000000000..c75ace9b9 --- /dev/null +++ b/hw/mcu/st/stm32f2xx_hal_driver @@ -0,0 +1 @@ +Subproject commit c75ace9b908a9aca631193ebf2466963b8ea33d0 From 1e02f6e066744203bbd549f2d0e82bf98331804e Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 30 Oct 2020 13:11:23 +0700 Subject: [PATCH 155/167] f3 use offical st driver repo --- .gitmodules | 6 ++++++ hw/bsp/stm32f303disco/board.mk | 17 +++++++++-------- hw/mcu/st/cmsis_device_f3 | 1 + hw/mcu/st/stm32f3xx_hal_driver | 1 + 4 files changed, 17 insertions(+), 8 deletions(-) create mode 160000 hw/mcu/st/cmsis_device_f3 create mode 160000 hw/mcu/st/stm32f3xx_hal_driver diff --git a/.gitmodules b/.gitmodules index ee7372aef..3a3f50fcc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -55,3 +55,9 @@ [submodule "hw/mcu/st/stm32f2xx_hal_driver"] path = hw/mcu/st/stm32f2xx_hal_driver url = https://github.com/STMicroelectronics/stm32f2xx_hal_driver.git +[submodule "hw/mcu/st/cmsis_device_f3"] + path = hw/mcu/st/cmsis_device_f3 + url = https://github.com/STMicroelectronics/cmsis_device_f3.git +[submodule "hw/mcu/st/stm32f3xx_hal_driver"] + path = hw/mcu/st/stm32f3xx_hal_driver + url = https://github.com/STMicroelectronics/stm32f3xx_hal_driver.git diff --git a/hw/bsp/stm32f303disco/board.mk b/hw/bsp/stm32f303disco/board.mk index cb94dac3b..3459c28af 100644 --- a/hw/bsp/stm32f303disco/board.mk +++ b/hw/bsp/stm32f303disco/board.mk @@ -12,19 +12,20 @@ CFLAGS += \ # mcu driver cause following warnings CFLAGS += -Wno-error=unused-parameter -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F3xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F3xx +ST_FAMILY = f3 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F303VCTx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f3xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f3xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f3xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f3xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f3xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32f3xx_hal_gpio.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f303xc.s diff --git a/hw/mcu/st/cmsis_device_f3 b/hw/mcu/st/cmsis_device_f3 new file mode 160000 index 000000000..5e4ee5ed7 --- /dev/null +++ b/hw/mcu/st/cmsis_device_f3 @@ -0,0 +1 @@ +Subproject commit 5e4ee5ed7a7b6c85176bb70a9fd3c72d6eb99f1b diff --git a/hw/mcu/st/stm32f3xx_hal_driver b/hw/mcu/st/stm32f3xx_hal_driver new file mode 160000 index 000000000..1761b6207 --- /dev/null +++ b/hw/mcu/st/stm32f3xx_hal_driver @@ -0,0 +1 @@ +Subproject commit 1761b6207318ede021706e75aae78f452d72b6fa From b9ca7e91dff4861a4ca2c65f462b6b1cbf9e06cc Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 30 Oct 2020 13:18:56 +0700 Subject: [PATCH 156/167] f7 use offical st driver repo --- .gitmodules | 6 ++++++ hw/bsp/stlinkv3mini/board.mk | 21 +++++++++++---------- hw/bsp/stm32f723disco/board.mk | 21 +++++++++++---------- hw/bsp/stm32f746disco/board.mk | 21 +++++++++++---------- hw/bsp/stm32f746nucleo/board.mk | 21 +++++++++++---------- hw/bsp/stm32f767nucleo/board.mk | 21 +++++++++++---------- hw/bsp/stm32f769disco/board.mk | 21 +++++++++++---------- hw/mcu/st/cmsis_device_f7 | 1 + hw/mcu/st/stm32f7xx_hal_driver | 1 + 9 files changed, 74 insertions(+), 60 deletions(-) create mode 160000 hw/mcu/st/cmsis_device_f7 create mode 160000 hw/mcu/st/stm32f7xx_hal_driver diff --git a/.gitmodules b/.gitmodules index 3a3f50fcc..abf1439a9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -61,3 +61,9 @@ [submodule "hw/mcu/st/stm32f3xx_hal_driver"] path = hw/mcu/st/stm32f3xx_hal_driver url = https://github.com/STMicroelectronics/stm32f3xx_hal_driver.git +[submodule "hw/mcu/st/cmsis_device_f7"] + path = hw/mcu/st/cmsis_device_f7 + url = https://github.com/STMicroelectronics/cmsis_device_f7.git +[submodule "hw/mcu/st/stm32f7xx_hal_driver"] + path = hw/mcu/st/stm32f7xx_hal_driver + url = https://github.com/STMicroelectronics/stm32f7xx_hal_driver.git diff --git a/hw/bsp/stlinkv3mini/board.mk b/hw/bsp/stlinkv3mini/board.mk index 4ca6cfd68..5157fbf14 100644 --- a/hw/bsp/stlinkv3mini/board.mk +++ b/hw/bsp/stlinkv3mini/board.mk @@ -26,21 +26,22 @@ endif # mcu driver cause following warnings CFLAGS += -Wno-error=shadow -Wno-error=cast-align -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F7xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F7xx +ST_FAMILY = f7 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F723xE_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f7xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_uart.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_pwr_ex.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f723xx.s diff --git a/hw/bsp/stm32f723disco/board.mk b/hw/bsp/stm32f723disco/board.mk index 9ec23bfde..50c25810f 100644 --- a/hw/bsp/stm32f723disco/board.mk +++ b/hw/bsp/stm32f723disco/board.mk @@ -29,21 +29,22 @@ endif # mcu driver cause following warnings CFLAGS += -Wno-error=shadow -Wno-error=cast-align -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F7xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F7xx +ST_FAMILY = f7 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F723xE_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f7xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_uart.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_pwr_ex.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f723xx.s diff --git a/hw/bsp/stm32f746disco/board.mk b/hw/bsp/stm32f746disco/board.mk index 48cb3f141..95feac1f6 100644 --- a/hw/bsp/stm32f746disco/board.mk +++ b/hw/bsp/stm32f746disco/board.mk @@ -29,21 +29,22 @@ endif # mcu driver cause following warnings CFLAGS += -Wno-error=shadow -Wno-error=cast-align -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32F7xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32F7xx +ST_FAMILY = f7 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F746ZGTx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f7xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_uart.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_pwr_ex.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f746xx.s diff --git a/hw/bsp/stm32f746nucleo/board.mk b/hw/bsp/stm32f746nucleo/board.mk index 95445486a..140e2d639 100644 --- a/hw/bsp/stm32f746nucleo/board.mk +++ b/hw/bsp/stm32f746nucleo/board.mk @@ -12,21 +12,22 @@ CFLAGS += \ # 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 +ST_FAMILY = f7 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F746ZGTx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f7xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_uart.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_pwr_ex.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f746xx.s diff --git a/hw/bsp/stm32f767nucleo/board.mk b/hw/bsp/stm32f767nucleo/board.mk index fc638ddcb..c6be2bcbf 100644 --- a/hw/bsp/stm32f767nucleo/board.mk +++ b/hw/bsp/stm32f767nucleo/board.mk @@ -12,21 +12,22 @@ CFLAGS += \ # 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 +ST_FAMILY = f7 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F767ZITx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f7xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_uart.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_pwr_ex.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f767xx.s diff --git a/hw/bsp/stm32f769disco/board.mk b/hw/bsp/stm32f769disco/board.mk index 962dddc68..ced2240c0 100644 --- a/hw/bsp/stm32f769disco/board.mk +++ b/hw/bsp/stm32f769disco/board.mk @@ -26,21 +26,22 @@ endif # 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 +ST_FAMILY = f7 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32F769ZITx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32f7xx.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_uart.c \ - $(ST_HAL_DRIVER)/Src/stm32f7xx_hal_pwr_ex.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f769xx.s diff --git a/hw/mcu/st/cmsis_device_f7 b/hw/mcu/st/cmsis_device_f7 new file mode 160000 index 000000000..fc676ef1a --- /dev/null +++ b/hw/mcu/st/cmsis_device_f7 @@ -0,0 +1 @@ +Subproject commit fc676ef1ad177eb874eaa06444d3d75395fc51f4 diff --git a/hw/mcu/st/stm32f7xx_hal_driver b/hw/mcu/st/stm32f7xx_hal_driver new file mode 160000 index 000000000..f7ffdf6bf --- /dev/null +++ b/hw/mcu/st/stm32f7xx_hal_driver @@ -0,0 +1 @@ +Subproject commit f7ffdf6bf72110e58b42c632b0a051df5997e4ee From 3659d8e89a8918f27d339cbc3688301b5ed2b2d8 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 30 Oct 2020 13:28:14 +0700 Subject: [PATCH 157/167] h7 use offical st driver repo --- .gitmodules | 6 ++++++ hw/bsp/stm32h743eval/board.mk | 21 +++++++++++---------- hw/bsp/stm32h743nucleo/board.mk | 21 +++++++++++---------- hw/bsp/stm32h745disco/board.mk | 21 +++++++++++---------- hw/mcu/st/cmsis_device_h7 | 1 + hw/mcu/st/stm32h7xx_hal_driver | 1 + 6 files changed, 41 insertions(+), 30 deletions(-) create mode 160000 hw/mcu/st/cmsis_device_h7 create mode 160000 hw/mcu/st/stm32h7xx_hal_driver diff --git a/.gitmodules b/.gitmodules index abf1439a9..6a75df141 100644 --- a/.gitmodules +++ b/.gitmodules @@ -67,3 +67,9 @@ [submodule "hw/mcu/st/stm32f7xx_hal_driver"] path = hw/mcu/st/stm32f7xx_hal_driver url = https://github.com/STMicroelectronics/stm32f7xx_hal_driver.git +[submodule "hw/mcu/st/cmsis_device_h7"] + path = hw/mcu/st/cmsis_device_h7 + url = https://github.com/STMicroelectronics/cmsis_device_h7.git +[submodule "hw/mcu/st/stm32h7xx_hal_driver"] + path = hw/mcu/st/stm32h7xx_hal_driver + url = https://github.com/STMicroelectronics/stm32h7xx_hal_driver.git diff --git a/hw/bsp/stm32h743eval/board.mk b/hw/bsp/stm32h743eval/board.mk index 543b40a30..87de060c5 100644 --- a/hw/bsp/stm32h743eval/board.mk +++ b/hw/bsp/stm32h743eval/board.mk @@ -23,21 +23,22 @@ endif # suppress warning caused by vendor mcu driver CFLAGS += -Wno-error=maybe-uninitialized -Wno-error=cast-align -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32H7xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32H7xx +ST_FAMILY = h7 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32H743XIHx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32h7xx.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_uart.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_pwr_ex.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32h743xx.s diff --git a/hw/bsp/stm32h743nucleo/board.mk b/hw/bsp/stm32h743nucleo/board.mk index 43a4999a4..eade0f09a 100644 --- a/hw/bsp/stm32h743nucleo/board.mk +++ b/hw/bsp/stm32h743nucleo/board.mk @@ -12,21 +12,22 @@ CFLAGS += \ # suppress warning caused by vendor mcu driver CFLAGS += -Wno-error=maybe-uninitialized -Wno-error=cast-align -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32H7xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32H7xx +ST_FAMILY = h7 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32H743ZITx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32h7xx.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_uart.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_pwr_ex.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32h743xx.s diff --git a/hw/bsp/stm32h745disco/board.mk b/hw/bsp/stm32h745disco/board.mk index eb87e7461..8489748c7 100644 --- a/hw/bsp/stm32h745disco/board.mk +++ b/hw/bsp/stm32h745disco/board.mk @@ -18,21 +18,22 @@ CFLAGS += \ # suppress warning caused by vendor mcu driver CFLAGS += -Wno-error=maybe-uninitialized -Wno-error=cast-align -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32H7xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32H7xx +ST_FAMILY = h7 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32H74xXIHx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32h7xx.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_uart.c \ - $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_pwr_ex.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32h745xx.s diff --git a/hw/mcu/st/cmsis_device_h7 b/hw/mcu/st/cmsis_device_h7 new file mode 160000 index 000000000..60dc2c913 --- /dev/null +++ b/hw/mcu/st/cmsis_device_h7 @@ -0,0 +1 @@ +Subproject commit 60dc2c913203dc8629dc233d4384dcc41c91e77f diff --git a/hw/mcu/st/stm32h7xx_hal_driver b/hw/mcu/st/stm32h7xx_hal_driver new file mode 160000 index 000000000..d8461b980 --- /dev/null +++ b/hw/mcu/st/stm32h7xx_hal_driver @@ -0,0 +1 @@ +Subproject commit d8461b980b59b1625207d8c4f2ce0a9c2a7a3b04 From ac231d7b2d45618c813cfd76988170c0dfa164d8 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 30 Oct 2020 13:40:20 +0700 Subject: [PATCH 158/167] l0 use offical st driver repo --- .gitmodules | 6 ++++++ hw/bsp/stm32l0538disco/board.mk | 17 +++++++++-------- hw/bsp/stm32l0538disco/stm32l0538disco.c | 4 ++-- hw/mcu/st/cmsis_device_l0 | 1 + hw/mcu/st/stm32l0xx_hal_driver | 1 + 5 files changed, 19 insertions(+), 10 deletions(-) create mode 160000 hw/mcu/st/cmsis_device_l0 create mode 160000 hw/mcu/st/stm32l0xx_hal_driver diff --git a/.gitmodules b/.gitmodules index 6a75df141..3255977a2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -73,3 +73,9 @@ [submodule "hw/mcu/st/stm32h7xx_hal_driver"] path = hw/mcu/st/stm32h7xx_hal_driver url = https://github.com/STMicroelectronics/stm32h7xx_hal_driver.git +[submodule "hw/mcu/st/cmsis_device_l0"] + path = hw/mcu/st/cmsis_device_l0 + url = https://github.com/STMicroelectronics/cmsis_device_l0.git +[submodule "hw/mcu/st/stm32l0xx_hal_driver"] + path = hw/mcu/st/stm32l0xx_hal_driver + url = https://github.com/STMicroelectronics/stm32l0xx_hal_driver.git diff --git a/hw/bsp/stm32l0538disco/board.mk b/hw/bsp/stm32l0538disco/board.mk index bcfaee7ac..49818e3a3 100644 --- a/hw/bsp/stm32l0538disco/board.mk +++ b/hw/bsp/stm32l0538disco/board.mk @@ -12,19 +12,20 @@ CFLAGS += \ # mcu driver cause following warnings CFLAGS += -Wno-error=unused-parameter -Wno-error=maybe-uninitialized -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32L0xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32L0xx +ST_FAMILY = l0 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32L053C8Tx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32l0xx.c \ - $(ST_HAL_DRIVER)/Src/stm32l0xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32l0xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32l0xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32l0xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32l0xx_hal_gpio.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l053xx.s diff --git a/hw/bsp/stm32l0538disco/stm32l0538disco.c b/hw/bsp/stm32l0538disco/stm32l0538disco.c index ab04e5c51..f0f1d028b 100644 --- a/hw/bsp/stm32l0538disco/stm32l0538disco.c +++ b/hw/bsp/stm32l0538disco/stm32l0538disco.c @@ -127,7 +127,7 @@ void board_init(void) GPIO_InitStruct.Pin = LED_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; - GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); board_led_write(false); @@ -137,7 +137,7 @@ void board_init(void) GPIO_InitStruct.Pin = BUTTON_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLDOWN; - GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); // USB diff --git a/hw/mcu/st/cmsis_device_l0 b/hw/mcu/st/cmsis_device_l0 new file mode 160000 index 000000000..06748ca1f --- /dev/null +++ b/hw/mcu/st/cmsis_device_l0 @@ -0,0 +1 @@ +Subproject commit 06748ca1f93827befdb8b794402320d94d02004f diff --git a/hw/mcu/st/stm32l0xx_hal_driver b/hw/mcu/st/stm32l0xx_hal_driver new file mode 160000 index 000000000..fbdacaf6f --- /dev/null +++ b/hw/mcu/st/stm32l0xx_hal_driver @@ -0,0 +1 @@ +Subproject commit fbdacaf6f8c82a4e1eb9bd74ba650b491e97e17b From 3b890d2391de126a234aa08db05c7091f09fcbf6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 30 Oct 2020 14:01:05 +0700 Subject: [PATCH 159/167] l4 use offical st driver repo --- .gitmodules | 12 ++++++ hw/bsp/stm32l476disco/board.mk | 25 ++++++----- hw/bsp/stm32l476disco/stm32l4xx_hal_conf.h | 46 +++++++++++++++++++-- hw/bsp/stm32l4r5nucleo/board.mk | 24 ++++++----- hw/bsp/stm32l4r5nucleo/stm32l4xx_hal_conf.h | 43 +++++++++++++++++-- hw/mcu/st/cmsis_device_l1 | 1 + hw/mcu/st/cmsis_device_l4 | 1 + hw/mcu/st/stm32l1xx_hal_driver | 1 + hw/mcu/st/stm32l4xx_hal_driver | 1 + 9 files changed, 127 insertions(+), 27 deletions(-) create mode 160000 hw/mcu/st/cmsis_device_l1 create mode 160000 hw/mcu/st/cmsis_device_l4 create mode 160000 hw/mcu/st/stm32l1xx_hal_driver create mode 160000 hw/mcu/st/stm32l4xx_hal_driver diff --git a/.gitmodules b/.gitmodules index 3255977a2..939459286 100644 --- a/.gitmodules +++ b/.gitmodules @@ -79,3 +79,15 @@ [submodule "hw/mcu/st/stm32l0xx_hal_driver"] path = hw/mcu/st/stm32l0xx_hal_driver url = https://github.com/STMicroelectronics/stm32l0xx_hal_driver.git +[submodule "hw/mcu/st/cmsis_device_l1"] + path = hw/mcu/st/cmsis_device_l1 + url = https://github.com/STMicroelectronics/cmsis_device_l1.git +[submodule "hw/mcu/st/stm32l1xx_hal_driver"] + path = hw/mcu/st/stm32l1xx_hal_driver + url = https://github.com/STMicroelectronics/stm32l1xx_hal_driver.git +[submodule "hw/mcu/st/cmsis_device_l4"] + path = hw/mcu/st/cmsis_device_l4 + url = https://github.com/STMicroelectronics/cmsis_device_l4.git +[submodule "hw/mcu/st/stm32l4xx_hal_driver"] + path = hw/mcu/st/stm32l4xx_hal_driver + url = https://github.com/STMicroelectronics/stm32l4xx_hal_driver.git diff --git a/hw/bsp/stm32l476disco/board.mk b/hw/bsp/stm32l476disco/board.mk index e2fc010dc..e79feda07 100644 --- a/hw/bsp/stm32l476disco/board.mk +++ b/hw/bsp/stm32l476disco/board.mk @@ -9,21 +9,26 @@ CFLAGS += \ -DSTM32L476xx \ -DCFG_TUSB_MCU=OPT_MCU_STM32L4 -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32L4xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32L4xx +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=maybe-uninitialized -Wno-error=cast-align + +ST_FAMILY = l4 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32L476VGTx_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32l4xx.c \ - $(ST_HAL_DRIVER)/Src/stm32l4xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_pwr.c \ - $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_pwr_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_gpio.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l476xx.s diff --git a/hw/bsp/stm32l476disco/stm32l4xx_hal_conf.h b/hw/bsp/stm32l476disco/stm32l4xx_hal_conf.h index dce4008d0..312f86da1 100644 --- a/hw/bsp/stm32l476disco/stm32l4xx_hal_conf.h +++ b/hw/bsp/stm32l476disco/stm32l4xx_hal_conf.h @@ -48,8 +48,8 @@ /* #define HAL_FIREWALL_MODULE_ENABLED */ #define HAL_FLASH_MODULE_ENABLED /* #define HAL_NAND_MODULE_ENABLED */ -#define HAL_NOR_MODULE_ENABLED -#define HAL_SRAM_MODULE_ENABLED +// #define HAL_NOR_MODULE_ENABLED +// #define HAL_SRAM_MODULE_ENABLED /* #define HAL_HCD_MODULE_ENABLED */ #define HAL_GPIO_MODULE_ENABLED //#define HAL_I2C_MODULE_ENABLED @@ -72,7 +72,7 @@ /* #define HAL_SWPMI_MODULE_ENABLED */ /* #define HAL_TIM_MODULE_ENABLED */ /* #define HAL_TSC_MODULE_ENABLED */ -//#define HAL_UART_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED /* #define HAL_USART_MODULE_ENABLED */ /* #define HAL_WWDG_MODULE_ENABLED */ @@ -172,6 +172,46 @@ #define INSTRUCTION_CACHE_ENABLE 1U #define DATA_CACHE_ENABLE 1U + +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ +#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U /* HRTIM register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_JPEG_REGISTER_CALLBACKS 0U /* JPEG register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ +#define USE_HAL_MDIOS_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ +#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_SWPMI_REGISTER_CALLBACKS 0U /* SWPMI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + /* ########################## Assert Selection ############################## */ /** * @brief Uncomment the line below to expanse the "assert_param" macro in the diff --git a/hw/bsp/stm32l4r5nucleo/board.mk b/hw/bsp/stm32l4r5nucleo/board.mk index 8ccefb7f8..57df89201 100644 --- a/hw/bsp/stm32l4r5nucleo/board.mk +++ b/hw/bsp/stm32l4r5nucleo/board.mk @@ -11,23 +11,25 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_STM32L4 # suppress warning caused by vendor mcu driver -CFLAGS += -Wno-error=maybe-uninitialized -Wno-error=cast-align +CFLAGS += -Wno-error=maybe-uninitialized -Wno-error=cast-align -ST_HAL_DRIVER = hw/mcu/st/st_driver/STM32L4xx_HAL_Driver -ST_CMSIS = hw/mcu/st/st_driver/CMSIS/Device/ST/STM32L4xx +ST_FAMILY = l4 +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/STM32L4RXxI_FLASH.ld SRC_C += \ - $(ST_CMSIS)/Source/Templates/system_stm32l4xx.c \ - $(ST_HAL_DRIVER)/Src/stm32l4xx_hal.c \ - $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_rcc_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_uart.c \ - $(ST_HAL_DRIVER)/Src/stm32l4xx_hal_pwr_ex.c + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l4r5xx.s diff --git a/hw/bsp/stm32l4r5nucleo/stm32l4xx_hal_conf.h b/hw/bsp/stm32l4r5nucleo/stm32l4xx_hal_conf.h index 66822ff59..470ef1290 100644 --- a/hw/bsp/stm32l4r5nucleo/stm32l4xx_hal_conf.h +++ b/hw/bsp/stm32l4r5nucleo/stm32l4xx_hal_conf.h @@ -48,8 +48,8 @@ /* #define HAL_FIREWALL_MODULE_ENABLED */ #define HAL_FLASH_MODULE_ENABLED /* #define HAL_NAND_MODULE_ENABLED */ -#define HAL_NOR_MODULE_ENABLED -#define HAL_SRAM_MODULE_ENABLED +// #define HAL_NOR_MODULE_ENABLED +// #define HAL_SRAM_MODULE_ENABLED /* #define HAL_HCD_MODULE_ENABLED */ #define HAL_GPIO_MODULE_ENABLED //#define HAL_I2C_MODULE_ENABLED @@ -172,7 +172,44 @@ #define INSTRUCTION_CACHE_ENABLE 1U #define DATA_CACHE_ENABLE 1U -#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ +#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U /* HRTIM register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_JPEG_REGISTER_CALLBACKS 0U /* JPEG register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ +#define USE_HAL_MDIOS_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ +#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_SWPMI_REGISTER_CALLBACKS 0U /* SWPMI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ /* ########################## Assert Selection ############################## */ /** diff --git a/hw/mcu/st/cmsis_device_l1 b/hw/mcu/st/cmsis_device_l1 new file mode 160000 index 000000000..7f16ec0a1 --- /dev/null +++ b/hw/mcu/st/cmsis_device_l1 @@ -0,0 +1 @@ +Subproject commit 7f16ec0a1c4c063f84160b4cc6bf88ad554a823e diff --git a/hw/mcu/st/cmsis_device_l4 b/hw/mcu/st/cmsis_device_l4 new file mode 160000 index 000000000..6ca7312fa --- /dev/null +++ b/hw/mcu/st/cmsis_device_l4 @@ -0,0 +1 @@ +Subproject commit 6ca7312fa6a5a460b5a5a63d66da527fdd8359a6 diff --git a/hw/mcu/st/stm32l1xx_hal_driver b/hw/mcu/st/stm32l1xx_hal_driver new file mode 160000 index 000000000..44efc446f --- /dev/null +++ b/hw/mcu/st/stm32l1xx_hal_driver @@ -0,0 +1 @@ +Subproject commit 44efc446fa69ed8344e7fd966e68ed11043b35d9 diff --git a/hw/mcu/st/stm32l4xx_hal_driver b/hw/mcu/st/stm32l4xx_hal_driver new file mode 160000 index 000000000..aee3d5bf2 --- /dev/null +++ b/hw/mcu/st/stm32l4xx_hal_driver @@ -0,0 +1 @@ +Subproject commit aee3d5bf283ae5df87532b781bdd01b7caf256fc From 6e7f2064cf8d5feaca9a59ce0593198a3fc29d12 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 30 Oct 2020 14:04:46 +0700 Subject: [PATCH 160/167] add more stm mcu --- .gitmodules | 18 ++++++++++++++++++ hw/bsp/stm32l476disco/board.mk | 2 +- hw/mcu/st/cmsis_device_g0 | 1 + hw/mcu/st/cmsis_device_g4 | 1 + hw/mcu/st/cmsis_device_l5 | 1 + hw/mcu/st/stm32g0xx_hal_driver | 1 + hw/mcu/st/stm32g4xx_hal_driver | 1 + hw/mcu/st/stm32l5xx_hal_driver | 1 + 8 files changed, 25 insertions(+), 1 deletion(-) create mode 160000 hw/mcu/st/cmsis_device_g0 create mode 160000 hw/mcu/st/cmsis_device_g4 create mode 160000 hw/mcu/st/cmsis_device_l5 create mode 160000 hw/mcu/st/stm32g0xx_hal_driver create mode 160000 hw/mcu/st/stm32g4xx_hal_driver create mode 160000 hw/mcu/st/stm32l5xx_hal_driver diff --git a/.gitmodules b/.gitmodules index 939459286..81ba7f068 100644 --- a/.gitmodules +++ b/.gitmodules @@ -91,3 +91,21 @@ [submodule "hw/mcu/st/stm32l4xx_hal_driver"] path = hw/mcu/st/stm32l4xx_hal_driver url = https://github.com/STMicroelectronics/stm32l4xx_hal_driver.git +[submodule "hw/mcu/st/cmsis_device_g0"] + path = hw/mcu/st/cmsis_device_g0 + url = https://github.com/STMicroelectronics/cmsis_device_g0.git +[submodule "hw/mcu/st/stm32g0xx_hal_driver"] + path = hw/mcu/st/stm32g0xx_hal_driver + url = https://github.com/STMicroelectronics/stm32g0xx_hal_driver.git +[submodule "hw/mcu/st/cmsis_device_g4"] + path = hw/mcu/st/cmsis_device_g4 + url = https://github.com/STMicroelectronics/cmsis_device_g4.git +[submodule "hw/mcu/st/stm32g4xx_hal_driver"] + path = hw/mcu/st/stm32g4xx_hal_driver + url = https://github.com/STMicroelectronics/stm32g4xx_hal_driver.git +[submodule "hw/mcu/st/cmsis_device_l5"] + path = hw/mcu/st/cmsis_device_l5 + url = https://github.com/STMicroelectronics/cmsis_device_l5.git +[submodule "hw/mcu/st/stm32l5xx_hal_driver"] + path = hw/mcu/st/stm32l5xx_hal_driver + url = https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git diff --git a/hw/bsp/stm32l476disco/board.mk b/hw/bsp/stm32l476disco/board.mk index e79feda07..fb55dbb5b 100644 --- a/hw/bsp/stm32l476disco/board.mk +++ b/hw/bsp/stm32l476disco/board.mk @@ -10,7 +10,7 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_STM32L4 # suppress warning caused by vendor mcu driver -CFLAGS += -Wno-error=maybe-uninitialized -Wno-error=cast-align +CFLAGS += -Wno-error=maybe-uninitialized -Wno-error=cast-align ST_FAMILY = l4 ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) diff --git a/hw/mcu/st/cmsis_device_g0 b/hw/mcu/st/cmsis_device_g0 new file mode 160000 index 000000000..08258b28e --- /dev/null +++ b/hw/mcu/st/cmsis_device_g0 @@ -0,0 +1 @@ +Subproject commit 08258b28ee95f50cb9624d152a1cbf084be1f9a5 diff --git a/hw/mcu/st/cmsis_device_g4 b/hw/mcu/st/cmsis_device_g4 new file mode 160000 index 000000000..ce822adb1 --- /dev/null +++ b/hw/mcu/st/cmsis_device_g4 @@ -0,0 +1 @@ +Subproject commit ce822adb1dc552b3aedd13621edbc7fdae124878 diff --git a/hw/mcu/st/cmsis_device_l5 b/hw/mcu/st/cmsis_device_l5 new file mode 160000 index 000000000..d922865fc --- /dev/null +++ b/hw/mcu/st/cmsis_device_l5 @@ -0,0 +1 @@ +Subproject commit d922865fc0326a102c26211c44b8e42f52c1e53d diff --git a/hw/mcu/st/stm32g0xx_hal_driver b/hw/mcu/st/stm32g0xx_hal_driver new file mode 160000 index 000000000..5b53e6cee --- /dev/null +++ b/hw/mcu/st/stm32g0xx_hal_driver @@ -0,0 +1 @@ +Subproject commit 5b53e6cee664a82b16c86491aa0060e2110c00cb diff --git a/hw/mcu/st/stm32g4xx_hal_driver b/hw/mcu/st/stm32g4xx_hal_driver new file mode 160000 index 000000000..8b4518417 --- /dev/null +++ b/hw/mcu/st/stm32g4xx_hal_driver @@ -0,0 +1 @@ +Subproject commit 8b4518417706d42eef5c14e56a650005abf478a8 diff --git a/hw/mcu/st/stm32l5xx_hal_driver b/hw/mcu/st/stm32l5xx_hal_driver new file mode 160000 index 000000000..675c32a75 --- /dev/null +++ b/hw/mcu/st/stm32l5xx_hal_driver @@ -0,0 +1 @@ +Subproject commit 675c32a75df37f39d50d61f51cb0dcf53f07e1cb From 4f3ac8c492e5b45bed3270b80e4efe7c00a46a0e Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 30 Oct 2020 14:08:54 +0700 Subject: [PATCH 161/167] add CMSIS_5 submodule --- .gitmodules | 3 +++ lib/CMSIS_5 | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/CMSIS_5 diff --git a/.gitmodules b/.gitmodules index 81ba7f068..965bbb69e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -109,3 +109,6 @@ [submodule "hw/mcu/st/stm32l5xx_hal_driver"] path = hw/mcu/st/stm32l5xx_hal_driver url = https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git +[submodule "lib/CMSIS_5"] + path = lib/CMSIS_5 + url = https://github.com/ARM-software/CMSIS_5.git diff --git a/lib/CMSIS_5 b/lib/CMSIS_5 new file mode 160000 index 000000000..b7b26f50d --- /dev/null +++ b/lib/CMSIS_5 @@ -0,0 +1 @@ +Subproject commit b7b26f50d00072812aec8453f643e24bafedccb5 From a6efe475e7b68b5fbba371a1a73ecf474ef226c4 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 30 Oct 2020 14:14:28 +0700 Subject: [PATCH 162/167] use cmsis 5 for all stm32 --- hw/bsp/feather_stm32f405/board.mk | 2 +- hw/bsp/pyboardv11/board.mk | 2 +- hw/bsp/stlinkv3mini/board.mk | 2 +- hw/bsp/stm32f070rbnucleo/board.mk | 2 +- hw/bsp/stm32f072disco/board.mk | 2 +- hw/bsp/stm32f103bluepill/board.mk | 2 +- hw/bsp/stm32f207nucleo/board.mk | 2 +- hw/bsp/stm32f303disco/board.mk | 2 +- hw/bsp/stm32f401blackpill/board.mk | 2 +- hw/bsp/stm32f407disco/board.mk | 2 +- hw/bsp/stm32f411blackpill/board.mk | 2 +- hw/bsp/stm32f411disco/board.mk | 2 +- hw/bsp/stm32f412disco/board.mk | 2 +- hw/bsp/stm32f723disco/board.mk | 2 +- hw/bsp/stm32f746disco/board.mk | 2 +- hw/bsp/stm32f746nucleo/board.mk | 2 +- hw/bsp/stm32f767nucleo/board.mk | 2 +- hw/bsp/stm32f769disco/board.mk | 2 +- hw/bsp/stm32h743eval/board.mk | 2 +- hw/bsp/stm32h743nucleo/board.mk | 2 +- hw/bsp/stm32h745disco/board.mk | 2 +- hw/bsp/stm32l0538disco/board.mk | 2 +- hw/bsp/stm32l476disco/board.mk | 2 +- hw/bsp/stm32l4r5nucleo/board.mk | 2 +- 24 files changed, 24 insertions(+), 24 deletions(-) diff --git a/hw/bsp/feather_stm32f405/board.mk b/hw/bsp/feather_stm32f405/board.mk index fdba8cd0d..3a2134875 100644 --- a/hw/bsp/feather_stm32f405/board.mk +++ b/hw/bsp/feather_stm32f405/board.mk @@ -31,7 +31,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f405xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/pyboardv11/board.mk b/hw/bsp/pyboardv11/board.mk index aa185ae3c..a8fc2ca1e 100644 --- a/hw/bsp/pyboardv11/board.mk +++ b/hw/bsp/pyboardv11/board.mk @@ -27,7 +27,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f405xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stlinkv3mini/board.mk b/hw/bsp/stlinkv3mini/board.mk index 5157fbf14..fb8b6b29f 100644 --- a/hw/bsp/stlinkv3mini/board.mk +++ b/hw/bsp/stlinkv3mini/board.mk @@ -47,7 +47,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f723xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f070rbnucleo/board.mk b/hw/bsp/stm32f070rbnucleo/board.mk index 70aeccc0b..be2ce3b83 100644 --- a/hw/bsp/stm32f070rbnucleo/board.mk +++ b/hw/bsp/stm32f070rbnucleo/board.mk @@ -32,7 +32,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f070xb.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f072disco/board.mk b/hw/bsp/stm32f072disco/board.mk index 4b73b570b..bbb7baf5a 100644 --- a/hw/bsp/stm32f072disco/board.mk +++ b/hw/bsp/stm32f072disco/board.mk @@ -32,7 +32,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f072xb.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f103bluepill/board.mk b/hw/bsp/stm32f103bluepill/board.mk index 8ab973776..8dc1fa3f5 100644 --- a/hw/bsp/stm32f103bluepill/board.mk +++ b/hw/bsp/stm32f103bluepill/board.mk @@ -30,7 +30,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f103xb.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f207nucleo/board.mk b/hw/bsp/stm32f207nucleo/board.mk index cad816d9f..025c2d7b7 100644 --- a/hw/bsp/stm32f207nucleo/board.mk +++ b/hw/bsp/stm32f207nucleo/board.mk @@ -31,7 +31,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f207xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f303disco/board.mk b/hw/bsp/stm32f303disco/board.mk index 3459c28af..3abaf5cec 100644 --- a/hw/bsp/stm32f303disco/board.mk +++ b/hw/bsp/stm32f303disco/board.mk @@ -31,7 +31,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f303xc.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f401blackpill/board.mk b/hw/bsp/stm32f401blackpill/board.mk index 3d52a79ed..522b02774 100644 --- a/hw/bsp/stm32f401blackpill/board.mk +++ b/hw/bsp/stm32f401blackpill/board.mk @@ -27,7 +27,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f401xc.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f407disco/board.mk b/hw/bsp/stm32f407disco/board.mk index 542588fc2..76e13af32 100644 --- a/hw/bsp/stm32f407disco/board.mk +++ b/hw/bsp/stm32f407disco/board.mk @@ -31,7 +31,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f407xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f411blackpill/board.mk b/hw/bsp/stm32f411blackpill/board.mk index 5b7a70017..5800331d9 100644 --- a/hw/bsp/stm32f411blackpill/board.mk +++ b/hw/bsp/stm32f411blackpill/board.mk @@ -27,7 +27,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f411xe.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f411disco/board.mk b/hw/bsp/stm32f411disco/board.mk index cea8d2cdb..e13bf641e 100644 --- a/hw/bsp/stm32f411disco/board.mk +++ b/hw/bsp/stm32f411disco/board.mk @@ -31,7 +31,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f411xe.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f412disco/board.mk b/hw/bsp/stm32f412disco/board.mk index d991c4b75..9356f344d 100644 --- a/hw/bsp/stm32f412disco/board.mk +++ b/hw/bsp/stm32f412disco/board.mk @@ -32,7 +32,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f412zx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f723disco/board.mk b/hw/bsp/stm32f723disco/board.mk index 50c25810f..b784c3742 100644 --- a/hw/bsp/stm32f723disco/board.mk +++ b/hw/bsp/stm32f723disco/board.mk @@ -50,7 +50,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f723xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f746disco/board.mk b/hw/bsp/stm32f746disco/board.mk index 95feac1f6..e02dbc3f5 100644 --- a/hw/bsp/stm32f746disco/board.mk +++ b/hw/bsp/stm32f746disco/board.mk @@ -50,7 +50,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f746xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f746nucleo/board.mk b/hw/bsp/stm32f746nucleo/board.mk index 140e2d639..e7b240240 100644 --- a/hw/bsp/stm32f746nucleo/board.mk +++ b/hw/bsp/stm32f746nucleo/board.mk @@ -33,7 +33,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f746xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f767nucleo/board.mk b/hw/bsp/stm32f767nucleo/board.mk index c6be2bcbf..9a6bada05 100644 --- a/hw/bsp/stm32f767nucleo/board.mk +++ b/hw/bsp/stm32f767nucleo/board.mk @@ -33,7 +33,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f767xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32f769disco/board.mk b/hw/bsp/stm32f769disco/board.mk index ced2240c0..a963b905b 100644 --- a/hw/bsp/stm32f769disco/board.mk +++ b/hw/bsp/stm32f769disco/board.mk @@ -47,7 +47,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f769xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32h743eval/board.mk b/hw/bsp/stm32h743eval/board.mk index 87de060c5..7f42e1a88 100644 --- a/hw/bsp/stm32h743eval/board.mk +++ b/hw/bsp/stm32h743eval/board.mk @@ -44,7 +44,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32h743xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32h743nucleo/board.mk b/hw/bsp/stm32h743nucleo/board.mk index eade0f09a..2a5ed8fc2 100644 --- a/hw/bsp/stm32h743nucleo/board.mk +++ b/hw/bsp/stm32h743nucleo/board.mk @@ -33,7 +33,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32h743xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32h745disco/board.mk b/hw/bsp/stm32h745disco/board.mk index 8489748c7..78f22a5a2 100644 --- a/hw/bsp/stm32h745disco/board.mk +++ b/hw/bsp/stm32h745disco/board.mk @@ -39,7 +39,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32h745xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32l0538disco/board.mk b/hw/bsp/stm32l0538disco/board.mk index 49818e3a3..9e3423fbc 100644 --- a/hw/bsp/stm32l0538disco/board.mk +++ b/hw/bsp/stm32l0538disco/board.mk @@ -31,7 +31,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l053xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32l476disco/board.mk b/hw/bsp/stm32l476disco/board.mk index fb55dbb5b..994849d9e 100644 --- a/hw/bsp/stm32l476disco/board.mk +++ b/hw/bsp/stm32l476disco/board.mk @@ -34,7 +34,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l476xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) diff --git a/hw/bsp/stm32l4r5nucleo/board.mk b/hw/bsp/stm32l4r5nucleo/board.mk index 57df89201..cee5ce86e 100644 --- a/hw/bsp/stm32l4r5nucleo/board.mk +++ b/hw/bsp/stm32l4r5nucleo/board.mk @@ -35,7 +35,7 @@ SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l4r5xx.s INC += \ - $(TOP)/hw/mcu/st/st_driver/CMSIS/Include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/hw/bsp/$(BOARD) From 1e7af854c209cb707c299024c7dcfb80125bef54 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 30 Oct 2020 14:21:29 +0700 Subject: [PATCH 163/167] remove st_driver submodule --- .gitmodules | 3 --- hw/mcu/st/st_driver | 1 - 2 files changed, 4 deletions(-) delete mode 160000 hw/mcu/st/st_driver diff --git a/.gitmodules b/.gitmodules index 965bbb69e..dd55bdc0c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,9 +4,6 @@ [submodule "tools/uf2"] path = tools/uf2 url = https://github.com/microsoft/uf2.git -[submodule "hw/mcu/st/st_driver"] - path = hw/mcu/st/st_driver - url = https://github.com/hathach/st_driver.git [submodule "hw/mcu/sony/cxd56/spresense-exported-sdk"] path = hw/mcu/sony/cxd56/spresense-exported-sdk url = https://github.com/sonydevworld/spresense-exported-sdk.git diff --git a/hw/mcu/st/st_driver b/hw/mcu/st/st_driver deleted file mode 160000 index ceb49a6f2..000000000 --- a/hw/mcu/st/st_driver +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ceb49a6f2d4afbf88ed29de94bb86095f41761ac From 3ea813875034be8878d3f01a740c377ebb6c8306 Mon Sep 17 00:00:00 2001 From: Jacob Potter Date: Sat, 31 Oct 2020 10:57:53 -0600 Subject: [PATCH 164/167] 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(-) 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 */\ From 67ac40b98d217dde82090bf10a0cf55af5d1c44b Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 1 Nov 2020 13:37:56 +0700 Subject: [PATCH 165/167] 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(-) 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: Mon, 2 Nov 2020 15:44:12 +0700 Subject: [PATCH 166/167] use same51 driver to adafruit asf4 submodule --- hw/bsp/d5035_01/board.mk | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/hw/bsp/d5035_01/board.mk b/hw/bsp/d5035_01/board.mk index 0a7db6403..4c3917d26 100644 --- a/hw/bsp/d5035_01/board.mk +++ b/hw/bsp/d5035_01/board.mk @@ -1,3 +1,5 @@ +HWREV ?= 1 + CFLAGS += \ -mthumb \ -mabi=aapcs \ @@ -12,41 +14,37 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_SAME5X \ -DD5035_01=1 \ -DBOARD_NAME="\"D5035-01\"" \ - -DSVC_Handler=SVCall_Handler - -HWREV ?= 1 - -CFLAGS += -DHWREV=$(HWREV) - + -DSVC_Handler=SVCall_Handler \ + -DHWREV=$(HWREV) # All source paths should be relative to the top level. LD_FILE = hw/bsp/$(BOARD)/same51j19a_flash.ld SRC_C += \ - hw/mcu/microchip/same51/gcc/gcc/startup_same51.c \ - hw/mcu/microchip/same51/gcc/system_same51.c \ + hw/mcu/microchip/samd/asf4/same51/gcc/gcc/startup_same51.c \ + hw/mcu/microchip/samd/asf4/same51/gcc/system_same51.c \ ifdef SYSCALLS ifneq ($(SYSCALLS),0) - SRC_C += hw/mcu/microchip/same51/hal/utils/src/utils_syscalls.c + SRC_C += hw/mcu/microchip/samd/asf4/same51/hal/utils/src/utils_syscalls.c endif endif ifdef LOG ifneq ($(LOG),0) - SRC_C += hw/mcu/microchip/same51/hal/utils/src/utils_syscalls.c + SRC_C += hw/mcu/microchip/samd/asf4/same51/hal/utils/src/utils_syscalls.c endif endif INC += \ - $(TOP)/hw/mcu/microchip/same51/ \ - $(TOP)/hw/mcu/microchip/same51/config \ - $(TOP)/hw/mcu/microchip/same51/include \ - $(TOP)/hw/mcu/microchip/same51/hal/include \ - $(TOP)/hw/mcu/microchip/same51/hal/utils/include \ - $(TOP)/hw/mcu/microchip/same51/hpl/port \ - $(TOP)/hw/mcu/microchip/same51/hri \ - $(TOP)/hw/mcu/microchip/same51/CMSIS/Core/Include + $(TOP)/hw/mcu/microchip/samd/asf4/same51/ \ + $(TOP)/hw/mcu/microchip/samd/asf4/same51/config \ + $(TOP)/hw/mcu/microchip/samd/asf4/same51/include \ + $(TOP)/hw/mcu/microchip/samd/asf4/same51/hal/include \ + $(TOP)/hw/mcu/microchip/samd/asf4/same51/hal/utils/include \ + $(TOP)/hw/mcu/microchip/samd/asf4/same51/hpl/port \ + $(TOP)/hw/mcu/microchip/samd/asf4/same51/hri \ + $(TOP)/hw/mcu/microchip/samd/asf4/same51/CMSIS/Include # For TinyUSB port source VENDOR = microchip From 6fcd540cb68483b1b1b25344a1a5e4560c77e276 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 2 Nov 2020 16:50:46 +0700 Subject: [PATCH 167/167] 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(-) 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) ) {