The Linux USB subsystem uses only one data transfer structure called USB Request Block (URB). This structure contains all parameters to setup any USB transfer type. All transfer requests are sent asynchronously to the USB core and the completion of the request is signalled via a callback function.
As shown in figure 7 the URB structure contains elements common to all
transfer types (marked with C). Elements marked with are input parameters, M
means mandatory and O means optional. Elements marked with
are return
values. Elements marked with T are transient parameters (input and output). All
non common elements are marked on three columns which represent control,
interrupt and isochronous transfers. A X marks this element to be used with the
associated transfer type.
The URB structure might look confusing but this is just an overview of its versatility. There are several helping macros to setup the right parameters but first the common elements will be explained as they are very important.
This element is a pointer to the usb_device structure (introduced in the framework function probe section 2.1.2).
The pipe element is used to encode the endpoint number and properties. There exist several macros to create an appropriate pipe value:
pipe=usb_rcvctrlpipe(dev,endpoint)
Creates a pipe for downstream (snd) or upstream (rcv) control transfers to a given endpoint. The argument dev is a pointer to a usb_device structure. The argument endpoint is usually 0.
pipe=usb_rcvbulkpipe(dev,endpoint)
Creates a pipe for downstream (snd) or upstream (rcv) bulk transfers to a given
endpoint. The endpoint is of 1 endpoint
15 (depending on
active endpoint descriptors)
pipe=usb_rcvintpipe(dev,endpoint)
Creates a pipe for downstream (snd) or upstream (rcv) interrupt transfers to a
given endpoint. The endpoint is of 1 endpoint
15 (depending on
active endpoint descriptors)
pipe=usb_rcvisopipe(dev,endpoint)
Creates a pipe for downstream (snd) or upstream (rcv) isochronous transfers to
a given endpoint. The endpoint is of 1 endpoint
15 (depending on
active endpoint descriptors)
This element is a pointer to the associated transfer buffer which contains data transferred from or to a device. This buffer has to be allocated as a non-pageable contiguous physical memory block (simply use void *kmalloc(size_t, GFP_KERNEL);).
This element specifies the size of the transfer buffer in bytes. For interrupt and control transfers the value has to be less or equal the maximum packet size of the associated endpoint. The maximum packet size can be found as element wMaxPacketSize of an endpoint descriptor. Because there is no endpoint descriptor for the default endpoint 0 which is used for all control transfers the maximum packet size can be found as element maxpacketsize of the usb_device structure.
Bulk transfers which are bigger than wMaxPacketSize are automatically split into smaller portions.
As noted above the USB subsystem processes requests asynchronously. This element allows to specify a pointer to a caller supplied handler function which is called after the request is completed. The purpose of this handler is to finish the caller specific part of the request as fast as possible because it is called out of the host controller's hardware interrupt handler. This even implies all other restrictions that apply for code which is written for interrupt handlers.
Optionally a pointer to a request related context structure can be given. Figure 8 shows a simple completion handler.
A number of transfer flags may be specified to change the behaviour when processing the transfer request.
This flag disables short packets. A short packet condition occures if an upstream request transfers less data than maximum packet size of the associated endpoint.
When scheduling isochronous requests this flag tells the host controller to start the transfer as soon as possible. If USB_ISO_ASAP is not specified a start frame has to be given. It is recommended to use this flag if isochronous transfers do not have to be synchronized with the current frame number. The current frame number is a 11 bit counter that increments every millisecond (which is the duration of 1 frame on the bus). Further documentation can be found in [4] sections 5.10.6 and 5.10.8.
When a URB has to be cancelled (see 2.3.2) it can be done synchronously or asynchronously. Use this flag to switch on asynchronous URB unlinking.
This flag is only set by the host controller to mark the URB as killed by timeout. The URB status carries the actual error which caused the timeout.
This flag is used to allow queueing for bulk transfers. Normally only one bulk transfer can be queued for an endpoint of a particular device.
It is possible to link several URBs in a chain by using the next pointer. This allows you to send a sequence of USB transfer requests to the USB core. The chain has to be terminated by a NULL pointer or the last URB has to be linked with the first. This allows to automatically reschedule a number of URBs to transfer a continous data stream.
This element carries the status of an ongoing or already finished request. After successfully sending a request to the USB core the status is -EINPROGRESS. The successful completion of a request is indicated by 0. There exist a number of error conditions which are documented in section 3.1.
After a request has completed this element counts the number of bytes transferred.
The remaining elements of the URB are specific to the transfer type.
No additional parameters have to be specified.
Control transfers consist of 2 or 3 stages (see [4] sections 5.5, 8.5.2). The first stage is the downstream transfer of the setup packet. This element takes the pointer to a buffer containing the setup data. This buffer has to be allocated as a non-pageable contiguous physical memory block (simply use void *kmalloc(size_t, GFP_KERNEL);).
This element is returned to indicate the first frame number the interrupt is scheduled.
This element specifies the first frame number the isochronous transfer is scheduled. Setting the start_frame allows to synchronize transfers to or from a endpoint. If the USB_ISO_ASAP flag is specified this element is returned to indicate the first frame number the isochonous transfer is scheduled.
Isochronous transfer requests are sent to the USB core as a set of single requests. A single requests transfers a data packet up to the maximum packet size of the specified endpoint (pipe). This element sets the number of packets for the transfer.
After the request is completed (URB status is != -EINPROGRESS) this element counts the number of errorneous packets. Detailed information about the single transfer requests can be found in the iso_frame_desc structure.
This additional array of structures at the end of every isochronous URB sets up the transfer parameters for every single request packet.
Specifies the offsetaddress to the transfer_buffer for a single request.
Specifies the length of the data buffer for a single packet. If length is set to 0 for a single request the USB frame is skipped and no transfer will be initiated. This option can be used to synchronize isochronous data streams (specified in [4] section 5.6).
Returns the actual number of bytes transferred by this request.
Returns the status of this request. Further documentation can be found in section 3.1.