STRUCT URB(9)
π struct urb(9) β USB Request Block π
okay bestie, this is the Kernel API Manual page for struct urb, aka the USB Request Block β the literal icon, the moment, the main character of USB requests. π
β¨ NAME β¨
struct urb β USB Request Block. That's the whole name, no cap. π
π SYNOPSIS π
struct urb {
struct list_head urb_list;
struct list_head anchor_list;
struct usb_anchor *anchor;
struct usb_device *dev;
struct usb_host_endpoint *ep;
unsigned int pipe;
unsigned int stream_id;
int status;
unsigned int transfer_flags;
void *transfer_buffer;
dma_addr_t transfer_dma;
struct scatterlist *sg;
struct sg_table *sgt;
int num_mapped_sgs;
int num_sgs;
u32 transfer_buffer_length;
u32 actual_length;
unsigned char *setup_packet;
dma_addr_t setup_dma;
int start_frame;
int number_of_packets;
int interval;
int error_count;
void *context;
usb_complete_t complete;
struct usb_iso_packet_descriptor iso_frame_desc[];
};
π¦ Members π¦
okay so here's the whole cast of fields, one by one, no skips, no "we'll get to it later" energy. π
urb_listβ for use by the current owner of the URB. That's it. That's the gig. π«Άanchor_listβ this field is the URB's membership in the list of an anchor. Cute, linked-list coded. β¨anchorβ used to anchor URBs to a common mooring. Nautical but make it USB. πdevβ identifies the USB device that's gonna perform the request. πepβ points to the endpoint's data structure. It will eventually replacepipe. Lowkey foreshadowing. π¦pipeβ holds the endpoint number, direction, type, and more. You create these values with the eight macros available:usb_{snd,rcv}TYPEpipe(dev,endpoint), where theTYPEis"ctrl"(control),"bulk","int"(interrupt), or"iso"(isochronous). For example,usb_sndbulkpipeorusb_rcvintpipe. Endpoint numbers range from zero to fifteen. Note that"in"endpoint two is a different endpoint (and pipe) from"out"endpoint two β yes, they are not the same bestie. The current configuration controls the existence, type, and maximum packet size of any given endpoint. πstream_idβ the endpoint's stream ID for bulk streams. Slay. πstatusβ this is read in non-iso completion functions to get the status of the particular request. ISO requests only use it to tell whether the URB was unlinked; the detailed status for each frame is in the fields of theiso_frame-desc. πtransfer_flagsβ a variety of flags may be used to affect how URB submission, unlinking, or operation are handled. Different kinds of URB can use different flags. Mix and match, bestie, but read the docs. πtransfer_bufferβ this identifies the buffer to (or from) which the I/O request will be performed unlessURB_NO_TRANSFER_DMA_MAPis set (however, do not leave garbage intransfer_buffereven then). This buffer must be suitable for DMA; allocate it withkmallocor equivalent. For transfers to"in"endpoints, contents of this buffer will be modified. This buffer is used for the data stage of control transfers. π«Άtransfer_dmaβ whentransfer_flagsincludesURB_NO_TRANSFER_DMA_MAP, the device driver is saying that it provided this DMA address, which the host controller driver should use in preference to thetransfer_buffer. πsgβ scatter gather buffer list. The buffer size of each element in the list (except the last) must be divisible by the endpoint's max packet size ifno_sg_constraintisn't set instruct usb_bus. Math check, bestie. π§sgtβ used to hold a scatter gather table returned byusb_alloc_noncoherent, which describes the allocated non-coherent and possibly non-contiguous memory and is guaranteed to have 1 single DMA mapped segment. The allocated memory needs to be freed byusb_free_noncoherent. Free it, don't ghost it. πnum_mapped_sgsβ (internal) number of mapped sg entries. Internal business, but we still love her. πnum_sgsβ number of entries in thesglist. Count 'em. π₯transfer_buffer_lengthβ how big istransfer_buffer. The transfer may be broken up into chunks according to the current maximum packet size for the endpoint, which is a function of the configuration and is encoded in thepipe. When the length is zero, neithertransfer_buffernortransfer_dmais used. Zero means neither, periodt. β¨actual_lengthβ this is read in non-iso completion functions, and it tells how many bytes (out oftransfer_buffer_length) were transferred. It will normally be the same as requested, unless either an error was reported or a short read was performed. TheURB_SHORT_NOT_OKtransfer flag may be used to make such short reads be reported as errors. πsetup_packetβ only used for control transfers, this points to eight bytes of setup data. Control transfers always start by sending this data to the device. Thentransfer_bufferis read or written, if needed. Eight bytes, main character energy. πsetup_dmaβ DMA pointer for the setup packet. The caller must not use this field;setup_packetmust point to a valid buffer. Ma'am, read that again. πstart_frameβ returns the initial frame for isochronous transfers. π¦number_of_packetsβ lists the number of ISO transfer buffers. Count the packets, bestie. πΈintervalβ specifies the polling interval for interrupt or isochronous transfers. The units are frames (milliseconds) for full and low speed devices, and microframes (1/8 millisecond) for highspeed and SuperSpeed devices. Units matter, iykyk. βerror_countβ returns the number of ISO transfers that reported errors. Not the vibe, but we track it. πcontextβ for use in completion functions. This normally points to request-specific driver context. Your little custom corner. π«Άcompleteβ completion handler. This URB is passed as the parameter to the completion function. The completion function may then do what it likes with the URB, including resubmitting or freeing it. Main character gets passed around, honestly. πiso_frame_descβ used to provide arrays of ISO transfer buffers and to collect the transfer status for each buffer. Iconic array behavior. π
β¨ DESCRIPTION β¨
Okay bestie, so this structure is literally the whole personality of USB transfer requests π
. Every URB out there has to be allocated by calling usb_alloc_urb and freed with a call to usb_free_urb β like, that's the law, no cap.
Setup? You can do that with the various usb_fill_*_urb functions, iconic. Then you submit them with usb_submit_urb, and if you've got pending requests you want gone, cancel them with usb_unlink_urb or usb_kill_urb. Easy. Slay.
π§Ί Data Transfer Buffers
Normally drivers provide I/O buffers allocated with kmalloc or otherwise taken from the general page pool. That's what transfer_buffer gives you (and control requests also use setup_packet), and host controller drivers perform a dma mapping (and unmapping) for each buffer transferred. Lowkey those mapping ops can be expensive on some platforms (maybe using a dma bounce buffer or talking to an IOMMU π), although honestly they're cheap on commodity x86 and ppc hardware, so vibe check passed there.
Alternatively, drivers may pass the URB_NO_TRANSFER_DMA_MAP transfer flag, which tells the host controller driver that no such mapping is needed for the transfer_buffer since the device driver is DMA-aware. For example, a device driver might allocate a DMA buffer with usb_alloc_coherent or call usb_buffer_map. When this transfer flag is provided, host controller drivers will attempt to use the dma address found in the transfer_dma field rather than determining a dma address themselves. Periodt.
Heads up bestie:transfer_buffermust still be set if the controller does not support DMA (as indicated byhcd_uses_dma) and when talking to root hub. If you have to transfer between highmem zone and the device on such controller, create a bounce buffer or bail out with an error. And iftransfer_buffercannot be set (is in highmem) and the controller is DMA capable, assignNULLto it, so that usbmon knows not to use the value β¨. Thesetup_packetmust always be set, so it cannot be located in highmem β that's just how it is, sorry.
π οΈ Initialization
All URBs submitted must initialize the dev, pipe, transfer_flags (may be zero), and complete fields. Every single one. All URBs must also initialize transfer_buffer and transfer_buffer_length. Don't skip this, I'm begging π.
They may provide the URB_SHORT_NOT_OK transfer flag, indicating that short reads are to be treated as errors β and that flag is invalid for write requests, so don't even try it.
Bulk URBs may use the URB_ZERO_PACKET transfer flag, indicating that bulk OUT transfers should always terminate with a short packet, even if it means adding an extra zero length packet. It's giving thorough. Obsessed.
Control URBs must provide a valid pointer in the setup_packet field. And unlike the transfer_buffer, the setup_packet may not be mapped for DMA beforehand β noted, king.
Interrupt URBs must provide an interval, saying how often (in milliseconds or, for highspeed devices, 125 microsecond units) to poll for transfers. After the URB has been submitted, the interval field reflects how the transfer was actually scheduled. And the polling interval may be more frequent than requested β for example, some controllers have a maximum interval of 32 milliseconds, while others support intervals of up to 1024 milliseconds. Isochronous URBs also have transfer intervals, so yeah, they're in the club too.
(Note that for isochronous endpoints, as well as high speed interrupt endpoints, the encoding of the transfer interval in the endpoint descriptor is logarithmic. Device drivers must convert that value to linear units themselves. Math is your problem bestie, not mine π§.)
If an isochronous endpoint queue isn't already running, the host controller will schedule a new URB to start as soon as bandwidth utilization allows. But if the queue is running, then a new URB will be scheduled to start in the first transfer slot following the end of the preceding URB, if that slot has not already expired. And if the slot has expired (which can happen when IRQ delivery is delayed for a long time π), the scheduling behavior depends on the URB_ISO_ASAP flag:
- If the flag is clear, then the URB will be scheduled to start in the expired slot, implying that some of its packets will not be transferred.
- If the flag is set, then the URB will be scheduled in the first unexpired slot, breaking the queue's synchronization.
Upon URB completion, the start_frame field will be set to the (micro)frame number in which the transfer was scheduled. Ranges for frame counter values are HC-specific and can go from as low as 256 to as high as 65536 frames. Numbers! Fun!
Isochronous URBs have a different data transfer model, in part because the quality of service is only "best effort" π. Callers provide specially allocated URBs, with number_of_packets worth of iso_frame_desc structures at the end. Each such packet is an individual ISO transfer. Isochronous URBs are normally queued, submitted by drivers to arrange that transfers are at least double buffered, and then explicitly resubmitted in completion handlers, so that data (such as audio or video) streams at as constant a rate as the host controller scheduler can support. Iconic behavior honestly π.
π¬ Completion Callbacks
The completion callback is made in_interrupt, and one of the first things that a completion handler should do is check the status field. The status field is provided for all URBs β it's used to report unlinked URBs, and status for all non-ISO transfers. And it should not be examined before the URB is returned to the completion handler. Rude if you do.
The context field is normally used to link URBs back to the relevant driver or request state. Very main character energy.
When the completion callback is invoked for non-isochronous URBs, the actual_length field tells how many bytes were transferred. This field is updated even when the URB terminated with an error or was unlinked. Loyal like that π.
ISO transfer status is reported in the status and actual_length fields of the iso_frame_desc array, and the number of errors is reported in error_count. Completion callbacks for ISO transfers will normally (re)submit URBs to ensure a constant transfer rate. The grind never stops π₯.
Big note bestie: even fields marked "public" should not be touched by the driver when the urb is owned by the hcd β that is, since the call to usb_submit_urb till the entry into the completion routine. Hands off the merch π.
π SEE ALSO π
Kernel file ./include/linux/usb.h:
struct usb_host_endpoint(9)struct usb_interface(9)usb_set_intfdata(9)struct usb_interface_cache(9)struct usb_host_config(9)struct usb_device(9)usb_hub_for_each_child(9)usb_interface_claimed(9)usb_make_path(9)USB_DEVICE(9)USB_DEVICE_VER(9)USB_DEVICE_INTERFACE_CLASS(9)USB_DEVICE_INTERFACE_PROTOCOL(9)USB_DEVICE_INTERFACE_NUMBER(9)USB_DEVICE_INFO(9)USB_INTERFACE_INFO(9)USB_DEVICE_AND_INTERFACE_INFO(9)USB_VENDOR_AND_INTERFACE_INFO(9)struct usb_driver(9)struct usb_device_driver(9)struct usb_class_driver(9)module_usb_driver(9)usb_fill_control_urb(9)usb_fill_bulk_urb(9)usb_fill_int_urb(9)usb_urb_dir_in(9)usb_urb_dir_out(9)struct usb_sg_request(9)
That's a wrap bestie π«Ά this lil page lives in./include/linux, dated October 2026, and it's literally titledstruct urb(9). Study it, love it, cite it. Mwah π
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms