USB device driver debugging

Source: Internet
Author: User

It indicates that any short read that may occur on an in endpoint should be treated as an error by the USB core. this value is only useful for reading urb from a USB device, not for writing URBS.

Urb_iso_asap

If this urb is synchronized, this bit can be set. If the driver wants this urb to be scheduled, as long as the bandwidth permits it, and set the start_frame variable in this urb. if the synchronized urb bit is not set, the driver must specify the start_frame value and be able to restore it correctly. If it is not started at that time. see the following section for more information about synchronizing urb messages.

Urb_no_transfer_dma_map

It should be set. When urb contains a DMA buffer to be sent, the USB core uses the buffer directed by the transfer_dma variable instead of the buffer directed by the transfer_buffer variable.

Urb_no_setup_dma_map

Like urb_no_transfer_dma_map, this bit is used to control the urb that has been established by a 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.

Urb_async_unlink

If it is set to bits, the call to usb_unlink_urb of the urb will be returned almost immediately, and the urb will be unbound later. otherwise, this function waits until urb is completely dechained and ends before returning. use this bit with caution because it may be difficult to debug synchronization issues.

Urb_no_fsbr

Only the uhci USB host controller driver is used, and it is told not to try the front side bus reclamation logic. generally, this bit should not be set because machines with uhci host controllers create a lot of CPU burden and the PCI bus is saturated by urb waiting for this bit to be set.

Urb_zero_packet

If it is set to a bit, a block out urb ends by sending a short packet that does not contain data. when the data is aligned to an endpoint message boundary. this is required by some bad USB devices (such as some USB-to-IR devices) to work properly ..

Urb_no_interrupt

If it is set, the hardware may not interrupt when urb ends. this bit should be used with caution and only used when queuing multiple URBS to the same endpoint. the USB core function uses this function for DMA buffer transfer.

Void * transfer_buffer

A pointer to a buffer used to send data to a device (for an out urb) or to obtain data from the device (for an in urb. to properly access this buffer, the host controller must be created using a call to kmalloc, not on a stack or statically. for the control endpoint, this buffer is the data phase sent.

Dma_addr_t transfer_dma

Buffer used to transmit data to a USB device using DMA.

Int transfer_buffer_length

The buffer length is directed by the transfer_buffer or transfer_dma variable (because only one buffer can be used by one urb). If this is 0, no transfer buffer is used by the USB core.

For an out endpoint, if the maximum size of this endpoint is smaller than the value specified by this variable, the transfer of this USB device is divided into smaller blocks to transmit data correctly. this large transfer occurs in consecutive USB frames. committing a large piece of data is very fast in a urb, and the USB host controller is divided into smaller ones, which is smaller than sending a buffer in a continuous order.

Unsigned char * setup_packet

Pointer to a setup packet that controls urb. It is transmitted before the data in the transport buffer. This variable is only valid for controlling urb.

Dma_addr_t setup_dma

The DMA buffer for the setupt packet controlling the urb. It is transmitted before the data in the normal transmission buffer. This variable is only valid for controlling the urb.

Usb_complete_t complete

Pointer to the handler function, which is called by the USB core when the urb is completely transferred or when an error occurs in urb. in this function, the USB driver can check this urb, release it, or resubmit it for another transfer. (See "completingurbs: Completed callback handler" for more details ).

The usb_complete_t type is defined as follows:

Typedef void (* usb_complete_t) (struct urb *, struct pt_regs *);

Void * Context

A pointer to a data point that can be set by a USB driver. It can be used by the processor when urb is returned to the driver. For details about this variable, see subsequent sections.

Int actual_length

When this urb is complete, this variable is set to the actual length of the data, or sent by this urb (for out urb) or accepted by this urb (for in urb. for in urb, this must be used to replace the transfer_buffer_length variable, because the received data may be smaller than the entire buffer size.

Int status

When the urb is terminated or started to be processed by the USB core, this variable is set to the current status of urb. the only time that a USB driver securely accesses this variable is in the urb processor function (described in "completingurbs: Completed callback handler ). this restriction prevents competition, which occurs when the urb is processed by the USB core. for synchronous urb, a successful value (0) in this variable only indicates whether the urb has been dechained. to obtain the detailed status on the synchronized urb, check the iso_frame_desc variable.

The valid values of this variable include:

0
This urb transfer is successful.

-Enoent
This urb is stopped by calling usb_kill_urb.

-Econnreset

Urb is called for usb_unlink_urb and the transfer_flags variable is set to urb_async_unlink.

-Einprogress

This urb is still being processed by the USB host controller. If your driver has seen this value, it is a bug in your driver.

-Eproto
This urb has the following error:

A bitstuff error occurs during transmission.

The hardware did not receive the response frame in time.

-Eilseq
There is a CRC mismatch in this urb transfer.

-Epipe
This endpoint is now stopped. If the included endpoint is not a control endpoint, this error can be cleared by calling the function usb_clear_halt.

-Ecomm
In transmission, data is received faster than can be written into the system memory. This error value is only for in urb.

-Enosr
During transmission, data cannot be obtained from the system memory quickly enough to keep up with the requested USB data rate. This error is only for out urb.

-Eoverflow

This urb has a "babble" error. A "babble" error occurs when the endpoint receives more data than the specified maximum packet size of the endpoint.

-Eremoteio

This occurs only when the urb_short_not_ OK flag is set in the transfer_flags variable of urb, and indicates that the complete amount of data in the urb request is not received.

-Enodev
The USB device is now removed from the system.

-Exdev
Synchronization occurs only on the urb and means that the transfer is only partially completed. To decide what to send, the driver must view the individual frame status.

-Einval
This urb has a very bad thing. The USB Kernel documentation describes what this value means:

If this occurs, exit and go home.

It can also happen. If a parameter is incorrectly set in the urb structure, or if the urb is submitted to the USB core's usb_submit_urb call, there is an incorrect function parameter.

-Eshudown

This USB host controller driver has a serious error; it is currently disabled, or the device and system are removed from the connection, and the urb is submitted after the device is removed. it can also happen when the configuration of this device changes, and this urb is submitted to the device.

Generally, the error values-eproto,-eilseq, and-eoverflow indicate the device's Hardware problems, device firmware, or the cable connecting the device to the computer.
Int start_frame
Sets or returns the initial frame number to be used for synchronous transmission.

Int Interval

The polling interval of urb. this is only valid for interrupted or synchronized 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 devices, the unit is macro frame, which is equivalent to 1/8 microseconds. this value must be set by the USB driver to sync or interrupt urb before the urb is sent to the USB core.

Int number_of_packets

This parameter is valid only for the synchronized urb and specifies the number of the synchronous transport buffer to be processed by the urb. This value must be set by the USB driver to the synchronized urb before the urb is sent to the USB core.

Int error_count

It is set by the USB core and only sends synced urb after they are complete. It specifies the synchronous transfer number that reports any type of error.

Struct usb_iso_packet_descriptor iso_frame_desc [0]
Only valid for synchronizing urb. this variable is an array of struct usb_iso_packet_descriptor structures that constitute the urb. this structure allows a single urb to define multiple synchronous transfers at a time. it is also used to collect the transfer status of each individual transfer.

The structure usb_iso_packet_descriptor consists of the following members:

Unsigned int offset

The offset in the transmission buffer of the packet data (the first byte starts from 0 ).

Unsigned int Length

The length of the transmission buffer for this message.

Unsigned int actual_length

The length of the data buffer sent to the synchronous message.

Unsigned int status

The status of the packet transmitted separately. It can use the same returned value as the status variable in the main struct urb structure.

13.3.2. create and destroy urb
The struct urb structure must not be statically created in the driver, or in another structure, because it may damage the reference counting method that the USB core uses for urb. it must be created by calling the usb_alloc_urb function. this function has the following prototype:

Struct urb * usb_alloc_urb (INT iso_packets, int mem_flags );

The first parameter, iso_packet, is the number of synchronous packets that the urb should contain. if you do not want to create a synchronized urb, this variable should be set to 0. the 2nd parameters, mem_flags, are the same flag type as the memory allocated from the kernel that is passed to the kmalloc function call (see section 8th of "Flags Parameters, details about these signs ). if this function is successfully allocated enough memory to this urb,
A pointer pointing to urb is returned to the caller. If the returned value is null, an error occurs in the USB core and the driver needs to be properly cleaned up.

After creating an urb, it must be correctly initialized before it can be used by a USB core. For details about how to initialize different types of urb, see the next section.

To tell the USB core driver to use up the urb, the driver must call the usb_free_urb function. This function has only one parameter:

Void usb_free_urb (struct urb * urb );

The parameter is a pointer to the struct urb you want to release. After this function is called, The urb structure disappears and the driver cannot access it.

13.3.2.1. Interrupt urb
The function usb_fill_int_urb is a helper function that correctly initializes an urb to send an interrupt endpoint to the USB device:

Void usb_fill_int_urb (struct urb * urb, struct usb_device * Dev,
Unsigned int pipe, void * transfer_buffer,
Int buffer_length, usb_complete_t complete,
Void * context, int interval );

This function contains many parameters:

Struct urb * urb

Pointer to the urb to be initialized.

Struct usb_device * Dev

The USB device that the urb sends.

Unsigned int Pipe

The specific endpoint of the USB device to which the urb is sent. This value is created using the previously mentioned usb_sndintpipe or usb_rcvintpipe function.

Void * transfer_buffer

The pointer pointing to the buffer where the outgoing data is obtained or received. Note that this cannot be a static buffer and must be created using kmalloc.

Int buffer_length

The buffer length, directed by the transfer_buffer pointer.

Usb_complete_t complete

Pointer to the handler called when the urb is complete.

Void * Context

The pointer to the data block. It is added to the urb structure and will be obtained by the handler function later.

Int Interval

This urb should be scheduled. See the previous description of the struct urb structure to find the correct unit of this value.

13.3.2.2. Block urb
The initialization of block urb is very similar to the interruption of urb. This function is usb_fill_bulk_urb. It looks like this:

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,
Void * context );

This function parameter is the same as that of the usb_fill_int_urb function. however, there is no interval parameter because bulk urb has no interval value. note that the unsiged int pipe variable must be initialized and called by the usb_sndbulkpipe or usb_rcvbulkpipe function.

The usb_fill_int_urb function does not set the transfer_flags variable in urb. Therefore, any modification to this member must be completed by the driver.

13.3.2.3. Control urb
The method used to control the initialization of urb is almost the same as that of block urb. Call the function usb_fill_control_urb:

Void usb_fill_control_urb (struct urb * urb, struct usb_device * Dev,
Unsigned int pipe, unsigned char * setup_packet,
Void * transfer_buffer, int buffer_length,
Usb_complete_t complete, void * context );

Function parameters are the same as those of the usb_fill_bulk_urb function. Except for a new parameter, unsigned char * setup_packet must point to the setup packet data to be sent to the endpoint. also, the unsigned int pipe variable must be initialized and called using the usb_sndctrlpipe or usb_rcvictrlpipe function.

The usb_fill_control_urb function does not set the transfer_flags variable in urb. Therefore, any modification to this member must be completed by the game driver. most drivers do not use this function, because the synchronous API call described in "USB transfer without urb" is simpler.

13.3.2.4. Synchronize urb
Unfortunately, synced urb does not have an initialization function like interrupt, control, and block urb. therefore, they must be manually initialized in the driver before they can be submitted to the USB core. the following is an example of how to correctly initialize this type of urb. it is from konicawc. obtained in the C kernel driver, which is located in the drivers/USB/Media Directory of the main kernel source code tree.

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 = frames_per_desc;
Urb-> transfer_buffer_length = frames_per_desc;
For (j = 0; j <frames_per_desc; j ++ ){

Urb-> iso_frame_desc [J]. offset = J;
Urb-> iso_frame_desc [J]. Length = 1;
}

13.3.3. Submit urb
Once urb is correctly created and initialized by the USB driver, it is ready to be submitted to the USB core for sending to the USB device. This is achieved by calling the function usb_submit_urb:

Int usb_submit_urb (struct urb * urb, int mem_flags );

The urb parameter is a pointer to urb, which is sent to the device. the mem_flags parameter is equivalent to the same parameter passed to the kmalloc call, and is used to tell the USB core how to timely allocate any memory buffer at this time.

After urb is successfully submitted to the USB core, it should never attempt to access any members of the urb structure until the completion function is called.

Because the function usb_submit_urb can be called at any time (including from an interrupt context), The mem_flags variable must be correctly specified. There are only three valid values available, depending on when usb_submit_urb is called:

Gfp_atomic

This value should be used whenever the following is true:

The caller is in an urb processor, with an interrupt, a rear half, a tasklet, or a clock callback.

The caller holds a spin lock or read/write lock. Note that this value is unnecessary if a flag is being held.

Current-> state is not task_running. The status is always task_running unless the driver has changed the current status.

Gfp_noio

This value should be used if the driver is in the block I/O patch. It should also be used in all storage-type error handling patches.

Gfp_kernel

This should be used in all other cases and does not belong to the category mentioned above.

13.3.4. urb completed: callback handler completed
If the call to usb_submit_urb is successful and the URL control is passed to the USB core, this function returns 0; otherwise, a negative error value is returned. if the function succeeds, the urb completion handler (as specified by the completion function pointer) is called exactly once when urb is completed. when this function is called, the USB core completes the urb, and the control on it is now returned to the device driver.

There are only three methods. An urb can be terminated and the completed function can be called:

Urb is successfully sent to the device, and the device returns the correct confirmation. for an out urb, the data is successfully sent, and for an in urb, the request data is successfully received. if this happens, the status variable in urb is set to 0.

Some errors occur consecutively. When sending or receiving data from the device, it is recorded by the error value in the status variable in the urb structure.

This urb is removed from the USB core. 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 the device is removed from the system and an urb has been submitted to it.

An example of how to test different return values in an urb completed call is shown later in this chapter.

13.3.5. Cancel urb
To stop a urb that has been submitted to the USB core, the function usb_kill_urb or usb_unlink_urb should be called:

Int usb_kill_urb (struct urb * urb );

Int usb_unlink_urb (struct urb * urb );

The urb parameter for both of these functions is a pointer to the urb that is to be canceled.

When the function is usb_kill_urb, the lifecycle of the urb is stopped. This function is often used when the device is removed from the system and is in the disconnect callback.

For some drivers, the USB _ unlink_urb function should be used to inform the USB core to stop urb. this function does not wait until the urb stops completely before returning to the caller. this is useful when stopping urb during interrupt processing 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. in order to work properly, this function requires that the urb_async_unlink flag value be set to be requested to be stopped.
In urb.

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.