148 lines
5.3 KiB
HTML
148 lines
5.3 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title></title>
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<script src="resources/manual.js"></script>
|
|
</head>
|
|
<body>
|
|
<p>
|
|
This test requires a USB device implementing the USB CDC-ACM protocol
|
|
configured to loop back TX to RX. For example, this Arduino sketch could
|
|
be used:
|
|
|
|
<pre>
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
Serial.setTimeout(0);
|
|
while (!Serial) {
|
|
;
|
|
}
|
|
}
|
|
|
|
void loop() {
|
|
if (Serial.available()) {
|
|
char buf[1024]; // Greater than the endpoint packet size.
|
|
int count = Serial.readBytes(buf, sizeof buf);
|
|
Serial.write(buf, count);
|
|
}
|
|
}
|
|
</pre>
|
|
</p>
|
|
<script>
|
|
manual_usb_serial_test(async (t, device, inEndpoint, outEndpoint) => {
|
|
// Set up two IN transfers which should complete in order.
|
|
const transfer1 =
|
|
device.transferIn(inEndpoint.endpointNumber, inEndpoint.packetSize);
|
|
const transfer2 =
|
|
device.transferIn(inEndpoint.endpointNumber, inEndpoint.packetSize);
|
|
|
|
// Write a single byte to the port which should be echoed to complete
|
|
// transfer1.
|
|
let result = await device.transferOut(
|
|
outEndpoint.endpointNumber, new Uint8Array(['a'.charCodeAt(0)]));
|
|
assert_equals(result.status, 'ok');
|
|
assert_equals(result.bytesWritten, 1);
|
|
|
|
result = await transfer1;
|
|
assert_equals(result.status, 'ok');
|
|
assert_not_equals(result.data, null);
|
|
assert_equals(result.data.byteLength, 1, 'byteLength');
|
|
assert_equals(result.data.getUint8(0), 'a'.charCodeAt(0));
|
|
|
|
// Set up a third IN transfer which will be canceled when the device is
|
|
// closed at the end of the test.
|
|
const transfer3 = promise_rejects_dom(
|
|
t, 'AbortError',
|
|
device.transferIn(inEndpoint.endpointNumber,
|
|
inEndpoint.packetSize));
|
|
|
|
// Write a single byte to the port which should be echoed to complete
|
|
// transfer2.
|
|
result = await device.transferOut(
|
|
outEndpoint.endpointNumber, new Uint8Array(['b'.charCodeAt(0)]));
|
|
assert_equals(result.status, 'ok');
|
|
assert_equals(result.bytesWritten, 1);
|
|
|
|
result = await transfer2;
|
|
assert_equals(result.status, 'ok');
|
|
assert_not_equals(result.data, null);
|
|
assert_equals(result.data.byteLength, 1, 'byteLength');
|
|
assert_equals(result.data.getUint8(0), 'b'.charCodeAt(0));
|
|
|
|
await device.close();
|
|
await transfer3;
|
|
}, 'Multiple small IN transfers on an endpoint complete in order');
|
|
|
|
manual_usb_serial_test(async (t, device, inEndpoint, outEndpoint) => {
|
|
const bufferLength = outEndpoint.packetSize * 20;
|
|
const parallelRequests = 6;
|
|
|
|
// Keep track of the order in which transfers are submitted.
|
|
let enqueueSequence = 0;
|
|
let dequeueSequence = 0;
|
|
const received = new Uint8Array(bufferLength);
|
|
let receivedOffset = 0;
|
|
let done = false;
|
|
const transfers = [];
|
|
|
|
async function readNext(sequence) {
|
|
let result;
|
|
try {
|
|
result = await device.transferIn(inEndpoint.endpointNumber,
|
|
inEndpoint.packetSize);
|
|
} catch (e) {
|
|
// The last few transfers will fail when the device is closed.
|
|
assert_true(done);
|
|
assert_equals(dequeueSequence++, sequence, 'dequeueSequence done');
|
|
assert_equals(receivedOffset, bufferLength, 'receivedOffset');
|
|
assert_equals(e.name, 'AbortError');
|
|
return;
|
|
}
|
|
|
|
assert_equals(dequeueSequence++, sequence, 'dequeueSequence');
|
|
assert_equals(result.status, 'ok');
|
|
assert_not_equals(result.data, null);
|
|
|
|
const data = new Uint8Array(
|
|
result.data.buffer, result.data.byteOffset,
|
|
result.data.byteLength);
|
|
received.set(data, receivedOffset);
|
|
receivedOffset += result.data.byteLength;
|
|
|
|
// Check |done| because there might be zero-length packet completions
|
|
// after the data has been completely received.
|
|
if (!done) {
|
|
if (receivedOffset == bufferLength) {
|
|
done = true;
|
|
assert_array_equals(received, buffer);
|
|
await device.close();
|
|
} else {
|
|
await readNext(enqueueSequence++);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (let i = 0; i < parallelRequests; ++i) {
|
|
transfers.push(readNext(enqueueSequence++));
|
|
}
|
|
|
|
// Write a large buffer to the device which will be split up into
|
|
// smaller packets when echoed back.
|
|
const buffer = new Uint8Array(bufferLength);
|
|
for (let i = 0; i < buffer.byteLength; ++i) {
|
|
buffer[i] = i;
|
|
}
|
|
let result = await device.transferOut(
|
|
outEndpoint.endpointNumber, buffer);
|
|
assert_equals(result.status, 'ok');
|
|
assert_equals(result.bytesWritten, buffer.byteLength);
|
|
|
|
await Promise.all(transfers);
|
|
assert_equals(dequeueSequence, enqueueSequence);
|
|
}, 'Multiple large IN transfers on an endpoint complete in order');
|
|
</script>
|
|
</body>
|
|
</html>
|