diff options
| author | HiFiPhile <[email protected]> | 2024-05-13 22:51:25 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-05-13 22:51:25 +0200 |
| commit | ae01de246421df8638f05cab7b1c6e15e0184952 (patch) | |
| tree | c9e03cee143f75fcfd6a43ed3648f6ce7b7bf55c /src/device | |
| parent | 7cf1bdd2848d6c36e9659acaf77c83a1fa99d04f (diff) | |
| parent | ad734e658cc9e39021a93fc21e077f1b1709c0ff (diff) | |
Merge pull request #2416 from Rocky04/test-mode-support
Add DWC2 Test Mode Support
Diffstat (limited to 'src/device')
| -rw-r--r-- | src/device/dcd.h | 15 | ||||
| -rw-r--r-- | src/device/usbd.c | 63 |
2 files changed, 71 insertions, 7 deletions
diff --git a/src/device/dcd.h b/src/device/dcd.h index d4f105aa3..9447d6d9d 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -97,6 +97,14 @@ typedef struct TU_ATTR_ALIGNED(4) { }; } dcd_event_t; +typedef enum { + TEST_J = 1, + TEST_K, + TEST_SE0_NAK, + TEST_PACKET, + TEST_FORCE_ENABLE, +} test_mode_t; + //TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct"); //--------------------------------------------------------------------+ @@ -149,6 +157,13 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; // Enable/Disable Start-of-frame interrupt. Default is disabled void dcd_sof_enable(uint8_t rhport, bool en); +#if CFG_TUD_TEST_MODE +// Check if the test mode is supported, returns true is test mode selector is supported +bool dcd_check_test_mode_support(test_mode_t test_selector) TU_ATTR_WEAK; + +// Put device into a test mode (needs power cycle to quit) +void dcd_enter_test_mode(uint8_t rhport, test_mode_t test_selector) TU_ATTR_WEAK; +#endif //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index e33f39bcf..25d890dc7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -313,7 +313,9 @@ TU_ATTR_ALWAYS_INLINE static inline bool queue_event(dcd_event_t const * event, 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); - +#if CFG_TUD_TEST_MODE +static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +#endif // from usbd_control.c void usbd_control_reset(void); void usbd_control_set_request(tusb_control_request_t const *request); @@ -753,14 +755,47 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const break; case TUSB_REQ_SET_FEATURE: - // Only support remote wakeup for device feature - TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); + // Handle the feature selector + switch(p_request->wValue) + { + // Support for remote wakeup + case TUSB_REQ_FEATURE_REMOTE_WAKEUP: + TU_LOG_USBD(" Enable Remote Wakeup\r\n"); - TU_LOG_USBD(" Enable Remote Wakeup\r\n"); + // Host may enable remote wake up before suspending especially HID device + _usbd_dev.remote_wakeup_en = true; + tud_control_status(rhport, p_request); + break; - // Host may enable remote wake up before suspending especially HID device - _usbd_dev.remote_wakeup_en = true; - tud_control_status(rhport, p_request); +#if CFG_TUD_TEST_MODE + // Support for TEST_MODE + case TUSB_REQ_FEATURE_TEST_MODE: { + // Only handle the test mode if supported and valid + TU_VERIFY(dcd_enter_test_mode && dcd_check_test_mode_support && 0 == tu_u16_low(p_request->wIndex)); + + uint8_t selector = tu_u16_high(p_request->wIndex); + + // Stall request if the selected test mode isn't supported + if (!dcd_check_test_mode_support((test_mode_t)selector)) + { + TU_LOG_USBD(" Unsupported Test Mode (test selector index: %d)\r\n", selector); + + return false; + } + + // Acknowledge request + tud_control_status(rhport, p_request); + + TU_LOG_USBD(" Enter Test Mode (test selector index: %d)\r\n", selector); + + usbd_control_set_complete_callback(process_test_mode_cb); + break; + } +#endif /* CFG_TUD_TEST_MODE */ + + // Stall unsupported feature selector + default: return false; + } break; case TUSB_REQ_CLEAR_FEATURE: @@ -1088,6 +1123,20 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const } } +#if CFG_TUD_TEST_MODE +static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + // At this point it should already be ensured that dcd_enter_test_mode() is defined + + // Only enter the test mode after the request for it has completed + TU_VERIFY(CONTROL_STAGE_ACK == stage); + + dcd_enter_test_mode(rhport, (test_mode_t)tu_u16_high(request->wIndex)); + + return true; +} +#endif /* CFG_TUD_TEST_MODE */ + //--------------------------------------------------------------------+ // DCD Event Handler //--------------------------------------------------------------------+ |
