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 of | Stages | |
|---|---|---|
| A transaction — Module 12 | packets | token, data, handshake |
| A control transfer — this module | transactions | setup, 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:
struct usb_ctrlrequest {
__u8 bRequestType;
__u8 bRequest;
__le16 wValue;
__le16 wIndex;
__le16 wLength;
} __attribute__ ((packed));| Field | Bytes | Says |
|---|---|---|
bmRequestType | 1 | direction, type, recipient — §2 |
bRequest | 1 | which request — Chapter 13.4 |
wValue | 2 | a request-specific parameter |
wIndex | 2 | usually an interface or endpoint |
wLength | 2 | how many bytes the data stage will carry |
The last one is the structural field, and it is worth separating from the rest:
wLengthdecides 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.
bit 7 6 5 4 3 2 1 0
┌───┬───────┬─────────────────────┐
│ D │ type │ recipient │
└───┴───────┴─────────────────────┘| Field | Bits | Mask | Values |
|---|---|---|---|
| Direction | 7 | 0x80 | USB_DIR_OUT = 0, USB_DIR_IN = 0x80 |
| Type | 6:5 | 0x60 | standard 0, class 1, vendor 2, reserved 3 |
| Recipient | 4:0 | 0x1F | device 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:
#define USB_RECIP_MASK 0x1f3. 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.
4. The Setup Stage on the Wire
One transaction, and its three packets are constrained more tightly than an ordinary one.
| Packet | Constraint |
|---|---|
| SETUP token | Chapter 11.1 §3's fourth token PID |
| DATA0 | always DATA0 — a SETUP resets the toggle (Chapter 11.2 §4) |
| exactly 8 bytes | not up to 8. A SETUP with any other length is an error |
| ACK | always — 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.
5. The SETUP Decoder, as RTL
// ─────────────────────────────────────────────────────────────────────────
// 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;
endmoduleWhat 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 cycles6. 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.
| direction | type | recipient | wValue | wIndex | wLength | data stage | |
|---|---|---|---|---|---|---|---|
| golden | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| S1 big-endian 16-bit fields | 0 | 0 | 0 | 607 | 605 | 607 | 0 |
S2 recipient masked 0x03 | 0 | 0 | 552 | 0 | 0 | 0 | 0 |
| S3 direction from bit 6 | 285 | 0 | 0 | 0 | 0 | 0 | 0 |
| S4 type from bits 5:4 | 0 | 472 | 0 | 0 | 0 | 0 | 0 |
| S5 data stage from direction | 0 | 0 | 0 | 0 | 0 | 0 | 302 |
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
// ─────────────────────────────────────────────────────────────────────────
// 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/wLengthwhose two halves differ, including0x00FFagainst0xFF00; - 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
bRequestacross 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, changesbRequest, 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
Related tutorials
- Related topic
Control Data Stage
A data stage with a declared length has two ways to end, not one — and the cap that stops a device overrunning the host's buffer is invisible to a bench that never lets the device hold more than was asked for.
- Related topic
Status Stage
A zero-length packet running the opposite way to the data stage — the only place a device can report that a request it already accepted has failed.
- Related topic
Standard Device Requests
Eleven requests whose codes are not contiguous — and a legality table that is not a list of rules but a graph, in which one wrong entry makes the device permanently unenumerable.
- Related topic
The Parallel Port
Why presenting eight data lines at once forces an explicit data/strobe/acknowledge handshake, what that costs in timing discipline, a synthesizable teaching FSM that implements it with the assertions that protect it, and why an interface shaped around one peripheral's operational model cannot generalise.
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.
