Skip to content

Commit ae01de2

Browse files
authored
Merge pull request #2416 from Rocky04/test-mode-support
Add DWC2 Test Mode Support
2 parents 7cf1bdd + ad734e6 commit ae01de2

File tree

5 files changed

+100
-7
lines changed

5 files changed

+100
-7
lines changed

src/common/tusb_mcu.h

+3
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@
195195
#elif TU_CHECK_MCU(OPT_MCU_STM32F4)
196196
#define TUP_USBIP_DWC2
197197
#define TUP_USBIP_DWC2_STM32
198+
#define TUP_USBIP_DWC2_TEST_MODE
198199

199200
// For most mcu, FS has 4, HS has 6. TODO 446/469/479 HS has 9
200201
#define TUP_DCD_ENDPOINT_MAX 6
@@ -209,6 +210,7 @@
209210
// MCU with on-chip HS Phy
210211
#if defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F733xx)
211212
#define TUP_RHPORT_HIGHSPEED 1 // Port0: FS, Port1: HS
213+
#define TUP_USBIP_DWC2_TEST_MODE
212214
#endif
213215

214216
#elif TU_CHECK_MCU(OPT_MCU_STM32H7)
@@ -277,6 +279,7 @@
277279
defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx)
278280
#define TUP_DCD_ENDPOINT_MAX 9
279281
#define TUP_RHPORT_HIGHSPEED 1
282+
#define TUP_USBIP_DWC2_TEST_MODE
280283
#else
281284
#define TUP_DCD_ENDPOINT_MAX 6
282285
#endif

src/device/dcd.h

+15
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ typedef struct TU_ATTR_ALIGNED(4) {
9797
};
9898
} dcd_event_t;
9999

100+
typedef enum {
101+
TEST_J = 1,
102+
TEST_K,
103+
TEST_SE0_NAK,
104+
TEST_PACKET,
105+
TEST_FORCE_ENABLE,
106+
} test_mode_t;
107+
100108
//TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct");
101109

102110
//--------------------------------------------------------------------+
@@ -149,6 +157,13 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK;
149157
// Enable/Disable Start-of-frame interrupt. Default is disabled
150158
void dcd_sof_enable(uint8_t rhport, bool en);
151159

160+
#if CFG_TUD_TEST_MODE
161+
// Check if the test mode is supported, returns true is test mode selector is supported
162+
bool dcd_check_test_mode_support(test_mode_t test_selector) TU_ATTR_WEAK;
163+
164+
// Put device into a test mode (needs power cycle to quit)
165+
void dcd_enter_test_mode(uint8_t rhport, test_mode_t test_selector) TU_ATTR_WEAK;
166+
#endif
152167
//--------------------------------------------------------------------+
153168
// Endpoint API
154169
//--------------------------------------------------------------------+

src/device/usbd.c

+56-7
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,9 @@ TU_ATTR_ALWAYS_INLINE static inline bool queue_event(dcd_event_t const * event,
313313
static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request);
314314
static bool process_set_config(uint8_t rhport, uint8_t cfg_num);
315315
static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request);
316-
316+
#if CFG_TUD_TEST_MODE
317+
static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
318+
#endif
317319
// from usbd_control.c
318320
void usbd_control_reset(void);
319321
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
753755
break;
754756

755757
case TUSB_REQ_SET_FEATURE:
756-
// Only support remote wakeup for device feature
757-
TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
758+
// Handle the feature selector
759+
switch(p_request->wValue)
760+
{
761+
// Support for remote wakeup
762+
case TUSB_REQ_FEATURE_REMOTE_WAKEUP:
763+
TU_LOG_USBD(" Enable Remote Wakeup\r\n");
764+
765+
// Host may enable remote wake up before suspending especially HID device
766+
_usbd_dev.remote_wakeup_en = true;
767+
tud_control_status(rhport, p_request);
768+
break;
758769

759-
TU_LOG_USBD(" Enable Remote Wakeup\r\n");
770+
#if CFG_TUD_TEST_MODE
771+
// Support for TEST_MODE
772+
case TUSB_REQ_FEATURE_TEST_MODE: {
773+
// Only handle the test mode if supported and valid
774+
TU_VERIFY(dcd_enter_test_mode && dcd_check_test_mode_support && 0 == tu_u16_low(p_request->wIndex));
760775

761-
// Host may enable remote wake up before suspending especially HID device
762-
_usbd_dev.remote_wakeup_en = true;
763-
tud_control_status(rhport, p_request);
776+
uint8_t selector = tu_u16_high(p_request->wIndex);
777+
778+
// Stall request if the selected test mode isn't supported
779+
if (!dcd_check_test_mode_support((test_mode_t)selector))
780+
{
781+
TU_LOG_USBD(" Unsupported Test Mode (test selector index: %d)\r\n", selector);
782+
783+
return false;
784+
}
785+
786+
// Acknowledge request
787+
tud_control_status(rhport, p_request);
788+
789+
TU_LOG_USBD(" Enter Test Mode (test selector index: %d)\r\n", selector);
790+
791+
usbd_control_set_complete_callback(process_test_mode_cb);
792+
break;
793+
}
794+
#endif /* CFG_TUD_TEST_MODE */
795+
796+
// Stall unsupported feature selector
797+
default: return false;
798+
}
764799
break;
765800

766801
case TUSB_REQ_CLEAR_FEATURE:
@@ -1088,6 +1123,20 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
10881123
}
10891124
}
10901125

1126+
#if CFG_TUD_TEST_MODE
1127+
static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
1128+
{
1129+
// At this point it should already be ensured that dcd_enter_test_mode() is defined
1130+
1131+
// Only enter the test mode after the request for it has completed
1132+
TU_VERIFY(CONTROL_STAGE_ACK == stage);
1133+
1134+
dcd_enter_test_mode(rhport, (test_mode_t)tu_u16_high(request->wIndex));
1135+
1136+
return true;
1137+
}
1138+
#endif /* CFG_TUD_TEST_MODE */
1139+
10911140
//--------------------------------------------------------------------+
10921141
// DCD Event Handler
10931142
//--------------------------------------------------------------------+

src/portable/synopsys/dwc2/dcd_dwc2.c

+21
Original file line numberDiff line numberDiff line change
@@ -1195,4 +1195,25 @@ void dcd_int_handler(uint8_t rhport) {
11951195
// }
11961196
}
11971197

1198+
#if defined(TUP_USBIP_DWC2_TEST_MODE) && CFG_TUD_TEST_MODE
1199+
1200+
bool dcd_check_test_mode_support(test_mode_t test_selector) {
1201+
// Check if test mode selector is unsupported
1202+
if (TEST_FORCE_ENABLE < test_selector || TEST_J > test_selector) {
1203+
return false;
1204+
}
1205+
1206+
return true;
1207+
}
1208+
1209+
void dcd_enter_test_mode(uint8_t rhport, test_mode_t test_selector) {
1210+
// Get port address...
1211+
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
1212+
1213+
// Enable the test mode
1214+
dwc2->dctl = (dwc2->dctl & ~DCTL_TCTL_Msk) | (test_selector << DCTL_TCTL_Pos);
1215+
}
1216+
1217+
#endif /* TUP_USBIP_DWC2_TEST_MODE && CFG_TUD_TEST_MODE */
1218+
11981219
#endif

src/tusb_option.h

+5
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,11 @@
364364
#define CFG_TUD_INTERFACE_MAX 16
365365
#endif
366366

367+
// USB 2.0 compliance test mode support
368+
#ifndef CFG_TUD_TEST_MODE
369+
#define CFG_TUD_TEST_MODE 0
370+
#endif
371+
367372
//------------- Device Class Driver -------------//
368373
#ifndef CFG_TUD_BTH
369374
#define CFG_TUD_BTH 0

0 commit comments

Comments
 (0)