1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
<!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>
|