Linux Device Driver Learning (18)-USB Driver (3)

Source: Internet
Author: User
USB urb (USB request block) Kernel 2.6.29.4The USB device driver code communicates with all USB devices through urb. Urb uses the struct urb structure description (include/Linux/USB. h ).
Urb sends or receives data asynchronously from a specific endpoint of the same USB device. A USB device driver can allocate multiple URBS to one endpoint or reuse a single urb to multiple different endpoints Based on the driver's needs. Each endpoint in the device processes an urb queue, So multiple URBS can be sent to the same endpoint before the queue is cleared. The typical lifecycle of an urb is as follows:
(1) created;
(2) is allocated to a specific endpoint of a specific USB device;
(3) submitted to the USB core;
(4) The driver is submitted by the USB core to a specific USB host controller of a specific device;
(5) processed by the USB Host Controller and transmitted to the device;
(6) After the above operations are completed, the USB host controller driver notifies the USB device driver. Urb can also be canceled at any time by the submitted drive; if the device is removed, urb can be canceled by the USB core. Urb is dynamically created and contains an internal reference count so that they can be automatically released when the last user releases them. Struct urb
Struct urb {/* Private: USB core and host controller only fields in the urb */struct kref;/* urb reference count */void * hcpriv; /* private data of the Host Controller */atomic_t use_count;/* current submission count */atomic_t reject;/* Submission failure count */INT unlinked; /* connection failure code * // * Public: incluented fields in the urb that can be used by drivers */struct list_head urb_list; /* List head for use by the urb's * Current Owner */struct list_head ancho R_list;/* The urb may be anchored */struct usb_anchor * anchor; struct usb_device * dev;/* points to the pointer of the target struct usb_device to be sent by the urb, this variable must be initialized by the USB driver before the urb is sent to the USB core. */struct usb_host_endpoint * EP;/* (internal) pointer to endpoint */unsigned int pipe;/* the endpoint message of the urb to be sent to the specific struct usb_device, this variable must be initialized by the USB driver before the urb is sent to the USB core. the following function must generate */INT status;/* When urb starts processing or processing by the USB core, this variable is set to the current status of urb. Status. the only time that the USB driver can safely access this variable is in the urb end processing routine function. this restriction is used to prevent competition. for a time-like urb, the success value (0) in this variable only indicates whether the urb has been dechained. to obtain the detailed status of the hour urb, check the iso_frame_desc variable. */unsigned int transfer_flags;/* transmission setting */void * transfer_buffer;/* Indicates whether to send data to or receive data from the device (in urb) buffer pointer. In order for the host controller driver to correctly access this buffer, it must be created using the kmalloc call, not in the stack or static memory. For the control endpoint, this buffer is used for data transfer */dma_addr_t transfer_dma;/* is used to transmit data to the buffer zone of the USB device in DMA mode */INT transfer_buffer_length; /* the size of the buffer to which the transfer_buffer or transfer_dma variable points. If this is 0, the transfer buffer is not used by the USB core. For an out endpoint, if the size of this endpoint is smaller than the value specified by this variable, the transmission of this USB device will be divided into smaller blocks to transmit data correctly. This large transfer is performed with consecutive USB frames. Commit a large piece of data in an urb and divide the USB host controller into smaller blocks, which is much faster than sending small buffers in a sequential order */INT actual_length; /* after the urb is complete, the variable is set to the actual length of the data sent by the urb (for out urb) or received by the (for in urb. for in urb, this variable must be used instead of transfer_buffer_length, because the received data may be smaller than the entire buffer */unsigned char * setup_packet;/* points to the set data packet pointer that controls urb. it is transmitted before the data in the transmission buffer (used to control urb) */dma_addr_t setup_dma;/* controls urb to set the DMA buffer address of the data packet, it is transmitted (used to control urb) */INT start_frame;/* sets or returns the initial number of frames (used to transmit data in the normal buffer zone) Wait hour urb) */INT number_of_packets;/* specify the number of equal hour transmission buffers processed by urb (used for equal hour urb, which must be set before urb is sent to the USB core) */INT interval;/* urb polling interval. valid only for the interrupted or equal hour urb. the unit of this value varies according to the device speed. for low-speed and high-speed devices, the unit is frame, which is equivalent to milliseconds. for other devices, the unit is microframe, equivalent to 1/8 milliseconds. this value must be set before urb is sent to the USB core. */INT error_count;/* indicates the urb error count, which is set by the USB core */void * context;/* Indicates a data block that can be set by the USB driver module. when urb is returned to the driver, it can be used in the end processing routine. */usb_complete_t complete;/* function pointer of the End Processing routine. When urb is completely transmitted or an error occurs, it Will be called by USB core. this function checks the urb and decides to release it or resubmit it to another transmission */struct usb_iso_packet_descriptor iso_frame_desc [0];/* (used only for the hour urb) the usb_iso_packet_descriptor struct allows a single urb to define multiple transmission times at a time. It is used to collect each individual transmission status */}; struct usb_iso_packet_descriptor {unsigned int offset; /* the offset of the data packet in the transmission buffer (the first byte is 0) */unsigned int length;/* the buffer size of the data packet */unsigned int actual_length; /* indicates the length of data in the transmission buffer received by the data packet */INT status;/* indicates the transmission status of a single and other data packet. It can take the same return value as the state variable */} of the main struct urb struct; typedef void (* usb_complete_t) (struct urb *);
In the above struct, the unsigned int pipe; generation function (define ):
Static inline unsigned int _ create_pipe (struct usb_device * Dev, unsigned int endpoint) {return (Dev-> devnum <8) | (endpoint <15 );} /* create various pipes... */# define usb_sndctrlpipe (Dev, endpoint) \ (pipe_control <30) | _ create_pipe (Dev, endpoint) # define usb_rcvctrlpipe (Dev, endpoint) \ (pipe_control <30) | _ create_pipe (Dev, endpoint) | usb_dir_in) # define usb_sndisocpipe (Dev, endpoint) \ (pipe_isochronous <30) | _ create_pipe (Dev, endpoint) # define usb_rcvisocpipe (Dev, endpoint) \ (pipe_isochronous <30) | _ create_pipe (Dev, endpoint) | usb_dir_in) # define usb_sndbulkpipe (Dev, endpoint) \ (pipe_bulk <30) | _ create_pipe (Dev, endpoint) # define usb_rcvbulkpipe (Dev, endpoint) \ (pipe_bulk <30) | _ create_pipe (Dev, endpoint) | usb_dir_in) # define usb_sndintpipe (Dev, endpoint) \ (pipe_interrupt <30) | _ create_pipe (Dev, endpoint) # define usb_rcvintpipe (Dev, endpoint) \ (pipe_interrupt <30) | _ create_pipe (Dev, endpoint) | usb_dir_in) // SND: Out RCV: in ctrl: When controlling ISOC:, bulk: Batch INT: interrupted
The value range of the unsigned int transfer_flags; in the above struct:
/** Urb-> transfer_flags: ** Note: urb_dir_in/out is automatically set in usb_submit_urb (). */# When define urb_short_not_ OK 0x0001/* is set, any brief reads on the in endpoint are considered as errors by the USB core. it is only useful for urb read from a USB device */# define urb_iso_asap 0x0002/* if it is equal to urb, the driver can set this bit when it wants to schedule this urb, as long as the bandwidth permits and you want to set the start_frame variable in urb at this time. if no position is set, the driver must specify the start_frame value, and if the transmission cannot be started at that time, you must be able to correctly recover */# define urb_no_transfer_dma_map 0x0004/* When urb contains the DMA buffer to be sent, it should be set. the USB core uses the buffer to which the transfer_dma variable points, instead of the buffer to which the transfer_buffer variable points. */# define urb_no_setup_dma_map 0x0008/* is similar to urb_no_transfer_dma_map. This bit is used to control the urb created by the DMA buffer. if it is set, the USB core uses the setup_dma variable instead of the buffer pointed to by the setup_packet variable. */# define urb_no_fsbr 0x0020/* used only by the uhci USB host controller driver and told it not to try to use the front side bus reclamation logic. generally, this bit should not be set because machines with uhci host controllers will increase the CPU burden, and the PCI bus will be busy waiting for the urb */# define urb_zero_packet 0x0040/* with this bit. If it is set to a bit, the batch out of urb will end by sending a short packet that does not contain the data, at this time, the data is aligned to the boundary of an endpoint data packet. this is required for some dropped USB devices to work correctly */# define urb_no_interrupt 0x0080/* if it is set, the hardware may not be interrupted when urb ends. this bit should be used with caution and only used when multiple URBS queue to the same endpoint. the USB core function uses this bit for DMA buffer transfer. */# define urb_free_buffer 0x0100/* Free Transfer Buffer with the urb */# define urb_dir_in 0x0200/* Transfer from device to host */# define urb_dir_out 0 # define urb_dir_mask urb_dir_in
Common int status; values in the preceding struct (in include/ASM-generic/errno. h and errno_base.h ):
// 0 indicates that the urb is successfully transferred * // The following definitions are negative when used # define enoent 2/* The urb is stopped by usb_kill_urb */# define econnreset 104/* The urb is directed by usb_unlink_urb chain, transfer_flags is set to urb_async_unlink */# define progress 115/* The urb is still being processed by the USB Host Controller */# define eproto 71/* an error occurs in urb: A bitstuff error occurs during transmission or the hardware does not receive the response frame in time */# define eilseq 84/* CRC verification error occurs during urb transmission */# define epipe 32/* the endpoint is stopped. if this endpoint is not the control endpoint, you can clear this error using the usb_clear_halt function */# define eco Mm 70/* the data transmission speed is faster than the system memory speed. this error only occurs in urb */# define enosr 63/* the speed at which data is retrieved from the system memory cannot match the USB data transfer speed. This error only occurs in out urb. */# define eoverflow 75/* A "babble" (crosstalk) error occurs in urb: the data received by the endpoint is greater than the maximum data packet size of the endpoint */# define eremoteio 181/* When the urb_short_not_ OK mark of the transfer_flags variable of the urb is set, the data in the urb request is not completely received */# define enodev 19/* the USB device pulls out from the system */# define exdev 18/* only occurs in the urb at the same time, indicates that the transfer is completed. to determine the transmitted content, the driver must view the individual frame status. */# define einval 2 2/* If one of urb's parameter settings is incorrect or there is an incorrect parameter in the usb_submit_urb call to submit urb to the USB core, an error may occur */# define eshudown 108/* the USB host controller driver has a serious error. It has been disabled or the device has been removed from the system. This urb is submitted after the device is removed. It may also happen when the urb is submitted to the device, the device configuration has been changed */
Create and log out of urbThe struct urb structure cannot be created statically. You must use the usb_alloc_urb function to create a. function prototype:
Struct urb * usb_alloc_urb (INT iso_packets, gfp_t mem_flags); // int iso_packets: the number of data packets when urb contains. If urb is not used, it is 0 // gfp_t mem_flags: it is the same as the flag type passed to the kmalloc function call to allocate memory from the kernel. // return value: if enough memory is allocated to urb, the returned value is the pointer to urb. if the returned value is null, an error occurs in the USB core and the driver needs to be cleaned up properly.

If the driver has used urb, you must call the usb_free_urb function to release urb. Function prototype:

Void usb_free_urb (struct urb * urb); // struct urb * urb: struct urb pointer to be released
Based on the kernel source code, you can use your own kmalloc space to create the urb, And then you must use
void usb_init_urb(struct urb *urb);
Can be used after initialization. In fact, the usb_alloc_urb function is implemented in this way, so I certainly do not recommend this approach.

Initialize urb
Static inline void Merge (struct urb * urb, struct usb_device * Dev, unsigned int pipe, void * transfer_buffer, int buffer_length, usb_complete_t complete_fn, void * context, int interval ); static inline void usb_fill_bulk_urb (struct urb * urb, struct usb_device * Dev, unsigned int pipe, void * transfer_buffer, int buffer_length, usb_complete_t complete_fn, void * context ); static inline void encode (struct urb * urb, struct usb_device * Dev, unsigned int pipe, unsigned char * setup_packet, void * transfer_buffer, int buffer_length, complete complete_fn, void * context ); // struct urb * urb: pointer to the urb to be initialized // struct usb_device * Dev: pointer to the USB device to be sent to urb. // unsigned int pipe: The specific endpoint of the USB device to which the urb is sent. you must use the previously mentioned USB _ ******* pipe function to create // void * transfer_buffer: pointer to the buffer for sending or receiving data. note: it cannot be a static buffer, but must be created using kmalloc. // int buffer_length: the size of the buffer to which the transfer_buffer Pointer Points. // usb_complete_t complete: pointer to the processing routine function of urb. // void * context: pointer to a small data block, added to the urb structure to be used by the function of the ending processing routine. // int interval: interval at which the urb is interrupted and scheduled. // The function does not set the transfer_flags variable in urb. Therefore, the modification to this member must be manually completed by the driver./* and so on. When urb does not initialize the function, it must be manually initialized, the following is an example */urb-> Dev = dev; urb-> context = UVD; urb-> pipe = usb_rcvisocpipe (Dev, UVD-> video_endp-1 ); urb-> interval = 1; urb-> transfer_flags = urb_iso_asap; urb-> transfer_buffer = cam-> sts_buf [I]; urb-> complete = konicawc_isoc_irq; urb-> number_of_packets = bytes; urb-> transfer_buffer_length = frames_per_desc; For (j = 0; j <strong; j ++) {urb-> iso_frame_desc [J]. offset = J; urb-> iso_frame_desc [J]. length = 1 ;}
In fact, the three initialization functions are simple packaging and inline functions. In fact, there is no big difference between it and the time-based urb manual initialization. Submit urbOnce urb is correctly created and initialized, it can be submitted to the USB core to be sent to the USB device. This is achieved by calling the function usb_submit_urb:
Int usb_submit_urb (struct urb * urb, gfp_t mem_flags); // struct urb * urb: pointer to the submitted urb // gfp_t mem_flags: The same parameter is called using the pointer passed to kmalloc, used to tell the USB core how to allocate memory buffer in a timely manner/* because the function usb_submit_urb can be called at any time (including from an interrupt context), The mem_flags variable must be correctly set. according to the time when usb_submit_urb is called, only three valid values are available: gfp_atomic should be used if the following conditions are met: 1. the caller is in an urb end processing routine, interrupt processing routine, bottom half, tasklet, or a timer callback function. 2. the caller holds the spin lock or read/write lock. note that this value is unnecessary if a semaphore is being held. 3. current-> state is not task_running. unless the driver has changed the current status, the status should always be task_running. the gfp_noio driver is in block I/O processing. it should also be used for error handling of all storage types. gfp_kernel does not belong to any other situations mentioned above */
After urb is successfully submitted to the USB core, no member of the urb structure can be accessed until the processing routine function is called. Urb End Processing RoutineIf usb_submit_urb is successfully called and the control of urb is passed to the USB core, the function returns 0; otherwise, a negative error code is returned. if the function is called successfully, the processing routine will be called once when urb ends. when this function is called, the USB core completes the urb and returns its control to the device driver. there are only three cases where urb ends and the end processing routine is called: (1) urb is successfully sent to the device and the device returns the correct confirmation. in this case, the status variable in urb is set to 0.

(2) When an error occurs, the error value is recorded in the status variable in the urb structure.

(3) urb from USB core Unlink. this occurs either when the driver notifies the USB core to cancel a submitted urb by calling usb_unlink_urb or usb_kill_urb, or when a urb has been submitted to it, the device is removed from the system. Cancel urbUse the following function to stop a urb that has been submitted to the USB core:
void usb_kill_urb(struct urb *urb)int usb_unlink_urb(struct urb *urb);
If you call the usb_kill_urb function, the lifecycle of urb is terminated. This is usually called in the disconnect callback function when the device is removed from the system.

For some drivers, you should call the usb_unlink_urb function to stop the USB core urb. this function will not be returned until urb is completely stopped. this is useful for stopping urb In the interrupt processing routine or holding a spin lock, because waiting for a completely stopped urb requires the USB core to have the ability to sleep the calling process (wait_event () function ).
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.