Skip to content
VLSI Mentor

USB · Module 13

Setup Stage

Eight bytes that describe the whole transfer before any of it happens — bmRequestType's three fields, the five-bit recipient mask that looks like two, and the byte order that hides in enumeration.

Module 12 built a transaction: token, data, handshake. A control transfer is made of several of those, and this module is about the sequence.

Be precise about the levels, because both use the word stage:

Made ofStages
A transaction — Module 12packetstoken, data, handshake
A control transfer — this moduletransactionssetup, data, status

The setup stage is exactly one transaction — a SETUP token, one 8-byte data packet, and a handshake. And those eight bytes describe everything that follows.

1. Eight Bytes That Describe the Rest

A control transfer's shape is not discovered as it proceeds. It is declared up front, in a packet the kernel models exactly:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
struct usb_ctrlrequest {
	__u8  bRequestType;
	__u8  bRequest;
	__le16 wValue;
	__le16 wIndex;
	__le16 wLength;
} __attribute__ ((packed));
FieldBytesSays
bmRequestType1direction, type, recipient — §2
bRequest1which request — Chapter 13.4
wValue2a request-specific parameter
wIndex2usually an interface or endpoint
wLength2how many bytes the data stage will carry

The last one is the structural field, and it is worth separating from the rest:

wLength decides whether a data stage exists at all. Zero means the transfer is setup then status, with nothing in between.

And bmRequestType's direction bit decides which way that data stage runs — but only if it exists. §6's S5 is the mutation that conflates those two facts.

2. One Byte, Three Fields

bmRequestType is three fields packed into eight bits, and the masks are worth stating exactly because one of them is not what it looks like.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   bit  7     6  5     4   3   2   1   0
       ┌───┬───────┬─────────────────────┐
       │ D │ type  │     recipient       │
       └───┴───────┴─────────────────────┘
FieldBitsMaskValues
Direction70x80USB_DIR_OUT = 0, USB_DIR_IN = 0x80
Type6:50x60standard 0, class 1, vendor 2, reserved 3
Recipient4:00x1Fdevice 0, interface 1, endpoint 2, other 3

The recipient field is five bits wide and has four defined values. The kernel's mask says so unambiguously:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
#define USB_RECIP_MASK  0x1f

3. What the Eight Bytes Commit To

The setup stage is not a question. It is a declaration of the transfer's entire shape, and both ends are bound by it:

The number of stages is fixed. wLength = 0 means two stages. Non-zero means three.

The direction of the data stage is fixed. Bit 7 of bmRequestType, and it cannot change mid-transfer.

The maximum size is fixed. The device may return fewer than wLength bytes — Chapter 13.2 — but never more.

And the device may not refuse the setup stage. Chapter 11.3 §5 established this and measured what removing it costs: a device that could decline a SETUP could refuse the request that fixes it. The setup stage is always ACKed, whatever state the endpoint is in.

By the end of the setup stage, both ends know how many transactions remain, which direction each runs, and how many bytes are at stake — and none of that is re-stated by any later packet.

Which is the same structural move as Chapter 12.1's token, one level up: a small packet that names everything, followed by packets that name nothing and are interpreted against it.

A block diagram of the eight-byte SETUP packet. The first byte, bmRequestType, splits into three fields: bit seven gives the direction, bits six and five give the request type as standard, class, vendor or reserved, and bits four to zero give the recipient as device, interface, endpoint or other. The second byte is the request code. Bytes two and three form wValue and bytes four and five form wIndex, both little-endian parameters. Bytes six and seven form wLength, also little-endian, which decides whether a data stage exists at all. The direction bit and wLength together determine the transfer's shape: how many stages it has and which way each runs.8-byte SETUPone transactionbmRequestTypebyte 0 — three fieldsbRequestbyte 1 — which requestwValue · wIndexbytes 2–5, little-endianwLengthbytes 6–7, little-endianbit 7 · 0x80directionbits 4:0 · 0x1Frecipient — FIVE bitsTransfer shapehow many stages, whichwaywhich wayhow many12
Figure 1 — the eight bytes and what each decides. Only bmRequestType and wLength shape the transfer; bRequest, wValue and wIndex are parameters to whatever that shape carries. The recipient field's five-bit mask is the one that looks narrower than it is.

4. The Setup Stage on the Wire

One transaction, and its three packets are constrained more tightly than an ordinary one.

PacketConstraint
SETUP tokenChapter 11.1 §3's fourth token PID
DATA0always DATA0 — a SETUP resets the toggle (Chapter 11.2 §4)
exactly 8 bytesnot up to 8. A SETUP with any other length is an error
ACKalways — the device may not refuse it

The fixed length is what makes the decode combinational. There is no length field to read first, no variable-size parsing — eight bytes arrive and every field's position is known in advance, which is why §5's block is pure wiring.

And the mandatory DATA0 is a second resynchronisation point, on top of the toggle rule: a device that has lost track of its control endpoint's toggle recovers on the next SETUP without any explicit action.

A sequence diagram of a control transfer's setup stage. The host sends a SETUP token addressed to endpoint zero, followed by a DATA0 packet carrying exactly eight bytes. The device's control endpoint receives them and must acknowledge, because a SETUP may never be refused. The device then decodes the eight bytes: the direction bit tells it which way any data stage will run, wLength tells it whether a data stage exists and how large it may be, and the type and recipient fields tell it what kind of request this is and what it applies to. From that point both ends know the transfer's complete shape — how many transactions remain and which direction each runs — and no later packet restates any of it.The setup stage, and what it settlesHostControl endpointRequest decodeSETUP token · ENDP=0DATA0 · exactly 8bytesACK — a SETUP isnever refusedbmRequestType ·bRequest · wValue ·wIndex · wLengthbit 7 → which waythe data stage runswLength → whetherthere IS a datastagebits 4:0 → device,interface, endpoint…or undefinedthe shape is nowfixed for both ends
Figure 2 — one control transfer's first stage, and what it fixes. The three packets of the setup transaction are ordinary; what is unusual is that the device cannot refuse the last one, and that the eight bytes it just received determine every transaction after it.

5. The SETUP Decoder, as RTL

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// usb_setup_pkg + usb_setup_decode
//
// Classification: SIMPLIFIED SYNTHESIZABLE TEACHING RTL plus a CONCEPTUAL
// package. It turns section 1's eight bytes into the fields section 3 says
// the rest of the transfer depends on.
//
// WHAT IT MODELS. The field extraction of sections 1 and 2, and the two
// derived facts that shape the transfer: does a data stage exist, and which
// way does it run.
//
// WHAT IT DOES NOT MODEL. The SETUP transaction itself (Module 12 -- the
// eight bytes arrive here already received and acknowledged); which request
// this is or what it means (Chapter 13.4); the data stage (Chapter 13.2) or
// the status stage (Chapter 13.3); and the device state that decides whether
// a request is legal right now (Module 8, and Chapter 13.4 section 4).
//
// ── WHY IT IS PURELY COMBINATIONAL ──────────────────────────────────────
// Section 4: a SETUP is EXACTLY eight bytes, always. There is no length to
// read first and no variable-size parsing, so every field's position is
// known before the packet arrives. A registered stage here would add a cycle
// to the start of every control transfer for no information.
// ─────────────────────────────────────────────────────────────────────────
package usb_setup_pkg;

  // Section 2, bits 6:5. Values from ch9.h's USB_TYPE_* shifted right by 5.
  typedef enum logic [1:0] {
    RT_STANDARD = 2'd0, RT_CLASS = 2'd1, RT_VENDOR = 2'd2, RT_RESERVED = 2'd3
  } req_type_e;

  // Section 2, bits 4:0. FIVE bits, four defined values -- and that gap is
  // the point. Typing this as logic [4:0] rather than [1:0] is what makes
  // "undefined recipient" representable at all.
  typedef enum logic [4:0] {
    RCP_DEVICE = 5'd0, RCP_INTERFACE = 5'd1, RCP_ENDPOINT = 5'd2, RCP_OTHER = 5'd3
  } recipient_e;

endpackage

module usb_setup_decode
  import usb_setup_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  // The eight bytes, in the order they arrived on the wire.
  input  logic        setup_valid,
  input  logic [7:0]  b0, b1, b2, b3, b4, b5, b6, b7,

  output logic        host_to_device,
  output req_type_e   req_type,
  output recipient_e  recipient,
  output logic        recipient_defined,   // see section 2
  output logic [7:0]  bRequest,
  output logic [15:0] wValue,
  output logic [15:0] wIndex,
  output logic [15:0] wLength,

  output logic        expects_data_stage,  // section 3
  output logic        data_stage_is_in
);

  // ── bmRequestType = b0, section 2 ───────────────────────────────────────
  // USB_DIR_IN is 0x80, so bit 7 SET means device-to-host.
  assign host_to_device = ~b0[7];

  // USB_TYPE_MASK is 0x60 -- bits 6:5, not 5:4.
  assign req_type = req_type_e'(b0[6:5]);

  // USB_RECIP_MASK is 0x1F -- FIVE bits. Masking with 0x03 would map every
  // undefined recipient onto a defined one, and section 6's S2 measures that
  // the standard requests never reach the difference.
  assign recipient = recipient_e'(b0[4:0]);

  // Which makes this output necessary rather than decorative: the enum has
  // four names and the field has thirty-two values, so "is this one of the
  // four" is a question the type cannot answer on its own.
  assign recipient_defined = (b0[4:0] <= 5'd3);

  assign bRequest = b1;

  // ── LITTLE ENDIAN ───────────────────────────────────────────────────────
  // The struct says __le16 and the wire sends the low byte first. Section
  // 1's callout measures which fields enumeration would catch if this were
  // backwards, and wIndex is the one it would not.
  assign wValue  = {b3, b2};
  assign wIndex  = {b5, b4};
  assign wLength = {b7, b6};

  // ── SECTION 3'S TWO DERIVED FACTS ───────────────────────────────────────
  // A data stage exists exactly when wLength is non-zero. NOT when the
  // direction bit says IN: an IN request with wLength 0 has no data stage,
  // and conflating the two is section 6's S5.
  assign expects_data_stage = setup_valid && (wLength != 16'd0);
  assign data_stage_is_in   = expects_data_stage && !host_to_device;

endmodule

What it models. The eight bytes as fields, and the two facts that fix the transfer's shape.

Engineering reason. Because everything after the setup stage is interpreted against these fields and none of them is restated.

Inputs. A validity indication and eight bytes.

State retained. None — see the header. The capture of these fields for the rest of the transfer is Chapter 12.1's problem one level up, and a control transfer needs the same treatment.

Outputs. Seven decoded fields, an undefined-recipient flag, and two derived shape indications.

Hardware implied. Wiring, one 5-bit magnitude comparison and one 16-bit zero test. Almost no gates.

Reset behaviour. Nothing to reset.

Assumptions. That the packet was exactly eight bytes — a shorter or longer one is a protocol error this block cannot detect and Module 12 must; that the bytes are presented in wire order; and that setup_valid implies the SETUP transaction was acknowledged.

Omissions. The transaction, the request semantics, the later stages, and the state legality — in the header.

What DV should verify. That every field matches the kernel's own masks — including recipients above 3; that the 16-bit fields are assembled little-endian; that a data stage is predicted from wLength and not from the direction bit; that wLength = 0 with an IN direction predicts no data stage; and that an undefined recipient is flagged rather than mapped onto a defined one.

Eight SETUP packets, decoded

8 cycles
A waveform of the SETUP decoder over eight control requests. The first is a GET_DESCRIPTOR with request type hexadecimal eighty, decoded as an IN transfer, standard type, device recipient, wValue hexadecimal zero one zero zero and wLength eighteen, so a data stage exists. The second is a SET_ADDRESS with request type zero, decoded as OUT, standard, device, wValue ten and wLength zero, so no data stage exists. The third is another GET_DESCRIPTOR for the configuration, with wLength nine and a data stage. The fourth is SET_CONFIGURATION, OUT with wLength zero and no data stage. The fifth is GET_STATUS, IN with wLength two. The sixth is a clear-halt request with request type two, decoded as OUT, standard type, endpoint recipient, with wLength zero. The seventh is a class request to an interface with request type hexadecimal twenty-one. The eighth is a vendor request with request type hexadecimal C zero, decoded as IN, vendor type, device recipient, with wValue hexadecimal B E E F and wLength sixty-four.IN? no — wLength 0 means no data stageIN? no — wLength 0 means nodata stagewLength 2 — a two-byte data stagewLength 2 — a two-byte datastagerecipient 2 — the endpoint, not the devicerecipient 2 — the endpoint,not the devicevendor type: enumeration never sends onevendor type: enumerationnever sends onerequestGET_DESCSET_ADDRGET_CONFSET_CONFGET_STATCLR_HALTHID idleVENDORbmRequestType80008000800221C0directionINOUTINOUTINOUTOUTINtype/recipstd/devstd/devstd/devstd/devstd/devstd/epclass/ifacevendor/devwValue0100000A02000001000000000000BEEFwLength1809020064data staget0t1t2t3t4t5t6t7
Figure 3 — eight real SETUP packets decoded, every column taken from a simulation of the block above. The first five are the canonical enumeration sequence; the last three are the ones that exercise fields enumeration never touches — an endpoint recipient, a class request to an interface, and a vendor request with non-zero wValue and wIndex.

6. Mutation Test

Five mutations over 640 SETUP packets — the nine canonical enumeration requests, all 28 recipient values from 4 to 31, three byte-order stress cases, and 600 randomised packets.

The unmutated block: 608 packets with a data stage, 552 with an undefined recipient, and 0 errors of every kind.

directiontyperecipientwValuewIndexwLengthdata stage
golden0000000
S1 big-endian 16-bit fields0006076056070
S2 recipient masked 0x03005520000
S3 direction from bit 6285000000
S4 type from bits 5:4047200000
S5 data stage from direction000000302

S1 — assemble the 16-bit fields big-endian

Measured: 607 of 640 wValue fields wrong, 605 wIndex, 607 wLength.

The 33 it gets right are the symmetric ones — values whose two bytes are equal, of which 0x0000 is overwhelmingly the most common.

And §1's callout is the finding: restricted to the nine canonical enumeration requests, it is caught 5 times for wValue, 5 for wLength, and only 3 for wIndex — because wIndex is zero in every device-recipient request. A byte-order bug in wIndex survives a complete enumeration.

S2 — mask the recipient with 0x03

Measured: 552 wrong recipients out of 640 — and zero of them among the nine canonical enumeration requests.

§2's callout, measured. Every standard request uses recipient 0, 1 or 2, where the two masks agree. The 552 all come from the deliberate sweep of recipients 4 to 31 and from the randomised phase.

So this is a defect that a complete, passing enumeration test cannot see — and enumeration is what a control-transfer bench is naturally built around.

S3 — take the direction from bit 6

Measured: 285 wrong directions, and every one of them also produced a wrong data-stage direction.

An off-by-one in a bit index. It is caught immediately by enumeration — GET_DESCRIPTOR has bmRequestType 0x80, whose bit 6 is zero, so the very first request of every enumeration decodes as OUT and the device tries to receive a descriptor it should be sending.

Loud, total, found in the first second of bring-up — included as the contrast for S2.

S4 — take the type from bits 5:4

Measured: 472 wrong.

The same class of error one field along. Not caught by standard requests either, for the same reason as S2 in reverse: every standard request has type 0, and bits 5:4 of a standard request's bmRequestType are also 0 whenever the recipient is 0 or 1.

It appears on the first class-specific request — which on a HID, audio or mass-storage device is the first thing the driver does after enumeration.

S5 — predict the data stage from the direction bit

Measured: 302 wrong out of 640.

§3's two facts conflated. SET_ADDRESS and SET_CONFIGURATION are OUT requests with wLength = 0 — the mutation predicts a data stage for neither, correctly — but GET_STATUS with wLength = 0, or any IN request the host truncates to zero, gets a data stage that will never come.

And the device then waits for a transaction the host is not going to send, which Chapter 12.5 resolves as a timeout — turning a decode error into a latency problem two modules away.

7. The Assertions

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// Classification: TEACHING ASSERTIONS about the SETUP decode.
// F-properties are FIELD extraction, stated against ch9.h's own masks
// rather than against this design's bit ranges -- Chapter 11.3 section 8's
// rule. D-properties are the derived shape.
// ─────────────────────────────────────────────────────────────────────────

// F1 -- THE THREE bmRequestType FIELDS, BY MASK. Written with the
// specification's hexadecimal masks rather than with bit slices, so that an
// off-by-one in a slice (sections 6's S3 and S4) cannot be reproduced by the
// property that is supposed to catch it.
property p_fields_by_mask;
  @(posedge clk) disable iff (!rst_n)
    setup_valid |-> ( (host_to_device == ((b0 & 8'h80) == 8'h00))
                   && (req_type       == req_type_e'((b0 & 8'h60) >> 5))
                   && (recipient      == recipient_e'(b0 & 8'h1F)) );
endproperty
assert property (p_fields_by_mask);

// F2 -- THE 16-BIT FIELDS ARE LITTLE-ENDIAN. Section 6's S1. Note it names
// the byte POSITIONS, which is the fact from the wire format, rather than
// restating the concatenation.
property p_little_endian;
  @(posedge clk) disable iff (!rst_n)
    setup_valid |-> ( (wValue [7:0] == b2) && (wValue [15:8] == b3)
                   && (wIndex [7:0] == b4) && (wIndex [15:8] == b5)
                   && (wLength[7:0] == b6) && (wLength[15:8] == b7) );
endproperty
assert property (p_little_endian);

// F3 -- AN UNDEFINED RECIPIENT IS FLAGGED, NOT MAPPED. Section 6's S2, and
// the only property that catches it. The four defined values are named
// explicitly so that adding a fifth is a deliberate edit here.
property p_undefined_recipient_flagged;
  @(posedge clk) disable iff (!rst_n)
    setup_valid |-> (recipient_defined ==
        ((b0 & 8'h1F) inside {5'd0, 5'd1, 5'd2, 5'd3}));
endproperty
assert property (p_undefined_recipient_flagged);

// D1 -- A DATA STAGE EXISTS EXACTLY WHEN wLength IS NON-ZERO. Section 3,
// and section 6's S5. An EQUIVALENCE: the implication form is satisfied by
// a design that never predicts one.
property p_data_stage_iff_length;
  @(posedge clk) disable iff (!rst_n)
    expects_data_stage == (setup_valid && (wLength != 16'd0));
endproperty
assert property (p_data_stage_iff_length);

// D2 -- AND IT DOES NOT DEPEND ON THE DIRECTION. Stated separately because
// it is the specific confusion S5 embodies, and because a failing assertion
// should name the misunderstanding rather than its symptom.
property p_data_stage_ignores_direction;
  @(posedge clk) disable iff (!rst_n)
    (setup_valid && (wLength == 16'd0)) |-> !expects_data_stage;
endproperty
assert property (p_data_stage_ignores_direction);

// D3 -- THE DATA STAGE RUNS THE WAY bmRequestType SAYS, WHEN IT EXISTS.
property p_data_direction;
  @(posedge clk) disable iff (!rst_n)
    data_stage_is_in == (expects_data_stage && !host_to_device);
endproperty
assert property (p_data_direction);

F1's form is the point. It could have been written as host_to_device == ~b0[7], which would restate the RTL exactly and catch nothing. Writing it with the specification's own masks — 0x80, 0x60, 0x1F — makes it a statement sourced from ch9.h rather than from the design, which is Chapter 11.3 §8's rule applied to a decode.

D2 is redundant with D1 and earns its place on diagnostics. Both fire on S5; only D2 says the data stage was predicted from the direction. A property set optimised for minimality is optimised for the wrong reader.

8. Verification

This chapter's commit point is every field meant what the specification says it means, including the values enumeration never uses.

Stimulus.

  • The nine canonical enumeration requests, byte-exact — GET_DESCRIPTOR(DEVICE), SET_ADDRESS, GET_DESCRIPTOR(CONFIG), SET_CONFIGURATION, GET_STATUS, CLEAR_FEATURE(ENDPOINT_HALT), GET_STATUS(interface), a class request, and a vendor request;
  • every recipient value from 4 to 31 — the twenty-eight the standard never uses;
  • byte-order stress: wValue/wIndex/wLength whose two halves differ, including 0x00FF against 0xFF00;
  • 600 randomised packets across all eight bytes.

Observation. All nine outputs per packet, against expectations computed from ch9.h's masks rather than from the design's bit ranges.

Reference model. Three mask-and-shift expressions and two concatenations — short enough that its independence comes from being transcribed from the header rather than derived from the RTL.

Coverage — crosses:

  • direction × type × recipient — all combinations of the defined values, plus all 28 undefined recipients
  • wLength = 0 × each direction — the cell S5 lives in
  • 16-bit fields with differing halves, equal halves, and zero
  • bRequest across the standard set and values outside it

Negative cases with defined outcomes: an undefined recipient is never mapped onto a defined one; a zero wLength never predicts a data stage; and no field is assembled big-endian.

9. Debugging: the Device That Enumerates and Then Does Nothing

A device enumerates perfectly on every host. Descriptors are read, the address is set, the configuration is selected. Then the class driver loads and nothing works — its first class-specific request either does nothing or produces a nonsensical response.

What does enumeration works establish? A great deal: the control endpoint, the setup stage, the data stage, the status stage, the toggle and the descriptors are all functional. Everything standard works.

What is different about a class request? §2: bmRequestType bits 6:5 are 1 instead of 0, and the recipient is usually an interface rather than the device.

So which fields does enumeration never exercise? Exactly those. §8's table: every standard request is type 0, and the type field is therefore constant across the entire enumeration.

Which two defects does that point at? §6's S4 — the type extracted from the wrong bits — and S2 — the recipient mask too narrow. Both are invisible to enumeration by construction, and both appear on the first class request.

How do you tell them apart in one observation? Look at what the device did. A wrong type field makes the device treat a class request as a standard one — so it will try to execute bRequest 0x0A as SET_INTERFACE rather than as the class's own request 0x0A. A wrong recipient mask leaves the type right and sends the request to the wrong target.

What if the device simply stalls? That is the correct behaviour for a request it does not recognise, and it points somewhere else — the class request may be unimplemented rather than misdecoded. A STALL is a device saying I do not support this; a nonsensical response is a device saying I misunderstood this.

And the fastest confirmation? Send a request with a recipient of 4 — undefined, and something no host will ever send by accident. A correct device stalls it. A device with a narrow mask executes it as a device request, which is unmistakable and harmless to try.

The signature to keep: enumeration perfect and class requests broken means a bmRequestType field that enumeration holds constant — and there are exactly two of them.

10. Common Misconceptions

11. Reason It Through

A device's control endpoint is being extended to support a vendor-specific request that carries a 4-byte payload. The engineer copies the handling of GET_DESCRIPTOR, changes bRequest, and finds the request works from a Linux test tool and fails from the customer's Windows application. Both send the same eight bytes — verified on an analyser.

If the eight bytes are identical, what can differ? Nothing about the setup stage. The divergence must be after it — in the data stage, the status stage, or in what the host does with the response.

What does copying GET_DESCRIPTOR bring along? Its shape: an IN data stage, sized by wLength. And its termination behaviour — Chapter 13.2 — which is where descriptor reads have a peculiarity most requests do not.

What peculiarity? A descriptor read commonly asks for more than exists: the host requests 255 bytes and the device returns 18, terminating with a short packet. A handler copied from that path may only terminate correctly when it returns fewer bytes than asked for.

So what happens with a 4-byte payload? If the application asks for exactly 4 and the device returns exactly 4, there is no short packet — the transfer is an exact multiple of nothing in particular, but it is also exactly wLength, and the device must recognise that as complete. Chapter 12.2 §3's terminator question, arriving in a control transfer.

Why would the two hosts differ? Because they may ask for different wLength values. A tool that asks for 64 gets a short packet and works; an application that asks for exactly 4 does not and hangs. The analyser shows identical setup bytes because the engineer compared the request, not the wLength.

What is the confirming test? Ask for one byte more than the device will return. If it starts working, the fault is termination, not decoding — and the setup stage was never involved.

And the transferable point: copying a working handler copies its assumptions, and the strongest assumptions are the ones the copied case never violated. GET_DESCRIPTOR is the most-copied control handler in existence and the least representative — it is the one request where the host routinely asks for more than exists.

12. Understanding Check

13. Summary

A control transfer is made of transactions, not packets — and its setup stage is one whole transaction: a SETUP token, a DATA0 packet of exactly eight bytes, and a mandatory ACK.

Those eight bytes declare the transfer's entire shape, and nothing after them restates it. wLength decides whether a data stage exists; bmRequestType bit 7 decides which way it runs if it does. Conflating those two is §6's S5, and it makes a device wait for a transaction the host will never send.

bmRequestType is three fields, and the recipient is five bits wide with four defined values — USB_RECIP_MASK is 0x1F. Masking it with 0x03 maps every undefined recipient onto a defined one, turning a malformed or class-extended request into an instruction to the device.

The 16-bit fields are little-endian, and a byte-swapped decoder survives more of enumeration than it should: wIndex is zero in every device-recipient request, so it is caught only 3 times in 9.

§6 measured five mutations over 640 packets — and §8 is the chapter's finding, which is about the bench rather than the design:

The specification's own request set exercises exactly one value of each field it does not vary.

Two of five defects — the recipient mask and the type field — escaped the nine canonical enumeration requests entirely, zero out of nine. And those nine are not a weak test: they are a complete, successful enumeration, the sequence every device must survive and the thing a control-transfer bench is naturally built to reproduce.

The remedy is a sweep across a field's encoded width rather than its defined values — twenty-eight extra stimuli for a five-bit field, which took the recipient mutation from 0 escapes to 552. It gets skipped because four documented meanings make the other twenty-eight look impossible, and they are not: class specifications extend the space, corrupted bytes pass CRC, and five bits on the wire carry five bits whatever the table says.

14. What Comes Next

The setup stage declared a data stage of wLength bytes. Chapter 13.2 is that stage — and its rules are not quite Chapter 12.2's.

A control data stage has a declared length, which an ordinary transfer does not, so it has two ways to end rather than one: the declared count is exhausted, or a short packet arrives first. The device may return fewer bytes than asked for and must never return more, and §11's worked example is what happens to a handler that only ever learned the first of those rules.

Browse the full path on the USB tutorials index.

Continue learning

Standards & specifications

Governing standard
USB-IF (Universal Serial Bus Specification)(opens USB Implementers Forum (USB-IF) in a new tab)

Defines the USB bus — its electrical signalling, connectors, packet and transaction model, device framework and the descriptors a device must expose — together with the device-class specifications layered on it. It does not define host-controller register interfaces (xHCI and EHCI are separate documents) nor any operating system's driver architecture.

This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.

Where this fits

Part of the USB curriculum.