5 #include "sw/device/lib/testing/usb_testutils_controlep.h"
10 #include "sw/device/lib/testing/test_framework/check.h"
11 #include "sw/device/lib/testing/usb_testutils.h"
13 #define MODULE_ID MAKE_MODULE_ID('u', 't', 'c')
16 static const uint8_t kDevDscr[] = {
40 typedef enum usb_setup_req {
41 kUsbSetupReqGetStatus = 0,
42 kUsbSetupReqClearFeature = 1,
43 kUsbSetupReqSetFeature = 3,
44 kUsbSetupReqSetAddress = 5,
45 kUsbSetupReqGetDescriptor = 6,
46 kUsbSetupReqSetDescriptor = 7,
47 kUsbSetupReqGetConfiguration = 8,
48 kUsbSetupReqSetConfiguration = 9,
49 kUsbSetupReqGetInterface = 10,
50 kUsbSetupReqSetInterface = 11,
51 kUsbSetupReqSynchFrame = 12
55 typedef enum vendor_setup_req {
56 kVendorSetupReqTestConfig = 0x7C,
57 kVendorSetupReqTestStatus = 0x7E
60 typedef enum usb_req_type {
61 kUsbReqTypeRecipientMask = 0x1f,
62 kUsbReqTypeDevice = 0,
63 kUsbReqTypeInterface = 1,
64 kUsbReqTypeEndpoint = 2,
66 kUsbReqTypeTypeMask = 0x60,
67 kUsbReqTypeStandard = 0,
68 kUsbReqTypeClass = 0x20,
69 kUsbReqTypeVendor = 0x40,
70 kUsbReqTypeReserved = 0x60,
71 kUsbReqTypeDirMask = 0x80,
72 kUsbReqTypeDirH2D = 0x00,
73 kUsbReqTypeDirD2H = 0x80,
76 typedef enum usb_desc_type {
77 kUsbDescTypeDevice = 1,
78 kUsbDescTypeConfiguration,
80 kUsbDescTypeInterface,
82 kUsbDescTypeDeviceQualifier,
83 kUsbDescTypeOtherSpeedConfiguration,
84 kUsbDescTypeInterfacePower,
87 typedef enum usb_feature_req {
88 kUsbFeatureEndpointHalt = 0,
89 kUsbFeatureDeviceRemoteWakeup = 1,
90 kUsbFeatureTestMode = 2,
91 kUsbFeatureBHnpEnable = 3,
92 kUsbFeatureAHnpSupport = 4,
93 kUsbFeatureAAltHnpSupport = 5
96 typedef enum usb_status {
97 kUsbStatusSelfPowered = 1,
98 kUsbStatusRemWake = 2,
104 uint8_t bmRequestType,
105 uint8_t bRequest, uint16_t wValue,
106 uint16_t wIndex, uint16_t wLength) {
110 size_t bytes_written;
113 .
number = (uint8_t)wIndex,
114 .direction = ((bmRequestType & 0x80U) != 0U),
119 case kUsbSetupReqGetDescriptor:
120 if ((wValue & 0xff00) == 0x100) {
122 len =
sizeof(kDevDscr);
128 CHECK(bytes_written == len);
130 return kUsbTestutilsCtWaitIn;
131 }
else if ((wValue & 0xff00) == 0x200) {
132 usb_testutils_xfr_flags_t flags = kUsbTestutilsXfrDoubleBuffered;
135 len = ctctx->cfg_dscr_len;
138 }
else if (wLength > len) {
141 flags |= kUsbTestutilsXfrEmployZLP;
144 if (len >= USBDEV_MAX_PACKET_SIZE) {
148 if (UNWRAP(usb_testutils_transfer_send(ctx, 0U, ctctx->
cfg_dscr, len,
150 return kUsbTestutilsCtError;
154 ctx->dev, &buffer, ctctx->
cfg_dscr, len, &bytes_written));
157 return kUsbTestutilsCtWaitIn;
159 return kUsbTestutilsCtError;
161 case kUsbSetupReqSetAddress:
163 ctctx->
new_dev = (uint8_t)(wValue & 0x7fU);
166 return kUsbTestutilsCtAddrStatIn;
168 case kUsbSetupReqSetConfiguration:
174 return kUsbTestutilsCtCfgStatIn;
176 case kUsbSetupReqGetConfiguration:
183 ctx->dev, &buffer, &ctctx->
usb_config, len, &bytes_written));
185 return kUsbTestutilsCtWaitIn;
187 case kUsbSetupReqSetFeature:
188 if (wValue == kUsbFeatureEndpointHalt) {
193 return kUsbTestutilsCtStatIn;
195 return kUsbTestutilsCtError;
197 case kUsbSetupReqClearFeature:
198 if (wValue == kUsbFeatureEndpointHalt) {
206 return kUsbTestutilsCtStatIn;
209 return kUsbTestutilsCtError;
211 case kUsbSetupReqGetStatus:
213 type = bmRequestType & kUsbReqTypeRecipientMask;
214 if (type == kUsbReqTypeDevice) {
215 stat = kUsbStatusSelfPowered;
216 }
else if (type == kUsbReqTypeEndpoint) {
220 stat = halted ? kUsbStatusHalted : 0;
229 len, &bytes_written));
231 return kUsbTestutilsCtWaitIn;
233 case kUsbSetupReqSetInterface:
237 return kUsbTestutilsCtStatIn;
239 case kUsbSetupReqGetInterface:
247 len, &bytes_written));
249 return kUsbTestutilsCtWaitIn;
251 case kUsbSetupReqSynchFrame:
259 len, &bytes_written));
261 return kUsbTestutilsCtWaitIn;
267 if ((bmRequestType & kUsbReqTypeTypeMask) == kUsbReqTypeVendor &&
269 switch ((vendor_setup_req_t)bRequest) {
270 case kVendorSetupReqTestConfig: {
273 len = ctctx->test_dscr_len;
278 ctx->dev, &buffer, ctctx->
test_dscr, len, &bytes_written));
280 return kUsbTestutilsCtWaitIn;
282 case kVendorSetupReqTestStatus: {
287 return kUsbTestutilsCtError;
289 return kUsbTestutilsCtError;
292 static status_t ctrl_tx_done(
void *ctctx_v, usb_testutils_xfr_result_t result) {
296 TRC_C(
'A' + ctctx->ctrlstate);
297 switch (ctctx->ctrlstate) {
298 case kUsbTestutilsCtAddrStatIn:
303 ctctx->ctrlstate = kUsbTestutilsCtIdle;
305 ctctx->device_state = kUsbTestutilsDeviceAddressed;
307 case kUsbTestutilsCtCfgStatIn:
311 ctctx->ctrlstate = kUsbTestutilsCtIdle;
313 ctctx->device_state = kUsbTestutilsDeviceConfigured;
316 ctctx->device_state = kUsbTestutilsDeviceAddressed;
319 case kUsbTestutilsCtStatIn:
320 ctctx->ctrlstate = kUsbTestutilsCtIdle;
322 case kUsbTestutilsCtWaitIn:
323 ctctx->ctrlstate = kUsbTestutilsCtStatOut;
329 TRC_S(
"USB: unexpected IN ");
330 TRC_I((ctctx->ctrlstate << 24), 32);
342 TRC_C(
'0' + ctctx->ctrlstate);
343 size_t bytes_written;
346 switch (ctctx->ctrlstate) {
347 case kUsbTestutilsCtIdle:
350 alignas(uint32_t) uint8_t bp[8];
352 sizeof(bp), &bytes_written));
353 uint8_t bmRequestType = bp[0];
354 uint8_t bRequest = bp[1];
355 uint16_t wValue = (uint16_t)((bp[3] << 8) | bp[2]);
356 uint16_t wIndex = (uint16_t)((bp[5] << 8) | bp[4]);
357 uint16_t wLength = (uint16_t)((bp[7] << 8) | bp[6]);
358 TRC_C(
'0' + bRequest);
360 ctctx->ctrlstate = setup_req(ctctx, ctx, bmRequestType, bRequest,
361 wValue, wIndex, wLength);
362 if (ctctx->ctrlstate != kUsbTestutilsCtError) {
367 for (
int i = 0; i < packet_info.
length; i++) {
373 case kUsbTestutilsCtStatOut:
377 ctctx->ctrlstate = kUsbTestutilsCtIdle;
389 .direction = USBDEV_ENDPOINT_DIR_IN,
393 endpoint.
direction = USBDEV_ENDPOINT_DIR_OUT;
397 TRC_I((ctctx->ctrlstate << 24) | ((uint32_t)packet_info.
is_setup << 16) |
404 ctctx->ctrlstate = kUsbTestutilsCtIdle;
409 static status_t ctrl_reset(
void *ctctx_v) {
412 ctctx->ctrlstate = kUsbTestutilsCtIdle;
415 ctctx->device_state = kUsbTestutilsDeviceDefault;
421 const uint8_t *cfg_dscr,
423 const uint8_t *test_dscr,
424 size_t test_dscr_len) {
426 TRY(usb_testutils_endpoint_setup(
427 ctx, ep, kUsbTransferTypeControl, kUsbTransferTypeControl,
428 kUsbdevOutMessage, ctctx, ctrl_tx_done, ctrl_rx, NULL, ctrl_reset));
430 ctctx->ctrlstate = kUsbTestutilsCtIdle;
432 ctctx->cfg_dscr_len = cfg_dscr_len;
434 ctctx->test_dscr_len = test_dscr_len;
435 ctctx->device_state = kUsbTestutilsDeviceDefault;
446 status_t usb_testutils_controlep_config_wait(
452 uint32_t timeout_usecs = 8 * 1000;
460 uint64_t clk_cycles = 48 * timeout_usecs;
467 timeout_usecs = 30 * 1000000;
471 while (ctctx->device_state != kUsbTestutilsDeviceConfigured &&
473 TRY(usb_testutils_poll(ctx));
475 if (ctctx->device_state != kUsbTestutilsDeviceConfigured) {
477 return UNAVAILABLE();