<!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>