Skip to content

Commit be35df9

Browse files
fkjagodzinskic1728p9
authored andcommitted
Tests: USB: Update endpoint tests
Fix the host script issues present on Windows machines. Add 0 B payload size to bulk endpoints test. Update halt and abort tests according to PR comments. Add an explicit request to start reading on OUT endpoints.
1 parent a34526d commit be35df9

File tree

3 files changed

+112
-49
lines changed

3 files changed

+112
-49
lines changed

TESTS/host_tests/pyusb_basic.py

Lines changed: 63 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ def get_interface(dev, interface, alternate=0):
5555
VENDOR_TEST_CTRL_OUT_STATUS_DELAY = 8
5656
VENDOR_TEST_CTRL_IN_SIZES = 9
5757
VENDOR_TEST_CTRL_OUT_SIZES = 10
58+
VENDOR_TEST_READ_START = 11
5859
VENDOR_TEST_UNSUPPORTED_REQUEST = 32
5960

6061
REQUEST_GET_STATUS = 0
@@ -982,38 +983,63 @@ def halt_ep_test(dev, ep_out, ep_in, ep_to_halt, log):
982983
"""
983984
MIN_HALT_DELAY = 0.01
984985
MAX_HALT_DELAY = 0.1
985-
delay = random.uniform(MIN_HALT_DELAY, MAX_HALT_DELAY)
986-
ctrl_kwargs = {
987-
'bmRequestType': build_request_type(CTRL_OUT, CTRL_TYPE_STANDARD, CTRL_RECIPIENT_ENDPOINT),
988-
'bRequest': REQUEST_SET_FEATURE,
989-
'wValue': FEATURE_ENDPOINT_HALT,
990-
'wIndex': ep_to_halt.bEndpointAddress}
986+
POST_HALT_DELAY = 0.1
991987
ctrl_error = Event()
992988

989+
for ep in (ep_out, ep_in):
990+
try:
991+
if (usb.control.get_status(dev, ep) == 1):
992+
raise_unconditionally(lineno(), 'Endpoints must NOT be halted at the start of this test')
993+
except usb.core.USBError as err:
994+
raise_unconditionally(lineno(), 'Unable to get endpoint status ({!r}).'.format(err))
995+
993996
def timer_handler():
994997
"""Halt an endpoint using a USB control request."""
995998
try:
996-
dev.ctrl_transfer(**ctrl_kwargs)
999+
usb.control.set_feature(dev, FEATURE_ENDPOINT_HALT, ep_to_halt)
1000+
if (usb.control.get_status(dev, ep_to_halt) != 1):
1001+
raise RuntimeError('Invalid endpoint status after halt operation')
9971002
except Exception as err:
998-
log('Endpoint {:#04x} halt failed ({}).'.format(ctrl_kwargs['wIndex'], err))
9991003
ctrl_error.set()
1004+
log('Endpoint {:#04x} halt failed ({}).'.format(ep_to_halt.bEndpointAddress, err))
1005+
# Whether the halt operation was successful or not,
1006+
# wait a bit so the main thread has a chance to run into a USBError
1007+
# or report the failure of halt operation.
1008+
time.sleep(POST_HALT_DELAY)
10001009

1010+
delay = random.uniform(MIN_HALT_DELAY, MAX_HALT_DELAY)
10011011
delayed_halt = Timer(delay, timer_handler)
10021012
delayed_halt.start()
1003-
end_ts = time.time() + 1.5 * delay
1004-
try:
1005-
while time.time() < end_ts and not ctrl_error.is_set():
1006-
loopback_ep_test(ep_out, ep_in, ep_out.wMaxPacketSize)
1007-
except usb.core.USBError as err:
1008-
if err.errno not in (32, 110):
1009-
raise_unconditionally(lineno(), 'Unexpected error ({!r}).'.format(err))
1013+
# Keep transferring data to and from the device until one of the endpoints
1014+
# is halted.
1015+
while delayed_halt.is_alive():
10101016
if ctrl_error.is_set():
10111017
raise_unconditionally(lineno(), 'Halting endpoint {0.bEndpointAddress:#04x} failed'
10121018
.format(ep_to_halt))
1013-
else:
1014-
raise_unconditionally(lineno(), 'Halting endpoint {0.bEndpointAddress:#04x}'
1015-
' during transmission did not raise USBError.'
1016-
.format(ep_to_halt))
1019+
try:
1020+
loopback_ep_test(ep_out, ep_in, ep_out.wMaxPacketSize)
1021+
except usb.core.USBError as err:
1022+
try:
1023+
ep_status = usb.control.get_status(dev, ep_to_halt)
1024+
except usb.core.USBError as err:
1025+
raise_unconditionally(lineno(), 'Unable to get endpoint status ({!r}).'.format(err))
1026+
if ep_status == 1:
1027+
# OK, got USBError because of endpoint halt
1028+
return
1029+
else:
1030+
raise_unconditionally(lineno(), 'Unexpected error ({!r}).'.format(err))
1031+
raise_unconditionally(lineno(), 'Halting endpoint {0.bEndpointAddress:#04x}'
1032+
' during transmission did not raise USBError.'
1033+
.format(ep_to_halt))
1034+
1035+
1036+
def request_endpoint_read_start(dev, ep):
1037+
ctrl_kwargs = {
1038+
'bmRequestType': build_request_type(CTRL_OUT, CTRL_TYPE_VENDOR, CTRL_RECIPIENT_ENDPOINT),
1039+
'bRequest': VENDOR_TEST_READ_START,
1040+
'wValue': 0,
1041+
'wIndex': ep.bEndpointAddress}
1042+
dev.ctrl_transfer(**ctrl_kwargs)
10171043

10181044

10191045
USB_ERROR_FMT = str('Got {0!r} while testing endpoints '
@@ -1054,7 +1080,7 @@ def ep_test_data_correctness(dev, log, verbose=False):
10541080

10551081
if verbose:
10561082
log('Testing OUT/IN data correctness for bulk endpoint pair.')
1057-
for payload_size in range(1, bulk_out.wMaxPacketSize + 1):
1083+
for payload_size in range(bulk_out.wMaxPacketSize + 1):
10581084
try:
10591085
loopback_ep_test(bulk_out, bulk_in, payload_size)
10601086
except usb.USBError as err:
@@ -1113,21 +1139,19 @@ def ep_test_halt(dev, log, verbose=False):
11131139
while time.time() < end_ts:
11141140
halt_ep_test(dev, bulk_out, bulk_in, bulk_out, log)
11151141
bulk_out.clear_halt()
1116-
intf.set_altsetting() # Force the device to start reading data from all OUT endpoints again.
1142+
request_endpoint_read_start(dev, bulk_out)
11171143
halt_ep_test(dev, bulk_out, bulk_in, bulk_in, log)
11181144
bulk_in.clear_halt()
1119-
intf.set_altsetting() # Force the device to start reading data from all OUT endpoints again.
11201145

11211146
if verbose:
11221147
log('Testing endpoint halt at a random point of interrupt transmission.')
11231148
end_ts = time.time() + 1.0
11241149
while time.time() < end_ts:
11251150
halt_ep_test(dev, interrupt_out, interrupt_in, interrupt_out, log)
11261151
interrupt_out.clear_halt()
1127-
intf.set_altsetting() # Force the device to start reading data from all OUT endpoints again.
1152+
request_endpoint_read_start(dev, interrupt_out)
11281153
halt_ep_test(dev, interrupt_out, interrupt_in, interrupt_in, log)
1129-
interrupt_out.clear_halt()
1130-
intf.set_altsetting() # Force the device to start reading data from all OUT endpoints again.
1154+
interrupt_in.clear_halt()
11311155

11321156

11331157
def ep_test_parallel_transfers(dev, log, verbose=False):
@@ -1285,7 +1309,13 @@ def ep_test_abort(dev, log, verbose=False):
12851309
log('Testing aborting an in progress transfer for IN endpoints.')
12861310
for ep_in in (bulk_in, interrupt_in):
12871311
payload_size = (NUM_PACKETS_UNTIL_ABORT + NUM_PACKETS_AFTER_ABORT) * ep_in.wMaxPacketSize
1288-
payload_in = ep_in.read(payload_size)
1312+
payload_in = array.array('B')
1313+
while len(payload_in) < payload_size:
1314+
try:
1315+
packet = ep_in.read(ep_in.wMaxPacketSize)
1316+
payload_in.extend(packet)
1317+
except usb.core.USBError as err:
1318+
break
12891319
if verbose:
12901320
log('The size of data successfully received from endpoint {0.bEndpointAddress:#04x}: {1} B.'
12911321
.format(ep_in, len(payload_in)))
@@ -1303,8 +1333,13 @@ def ep_test_abort(dev, log, verbose=False):
13031333
log('Testing aborting an in progress transfer for OUT endpoints.')
13041334
for ep_out in (bulk_out, interrupt_out):
13051335
payload_size = (NUM_PACKETS_UNTIL_ABORT + NUM_PACKETS_AFTER_ABORT) * ep_out.wMaxPacketSize
1306-
payload_out = array.array('B', (0x01 for _ in range(payload_size)))
1307-
num_bytes_written = ep_out.write(payload_out)
1336+
payload_out = array.array('B', (0x01 for _ in range(ep_out.wMaxPacketSize)))
1337+
num_bytes_written = 0
1338+
while num_bytes_written < payload_size:
1339+
try:
1340+
num_bytes_written += ep_out.write(payload_out)
1341+
except usb.core.USBError:
1342+
break
13081343
if verbose:
13091344
log('The size of data successfully sent to endpoint {0.bEndpointAddress:#04x}: {1} B.'
13101345
.format(ep_out, num_bytes_written))

TESTS/usb_device/basic/USBEndpointTester.cpp

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#define VENDOR_TEST_CTRL_OUT 2
3030
#define VENDOR_TEST_CTRL_IN_SIZES 9
3131
#define VENDOR_TEST_CTRL_OUT_SIZES 10
32+
#define VENDOR_TEST_READ_START 11
3233

3334
#define EVENT_READY (1 << 0)
3435

@@ -130,6 +131,10 @@ USBEndpointTester::USBEndpointTester(USBPhy *phy, uint16_t vendor_id, uint16_t p
130131
_cnt_cb_int_in = 0;
131132
_cnt_cb_iso_out = 0;
132133
_cnt_cb_iso_in = 0;
134+
_num_packets_bulk_out_abort = 0;
135+
_num_packets_bulk_in_abort = 0;
136+
_num_packets_int_out_abort = 0;
137+
_num_packets_int_in_abort = 0;
133138

134139
EndpointResolver resolver(endpoint_table());
135140
resolver.endpoint_ctrl(64);
@@ -147,7 +152,6 @@ USBEndpointTester::USBEndpointTester(USBPhy *phy, uint16_t vendor_id, uint16_t p
147152
init();
148153
USBDevice::connect();
149154
flags.wait_any(EVENT_READY, osWaitForever, false);
150-
151155
}
152156

153157
USBEndpointTester::~USBEndpointTester()
@@ -217,6 +221,9 @@ void USBEndpointTester::callback_request(const setup_packet_t *setup)
217221
data = ctrl_buf;
218222
size = setup->wValue;
219223
break;
224+
case VENDOR_TEST_READ_START:
225+
result = (_request_read_start(setup)) ? Success : Failure;
226+
break;
220227
default:
221228
result = PassThrough;
222229
break;
@@ -225,6 +232,26 @@ void USBEndpointTester::callback_request(const setup_packet_t *setup)
225232
complete_request(result, data, size);
226233
}
227234

235+
bool USBEndpointTester::_request_read_start(const setup_packet_t *setup)
236+
{
237+
assert_locked();
238+
if (setup->bmRequestType.Recipient != ENDPOINT_RECIPIENT) {
239+
return false;
240+
}
241+
size_t ep_index = NUM_ENDPOINTS + 1;
242+
for (size_t i = 0; i < NUM_ENDPOINTS; i++) {
243+
if (_endpoints[i] == setup->wIndex) {
244+
ep_index = i;
245+
break;
246+
}
247+
}
248+
if (ep_index > NUM_ENDPOINTS) {
249+
return false;
250+
}
251+
endpoint_abort(_endpoints[ep_index]);
252+
return read_start(_endpoints[ep_index], _endpoint_buffs[ep_index], (*_endpoint_configs)[ep_index].max_packet);
253+
}
254+
228255
void USBEndpointTester::callback_request_xfer_done(const setup_packet_t *setup, bool aborted)
229256
{
230257
if (aborted) {
@@ -297,10 +324,10 @@ bool USBEndpointTester::_setup_interface(uint16_t interface, uint8_t alternate)
297324
_setup_non_zero_endpoints();
298325

299326
if (_abort_transfer_test && alternate >= 1) {
300-
_cnt_cb_bulk_out_abort = _cnt_cb_bulk_out;
301-
_cnt_cb_bulk_in_abort = _cnt_cb_bulk_in;
302-
_cnt_cb_int_out_abort = _cnt_cb_int_out;
303-
_cnt_cb_int_in_abort = _cnt_cb_int_in;
327+
_num_packets_bulk_out_abort = 0;
328+
_num_packets_bulk_in_abort = 0;
329+
_num_packets_int_out_abort = 0;
330+
_num_packets_int_in_abort = 0;
304331
start_ep_in_abort_test();
305332
}
306333
return true;
@@ -669,9 +696,9 @@ void USBEndpointTester::_cb_bulk_out(usb_ep_t endpoint)
669696
write_start(_endpoints[EP_BULK_IN], _endpoint_buffs[EP_BULK_IN], rx_size);
670697
} else {
671698
// Abort the transfer if enough data was received.
672-
uint32_t num_packets_received = _cnt_cb_bulk_out - _cnt_cb_bulk_out_abort;
699+
_num_packets_bulk_out_abort++;
673700
read_start(_endpoints[EP_BULK_OUT], _endpoint_buffs[EP_BULK_OUT], (*_endpoint_configs)[EP_BULK_OUT].max_packet);
674-
if (num_packets_received >= NUM_PACKETS_UNTIL_ABORT) {
701+
if (_num_packets_bulk_out_abort == NUM_PACKETS_UNTIL_ABORT) {
675702
endpoint_abort(endpoint);
676703
}
677704
}
@@ -686,14 +713,14 @@ void USBEndpointTester::_cb_bulk_in(usb_ep_t endpoint)
686713
// Receive more data from the host using the OUT endpoint.
687714
read_start(_endpoints[EP_BULK_OUT], _endpoint_buffs[EP_BULK_OUT], (*_endpoint_configs)[EP_BULK_OUT].max_packet);
688715
} else {
689-
uint32_t num_packets_sent = _cnt_cb_bulk_in - _cnt_cb_bulk_in_abort;
690-
if (num_packets_sent >= NUM_PACKETS_UNTIL_ABORT + NUM_PACKETS_AFTER_ABORT) {
716+
_num_packets_bulk_in_abort++;
717+
if (_num_packets_bulk_in_abort >= NUM_PACKETS_UNTIL_ABORT + NUM_PACKETS_AFTER_ABORT) {
691718
return;
692719
}
693720
// Abort the transfer if enough data was sent.
694-
memset(_endpoint_buffs[EP_BULK_IN], num_packets_sent, (*_endpoint_configs)[EP_BULK_IN].max_packet);
721+
memset(_endpoint_buffs[EP_BULK_IN], _num_packets_bulk_in_abort, (*_endpoint_configs)[EP_BULK_IN].max_packet);
695722
write_start(_endpoints[EP_BULK_IN], _endpoint_buffs[EP_BULK_IN], (*_endpoint_configs)[EP_BULK_IN].max_packet);
696-
if (num_packets_sent >= NUM_PACKETS_UNTIL_ABORT) {
723+
if (_num_packets_bulk_in_abort == NUM_PACKETS_UNTIL_ABORT) {
697724
endpoint_abort(endpoint);
698725
}
699726
}
@@ -710,9 +737,9 @@ void USBEndpointTester::_cb_int_out(usb_ep_t endpoint)
710737
write_start(_endpoints[EP_INT_IN], _endpoint_buffs[EP_INT_IN], rx_size);
711738
} else {
712739
// Abort the transfer if enough data was received.
713-
uint32_t num_packets_received = _cnt_cb_int_out - _cnt_cb_int_out_abort;
740+
_num_packets_int_out_abort++;
714741
read_start(_endpoints[EP_INT_OUT], _endpoint_buffs[EP_INT_OUT], (*_endpoint_configs)[EP_INT_OUT].max_packet);
715-
if (num_packets_received >= NUM_PACKETS_UNTIL_ABORT) {
742+
if (_num_packets_int_out_abort == NUM_PACKETS_UNTIL_ABORT) {
716743
endpoint_abort(endpoint);
717744
}
718745
}
@@ -726,14 +753,14 @@ void USBEndpointTester::_cb_int_in(usb_ep_t endpoint)
726753
// Receive more data from the host using the OUT endpoint.
727754
read_start(_endpoints[EP_INT_OUT], _endpoint_buffs[EP_INT_OUT], (*_endpoint_configs)[EP_INT_OUT].max_packet);
728755
} else {
729-
uint32_t num_packets_sent = _cnt_cb_int_in - _cnt_cb_int_in_abort;
730-
if (num_packets_sent >= NUM_PACKETS_UNTIL_ABORT + NUM_PACKETS_AFTER_ABORT) {
756+
_num_packets_int_in_abort++;
757+
if (_num_packets_int_in_abort >= NUM_PACKETS_UNTIL_ABORT + NUM_PACKETS_AFTER_ABORT) {
731758
return;
732759
}
733760
// Abort the transfer if enough data was sent.
734-
memset(_endpoint_buffs[EP_INT_IN], num_packets_sent, (*_endpoint_configs)[EP_INT_IN].max_packet);
761+
memset(_endpoint_buffs[EP_INT_IN], _num_packets_int_in_abort, (*_endpoint_configs)[EP_INT_IN].max_packet);
735762
write_start(_endpoints[EP_INT_IN], _endpoint_buffs[EP_INT_IN], (*_endpoint_configs)[EP_INT_IN].max_packet);
736-
if (num_packets_sent >= NUM_PACKETS_UNTIL_ABORT) {
763+
if (_num_packets_int_in_abort == NUM_PACKETS_UNTIL_ABORT) {
737764
endpoint_abort(endpoint);
738765
}
739766
}

TESTS/usb_device/basic/USBEndpointTester.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ class USBEndpointTester: public USBDevice {
7979
volatile uint32_t _cnt_cb_iso_out;
8080
volatile uint32_t _cnt_cb_iso_in;
8181

82-
volatile uint32_t _cnt_cb_bulk_out_abort;
83-
volatile uint32_t _cnt_cb_bulk_in_abort;
84-
volatile uint32_t _cnt_cb_int_out_abort;
85-
volatile uint32_t _cnt_cb_int_in_abort;
82+
volatile uint32_t _num_packets_bulk_out_abort;
83+
volatile uint32_t _num_packets_bulk_in_abort;
84+
volatile uint32_t _num_packets_int_out_abort;
85+
volatile uint32_t _num_packets_int_in_abort;
8686

8787
virtual const uint8_t *configuration_desc(uint8_t index);
8888
virtual void callback_state_change(DeviceState new_state);
@@ -103,6 +103,7 @@ class USBEndpointTester: public USBDevice {
103103

104104
private:
105105
const char *get_desc_string(const uint8_t *desc);
106+
bool _request_read_start(const setup_packet_t *setup);
106107
};
107108

108109
#endif

0 commit comments

Comments
 (0)