diff options
| author | hathach <[email protected]> | 2019-04-01 21:11:06 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2019-04-01 21:11:06 -0700 |
| commit | 0848c462b3e431a9da42e96537d2b597a4579636 (patch) | |
| tree | 746d6642e22e3ecf30d4f4c5f830c2a155bb28d7 | |
| parent | 86c24b310509a368cc6a9dfbec43ce531e71d598 (diff) | |
| parent | 2c1072c0aba48a2e6cbe93118c286b7999b0db43 (diff) | |
Merge pull request #51 from hathach/develop
Add suspend, resume and remote wakeup support
44 files changed, 635 insertions, 326 deletions
@@ -47,15 +47,15 @@ Currently the following OS are supported with tinyusb out of the box with a simp The stack supports the following MCUs - **Nordic:** nRF52840 -- **NXP:** LPC11Uxx, LPC13xx, LPC175x_6x, LPC177x_8x, LPC40xx, LPC43xx -- **MicroChip:** SAMD21, SAMD51 (device only) +- **NXP:** LPC11Uxx, LPC13xx, LPC175x_6x, LPC177x_8x, LPC18xx, LPC40xx, LPC43xx +- **MicroChip:** SAMD21, SAMD51 - **ST:** STM32F4 [Here is the list of supported Boards](docs/boards.md) ## Compiler & IDE -The stack is developed with GCC compiler, and should be compilable with others. However, it requires C99 to build with. Folder `examples` provide Makefile and Segger Embedded Studio build support. +The stack is developed with GCC compiler, and should be compilable with others. Folder `examples` provide Makefile and Segger Embedded Studio build support. ## Getting Started diff --git a/docs/porting.md b/docs/porting.md index 5f1df0d7a..5a97b3fb6 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -76,6 +76,9 @@ If your peripheral automatically changes address during enumeration (like the nr ##### dcd_set_config Called when the device received SET_CONFIG request, you can leave this empty if your peripheral does not require any specific action. +##### dcd_remote_wakeup +Called to remote wake up host when suspended (e.g hid keyboard) + #### Special events You must let TinyUSB know when certain events occur so that it can continue its work. There are a few methods you can call to queue events for TinyUSB to process. diff --git a/examples/device/cdc_msc_hid/ses/samd21/samd21.emProject b/examples/device/cdc_msc_hid/ses/samd21/samd21.emProject index e65873008..30aad55ca 100644 --- a/examples/device/cdc_msc_hid/ses/samd21/samd21.emProject +++ b/examples/device/cdc_msc_hid/ses/samd21/samd21.emProject @@ -67,6 +67,11 @@ <file file_name="../../../../../hw/mcu/microchip/samd/asf4/samd21/hpl/sysctrl/hpl_sysctrl.c" /> </folder> </folder> + <folder Name="hal"> + <folder Name="src"> + <file file_name="../../../../../hw/mcu/microchip/samd/asf4/samd21/hal/src/hal_atomic.c" /> + </folder> + </folder> </folder> </folder> </folder> diff --git a/examples/device/cdc_msc_hid/ses/samd51/samd51.emProject b/examples/device/cdc_msc_hid/ses/samd51/samd51.emProject index 280afdcd1..cc34dc63d 100644 --- a/examples/device/cdc_msc_hid/ses/samd51/samd51.emProject +++ b/examples/device/cdc_msc_hid/ses/samd51/samd51.emProject @@ -71,6 +71,11 @@ <file file_name="../../../../../hw/mcu/microchip/samd/asf4/samd51/hpl/gclk/hpl_gclk.c" /> </folder> </folder> + <folder Name="hal"> + <folder Name="src"> + <file file_name="../../../../../hw/mcu/microchip/samd/asf4/samd51/hal/src/hal_atomic.c" /> + </folder> + </folder> </folder> </folder> </folder> diff --git a/examples/device/cdc_msc_hid/src/main.c b/examples/device/cdc_msc_hid/src/main.c index 75d9a31dc..12e331af7 100644 --- a/examples/device/cdc_msc_hid/src/main.c +++ b/examples/device/cdc_msc_hid/src/main.c @@ -34,6 +34,14 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ + +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +static uint32_t blink_interval_ms = 250; + void led_blinking_task(void); extern void virtual_com_task(void); @@ -127,8 +135,16 @@ void usb_hid_task(void) if ( board_millis() < start_ms + interval_ms) return; // not enough time start_ms += interval_ms; - uint32_t const btn = board_buttons(); + uint32_t const btn = board_button_read(); + + if ( tud_suspended() && btn ) + { + // Wake up host if we are in suspend mode + // and REMOTE_WAKEUP feature is enabled by host + tud_remote_wakeup(); + } +#if 0 /*------------- Keyboard -------------*/ if ( tud_hid_keyboard_ready() ) { @@ -148,8 +164,9 @@ void usb_hid_task(void) tud_hid_keyboard_keycode(0, NULL); } } +#endif - +#if 0 /*------------- Mouse -------------*/ if ( tud_hid_mouse_ready() ) { @@ -160,33 +177,60 @@ void usb_hid_task(void) if ( btn & 0x04 ) tud_hid_mouse_move( 0 , -DELTA); // up if ( btn & 0x08 ) tud_hid_mouse_move( 0 , DELTA); // down } +#endif } uint16_t tud_hid_generic_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; } void tud_hid_generic_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { // TODO not Implemented + (void) report_id; + (void) report_type; + (void) buffer; + (void) bufsize; } + #endif //--------------------------------------------------------------------+ -// tinyusb callbacks +// Device callbacks //--------------------------------------------------------------------+ // Invoked when device is mounted void tud_mount_cb(void) { - + blink_interval_ms = 1000; } // Invoked when device is unmounted void tud_umount_cb(void) { + blink_interval_ms = 250; +} + +// 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 = 2500; +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) +{ + blink_interval_ms = 1000; } //--------------------------------------------------------------------+ @@ -194,14 +238,12 @@ void tud_umount_cb(void) //--------------------------------------------------------------------+ void led_blinking_task(void) { - const uint32_t interval_ms = 1000; static uint32_t start_ms = 0; - static bool led_state = false; // Blink every 1000 ms - if ( board_millis() < start_ms + interval_ms) return; // not enough time - start_ms += interval_ms; + if ( board_millis() < start_ms + blink_interval_ms) return; // not enough time + start_ms += blink_interval_ms; board_led_control(led_state); led_state = 1 - led_state; // toggle diff --git a/examples/device/cdc_msc_hid_freertos/src/main.c b/examples/device/cdc_msc_hid_freertos/src/main.c index 388bd9ad1..e47937bd5 100644 --- a/examples/device/cdc_msc_hid_freertos/src/main.c +++ b/examples/device/cdc_msc_hid_freertos/src/main.c @@ -158,7 +158,7 @@ void usb_hid_task(void* params) if ( board_millis() < start_ms + interval_ms) return; // not enough time start_ms += interval_ms; - uint32_t const btn = board_buttons(); + uint32_t const btn = board_button_read(); /*------------- Keyboard -------------*/ if ( tud_hid_keyboard_ready() ) diff --git a/hw/bsp/board.h b/hw/bsp/board.h index df9d5d11d..7d12d68fb 100644 --- a/hw/bsp/board.h +++ b/hw/bsp/board.h @@ -46,6 +46,7 @@ //--------------------------------------------------------------------+ // Board Porting API +// For simplicity, only one LED and one Button are used //--------------------------------------------------------------------+ // Initialize on-board peripherals : led, button, uart and USB @@ -54,9 +55,9 @@ void board_init(void); // Turn LED on or off void board_led_control(bool state); -// Get the current state of buttons on the board -// \return Bitmask where a '1' means active (pressed), a '0' means inactive. -uint32_t board_buttons(void); +// Get the current state of button +// a '1' means active (pressed), a '0' means inactive. +uint32_t board_button_read(void); // Get characters from UART int board_uart_read(uint8_t* buf, int len); @@ -65,28 +66,20 @@ int board_uart_read(uint8_t* buf, int len); int board_uart_write(void const * buf, int len); #if CFG_TUSB_OS == OPT_OS_NONE - -// Get current milliseconds, must be implemented in board.c when no OS is used -uint32_t board_millis(void); - + // Get current milliseconds, must be implemented when no RTOS is used + uint32_t board_millis(void); #elif CFG_TUSB_OS == OPT_OS_FREERTOS - -static inline uint32_t board_millis(void) -{ - return ( ( ((uint64_t) xTaskGetTickCount()) * 1000) / configTICK_RATE_HZ ); -} - + static inline uint32_t board_millis(void) + { + return ( ( ((uint64_t) xTaskGetTickCount()) * 1000) / configTICK_RATE_HZ ); + } #elif CFG_TUSB_OS == OPT_OS_MYNEWT - -static inline uint32_t board_millis(void) -{ - return os_time_ticks_to_ms32( os_time_get() ); -} - + static inline uint32_t board_millis(void) + { + return os_time_ticks_to_ms32( os_time_get() ); + } #elif - -#error "Need to implement board_millis() for this OS" - + #error "Need to implement board_millis() for this OS" #endif //--------------------------------------------------------------------+ diff --git a/hw/bsp/ea4088qs/board_ea4088qs.c b/hw/bsp/ea4088qs/board_ea4088qs.c index 4f4e19ee0..2d5110d25 100644 --- a/hw/bsp/ea4088qs/board_ea4088qs.c +++ b/hw/bsp/ea4088qs/board_ea4088qs.c @@ -127,7 +127,7 @@ static bool button_read(uint8_t id) } #endif -uint32_t board_buttons(void) +uint32_t board_button_read(void) { uint32_t result = 0; diff --git a/hw/bsp/ea4357/board_ea4357.c b/hw/bsp/ea4357/board_ea4357.c index 6d7d936db..898ad38ad 100644 --- a/hw/bsp/ea4357/board_ea4357.c +++ b/hw/bsp/ea4357/board_ea4357.c @@ -269,7 +269,7 @@ static bool button_read(uint8_t id) } #endif -uint32_t board_buttons(void) +uint32_t board_button_read(void) { uint32_t result = 0; diff --git a/hw/bsp/lpcxpresso11u68/board_lpcxpresso11u68.c b/hw/bsp/lpcxpresso11u68/board_lpcxpresso11u68.c index fa0966831..e1f1fd366 100644 --- a/hw/bsp/lpcxpresso11u68/board_lpcxpresso11u68.c +++ b/hw/bsp/lpcxpresso11u68/board_lpcxpresso11u68.c @@ -121,7 +121,7 @@ void board_led_control(bool state) //--------------------------------------------------------------------+ // Buttons //--------------------------------------------------------------------+ -uint32_t board_buttons(void) +uint32_t board_button_read(void) { // for(uint8_t i=0; i<BOARD_BUTTON_COUNT; i++) GPIOGetPinValue(buttons[i].port, buttons[i].pin); // return GPIOGetPinValue(buttons[0].port, buttons[0].pin) ? 0 : 1; // button is active low diff --git a/hw/bsp/lpcxpresso1347/board_lpcxpresso1347.c b/hw/bsp/lpcxpresso1347/board_lpcxpresso1347.c index 4f7909b12..70d41e547 100644 --- a/hw/bsp/lpcxpresso1347/board_lpcxpresso1347.c +++ b/hw/bsp/lpcxpresso1347/board_lpcxpresso1347.c @@ -144,7 +144,7 @@ static bool button_read(uint8_t id) } #endif -uint32_t board_buttons(void) +uint32_t board_button_read(void) { uint32_t result = 0; diff --git a/hw/bsp/lpcxpresso1769/board_lpcxpresso1769.c b/hw/bsp/lpcxpresso1769/board_lpcxpresso1769.c index 420c90e60..04ec13db0 100644 --- a/hw/bsp/lpcxpresso1769/board_lpcxpresso1769.c +++ b/hw/bsp/lpcxpresso1769/board_lpcxpresso1769.c @@ -180,7 +180,7 @@ static bool button_read(uint8_t id) } #endif -uint32_t board_buttons(void) +uint32_t board_button_read(void) { uint32_t result = 0; diff --git a/hw/bsp/mcb1800/board_mcb1800.c b/hw/bsp/mcb1800/board_mcb1800.c index b81ecaad2..90e705888 100644 --- a/hw/bsp/mcb1800/board_mcb1800.c +++ b/hw/bsp/mcb1800/board_mcb1800.c @@ -193,7 +193,7 @@ static bool button_read(uint8_t id) } */ -uint32_t board_buttons(void) +uint32_t board_button_read(void) { uint32_t result = 0; diff --git a/hw/bsp/metro_m0_express/board.mk b/hw/bsp/metro_m0_express/board.mk index 0776ea567..98c4401d2 100644 --- a/hw/bsp/metro_m0_express/board.mk +++ b/hw/bsp/metro_m0_express/board.mk @@ -19,7 +19,8 @@ SRC_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/hpl/sysctrl/hpl_sysctrl.c \ + hw/mcu/microchip/samd/asf4/samd21/hal/src/hal_atomic.c INC += \ -I$(TOP)/hw/mcu/microchip/samd/asf4/samd21/ \ diff --git a/hw/bsp/metro_m0_express/board_metro_m0_express.c b/hw/bsp/metro_m0_express/board_metro_m0_express.c index 11bb16c3c..8876b62bb 100644 --- a/hw/bsp/metro_m0_express/board_metro_m0_express.c +++ b/hw/bsp/metro_m0_express/board_metro_m0_express.c @@ -39,6 +39,7 @@ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ #define LED_PIN 17 +#define BUTTON_PIN 14 // pin D2 /* Referenced GCLKs, should be initialized firstly */ #define _GCLK_INIT_1ST (1 << 0 | 1 << 1) @@ -63,6 +64,10 @@ void board_init(void) gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); gpio_set_pin_level(LED_PIN, 0); + // 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); @@ -101,10 +106,12 @@ void board_led_control(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; +} -/*------------------------------------------------------------------*/ -/* TUSB HAL MILLISECOND - *------------------------------------------------------------------*/ #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; @@ -118,5 +125,4 @@ uint32_t board_millis(void) return system_ticks; } - #endif diff --git a/hw/bsp/metro_m4_express/board.mk b/hw/bsp/metro_m4_express/board.mk index 827613723..a0c94c448 100644 --- a/hw/bsp/metro_m4_express/board.mk +++ b/hw/bsp/metro_m4_express/board.mk @@ -21,7 +21,8 @@ SRC_C += \ hw/mcu/microchip/samd/asf4/samd51/hpl/gclk/hpl_gclk.c \ hw/mcu/microchip/samd/asf4/samd51/hpl/mclk/hpl_mclk.c \ hw/mcu/microchip/samd/asf4/samd51/hpl/osc32kctrl/hpl_osc32kctrl.c \ - hw/mcu/microchip/samd/asf4/samd51/hpl/oscctrl/hpl_oscctrl.c + hw/mcu/microchip/samd/asf4/samd51/hpl/oscctrl/hpl_oscctrl.c \ + hw/mcu/microchip/samd/asf4/samd51/hal/src/hal_atomic.c INC += \ -I$(TOP)/hw/mcu/microchip/samd/asf4/samd51/ \ diff --git a/hw/bsp/metro_m4_express/board_metro_m4_express.c b/hw/bsp/metro_m4_express/board_metro_m4_express.c index 6a134f807..aaaf7c483 100644 --- a/hw/bsp/metro_m4_express/board_metro_m4_express.c +++ b/hw/bsp/metro_m4_express/board_metro_m4_express.c @@ -35,7 +35,8 @@ //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ -#define LED_PIN 16 +#define LED_PIN 16 +#define BUTTON_PIN (32 + 17) // pin D2 /* Referenced GCLKs, should be initialized firstly */ #define _GCLK_INIT_1ST 0xFFFFFFFF @@ -61,6 +62,10 @@ void board_init(void) gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); gpio_set_pin_level(LED_PIN, 0); + // 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); @@ -90,6 +95,11 @@ void board_led_control(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; +} /*------------------------------------------------------------------*/ /* TUSB HAL MILLISECOND diff --git a/hw/bsp/pca10056/board_pca10056.c b/hw/bsp/pca10056/board_pca10056.c index 90f466356..44a4cb450 100644 --- a/hw/bsp/pca10056/board_pca10056.c +++ b/hw/bsp/pca10056/board_pca10056.c @@ -42,10 +42,7 @@ #define LED_PIN 13 #define LED_STATE_ON 0 -uint8_t _button_pins[] = { 11, 12, 24, 25 }; - -#define BOARD_BUTTON_COUNT sizeof(_button_pins) - +#define BUTTON_PIN 11 /*------------------------------------------------------------------*/ /* TUSB HAL MILLISECOND @@ -79,12 +76,12 @@ void board_init(void) NRF_CLOCK->LFCLKSRC = (uint32_t)((CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos) & CLOCK_LFCLKSRC_SRC_Msk); NRF_CLOCK->TASKS_LFCLKSTART = 1UL; - // LEDs + // LED nrf_gpio_cfg_output(LED_PIN); board_led_control(false); // Button - for(uint8_t i=0; i<BOARD_BUTTON_COUNT; i++) nrf_gpio_cfg_input(_button_pins[i], NRF_GPIO_PIN_PULLUP); + nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP); #if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer @@ -134,17 +131,10 @@ void board_led_control(bool state) nrf_gpio_pin_write(LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); } -uint32_t board_buttons(void) +uint32_t board_button_read(void) { - uint32_t ret = 0; - - for(uint8_t i=0; i<BOARD_BUTTON_COUNT; i++) - { - // button is active LOW - ret |= ( nrf_gpio_pin_read(_button_pins[i]) ? 0 : (1 << i)); - } - - return ret; + // button is active LOW + return (nrf_gpio_pin_read(BUTTON_PIN) ? 0 : 1); } int board_uart_read(uint8_t* buf, int len) diff --git a/hw/bsp/stm32f303disc/board_stm32f303disc.c b/hw/bsp/stm32f303disc/board_stm32f303disc.c index d2f6244f7..e4afbf8ce 100644 --- a/hw/bsp/stm32f303disc/board_stm32f303disc.c +++ b/hw/bsp/stm32f303disc/board_stm32f303disc.c @@ -97,6 +97,12 @@ void board_led_control(bool state) HAL_GPIO_WritePin(GPIOE, GPIO_PIN_9, state); } +uint32_t board_button_read(void) +{ + // TODO implement + return 0; +} + /*------------------------------------------------------------------*/ /* TUSB HAL MILLISECOND *------------------------------------------------------------------*/ diff --git a/hw/bsp/stm32f407g_disc1/board_stm32f407g_disc1.c b/hw/bsp/stm32f407g_disc1/board_stm32f407g_disc1.c index d7b4a4bd3..2622dde11 100644 --- a/hw/bsp/stm32f407g_disc1/board_stm32f407g_disc1.c +++ b/hw/bsp/stm32f407g_disc1/board_stm32f407g_disc1.c @@ -91,6 +91,12 @@ void board_led_control(bool state) } } +uint32_t board_button_read(void) +{ + // TODO implement + return 0; +} + /*------------------------------------------------------------------*/ /* TUSB HAL MILLISECOND diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 2ac8d471c..c194aacd8 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -99,7 +99,7 @@ static void _prep_out_transaction (uint8_t itf) bool tud_cdc_n_connected(uint8_t itf)
{
// DTR (bit 0) active is considered as connected
- return TU_BIT_TEST(_cdcd_itf[itf].line_state, 0);
+ return tud_ready() && TU_BIT_TEST(_cdcd_itf[itf].line_state, 0);
}
uint8_t tud_cdc_n_get_line_state (uint8_t itf)
diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 468edef45..25c721e13 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -38,7 +38,6 @@ #define CFG_TUD_CDC_EPSIZE 64
#endif
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -97,7 +96,6 @@ ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_li //--------------------------------------------------------------------+
// INTERNAL USBD-CLASS DRIVER API
-
//--------------------------------------------------------------------+
void cdcd_init (void);
bool cdcd_open (uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length);
diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 3a20a9cc8..5c81a1268 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -107,7 +107,7 @@ static inline hidd_interface_t* get_interface_by_itfnum(uint8_t itf_num) //--------------------------------------------------------------------+
bool tud_hid_generic_ready(void)
{
- return (_hidd_itf[ITF_IDX_GENERIC].ep_in != 0) && !dcd_edpt_busy(TUD_OPT_RHPORT, _hidd_itf[ITF_IDX_GENERIC].ep_in);
+ return tud_ready() && (_hidd_itf[ITF_IDX_GENERIC].ep_in != 0) && !dcd_edpt_busy(TUD_OPT_RHPORT, _hidd_itf[ITF_IDX_GENERIC].ep_in);
}
bool tud_hid_generic_report(uint8_t report_id, void const* report, uint8_t len)
@@ -265,6 +265,7 @@ void hidd_init(void) void hidd_reset(uint8_t rhport)
{
+ (void) rhport;
tu_memclr(_hidd_itf, sizeof(_hidd_itf));
#if CFG_TUD_HID_KEYBOARD
@@ -447,6 +448,7 @@ bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque // return false to stall control endpoint (e.g Host send non-sense DATA)
bool hidd_control_request_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);
@@ -469,6 +471,11 @@ bool hidd_control_request_complete(uint8_t rhport, tusb_control_request_t const bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
{
// nothing to do
+ (void) rhport;
+ (void) ep_addr;
+ (void) event;
+ (void) xferred_bytes;
+
return true;
}
diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 04a3178a3..ace91b40a 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -102,11 +102,6 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) //--------------------------------------------------------------------+
// APPLICATION API
//--------------------------------------------------------------------+
-bool tud_msc_ready(void)
-{
- return ( _mscd_itf.ep_in != 0 ) && ( _mscd_itf.ep_out != 0 ) ;
-}
-
bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier)
{
(void) lun;
diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index e030951be..74be7e06d 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -68,9 +68,6 @@ TU_VERIFY_STATIC(CFG_TUD_MSC_BUFSIZE < UINT16_MAX, "Size is not correct"); * \defgroup MSC_Device Device
* @{ */
-
-// Check if MSC interface is ready to use
-bool tud_msc_ready(void);
bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier);
//--------------------------------------------------------------------+
diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index d4a623aaa..3a4ddb4c3 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -105,6 +105,13 @@ typedef enum typedef enum
{
+ TUSB_REQ_FEATURE_EDPT_HALT = 0,
+ TUSB_REQ_FEATURE_REMOTE_WAKEUP = 1,
+ TUSB_REQ_FEATURE_TEST_MODE = 2
+}tusb_request_feature_selector_t;
+
+typedef enum
+{
TUSB_REQ_TYPE_STANDARD = 0,
TUSB_REQ_TYPE_CLASS,
TUSB_REQ_TYPE_VENDOR
@@ -159,8 +166,7 @@ typedef enum enum {
TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = TU_BIT(5),
- TUSB_DESC_CONFIG_ATT_SELF_POWER = TU_BIT(6),
- TUSB_DESC_CONFIG_ATT_BUS_POWER = TU_BIT(7)
+ TUSB_DESC_CONFIG_ATT_SELF_POWERED = TU_BIT(6),
};
#define TUSB_DESC_CONFIG_POWER_MA(x) ((x)/2)
diff --git a/src/device/dcd.h b/src/device/dcd.h index 186c4af0c..63f923faa 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -42,13 +42,14 @@ typedef enum DCD_EVENT_BUS_RESET = 1,
DCD_EVENT_UNPLUGGED,
DCD_EVENT_SOF,
- DCD_EVENT_SUSPENDED,
+ DCD_EVENT_SUSPEND,
DCD_EVENT_RESUME,
DCD_EVENT_SETUP_RECEIVED,
DCD_EVENT_XFER_COMPLETE,
- USBD_EVT_FUNC_CALL
+ // Not an DCD event, just a convenient way to defer ISR function
+ USBD_EVENT_FUNC_CALL
} dcd_eventid_t;
typedef struct ATTR_ALIGNED(4)
@@ -67,7 +68,7 @@ typedef struct ATTR_ALIGNED(4) uint32_t len;
}xfer_complete;
- // USBD_EVT_FUNC_CALL
+ // USBD_EVENT_FUNC_CALL
struct {
void (*func) (void*);
void* param;
@@ -80,7 +81,9 @@ TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct"); /*------------------------------------------------------------------*/
/* Device API
*------------------------------------------------------------------*/
-bool dcd_init (uint8_t rhport);
+
+// Initialize controller to device mode
+void dcd_init (uint8_t rhport);
// Enable device interrupt
void dcd_int_enable (uint8_t rhport);
@@ -91,9 +94,12 @@ void dcd_int_disable(uint8_t rhport); // Receive Set Address request, mcu port must also include status IN response
void dcd_set_address(uint8_t rhport, uint8_t dev_addr);
-// Receive Set Config request
+// Receive Set Configure request
void dcd_set_config (uint8_t rhport, uint8_t config_num);
+// Wake up host
+void dcd_remote_wakeup(uint8_t rhport);
+
/*------------------------------------------------------------------*/
/* Endpoint API
* - open : Configure endpoint's registers
diff --git a/src/device/usbd.c b/src/device/usbd.c index 604f35bc5..cdbd6db5b 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -40,13 +40,22 @@ // Device Data
//--------------------------------------------------------------------+
typedef struct {
- uint8_t config_num;
+ struct ATTR_PACKED
+ {
+ volatile uint8_t connected : 1;
+ volatile uint8_t configured : 1;
+ volatile uint8_t suspended : 1;
- 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 remote_wakeup_en : 1; // enable/disable by host
+ uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute
+ uint8_t self_powered : 1; // configuration descriptor's attribute
+ };
- uint8_t ep_busy_mask[2]; // bit mask for busy endpoint
+// uint8_t ep_busy_mask[2]; // bit mask for busy endpoint
uint8_t ep_stall_mask[2]; // bit mask for stalled endpoint
+
+ uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid)
+ uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid )
}usbd_device_t;
static usbd_device_t _usbd_dev = { 0 };
@@ -166,11 +175,24 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) );
//--------------------------------------------------------------------+
-// APPLICATION API
+// Application API
//--------------------------------------------------------------------+
bool tud_mounted(void)
{
- return _usbd_dev.config_num > 0;
+ return _usbd_dev.configured;
+}
+
+bool tud_suspended(void)
+{
+ return _usbd_dev.suspended;
+}
+
+bool tud_remote_wakeup(void)
+{
+ // only wake up host if this feature is supported and enabled and we are suspended
+ TU_VERIFY (_usbd_dev.suspended && _usbd_dev.remote_wakeup_support && _usbd_dev.remote_wakeup_en );
+ dcd_remote_wakeup(TUD_OPT_RHPORT);
+ return true;
}
//--------------------------------------------------------------------+
@@ -178,6 +200,8 @@ bool tud_mounted(void) //--------------------------------------------------------------------+
bool usbd_init (void)
{
+ tu_varclr(&_usbd_dev);
+
// Init device queue & task
_usbd_q = osal_queue_create(&_usbd_qdef);
TU_ASSERT(_usbd_q != NULL);
@@ -186,7 +210,7 @@ bool usbd_init (void) for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) usbd_class_drivers[i].init();
// Init device controller driver
- TU_ASSERT(dcd_init(TUD_OPT_RHPORT));
+ dcd_init(TUD_OPT_RHPORT);
dcd_int_enable(TUD_OPT_RHPORT);
return true;
@@ -195,6 +219,7 @@ bool usbd_init (void) static void usbd_reset(uint8_t rhport)
{
tu_varclr(&_usbd_dev);
+
memset(_usbd_dev.itf2drv, 0xff, sizeof(_usbd_dev.itf2drv)); // invalid mapping
memset(_usbd_dev.ep2drv , 0xff, sizeof(_usbd_dev.ep2drv )); // invalid mapping
@@ -239,7 +264,22 @@ void tud_task (void) switch ( event.event_id )
{
+ case DCD_EVENT_BUS_RESET:
+ usbd_reset(event.rhport);
+ break;
+
+ case DCD_EVENT_UNPLUGGED:
+ usbd_reset(event.rhport);
+
+ // invoke callback
+ if (tud_umount_cb) tud_umount_cb();
+ break;
+
case DCD_EVENT_SETUP_RECEIVED:
+ // Mark as connected after receiving 1st setup packet.
+ // But it is easier to set it every time instead of wasting time to check then set
+ _usbd_dev.connected = 1;
+
// Process control request
if ( !process_control_request(event.rhport, &event.setup_received) )
{
@@ -250,38 +290,33 @@ void tud_task (void) break;
case DCD_EVENT_XFER_COMPLETE:
- {
- // Invoke the class callback associated with the endpoint address
- uint8_t const ep_addr = event.xfer_complete.ep_addr;
-
- if ( 0 == tu_edpt_number(ep_addr) )
- {
- // control transfer DATA stage callback
- usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
- }
- else
+ // Only handle xfer callback in ready state
+ // if (_usbd_dev.connected && !_usbd_dev.suspended)
{
- uint8_t const drv_id = _usbd_dev.ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)];
- TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,);
+ // Invoke the class callback associated with the endpoint address
+ uint8_t const ep_addr = event.xfer_complete.ep_addr;
+
+ if ( 0 == tu_edpt_number(ep_addr) )
+ {
+ // control transfer DATA stage callback
+ usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
+ }
+ else
+ {
+ uint8_t const drv_id = _usbd_dev.ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)];
+ TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,);
- usbd_class_drivers[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
+ usbd_class_drivers[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
+ }
}
- }
break;
- case DCD_EVENT_BUS_RESET:
- usbd_reset(event.rhport);
- // TODO remove since if task is too slow, we could clear the event of the new attached
- osal_queue_reset(_usbd_q);
+ case DCD_EVENT_SUSPEND:
+ if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en);
break;
- case DCD_EVENT_UNPLUGGED:
- usbd_reset(event.rhport);
- // TODO remove since if task is too slow, we could clear the event of the new attached
- osal_queue_reset(_usbd_q);
-
- // invoke callback
- if (tud_umount_cb) tud_umount_cb();
+ case DCD_EVENT_RESUME:
+ if (tud_resume_cb) tud_resume_cb();
break;
case DCD_EVENT_SOF:
@@ -294,7 +329,7 @@ void tud_task (void) }
break;
- case USBD_EVT_FUNC_CALL:
+ case USBD_EVENT_FUNC_CALL:
if ( event.func_call.func ) event.func_call.func(event.func_call.param);
break;
@@ -315,98 +350,140 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const {
usbd_control_set_complete_callback(NULL);
- if ( TUSB_REQ_RCPT_DEVICE == p_request->bmRequestType_bit.recipient &&
- TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type )
+ switch ( p_request->bmRequestType_bit.recipient )
{
- //------------- Standard Device Requests e.g in enumeration -------------//
- void* data_buf = NULL;
- uint16_t data_len = 0;
+ //------------- Device Requests e.g in enumeration -------------//
+ case TUSB_REQ_RCPT_DEVICE:
+ if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type )
+ {
+ // Non standard request is not supported
+ TU_BREAKPOINT();
+ return false;
+ }
- switch ( p_request->bRequest )
- {
- case TUSB_REQ_SET_ADDRESS:
- // DCD must include zero-length status response since depending on mcu,
- // status could be sent either before or after changing device address
- dcd_set_address(rhport, (uint8_t) p_request->wValue);
- return true; // skip the rest
- break;
+ switch ( p_request->bRequest )
+ {
+ case TUSB_REQ_SET_ADDRESS:
+ // Depending on mcu, status phase could be sent either before or after changing device address
+ // Therefore DCD must include zero-length status response
+ dcd_set_address(rhport, (uint8_t) p_request->wValue);
+ return true; // skip status
+ break;
- case TUSB_REQ_GET_CONFIGURATION:
- data_buf = &_usbd_dev.config_num;
- data_len = 1;
- break;
+ case TUSB_REQ_GET_CONFIGURATION:
+ {
+ uint8_t cfgnum = _usbd_dev.configured ? 1 : 0;
+ usbd_control_xfer(rhport, p_request, &cfgnum, 1);
+ }
+ break;
- case TUSB_REQ_SET_CONFIGURATION:
- {
- uint8_t const config = (uint8_t) p_request->wValue;
+ case TUSB_REQ_SET_CONFIGURATION:
+ {
+ uint8_t const cfg_num = (uint8_t) p_request->wValue;
- dcd_set_config(rhport, config);
- _usbd_dev.config_num = config;
+ dcd_set_config(rhport, cfg_num);
+ _usbd_dev.configured = cfg_num ? 1 : 0;
- TU_ASSERT( TUSB_ERROR_NONE == process_set_config(rhport) );
- }
- break;
+ TU_ASSERT( process_set_config(rhport) );
+ usbd_control_status(rhport, p_request);
+ }
+ break;
- case TUSB_REQ_GET_DESCRIPTOR:
- data_buf = (void*) get_descriptor(p_request, &data_len);
- if ( data_buf == NULL || data_len == 0 ) return false;
- break;
+ case TUSB_REQ_GET_DESCRIPTOR:
+ {
+ uint16_t len = 0;
+ void* buf = (void*) get_descriptor(p_request, &len);
+ if ( buf == NULL || len == 0 ) return false;
- default:
- TU_BREAKPOINT();
- return false;
- }
+ usbd_control_xfer(rhport, p_request, buf, len);
+ }
+ break;
+
+ case TUSB_REQ_SET_FEATURE:
+ // Only support remote wakeup for device feature
+ TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
+
+ // Host may enable remote wake up before suspending especially HID device
+ _usbd_dev.remote_wakeup_en = true;
+ usbd_control_status(rhport, p_request);
+ break;
+
+ case TUSB_REQ_CLEAR_FEATURE:
+ // Only support remote wakeup for device feature
+ TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
+
+ // Host may disable remote wake up after resuming
+ _usbd_dev.remote_wakeup_en = false;
+ usbd_control_status(rhport, p_request);
+ break;
+
+ case TUSB_REQ_GET_STATUS:
+ {
+ // Device status bit mask
+ // - Bit 0: Self Powered
+ // - Bit 1: Remote Wakeup enabled
+ uint16_t status = (_usbd_dev.self_powered ? 1 : 0) | (_usbd_dev.remote_wakeup_en ? 2 : 0);
+ usbd_control_xfer(rhport, p_request, &status, 2);
+ }
+ break;
+
+ // Unknown/Unsupported request
+ default: TU_BREAKPOINT(); return false;
+ }
+ break;
- usbd_control_xfer(rhport, p_request, data_buf, data_len);
- }
- else if ( TUSB_REQ_RCPT_INTERFACE == p_request->bmRequestType_bit.recipient )
- {
//------------- Class/Interface Specific Request -------------//
- uint8_t const itf = tu_u16_low(p_request->wIndex);
- uint8_t const drvid = _usbd_dev.itf2drv[ itf ];
+ case TUSB_REQ_RCPT_INTERFACE:
+ {
+ uint8_t const itf = tu_u16_low(p_request->wIndex);
+ uint8_t const drvid = _usbd_dev.itf2drv[itf];
- TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT);
+ TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT);
- usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_request_complete );
+ usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_request_complete );
+
+ // stall control endpoint if driver return false
+ return usbd_class_drivers[drvid].control_request(rhport, p_request);
+ }
+ break;
- // control endpoint will be stalled if driver return false
- return usbd_class_drivers[drvid].control_request(rhport, p_request);
- }
- else if ( p_request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT &&
- p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD )
- {
//------------- Endpoint Request -------------//
- switch ( p_request->bRequest )
- {
- case TUSB_REQ_GET_STATUS:
+ case TUSB_REQ_RCPT_ENDPOINT:
+ // Non standard request is not supported
+ TU_VERIFY( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type );
+
+ switch ( p_request->bRequest )
{
- uint16_t status = usbd_edpt_stalled(rhport, tu_u16_low(p_request->wIndex)) ? 0x0001 : 0x0000;
- usbd_control_xfer(rhport, p_request, &status, 2);
- }
- break;
+ case TUSB_REQ_GET_STATUS:
+ {
+ uint16_t status = usbd_edpt_stalled(rhport, tu_u16_low(p_request->wIndex)) ? 0x0001 : 0x0000;
+ usbd_control_xfer(rhport, p_request, &status, 2);
+ }
+ break;
- case TUSB_REQ_CLEAR_FEATURE:
- // only endpoint feature is halted/stalled
- dcd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex));
- usbd_control_status(rhport, p_request);
- break;
+ case TUSB_REQ_CLEAR_FEATURE:
+ if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue )
+ {
+ dcd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex));
+ }
+ usbd_control_status(rhport, p_request);
+ break;
- case TUSB_REQ_SET_FEATURE:
- // only endpoint feature is halted/stalled
- usbd_edpt_stall(rhport, tu_u16_low(p_request->wIndex));
- usbd_control_status(rhport, p_request);
- break;
+ case TUSB_REQ_SET_FEATURE:
+ if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue )
+ {
+ usbd_edpt_stall(rhport, tu_u16_low(p_request->wIndex));
+ }
+ usbd_control_status(rhport, p_request);
+ break;
- default:
- TU_BREAKPOINT();
- return false;
- }
- }
- else
- {
- //------------- Unsupported Request -------------//
- TU_BREAKPOINT();
- return false;
+ // Unknown/Unsupported request
+ default: TU_BREAKPOINT(); return false;
+ }
+ break;
+
+ // Unknown recipient
+ default: TU_BREAKPOINT(); return false;
}
return true;
@@ -416,13 +493,18 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // This function parse configuration descriptor & open drivers accordingly
static bool process_set_config(uint8_t rhport)
{
- uint8_t const * desc_cfg = (uint8_t const *) usbd_desc_set->config;
- TU_ASSERT(desc_cfg != NULL);
+ tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) usbd_desc_set->config;
+ TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION);
+
+ // 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;
- uint8_t const * p_desc = desc_cfg + sizeof(tusb_desc_configuration_t);
- uint16_t const cfg_len = ((tusb_desc_configuration_t*)desc_cfg)->wTotalLength;
+ // 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;
- while( p_desc < desc_cfg + cfg_len )
+ while( p_desc < desc_end )
{
// Each interface always starts with Interface or Association descriptor
if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) )
@@ -459,7 +541,7 @@ static bool process_set_config(uint8_t rhport) // invoke callback
if (tud_mount_cb) tud_mount_cb();
- return TUSB_ERROR_NONE;
+ return true;
}
// Helper marking endpoint of interface belongs to class driver
@@ -515,9 +597,8 @@ static void const* get_descriptor(tusb_control_request_t const * p_request, uint }else
{
// out of range
- /* The 0xEE index string is a Microsoft USB extension.
- * It can be used to tell Windows what driver it should use for the device !!!
- */
+ // The 0xEE index string is a Microsoft USB extension.
+ // It can be used to tell Windows what driver it should use for the device !!!
return NULL;
}
break;
@@ -543,7 +624,13 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) switch (event->event_id)
{
case DCD_EVENT_BUS_RESET:
+ osal_queue_send(_usbd_q, event, in_isr);
+ break;
+
case DCD_EVENT_UNPLUGGED:
+ _usbd_dev.connected = 0;
+ _usbd_dev.configured = 0;
+ _usbd_dev.suspended = 0;
osal_queue_send(_usbd_q, event, in_isr);
break;
@@ -551,12 +638,23 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) // nothing to do now
break;
- case DCD_EVENT_SUSPENDED:
- // TODO support suspended
+ case DCD_EVENT_SUSPEND:
+ // NOTE: When plugging/unplugging device, the D+/D- state are unstable and can accidentally meet the
+ // SUSPEND condition ( Idle for 3ms ). Some MCUs such as samd don't distinguish suspend vs disconnect as well.
+ // We will skip handling SUSPEND/RESUME event if not currently connected
+ if ( _usbd_dev.connected )
+ {
+ _usbd_dev.suspended = 1;
+ osal_queue_send(_usbd_q, event, in_isr);
+ }
break;
case DCD_EVENT_RESUME:
- // TODO support resume
+ if ( _usbd_dev.connected )
+ {
+ _usbd_dev.suspended = 0;
+ osal_queue_send(_usbd_q, event, in_isr);
+ }
break;
case DCD_EVENT_SETUP_RECEIVED:
@@ -565,14 +663,14 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) case DCD_EVENT_XFER_COMPLETE:
// skip zero-length control status complete event, should dcd notifies us.
- if ( 0 == tu_edpt_number(event->xfer_complete.ep_addr) && event->xfer_complete.len == 0) break;
+ if ( (0 == tu_edpt_number(event->xfer_complete.ep_addr)) && (event->xfer_complete.len == 0) ) break;
osal_queue_send(_usbd_q, event, in_isr);
TU_ASSERT(event->xfer_complete.result == XFER_RESULT_SUCCESS,);
break;
- // Not an DCD event, just a convenient way to defer ISR function should we need
- case USBD_EVT_FUNC_CALL:
+ // Not an DCD event, just a convenient way to defer ISR function should we need to
+ case USBD_EVENT_FUNC_CALL:
osal_queue_send(_usbd_q, event, in_isr);
break;
@@ -642,7 +740,7 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) dcd_event_t event =
{
.rhport = 0,
- .event_id = USBD_EVT_FUNC_CALL,
+ .event_id = USBD_EVENT_FUNC_CALL,
};
event.func_call.func = func;
diff --git a/src/device/usbd.h b/src/device/usbd.h index 614b4f311..13c282e91 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -34,16 +34,9 @@ extern "C" {
#endif
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#include <common/tusb_common.h>
+#include "common/tusb_common.h"
#include "device/dcd.h"
-//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
-//--------------------------------------------------------------------+
-
/// \brief Descriptor pointer collector to all the needed.
typedef struct {
void const * device; ///< pointer to device descriptor \ref tusb_desc_device_t
@@ -60,27 +53,47 @@ typedef struct { }tud_desc_set_t;
-
// Must be defined by application
extern tud_desc_set_t tud_desc_set;
//--------------------------------------------------------------------+
-// APPLICATION API
+// Application API
//--------------------------------------------------------------------+
-bool tud_mounted(void);
+
+// Task function should be called in main/rtos loop
void tud_task (void);
+// Check if device is connected and configured
+bool tud_mounted(void);
+
+// Check if device is suspended
+bool tud_suspended(void);
+
+// Check if device is ready to transfer
+static inline bool tud_ready(void)
+{
+ return tud_mounted() && !tud_suspended();
+}
+
+// Remote wake up host, only if suspended and enabled by host
+bool tud_remote_wakeup(void);
+
//--------------------------------------------------------------------+
-// APPLICATION CALLBACK (WEAK is optional)
+// Application Callbacks (WEAK is optional)
//--------------------------------------------------------------------+
-// Callback invoked when device is mounted (configured)
+// Invoked when device is mounted (configured)
ATTR_WEAK void tud_mount_cb(void);
-// Callback invoked when device is unmounted (bus reset/unplugged)
+// Invoked when device is unmounted
ATTR_WEAK void tud_umount_cb(void);
-//void tud_device_suspended_cb(void);
+// Invoked when usb bus is suspended
+// Within 7ms, device must draw an average of current less than 2.5 mA from bus
+ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en);
+
+// Invoked when usb bus is resumed
+ATTR_WEAK void tud_resume_cb(void);
#ifdef __cplusplus
}
diff --git a/src/device/usbd_auto_desc.c b/src/device/usbd_auto_desc.c index c4213edba..e418cd23c 100644 --- a/src/device/usbd_auto_desc.c +++ b/src/device/usbd_auto_desc.c @@ -254,7 +254,7 @@ tusb_desc_device_t const _desc_auto_device = .iProduct = 0x02, .iSerialNumber = 0x03, - .bNumConfigurations = 0x01 // TODO multiple configurations + .bNumConfigurations = 0x01 }; @@ -342,7 +342,7 @@ desc_auto_cfg_t const _desc_auto_config_struct = .bConfigurationValue = 1, .iConfiguration = 0x00, - .bmAttributes = TUSB_DESC_CONFIG_ATT_BUS_POWER, + .bmAttributes = TU_BIT(7) | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, .bMaxPower = TUSB_DESC_CONFIG_POWER_MA(100) }, diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 24234f4d2..8460a11b0 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -114,6 +114,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result if ( _control_state.request.bmRequestType_bit.direction == TUSB_DIR_OUT )
{
+ TU_VERIFY(_control_state.buffer);
memcpy(_control_state.buffer, _usbd_ctrl_buf, xferred_bytes);
}
diff --git a/src/osal/osal.h b/src/osal/osal.h index 7ceb22125..d6c33de3f 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -61,7 +61,6 @@ typedef void (*osal_task_func_t)( void * ); * osal_queue_t osal_queue_create(osal_queue_def_t* qdef)
* osal_queue_receive (osal_queue_t const queue_hdl, void *p_data, uint32_t msec, uint32_t *p_error)
* bool osal_queue_send(osal_queue_t const queue_hdl, void const * data, bool in_isr)
- * osal_queue_reset()
*
* Semaphore
* osal_semaphore_def_t, osal_semaphore_t
diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 639501bbf..973a18546 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -125,11 +125,6 @@ static inline bool osal_queue_send(osal_queue_t const queue_hdl, void const * da return in_isr ? xQueueSendToBackFromISR(queue_hdl, data, NULL) : xQueueSendToBack(queue_hdl, data, OSAL_TIMEOUT_WAIT_FOREVER); } -static inline void osal_queue_reset(osal_queue_t const queue_hdl) -{ - xQueueReset(queue_hdl); -} - #ifdef __cplusplus } #endif diff --git a/src/osal/osal_mynewt.h b/src/osal/osal_mynewt.h index 9fa9f541e..6f3d05325 100644 --- a/src/osal/osal_mynewt.h +++ b/src/osal/osal_mynewt.h @@ -161,11 +161,6 @@ static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, b return true; } -static inline void osal_queue_reset(osal_queue_t const queue_hdl) -{ - // TODO implement later -} - #ifdef __cplusplus } #endif diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 6144f3e5c..d1d365bbe 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -190,13 +190,6 @@ static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, b return success;
}
-static inline void osal_queue_reset(osal_queue_t const qhdl)
-{
- // tusb_hal_int_disable_all();
- tu_fifo_clear(&qhdl->ff);
- // tusb_hal_int_enable_all();
-}
-
#ifdef __cplusplus
}
#endif
diff --git a/src/portable/microchip/samd21/dcd_samd21.c b/src/portable/microchip/samd21/dcd_samd21.c index 723bd6c3a..8ecfd3668 100644 --- a/src/portable/microchip/samd21/dcd_samd21.c +++ b/src/portable/microchip/samd21/dcd_samd21.c @@ -38,26 +38,27 @@ static ATTR_ALIGNED(4) UsbDeviceDescBank sram_registers[8][2]; static ATTR_ALIGNED(4) uint8_t _setup_packet[8]; // Setup the control endpoint 0. -static void bus_reset(void) { - // Max size of packets is 64 bytes. - UsbDeviceDescBank* bank_out = &sram_registers[0][TUSB_DIR_OUT]; - bank_out->PCKSIZE.bit.SIZE = 0x3; - UsbDeviceDescBank* bank_in = &sram_registers[0][TUSB_DIR_IN]; - bank_in->PCKSIZE.bit.SIZE = 0x3; +static void bus_reset(void) +{ + // Max size of packets is 64 bytes. + UsbDeviceDescBank* bank_out = &sram_registers[0][TUSB_DIR_OUT]; + bank_out->PCKSIZE.bit.SIZE = 0x3; + UsbDeviceDescBank* bank_in = &sram_registers[0][TUSB_DIR_IN]; + bank_in->PCKSIZE.bit.SIZE = 0x3; - UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[0]; - ep->EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(0x1) | USB_DEVICE_EPCFG_EPTYPE1(0x1); - ep->EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT0 | USB_DEVICE_EPINTENSET_TRCPT1 | USB_DEVICE_EPINTENSET_RXSTP; + UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[0]; + ep->EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(0x1) | USB_DEVICE_EPCFG_EPTYPE1(0x1); + ep->EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT0 | USB_DEVICE_EPINTENSET_TRCPT1 | USB_DEVICE_EPINTENSET_RXSTP; - // Prepare for setup packet - dcd_edpt_xfer(0, 0, _setup_packet, sizeof(_setup_packet)); + // Prepare for setup packet + dcd_edpt_xfer(0, 0, _setup_packet, sizeof(_setup_packet)); } /*------------------------------------------------------------------*/ /* Controller API *------------------------------------------------------------------*/ -bool dcd_init (uint8_t rhport) +void dcd_init (uint8_t rhport) { (void) rhport; @@ -79,9 +80,8 @@ bool dcd_init (uint8_t rhport) USB->DEVICE.CTRLA.reg = USB_CTRLA_MODE_DEVICE | USB_CTRLA_ENABLE | USB_CTRLA_RUNSTDBY; while (USB->DEVICE.SYNCBUSY.bit.ENABLE == 1) {} + USB->DEVICE.INTFLAG.reg |= USB->DEVICE.INTFLAG.reg; // clear pending USB->DEVICE.INTENSET.reg = USB_DEVICE_INTENSET_SOF | USB_DEVICE_INTENSET_EORST; - - return true; } void dcd_int_enable(uint8_t rhport) @@ -105,6 +105,10 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) while (USB->DEVICE.DeviceEndpoint[0].EPSTATUS.bit.BK1RDY == 1) {} USB->DEVICE.DADD.reg = USB_DEVICE_DADD_DADD(dev_addr) | USB_DEVICE_DADD_ADDEN; + + // Enable SUSPEND interrupt since the bus signal D+/D- are stable now. + USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTENCLR_SUSPEND; // clear pending + USB->DEVICE.INTENSET.reg = USB_DEVICE_INTENSET_SUSPEND; } void dcd_set_config (uint8_t rhport, uint8_t config_num) @@ -112,6 +116,14 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num) (void) rhport; (void) config_num; // Nothing to do + +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; + + USB->DEVICE.CTRLB.bit.UPRSM = 1; } /*------------------------------------------------------------------*/ @@ -292,21 +304,46 @@ void maybe_transfer_complete(void) { } } -void USB_Handler(void) { - uint32_t int_status = USB->DEVICE.INTFLAG.reg; +void USB_Handler(void) +{ + uint32_t int_status = USB->DEVICE.INTFLAG.reg & USB->DEVICE.INTENSET.reg; + USB->DEVICE.INTFLAG.reg = int_status; // clear interrupt /*------------- Interrupt Processing -------------*/ - if ( int_status & USB_DEVICE_INTFLAG_EORST ) + if ( int_status & USB_DEVICE_INTFLAG_SOF ) { - USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTENCLR_EORST; - bus_reset(); - dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } - if ( int_status & USB_DEVICE_INTFLAG_SOF ) + // SAMD doesn't distinguish between Suspend and Disconnect state. + // Both condition will cause SUSPEND interrupt triggered. + // To prevent being triggered when D+/D- are not stable, SUSPEND interrupt is only + // enabled when we received SET_ADDRESS request and cleared on Bus Reset + if ( int_status & USB_DEVICE_INTFLAG_SUSPEND ) { - USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_SOF; - dcd_event_bus_signal(0, DCD_EVENT_SOF, true); + // Enable wakeup interrupt + USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_WAKEUP; // clear pending + USB->DEVICE.INTENSET.reg = USB_DEVICE_INTFLAG_WAKEUP; + + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + } + + // Wakeup interrupt is only enabled when we got suspended. + // Wakeup interrupt will disable itself + if ( int_status & USB_DEVICE_INTFLAG_WAKEUP ) + { + // disable wakeup interrupt itself + USB->DEVICE.INTENCLR.reg = USB_DEVICE_INTFLAG_WAKEUP; + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + + if ( int_status & USB_DEVICE_INTFLAG_EORST ) + { + // Disable both suspend and wakeup interrupt + USB->DEVICE.INTENCLR.reg = USB_DEVICE_INTFLAG_WAKEUP | USB_DEVICE_INTFLAG_SUSPEND; + + bus_reset(); + dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); } // Setup packet received. diff --git a/src/portable/microchip/samd51/dcd_samd51.c b/src/portable/microchip/samd51/dcd_samd51.c index 9869956c7..d2e7aaf7d 100644 --- a/src/portable/microchip/samd51/dcd_samd51.c +++ b/src/portable/microchip/samd51/dcd_samd51.c @@ -38,26 +38,27 @@ static UsbDeviceDescBank sram_registers[8][2]; static ATTR_ALIGNED(4) uint8_t _setup_packet[8]; // Setup the control endpoint 0. -static void bus_reset(void) { - // Max size of packets is 64 bytes. - UsbDeviceDescBank* bank_out = &sram_registers[0][TUSB_DIR_OUT]; - bank_out->PCKSIZE.bit.SIZE = 0x3; - UsbDeviceDescBank* bank_in = &sram_registers[0][TUSB_DIR_IN]; - bank_in->PCKSIZE.bit.SIZE = 0x3; +static void bus_reset(void) +{ + // Max size of packets is 64 bytes. + UsbDeviceDescBank* bank_out = &sram_registers[0][TUSB_DIR_OUT]; + bank_out->PCKSIZE.bit.SIZE = 0x3; + UsbDeviceDescBank* bank_in = &sram_registers[0][TUSB_DIR_IN]; + bank_in->PCKSIZE.bit.SIZE = 0x3; - UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[0]; - ep->EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(0x1) | USB_DEVICE_EPCFG_EPTYPE1(0x1); - ep->EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT0 | USB_DEVICE_EPINTENSET_TRCPT1 | USB_DEVICE_EPINTENSET_RXSTP; + UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[0]; + ep->EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(0x1) | USB_DEVICE_EPCFG_EPTYPE1(0x1); + ep->EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT0 | USB_DEVICE_EPINTENSET_TRCPT1 | USB_DEVICE_EPINTENSET_RXSTP; - // Prepare for setup packet - dcd_edpt_xfer(0, 0, _setup_packet, sizeof(_setup_packet)); + // Prepare for setup packet + dcd_edpt_xfer(0, 0, _setup_packet, sizeof(_setup_packet)); } /*------------------------------------------------------------------*/ /* Controller API *------------------------------------------------------------------*/ -bool dcd_init (uint8_t rhport) +void dcd_init (uint8_t rhport) { (void) rhport; @@ -78,9 +79,9 @@ bool dcd_init (uint8_t rhport) USB->DEVICE.CTRLB.reg = USB_DEVICE_CTRLB_SPDCONF_FS; USB->DEVICE.CTRLA.reg = USB_CTRLA_MODE_DEVICE | USB_CTRLA_ENABLE | USB_CTRLA_RUNSTDBY; while (USB->DEVICE.SYNCBUSY.bit.ENABLE == 1) {} - USB->DEVICE.INTENSET.reg = USB_DEVICE_INTENSET_SOF | USB_DEVICE_INTENSET_EORST; - return true; + USB->DEVICE.INTFLAG.reg |= USB->DEVICE.INTFLAG.reg; // clear pending + USB->DEVICE.INTENSET.reg = USB_DEVICE_INTENSET_SOF | USB_DEVICE_INTENSET_EORST; } void dcd_int_enable(uint8_t rhport) @@ -110,6 +111,10 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) while (USB->DEVICE.DeviceEndpoint[0].EPSTATUS.bit.BK1RDY == 1) {} USB->DEVICE.DADD.reg = USB_DEVICE_DADD_DADD(dev_addr) | USB_DEVICE_DADD_ADDEN; + + // Enable SUSPEND interrupt since the bus signal D+/D- are stable now. + USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTENCLR_SUSPEND; // clear pending + USB->DEVICE.INTENSET.reg = USB_DEVICE_INTENSET_SUSPEND; } void dcd_set_config (uint8_t rhport, uint8_t config_num) @@ -119,6 +124,13 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num) // Nothing to do } +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; + + USB->DEVICE.CTRLB.bit.UPRSM = 1; +} + /*------------------------------------------------------------------*/ /* DCD Endpoint port *------------------------------------------------------------------*/ @@ -267,12 +279,42 @@ USB_TRFAIL1_PERR_0, USB_TRFAIL1_PERR_1, USB_TRFAIL1_PERR_2, USB_TRFAIL1_PERR_3, USB_TRFAIL1_PERR_4, USB_TRFAIL1_PERR_5, USB_TRFAIL1_PERR_6, USB_TRFAIL1_PERR_7, USB_UPRSM, USB_WAKEUP */ void USB_0_Handler(void) { - uint32_t int_status = USB->DEVICE.INTFLAG.reg; + uint32_t int_status = USB->DEVICE.INTFLAG.reg & USB->DEVICE.INTENSET.reg; /*------------- Interrupt Processing -------------*/ + // SAMD doesn't distinguish between Suspend and Disconnect state. + // Both condition will cause SUSPEND interrupt triggered. + // To prevent being triggered when D+/D- are not stable, SUSPEND interrupt is only + // enabled when we received SET_ADDRESS request and cleared on Bus Reset + if ( int_status & USB_DEVICE_INTFLAG_SUSPEND ) + { + USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_SUSPEND; + + // Enable wakeup interrupt + USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_WAKEUP; // clear pending + USB->DEVICE.INTENSET.reg = USB_DEVICE_INTFLAG_WAKEUP; + + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + } + + // Wakeup interrupt is only enabled when we got suspended. + // Wakeup interrupt will disable itself + if ( int_status & USB_DEVICE_INTFLAG_WAKEUP ) + { + USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_WAKEUP; + + // disable wakeup interrupt itself + USB->DEVICE.INTENCLR.reg = USB_DEVICE_INTFLAG_WAKEUP; + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); + } + if ( int_status & USB_DEVICE_INTFLAG_EORST ) { - USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTENCLR_EORST; + USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_EORST; + + // Disable both suspend and wakeup interrupt + USB->DEVICE.INTENCLR.reg = USB_DEVICE_INTFLAG_WAKEUP | USB_DEVICE_INTFLAG_SUSPEND; + bus_reset(); dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); } @@ -280,6 +322,7 @@ void USB_0_Handler(void) { // Setup packet received. maybe_handle_setup_packet(); } + /* USB_SOF_HSOF */ void USB_1_Handler(void) { USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_SOF; diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 3c2b6d45b..1f8e94420 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -177,10 +177,9 @@ static void xact_in_prepare(uint8_t epnum) //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ -bool dcd_init (uint8_t rhport) +void dcd_init (uint8_t rhport) { (void) rhport; - return true; } void dcd_int_enable(uint8_t rhport) @@ -200,13 +199,36 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) (void) rhport; (void) dev_addr; // Set Address is automatically update by hw controller, nothing to do + + // Enable usbevent for suspend and resume detection + // Since the bus signal D+/D- are stable now. + + // Clear current pending first + NRF_USBD->EVENTCAUSE |= NRF_USBD->EVENTCAUSE; + NRF_USBD->EVENTS_USBEVENT = 0; + + NRF_USBD->INTENSET = USBD_INTEN_USBEVENT_Msk; } void dcd_set_config (uint8_t rhport, uint8_t config_num) { (void) rhport; (void) config_num; - // Nothing to do +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; + + // Bring controller out of low power mode + NRF_USBD->LOWPOWER = 0; + + // Initiate RESUME signal + NRF_USBD->DPDMVALUE = USBD_DPDMVALUE_STATE_Resume; + NRF_USBD->TASKS_DPDMDRIVE = 1; + + // TODO There is no USBEVENT Resume interrupt + // We may manually raise DCD_EVENT_RESUME event here } //--------------------------------------------------------------------+ @@ -358,19 +380,44 @@ void USBD_IRQHandler(void) } } - /*------------- Interrupt Processing -------------*/ if ( int_status & USBD_INTEN_USBRESET_Msk ) { bus_reset(); dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); } + if ( int_status & USBD_INTEN_SOF_Msk ) + { + dcd_event_bus_signal(0, DCD_EVENT_SOF, true); + } + + if ( int_status & USBD_INTEN_USBEVENT_Msk ) + { + uint32_t const evt_cause = NRF_USBD->EVENTCAUSE & (USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk); + NRF_USBD->EVENTCAUSE = evt_cause; // clear interrupt + + if ( evt_cause & USBD_EVENTCAUSE_SUSPEND_Msk ) + { + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); + + // Put controller into low power mode + NRF_USBD->LOWPOWER = 1; + + // Leave HFXO disable to application, since it may be used by other + } + + if ( evt_cause & USBD_EVENTCAUSE_RESUME_Msk ) + { + dcd_event_bus_signal(0, DCD_EVENT_RESUME , true); + } + } + if ( int_status & EDPT_END_ALL_MASK ) { // DMA complete move data from SRAM -> Endpoint edpt_dma_end(); } - + // Setup tokens are specific to the Control endpoint. if ( int_status & USBD_INTEN_EP0SETUP_Msk ) { @@ -502,12 +549,6 @@ void USBD_IRQHandler(void) } } } - - // SOF interrupt - if ( int_status & USBD_INTEN_SOF_Msk ) - { - dcd_event_bus_signal(0, DCD_EVENT_SOF, true); - } } #endif diff --git a/src/portable/nordic/nrf5x/hal_nrf5x.c b/src/portable/nordic/nrf5x/hal_nrf5x.c index 8477a56cd..730b580b4 100644 --- a/src/portable/nordic/nrf5x/hal_nrf5x.c +++ b/src/portable/nordic/nrf5x/hal_nrf5x.c @@ -212,8 +212,8 @@ void tusb_hal_nrf_power_event (uint32_t event) nrf_usbd_isosplit_set(USBD_ISOSPLIT_SPLIT_HalfIN); - // Enable interrupt. SOF is used as CDC auto flush - NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_EPDATA_Msk | + // Enable interrupt + NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_EPDATA_Msk | USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk; // Enable interrupt, priorities should be set by application diff --git a/src/portable/nxp/lpc11_13_15/dcd_lpc11_13_15.c b/src/portable/nxp/lpc11_13_15/dcd_lpc11_13_15.c index 65b345957..fff29d5eb 100644 --- a/src/portable/nxp/lpc11_13_15/dcd_lpc11_13_15.c +++ b/src/portable/nxp/lpc11_13_15/dcd_lpc11_13_15.c @@ -126,22 +126,31 @@ static inline uint8_t ep_addr2id(uint8_t endpoint_addr) //--------------------------------------------------------------------+ // CONTROLLER API //--------------------------------------------------------------------+ -void dcd_int_enable(uint8_t rhport) +void dcd_init(uint8_t rhport) { (void) rhport; - NVIC_EnableIRQ(USB0_IRQn); + + LPC_USB->EPLISTSTART = (uint32_t) _dcd.ep; + LPC_USB->DATABUFSTART = SRAM_REGION; + + LPC_USB->INTSTAT = LPC_USB->INTSTAT; // clear all pending interrupt + LPC_USB->INTEN = INT_DEVICE_STATUS_MASK; + LPC_USB->DEVCMDSTAT |= CMDSTAT_DEVICE_ENABLE_MASK | CMDSTAT_DEVICE_CONNECT_MASK | + CMDSTAT_RESET_CHANGE_MASK | CMDSTAT_CONNECT_CHANGE_MASK | CMDSTAT_SUSPEND_CHANGE_MASK; + + NVIC_ClearPendingIRQ(USB0_IRQn); } -void dcd_int_disable(uint8_t rhport) +void dcd_int_enable(uint8_t rhport) { (void) rhport; - NVIC_DisableIRQ(USB0_IRQn); + NVIC_EnableIRQ(USB0_IRQn); } -void dcd_set_config(uint8_t rhport, uint8_t config_num) +void dcd_int_disable(uint8_t rhport) { (void) rhport; - (void) config_num; + NVIC_DisableIRQ(USB0_IRQn); } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) @@ -153,21 +162,15 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) LPC_USB->DEVCMDSTAT |= dev_addr; } -bool dcd_init(uint8_t rhport) +void dcd_set_config(uint8_t rhport, uint8_t config_num) { (void) rhport; + (void) config_num; +} - LPC_USB->EPLISTSTART = (uint32_t) _dcd.ep; - LPC_USB->DATABUFSTART = SRAM_REGION; - - LPC_USB->INTSTAT = LPC_USB->INTSTAT; // clear all pending interrupt - LPC_USB->INTEN = INT_DEVICE_STATUS_MASK; - LPC_USB->DEVCMDSTAT |= CMDSTAT_DEVICE_ENABLE_MASK | CMDSTAT_DEVICE_CONNECT_MASK | - CMDSTAT_RESET_CHANGE_MASK | CMDSTAT_CONNECT_CHANGE_MASK | CMDSTAT_SUSPEND_CHANGE_MASK; - - NVIC_EnableIRQ(USB0_IRQn); - - return true; +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; } //--------------------------------------------------------------------+ @@ -339,7 +342,7 @@ void USB_IRQHandler(void) // Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration. if (dev_cmd_stat & CMDSTAT_DEVICE_ADDR_MASK) { - dcd_event_bus_signal(0, DCD_EVENT_SUSPENDED, true); + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } } } diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index f18a91b1c..30252f56d 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -166,7 +166,7 @@ static void bus_reset(void) tu_memclr(&_dcd, sizeof(dcd_data_t)); } -bool dcd_init(uint8_t rhport) +void dcd_init(uint8_t rhport) { (void) rhport; @@ -185,9 +185,6 @@ bool dcd_init(uint8_t rhport) // USB IRQ priority should be set by application previously NVIC_ClearPendingIRQ(USB_IRQn); - NVIC_EnableIRQ(USB_IRQn); - - return true; } void dcd_int_enable(uint8_t rhport) @@ -217,6 +214,11 @@ void dcd_set_config(uint8_t rhport, uint8_t config_num) sie_write(SIE_CMDCODE_CONFIGURE_DEVICE, 1, 1); } +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; +} + //--------------------------------------------------------------------+ // CONTROL HELPER //--------------------------------------------------------------------+ @@ -481,7 +483,7 @@ static void bus_event_isr(uint8_t rhport) { if (dev_status & SIE_DEV_STATUS_SUSPEND_MASK) { - dcd_event_bus_signal(rhport, DCD_EVENT_SUSPENDED, true); + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); } else { diff --git a/src/portable/nxp/lpc18_43/dcd_lpc18_43.c b/src/portable/nxp/lpc18_43/dcd_lpc18_43.c index a92a1c7b1..5c2d27d92 100644 --- a/src/portable/nxp/lpc18_43/dcd_lpc18_43.c +++ b/src/portable/nxp/lpc18_43/dcd_lpc18_43.c @@ -121,7 +121,7 @@ static void bus_reset(uint8_t rhport) p_dcd->qhd[0].int_on_setup = 1; // OUT only } -bool dcd_init(uint8_t rhport) +void dcd_init(uint8_t rhport) { LPC_USBHS_T* const lpc_usb = LPC_USB[rhport]; dcd_data_t* p_dcd = dcd_data_ptr[rhport]; @@ -134,8 +134,6 @@ bool dcd_init(uint8_t rhport) lpc_usb->USBCMD_D &= ~0x00FF0000; // Interrupt Threshold Interval = 0 lpc_usb->USBCMD_D |= TU_BIT(0); // connect - - return true; } void dcd_int_enable(uint8_t rhport) @@ -163,6 +161,11 @@ void dcd_set_config(uint8_t rhport, uint8_t config_num) // nothing to do } +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; +} + //--------------------------------------------------------------------+ // HELPER //--------------------------------------------------------------------+ @@ -303,7 +306,7 @@ void hal_dcd_isr(uint8_t rhport) // Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration. if ((lpc_usb->DEVICEADDR >> 25) & 0x0f) { - dcd_event_bus_signal(rhport, DCD_EVENT_SUSPENDED, true); + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); } } } diff --git a/src/portable/st/stm32f3/dcd_stm32f3.c b/src/portable/st/stm32f3/dcd_stm32f3.c index 138c454a7..023037474 100644 --- a/src/portable/st/stm32f3/dcd_stm32f3.c +++ b/src/portable/st/stm32f3/dcd_stm32f3.c @@ -35,10 +35,8 @@ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ - -bool dcd_init (uint8_t rhport) +void dcd_init (uint8_t rhport) { - return true; } // Enable device interrupt @@ -57,6 +55,14 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) void dcd_set_config (uint8_t rhport, uint8_t config_num) {} +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { return false; diff --git a/src/portable/st/stm32f4/dcd_stm32f4.c b/src/portable/st/stm32f4/dcd_stm32f4.c index db72f92d3..f7128344d 100644 --- a/src/portable/st/stm32f4/dcd_stm32f4.c +++ b/src/portable/st/stm32f4/dcd_stm32f4.c @@ -128,7 +128,7 @@ static void end_of_reset(void) { /*------------------------------------------------------------------*/ /* Controller API *------------------------------------------------------------------*/ -bool dcd_init (uint8_t rhport) +void dcd_init (uint8_t rhport) { (void) rhport; @@ -161,8 +161,6 @@ bool dcd_init (uint8_t rhport) // Enable pullup, enable peripheral. USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBUSBSEN | USB_OTG_GCCFG_PWRDWN; - - return true; } void dcd_int_enable (uint8_t rhport) @@ -196,6 +194,11 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num) // Nothing to do } +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; +} + /*------------------------------------------------------------------*/ /* DCD Endpoint port *------------------------------------------------------------------*/ |
