USB · Module 13
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.
Three chapters have moved eight bytes, a payload and a zero-length packet without ever saying what any request means.
This chapter is the eleven standard requests — and its subject is not a table of codes. It is which requests are legal in which device state, because Module 8's state machine and this request set are the same mechanism seen from two sides.
1. Eleven Requests, and the Codes Are Not Contiguous
| Code | Request | Typical bmRequestType | Direction |
|---|---|---|---|
0x00 | GET_STATUS | 0x80 | IN |
0x01 | CLEAR_FEATURE | 0x00 | OUT |
0x02 | — | gap | |
0x03 | SET_FEATURE | 0x00 | OUT |
0x04 | — | gap | |
0x05 | SET_ADDRESS | 0x00 | OUT |
0x06 | GET_DESCRIPTOR | 0x80 | IN |
0x07 | SET_DESCRIPTOR | 0x00 | OUT |
0x08 | GET_CONFIGURATION | 0x80 | IN |
0x09 | SET_CONFIGURATION | 0x00 | OUT |
0x0A | GET_INTERFACE | 0x80 | IN |
0x0B | SET_INTERFACE | 0x00 | OUT |
0x0C | SYNCH_FRAME | 0x80 | IN |
Values from ch9.h's USB_REQ_* definitions, and the two gaps are real: 0x02 and 0x04 are not assigned.
Which is a small fact with a design consequence: a jump table indexed by bRequest has two entries that must be errors, and an implementation that treats code ≤ 0x0C as valid accepts two requests that do not exist. §6's R4 is the general form of that mistake, and the gaps are why the right structure is a case with an explicit default rather than a range check.
The get/set symmetry is nearly complete and not quite. GET_STATUS has no SET_STATUS; SYNCH_FRAME has no counterpart. Every pair that exists is adjacent except CLEAR_FEATURE/SET_FEATURE, which are 0x01 and 0x03 with a gap between them — so even the pattern that looks reliable is not.
2. The Legality Table
A request is not simply supported or unsupported. It is legal in some device states and not in others, and Module 8's three states are the axis.
| Request | Default | Address | Configured |
|---|---|---|---|
GET_DESCRIPTOR | yes | yes | yes |
SET_ADDRESS | yes | yes | — |
CLEAR_FEATURE / SET_FEATURE | device only | yes | yes |
GET_STATUS | — | yes | yes |
SET_DESCRIPTOR | — | yes | yes |
GET_CONFIGURATION / SET_CONFIGURATION | — | yes | yes |
GET_INTERFACE / SET_INTERFACE | — | — | yes only |
SYNCH_FRAME | — | — | yes only |
Three rows carry the structure:
GET_DESCRIPTOR is legal everywhere, because the host must be able to read a device it knows nothing about. Chapter 13.2 §3's probe is the first control transfer of every enumeration and it happens in Default.
SET_ADDRESS is legal in Default, because that is its entire purpose — it is the request that leaves Default, and Chapter 8.4 is the state it leads to.
Interface requests are legal only in Configured, because interfaces do not exist until a configuration selects them — Chapter 8.5. Asking which alternate setting an interface is using, before any interface exists, is not a question with an answer.
3. The Table Is a Graph
The section this chapter exists for.
Reading the table row by row makes it look like eleven independent rules. It is not. Two of the requests change the device's state, so the table describes a graph:
Default ──SET_ADDRESS(n≠0)──▶ Address ──SET_CONFIGURATION(n≠0)──▶ Configured
▲ │ │
└───────SET_ADDRESS(0)────────┘◀────────SET_CONFIGURATION(0)────────┘And the question that matters is not is each rule right but is the graph connected.
4. The Bootstrap Set
Which requests must work in Default, and why exactly those.
A device in Default has no assigned address — Chapter 8.3 — so it answers at address 0, and every unenumerated device on the bus answers at address 0. Which is why only one may be in Default at a time, and why the set of requests legal there is deliberately tiny:
| Legal in Default | Because |
|---|---|
GET_DESCRIPTOR | the host must read a device it knows nothing about |
SET_ADDRESS | it is the exit from Default |
CLEAR_FEATURE / SET_FEATURE to the device | recovery, before an address exists |
Everything else is undefined in Default, and the reason is uniform: it refers to something that does not exist yet. There is no configuration to get, no interface to select, and a status whose meaning depends on a configuration that has not been chosen.
The Default state's request set is exactly the set that does not presuppose anything the host has not yet established.
Which makes it a bootstrap set in the strict sense — the minimum from which everything else becomes reachable, and Chapter 10.2 §1's bootstrap argument arriving as a concrete eleven-row table.
5. Unsupported Is Not Illegal
Two different negatives that both produce a STALL and mean different things.
Unsupported: the device does not implement this request. SET_DESCRIPTOR is optional and most devices stall it in every state.
Illegal here: the device implements it and the request does not apply in the current state. GET_INTERFACE on a device that is not Configured.
Both stall, so a host cannot distinguish them — and it does not need to. But the device must, because they have different implications:
- Unsupported is static. It will stall in every state, forever, and that is a complete answer.
- Illegal here is dynamic. The same request will succeed after a
SET_CONFIGURATION, and a device that conflates the two will stall it even then.
A device that answers illegal here with the same logic it uses for unsupported has turned a state-dependent rule into a permanent one.
§6's R5 is exactly that inversion, and it is the reverse of what you would expect: it computes legality perfectly and then ignores it when deciding whether to stall.
6. The Request Router, as RTL
// ─────────────────────────────────────────────────────────────────────────
// usb_req_pkg + usb_std_request
//
// Classification: SIMPLIFIED SYNTHESIZABLE TEACHING RTL plus a CONCEPTUAL
// package. It answers three questions about a decoded SETUP: is this a
// standard request, do we know it, and is it legal in the state we are in.
//
// WHAT IT MODELS. Section 1's eleven codes and section 2's legality table.
//
// WHAT IT DOES NOT MODEL. The SETUP decode (Chapter 13.1); the stages that
// carry the request (Chapters 13.2 and 13.3); what each request DOES, which
// is the device's own business and is where wValue and wIndex are consumed;
// the device state machine itself (Module 8 -- consumed here as an input);
// and class or vendor requests, which this block deliberately claims none of.
//
// ── WHY A CASE AND NOT A RANGE CHECK ────────────────────────────────────
// Section 1: the codes are NOT contiguous -- 0x02 and 0x04 are gaps. A
// `bRequest <= 8'h0C` test accepts two requests that do not exist, and an
// indexed jump table has two entries that must be errors. The case's
// `default` arm is where both of those become one line.
// ─────────────────────────────────────────────────────────────────────────
package usb_req_pkg;
// Module 8's states, encoded so that ">=" expresses "at least this far
// through enumeration" -- which is how section 2's table actually reads.
typedef enum logic [1:0] {
ST_DEFAULT = 2'd0, ST_ADDRESS = 2'd1, ST_CONFIGURED = 2'd2
} dev_state_e;
// Section 1, from ch9.h's USB_REQ_* values.
localparam logic [7:0] REQ_GET_STATUS = 8'h00;
localparam logic [7:0] REQ_CLEAR_FEATURE = 8'h01;
localparam logic [7:0] REQ_SET_FEATURE = 8'h03; // 0x02 is a GAP
localparam logic [7:0] REQ_SET_ADDRESS = 8'h05; // 0x04 is a GAP
localparam logic [7:0] REQ_GET_DESCRIPTOR = 8'h06;
localparam logic [7:0] REQ_SET_DESCRIPTOR = 8'h07;
localparam logic [7:0] REQ_GET_CONFIGURATION = 8'h08;
localparam logic [7:0] REQ_SET_CONFIGURATION = 8'h09;
localparam logic [7:0] REQ_GET_INTERFACE = 8'h0A;
localparam logic [7:0] REQ_SET_INTERFACE = 8'h0B;
localparam logic [7:0] REQ_SYNCH_FRAME = 8'h0C;
endpackage
module usb_std_request
import usb_req_pkg::*;
import usb_setup_pkg::*;
(
input logic clk,
input logic rst_n,
// From Chapter 13.1's decode.
input logic req_valid,
input req_type_e req_type,
input recipient_e recipient,
input logic recipient_defined,
input logic [7:0] bRequest,
input logic [15:0] wValue,
input dev_state_e dev_state, // Module 8
output logic is_standard,
output logic known_request,
output logic legal_here,
output logic must_stall
);
assign is_standard = req_valid && (req_type == RT_STANDARD);
always_comb begin
known_request = 1'b0;
legal_here = 1'b0;
// Chapter 13.1 section 2: an undefined recipient is not a request we
// can route, whatever bRequest says.
if (is_standard && recipient_defined) begin
case (bRequest)
REQ_GET_STATUS: begin
known_request = 1'b1;
// Section 4: undefined in Default -- the status it would report
// depends on a configuration that has not been chosen.
legal_here = (dev_state >= ST_ADDRESS);
end
REQ_CLEAR_FEATURE, REQ_SET_FEATURE: begin
known_request = 1'b1;
// Legal in Default only for the DEVICE recipient: there are no
// interfaces or non-zero endpoints to apply a feature to yet.
legal_here = (dev_state >= ST_ADDRESS) ||
((dev_state == ST_DEFAULT) && (recipient == RCP_DEVICE));
end
REQ_SET_ADDRESS: begin
known_request = 1'b1;
// SECTION 3'S EDGE. This is the only exit from Default, and
// section 6's R2 measures what removing it costs: every state but
// Default becomes unreachable.
legal_here = (dev_state <= ST_ADDRESS);
end
REQ_GET_DESCRIPTOR: begin
known_request = 1'b1;
// Section 4: legal EVERYWHERE. The host must be able to read a
// device it knows nothing about, which is how enumeration starts.
legal_here = 1'b1;
end
REQ_SET_DESCRIPTOR: begin
known_request = 1'b1;
legal_here = (dev_state >= ST_ADDRESS);
end
REQ_GET_CONFIGURATION, REQ_SET_CONFIGURATION: begin
known_request = 1'b1;
legal_here = (dev_state >= ST_ADDRESS);
end
REQ_GET_INTERFACE, REQ_SET_INTERFACE, REQ_SYNCH_FRAME: begin
known_request = 1'b1;
// Chapter 8.5: interfaces do not exist until a configuration
// selects them, so these have no meaning before Configured.
legal_here = (dev_state == ST_CONFIGURED);
end
default: begin
// Section 1's two gaps and every code above 0x0C land here.
known_request = 1'b0;
legal_here = 1'b0;
end
endcase
end
end
// Section 5: the two negatives are computed separately and produce the
// same outward answer. Folding them -- section 6's R5 -- turns a
// state-dependent rule into a permanent one.
assign must_stall = req_valid && is_standard && (!known_request || !legal_here);
endmoduleWhat it models. Recognition and state-legality for the eleven standard requests.
Engineering reason. Because a request's legality is a property of the device's state, and the table those rules form must keep the state machine connected.
Inputs. The decoded SETUP fields and the device's state.
State retained. None — the device state arrives as an input and belongs to Module 8.
Outputs. Whether this is ours, whether we know it, whether it applies now, and the resulting stall.
Hardware implied. An 8-bit case and a handful of comparators.
Reset behaviour. Nothing to reset.
Assumptions. That dev_state is the state at the moment the SETUP arrived — a state change mid-transfer is Chapter 13.3 §4's deferral problem; that recipient_defined came from Chapter 13.1's five-bit mask; and that class and vendor requests are routed elsewhere entirely.
Omissions. The decode, the stages, the requests' effects, the state machine and the non-standard types — in the header.
What DV should verify. That the eleven codes are recognised and every other value of the byte is not — including the two gaps; that each request's legality matches the table in every state; that GET_DESCRIPTOR is legal in all three states; that SET_ADDRESS is legal in Default; that interface requests are legal only in Configured; and — the property no per-request check expresses — that the table leaves every state reachable.
7. Mutation Test
Five mutations over 3,116 requests — exhaustive over all 256 bRequest values × 3 device states × 4 recipients, plus 32 class and vendor requests and 12 with an undefined recipient.
The unmutated block: 82 accepted, 3,002 stalled, and 0 errors of every kind.
| legality wrong | stall wrong | SET_ADDRESS stalled in Default | interface request before Configured | unknown accepted | |
|---|---|---|---|---|---|
| golden | 0 | 0 | 0 | 0 | 0 |
R1 GET_STATUS legal everywhere | 4 | 4 | 0 | 0 | 0 |
R2 SET_ADDRESS illegal in Default | 8 | 8 | 4 | 0 | 0 |
| R3 interface requests from Address | 12 | 12 | 0 | 8 | 0 |
| R4 unknown codes accepted | 2 940 | 2 940 | 0 | 0 | 2 940 |
| R5 stall ignores legality | 0 | 82 | 0 | 16 | 0 |
R2 — make SET_ADDRESS illegal in Default
Measured: 8 wrong table entries, 4 of them SET_ADDRESS in Default.
Eight out of 3,116 is 0.26% of the bench. §3's reachability computation is the rest of the story: Address and Configured become unreachable, so the device can never enumerate on any host.
The smallest mutation in this chapter is the only one that makes the device completely useless.
R4 — accept unknown request codes
Measured: 2 940 wrong — by far the loudest, and the one that includes §1's two gaps.
Every undefined code becomes a recognised, legal request. The device then executes whatever its default arm does — which in a design that never expected to reach it is usually nothing, silently, with a successful status stage.
A host receives success for a request the device did not implement, which is Chapter 13.3 §6's T3 arriving from the other direction.
R3 — allow interface requests from Address
Measured: 12 wrong, of which 8 are interface requests before a configuration exists.
GET_INTERFACE on a device with no interfaces. The device must answer something, and whatever it answers is fabricated — there is no interface whose alternate setting could be reported.
The failure is a plausible wrong answer rather than an error, which is the hardest kind for a host to act on.
R1 — make GET_STATUS legal everywhere
Measured: 4 wrong — one per recipient, in Default.
The mildest of the five. A device reporting its status before it has an address reports something that depends on a configuration it does not have, and a host that asked will act on it.
It is included because its count is nearly identical to R2's and its impact is nothing like it — which is §8's point.
R5 — let the stall decision ignore legality
assign must_stall = req_valid && !known_request; // MUTANT R5Measured: legal_here is wrong on zero of 3,116 requests. must_stall is wrong on 82.
The design computes legality perfectly and then does not use it. §5's inversion: every request the device recognises is accepted in every state, so GET_INTERFACE succeeds in Default and SET_CONFIGURATION succeeds before an address exists.
And a bench checking that the legality table is correct passes completely, because it is. Chapter 12.2 §6 measured the same shape on short packets: classification and use are separate, and only one of them changes behaviour.
8. Verification
This chapter's commit point is every request was answered according to the state the device was actually in — and the device could still get to every state.
Stimulus. Exhaustive: all 256 values of bRequest × three device states × four recipients = 3,072 combinations, plus class and vendor types and undefined recipients. There is no sampling question here — the input space is small enough to enumerate completely, which is what Chapter 11.3 §10 established removes every excuse about reachability and none about what is being checked.
Observation. Recognition, legality and the stall decision, against a reference table transcribed from the specification rather than derived from the design — plus four obligations stated independently of both:
SET_ADDRESSis never stalled in Default;- an interface request never succeeds before Configured;
- an unrecognised standard request is always stalled;
GET_DESCRIPTORis never stalled.
The first and last are reachability obligations in disguise — they are the two edges without which enumeration cannot start or proceed.
Reference model. The legality table as a function, transcribed from USB 2.0 §9.4. Its independence is real but partial — it is a second copy of the same table, so a misreading of the specification would appear in both. The four obligations are what guard against that, and they are stated as consequences (the device must be able to leave Default) rather than as table entries.
Coverage — the crosses are the exhaustive product, and four cells deserve naming:
SET_ADDRESS× Default — the edgeGET_DESCRIPTOR× Default — the bootstrap read- interface requests × Address — the cell R3 lives in
bRequest=0x02and0x04— the gaps, which a range check silently accepts
Negative cases with defined outcomes: no unrecognised code is ever accepted — all 245 of them; no interface request succeeds outside Configured; no request is claimed for a class or vendor type; and nothing is accepted with an undefined recipient.
9. Debugging: the Device That Works Until It Is Reset
A device enumerates and works. After a bus reset — triggered by suspend/resume, a hub power cycle, or a host driver reload — it never comes back. Power-cycling the device fixes it. The failure is completely reproducible.
What does power-cycling fixes it tell you? That the device's state after a bus reset differs from its state after power-on, and only one of them works. Chapter 8.3: a bus reset returns the device to Default, which is also where power-on leaves it — so the two should be identical.
Unless something is not reset. A device whose internal notion of state survives the bus reset believes it is still Configured while the host believes it is in Default.
What does that break? §2's table, from both sides. The host sends SET_ADDRESS — legal in Default. The device, believing itself Configured, finds SET_ADDRESS illegal and stalls it.
And the device is applying the table correctly. SET_ADDRESS genuinely is not legal in Configured. The bug is not in the table; it is in the state fed to it — which is why reading the request-handling code finds nothing wrong.
How do you confirm it? Read the device's state register immediately after a bus reset. If it is not Default, the reset path missed it — and Chapter 8.3's reset obligations are the list to check against.
What if the state is correctly Default? Then the fault is the opposite: the device is in Default and something else did not reset — the address, the configuration index, an endpoint's toggle. The symptom is the same and the search is different.
Why is it completely reproducible? Because it is a missing reset, not a race. This class of bug never presents as flakiness, which misleads: reproducibility suggests logic and this is omission.
The signature to keep: works from power-on and not from a bus reset means something survived a reset that should not have — and the fastest discriminator is whether the device's own state register agrees with the host's view.
10. Common Misconceptions
11. Reason It Through
A device supports two configurations. A host selects configuration 2, uses the device, then sends
SET_CONFIGURATION(0). The device's endpoints stop working — correctly — but a subsequentSET_CONFIGURATION(2)is stalled, and the device has to be unplugged.
What does SET_CONFIGURATION(0) do? Chapter 8.5: it un-configures the device, returning it to Address. The endpoints stopping is correct.
Is SET_CONFIGURATION legal in Address? §2's table: yes — it is legal in Address and Configured. So the second request should succeed.
So why is it stalled? Two candidates, and they are distinguishable:
- The device did not actually move to Address. It cleared its endpoints and left its state at Configured — and
SET_CONFIGURATIONis legal there too, so that alone would not stall it. - The device moved somewhere else. If it treated
SET_CONFIGURATION(0)as a return to Default, then §2's table makesSET_CONFIGURATIONillegal — and the stall is the device correctly applying the table to a wrong state.
Which is more likely? The second, and the reason is a plausible misreading: SET_ADDRESS(0) returns to Default and SET_CONFIGURATION(0) returns to Address, and the symmetry of zero means go back invites collapsing them into one rule. They go back different distances.
How would you confirm it without instrumenting the device? Send SET_ADDRESS after the failure. If it succeeds, the device thinks it is in Default — because SET_ADDRESS is legal there and illegal in Configured. One request distinguishes the two hypotheses.
Is the device recoverable? In principle yes — a device in Default with a valid address can be re-addressed and reconfigured. In practice the host will not try, because it believes the device is in Address and has no reason to send SET_ADDRESS again.
And the transferable point: the device and the host each maintain a state variable and neither transmits it — Chapter 12.4 §2's two beliefs, one level up. The legality table is the only place the disagreement becomes visible, and it becomes visible as a stall on a request that should have worked. A stall that contradicts the table is evidence about the state, not about the request.
12. Understanding Check
13. Summary
Eleven standard requests, and the codes are not contiguous — 0x02 and 0x04 are gaps, so a range check accepts two requests that do not exist and the correct structure is a case with an explicit default.
A request is legal in some device states and not others, and the axis is Module 8's three states. GET_DESCRIPTOR is legal everywhere, because the host must read a device it knows nothing about. SET_ADDRESS is legal in Default, because it is the exit from it. Interface requests are legal only in Configured, because interfaces do not exist before a configuration selects them.
And the table is not a list of rules. It is a graph, because two requests change state — so the property that matters is reachability, and it is not expressible as an assertion about any request.
§7 measured five mutations over 3,116 exhaustive combinations, and the two smallest are the lesson:
Making
GET_STATUSlegal in Default is four wrong entries and leaks a status report. MakingSET_ADDRESSillegal in Default is four wrong entries and makes the device permanently unenumerable on every host.
A mutation score counts them equally. The graph does not.
The loudest mutation accepted every undefined code — 2 940 wrong, including §1's two gaps — and returned success for requests the device never implemented. And the subtlest computed the legality table perfectly and then ignored it: zero legality errors, 82 wrong stalls, with a bench checking the table passing completely.
§8's practice follows from §3, and it is a kind of check this curriculum has not needed before:
When a design's correctness depends on a table, check the table's structure, not only its entries — and do it at elaboration, because the table is fixed before a cycle runs.
Three states, two state-changing requests, four edges, a search that takes microseconds. It is the only thing that identifies a wrong SET_ADDRESS row as a disconnected graph rather than as four bad entries.
14. What Comes Next
Every piece is now in place: the stages, the requests, the states, the descriptors, the packets, the transactions. Chapter 13.5 assembles them.
It walks one real enumeration end to end — the reset, the 8-byte descriptor probe, the second reset, SET_ADDRESS, the full descriptor read, the configuration read in two parts, and SET_CONFIGURATION — as a sequence of control transfers, each one built from transactions, each transaction from packets.
And its subject is the ordering. Every step depends on the one before it, the dependencies are not all obvious, and §3's graph is what makes the sequence the only one that works.
Browse the full path on the USB tutorials index.
Continue learning
Related tutorials
- Related topic
USB Reset
Reset as an assertion rather than a question: what a bus reset clears, what it deliberately does not, and why a protocol bus reset and an RTL reset are different mechanisms with different scopes.
- Related topic
Configuration Selection
Addressed is not configured. What selecting a configuration switches on, why configuration zero is an un-select rather than a choice, and the RTL consequence of a state entered and left by the same request.
- Related topic
Powered State
The only state in which a device acts on its own initiative: when to present the pull-up, why a self-powered device must watch bus power to avoid back-powering a bus, and why Powered cannot become Default alone.
- Related topic
Default State
The state reachable from everywhere: why one unconditional edge makes a device recoverable from any condition, the device state machine with event priority and illegal-transition handling, and why clearing a state register is not clearing a state.
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.
