Title: USB Drivers
1USB Drivers
- Michael Mitchell
- COP 5641 / CIS 4930
2USB Device Basics
- Universal Serial Bus (USB) connects between a
computer and peripheral devices - Created to replace various slow buses (parallel,
serial, and keyboard connections) - USB 2.0 up to 480Mb/s (35 MB/s)
- USB 3.0 up to 6Gb/s (625 MB/s)
3USB Device Basics
- A USB device can never start sending data without
first being asked by the host controller - Single-master implementation
- Host polls various devices
- A device can request a fixed bandwidth (for audio
and video I/O) - Universal Serial Bus is a misnomer
- Actually a tree built out of point-to-point links
- Links are four-wire cables (ground, power, and
two signal wires)
4USB Device Basics The Protocol
- USB protocol defines a set of standards that any
device can follow - No need to write a driver for a device that is in
a predefined class and follows that standard, - Predefined classes storage devices, keyboards,
mice, joysticks, network devices, and modems - No defined standard for video devices and
USB-to-serial devices - A driver is needed for every device
5USB Device Basics Driver Types
- Linux supports two types of USB drivers
- Drivers on a host system
- Control the USB devices that are plugged into it
- Drivers on a device (USB gadget drivers)
- Control how that single device looks to the host
computer as a USB device - Some hardware devices can actually be both
- Called USB OTG (On The Go),
- E.g. Android 3.0, some printers
6USB Device Basics
7USB Device Basics
USB drivers bind to interfaces, not the device
8USB Overview
- A USB device has one or more configurations
- E.g., power and bandwidth requirements
- A configuration has one or more interfaces
- E.g., audio data, knobs for speakers
- An interface has one or more settings
- Different quality of services
- E.g., different frame sizes for digital cameras
- Also zero or more endpoints
- E.g., bulk, interrupt endpoints.
9Endpoints
- The most basic form of USB communication is
through an endpoint - Unidirectional Carries data in one direction
- From the host to device (OUT endpoint)
- From the device to the host (IN endpoint)
10Endpoints
- Four endpoint types
- CONTROL
- INTERRUPT
- BULK
- ISOCHRONOUS
11Endpoints
- CONTROL
- Used for configuring the device, retrieving
information and status about the device, or
sending commands to the device - Every device has a control endpoint called
endpoint 0 - Used by USB core to configure the device at
insertion time - Transfers are guaranteed with reserved bandwidth
12Endpoints
- INTERRUPT
- Transfer small amounts of data at a fixed rate
- For USB keyboards and mice
- Also used to control the device
- Not for large transfers
- Guaranteed reserved bandwidth
13Endpoints
- BULK
- Transfer large amounts of data
- No data loss
- Not time guaranteed
- A BULK packet might be split up across multiple
transfers - Used for printers, storage, and network devices
14Endpoints
- ISOCHRONOUS
- Transfer large amount of data
- For real-time data collections, A/V devices
- Unlike bulk endpoints, no guarantees (potential
data loss) - Control and bulk endpoints are used for
asynchronous data transfers - Interrupt and isochronous endpoints are periodic
with reserved bandwidth
15Endpoints
- Endpoint information is in struct
usb_endpoint_descriptor - embedded in struct usb_host_endpoint
- Note defined by the USB standard, so not Linux
looking - Some important fields
- bEndpointAddress (8-bit)
- Use USB_DIR_OUT and USB_DIR_IN bit masks to
determine the direction of data flow
16Endpoints
- bmAttributes
- Type of the endpoint
- USB_ENDPOINT_XFERTYPE_MASK to determine if the
endpoint is of type USB_ENDPOINT_XFER_ISOC,
USB_ENDPOINT_XFER_BULK, or USB_ENDPOINT_XFER_INT - wMaxPacketSize
- Maximum bytes that an endpoint can handle
- Larger transfers will be split into multiple
transfers
17Endpoints
- bInterval
- For interrupt endpoints, this value specifies the
milliseconds between interrupt requests for the
endpoint
18Interfaces
- USB endpoints are bundled into interfaces
- A interface handles only one type of logical
connection (E.g., a mouse) - Some devices have multiple interfaces
- E.g., a speaker
- One interface for buttons and one for audio
stream - USB interface may have alternate settings
- E.g., different settings to reserve different
amounts of bandwidth for the device
19Interfaces
- Described via struct usb_interface
- Passed from USB core to USB drivers
- Some important fields
- struct usb_host_interface altsetting
- An array of settings for this interface
- unsigned num_altsetting
- Number of alternative settings
20Interfaces
- struct usb_host_interface cur_altsetting
- A pointer into the altsetting array, denoting the
current setting - int minor
- Minor number assigned by the USB core to the
interface - Valid after a successful call to usb_register_dev
21Configurations
- USB interfaces are bundled into configurations
- A USB device can have multiple configurations
- Only one can be active at a time
- Can switch between them
- Described in struct usb_host_config
- embedded in struct usb_device
22USB Webcam Device Example
Configuration
Configuration Active
Configuration
Configuration Standby
DeviceUSB webcam
23USB and Sysfs
- Both USB devices and its interfaces are shown in
sysfs as individual devices - A USB mouse device can be represented as
- /sys/devices/pci000000/00000009.0/usb2/2-1
- The interface of the USB mouse device driver is
represented as - /sys/devices/pci000000/00000009.0/usb2/2-1/2-1
1.0
root_hub-hub_portconfiguration.interface
24USB and Sysfs
- For a two-level USB connection, the device name
is in the following format - root_hub-hub_port-hub_portconfiguration.interf
ace - In the sysfs directory, all USB information is
available - E.g., idVendor, idProduct, bMaxPower
- bConfigurationValue can be written to change the
active configuration
25USB and Sysfs
- More information is available in /proc/bus/usb
directory - User-space programs can directly communicate with
USB devices via the directory
26USB Urbs (USB Request Block)
- Communication between the host and device is done
asynchronously using USB Request Blocks (URBs). - Similar to packets in network communications.
- Every endpoint can handle a queue of URBs.
- Every URB has a completion handler.
- Flexible A driver may allocate many URBs for a
single endpoint, or reuse the same URB for
different endpoints. - See Documentation/usb/URB.txt in kernel sources.
27USB Urbs (USB Request Block)
- struct urb
- Used to send and receive data between endpoints
- Asynchronous
- Dynamically created
- Contains reference count for garbage collection
- Designed to achieve high throughput
- Defined in ltinclude/linux/usb.hgt
- Must be created with the usb_alloc_urb()
function. Shouldn't be allocated statically or
with kmalloc(). - Must be deleted with usb_free_urb().
28USB Urbs (USB Request Block)
- A typical lifecycle of an Urb
- A USB device driver creates an Urb
- Assigns it to a specific endpoint of a device
- Submits it to the USB core
- The USB core submits the Urb to specific USB host
controller driver - The USB host controller driver processes the Urb
and transfers it to the device - Notifies the USB device driver when the Urb is
done
29USB Urbs (USB Request Block)
- An Urb can be cancelled by the driver or the USB
core if the device is removed from the system
30Life Cycle of an Urb
Creation
USB core(controllerdriver)
Devicedriver
Assignedto an endpoint
Submittedto the USB core
Transferedto the device
yes
can bereused?
Notification attransfer completion
no
Deletion
31struct urb
- Important fields
- / destination USB device /
- / must be initialized by the USB driver before
the urb can be sent to the USB core / - struct usb_device dev
- / end point type information /
- / set to the return value from one of the usb
send and receive pipe functions / - / must be initialized by the USB driver before
the urb can be sent to the USB core / - unsigned int pipe
32struct urb
- / assigned to one of the transfer flags /
- unsigned int transfer_flags
- void transfer_buffer / points to a kmalloced
buffer / - dma_addr_t transfer_dma / buffer for DMA
transfers / - / buffer length for either the transfer_buffer
or the transfer_dma variable, 0 if neither
buffers are used / - int transfer_buffer_length
- / pointer to a setup packet for a control urb /
- / transferred before the data in the transfer
buffer / - unsigned char setup_packet
- / DMA buffer for the setup packet for a control
urb / - dma_addr_t setup_dma
33struct urb
- / pointer to the completion handler called by
USB core / - usb_complete_t complete
- / pointer to a data blob that can be set by the
USB driver / - void context
- / actual length of data sent/received by the urb
/ - int actual_length
- / accessed in the completion handler /
- / see status values /
- int status
- / the initial frame number for isochronous
transfers / - int start_frame
34struct urb
- / polling interval for the urb /
- / valid only for interrupt or isochronous urbs
/ - / for slow devices, the unit is in frames or
milliseconds / - / for other devices, the unit is in 1/8
milliseconds / - int interval
- / the number of isochronous transfer buffers
handled by this urb / - / must be set by the USB driver before the urb
is sent to the USB core / - int number_of_packets
- / number of isochronous transfers with errors /
- int error_count
35struct urb
- / allows a single urb to define a number of
isochronous transfers at once / - struct usb_iso_packet_descriptor
iso_frame_desc0 - struct usb_iso_packet_descriptor
- unsigned int offset / byte into the transfer
buffer / - unsigned int length / length of the transfer
buffer / -
- / length of data received into the transfer
buffer / - unsigned int actual_length
- unsigned int status / see status values /
-
36USB send and receive pipe functions
- / specifies a control OUT endpoint for the
specified USB device with the specified endpoint
number / - unsigned int usb_sndctrlpipe(struct usb_device
dev, - unsigned int
endpoint) - / specifies a control IN endpoint for the
specified USB device with the specified endpoint
number / - unsigned int usb_rcvctrlpipe(struct usb_device
dev, - unsigned int
endpoint) - / specifies a bulk OUT endpoint for the
specified USB device with the specified endpoint
number / - unsigned int usb_sndbulkpipe(struct usb_device
dev, - unsigned int
endpoint)
37USB send and receive pipe functions
- / specifies a bulk IN endpoint for the specified
USB device with the specified endpoint number / - unsigned int usb_rcvbulkpipe(struct usb_device
dev, - unsigned int
endpoint) - / specifies a interrupt OUT endpoint for the
specified USB device with the specified endpoint
number / - unsigned int usb_sndintpipe(struct usb_device
dev, - unsigned int
endpoint) - / specifies a interrupt IN endpoint for the
specified USB device with the specified endpoint
number / - unsigned int usb_rcvintpipe(struct usb_device
dev, - unsigned int
endpoint)
38USB send and receive pipe functions
- / specifies a isochronous OUT endpoint for the
specified USB device with the specified endpoint
number / - unsigned int usb_sndisocpipe(struct usb_device
dev, - unsigned int
endpoint) - / specifies a isochronous IN endpoint for the
specified USB device with the specified endpoint
number / - unsigned int usb_rcvisocpipe(struct usb_device
dev, - unsigned int
endpoint)
39URB Transfer flags
- URB_SHORT_NOT_OK
- Partial read should be treated as an error by the
USB core - URB_ISO_ASAP
- If the driver wants the isochronous urb to be
scheduled as soon as bandwidth allows - Set the start_frame variable
40URB Transfer flags
- URB_NO_TRANSFER_DMA_MAP
- Set when the urb contains a DMA buffer to be
transferred - Tells the USB core to use the buffer pointed by
the transfer_dma pointer, not the transfer_buffer
pointer
41URB Transfer flags
- URB_NO_SETUP_DMA_MAP
- Used for control urbs with DMA buffer already set
up - Tells the USB core to use the buffer pointed by
the setup_dma pointer instead of the setup_packet
pointer - URB_ASYNC_UNLINK
- Tells usb_unlink_urb() to return immediate and
unlink the urb in the background
42URB Transfer flags
- URB_NO_FSBR
- For UHCI USB host controller
- Generally not used
- URB_ZERO_PACKET
- Tells a bulk out urb finishes by sending an empty
packet when the data is aligned to an endpoint
packet boundary
43URB Transfer flags
- URB_NO_INTERRUPT
- Indicates that the HW may not generate an
interrupt when the urb is finished - Used when queuing multiple urbs to the same
endpoint - Used by USB core to perform DMA transfers
44URB Status Values
- 0
- The urb transfer was successful
- For isochronous urbs, only indicates whether the
urb has been unlinked - Detailed status in iso_frame_desc
- -ENOENT
- Urb stopped by usb_kill_urb
- -ECONNRESET
- Urb was unlinked by usb_unlink_urb
- transfer_flags set to URB_ASYNC_UNLINK
45URB Status Values
- -EINPROGRESS
- Urb still being processed by the USB host
controller - A bug if seen at the driver level
- -EPROTO (a HW problem)
- A bitstuff error happened during the transfer
- No response packet was received
- -EILSEQ (a HW problem)
- CRC mismatch
46URB Status Values
- -EPIPE
- The endpoint is now stalled
- If not a control endpoint, can clear this error
with usb_clear_halt - -ECOMM
- Data received faster than it could be written to
system memory - -ENOSR
- Data cannot be retrieved from the system memory
during the transfer fast enough to keep up with
the requested USB data rate
47URB Status Values
- -EOVERFLOW (a HW problem)
- When the endpoint receives more data than the
specified max - -EREMOTEIO
- Full amount of data was not received
- Occurs when the URB_SHORT_NOT_OK is set
- -ENODEV
- The USB device is gone from the system
48URB Status Values
- -ESHUTDOWN
- Host controller driver has been disabled or
disconnected - Urb was submitted after the device was removed
- Configuration change while the urb was submitted
49URB Status Values
- -EXDEV
- Only for a isochronous urb
- Transfer was partially completed
- -EINVAL
- ISO madness, if this happens Log off and go
home - Incorrect function parameter
50Creating and Destroying Urbs
- All URBs need to be created dynamically
- Or the reference count would not work
- To create a URB, call
- struct urb usb_alloc_urb(int iso_packets,
- gfp_t mem_flags)
- Returns pointer to the URB or NULL on failure
- iso_packets number of isochronous packets this
urb should contain - mem_flags same as kmalloc flags
- To destroy a urb, call
- void usb_free_urb(struct urb urb)
51Interrupt urbs
- To initialize an interrupt urb, call
- 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)
- urb a pointer to the urb to be initialized
- dev The destination USB device
- pipe the destination endpoint of this urb
52Interrupt urbs
- transfer_buffer a pointer to a kmalloced buffer
- buffer_length the length of the transfer buffer
- complete pointer to the completion handler
- context pointer to the blob, retrieved by the
completion handler function - interval scheduling interval for this urb
53Bulk urbs
- To initialize an bulk urb, call
- 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)
- Similar to interrupt urb initialization
- Exception No final interval parameter
54Control urbs
- To initialize a control urb, call
- 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) - Similar to bulk urb initialization
- setup_packet points to the setup packet data
- Also, does not set the transfer_flags
55Isochronous urbs
- Have no initialization functions
- Need to be initialized by hand
- / from /drivers/media/video/usbvideo/konicawc.c
/ - urb-gtdev dev
- urb-gtcontext uvd
- urb-gtpipe usb_rcvisocpipe(dev, uvd-gtvideo_endp
- 1) - urb-gtinterval 1
- urb-gttransfer_flags URB_ISO_ASAP
- urb-gttransfer_buffer cam-gtsts_bufi
- urb-gtcomplete konicawc_isoc_irq
- urb-gtnumber_of_packets FRAMES_PER_DESC
- urb-gttransfer_buffer_length FRAMES_PER_DESC
- for (j0 j lt FRAMES_PER_DESC j)
- urb-gtiso_frame_descj.offset j
- urb-gtiso_frame_descj.length 1
-
56Submitting Urbs
- To send a urb to the USB core, call
- int usb_submit_urb(struct urb urb, gfp_t
mem_flags) - urb a pointer to the urb
- mem_flags same as kmalloc flags
- GTP_KERNEL, GFP_ATOMIC, etc.
- Should not access a submitted urb until the
complete function is called
57Completing Urbs The Completion Callback Handler
- Called exactly once when the urb is completed
- When this function is called, the USB core is
finished with the urb, and control is returned to
the device driver
58Completing Urbs The Completion Callback Handler
- The completion handler is called under three
conditions - The urb is successfully sent to the device and
acknowledged - An error has occurred
- Check the status variable
- The urb was unlinked (the submission was
cancelled) when a device is removed from the
system
59Canceling Urbs
- To stop a submitted urb, call
- int usb_kill_urb(struct urb urb)
- Used when the device is disconnected from the
system - int usb_unlink_urb(struct urb urb)
- Tells the USB core to stop an urb
- Returns before the urb is fully stopped
- Useful while in an interrupt handler
- Requires setting the URB_ASYNC_UNLINK
60Actually writing a USB Driver
- Similar to a pci_driver
- Driver registers its driver object with the USB
subsystem - Later uses vendor and device identifiers to tell
if its hardware has been installed
61What Devices Does the Driver Support?
- struct usb_device_id lists supported types of USB
devices - Important fields
- __u16 match_flags
- Determines which fields in the structure the
device should be matched against - Check include/linux/mod_devicetable.h
- __u16 idVendor
- __u16 idProduct
62What Devices Does the Driver Support?
- __u16 bcdDevice_lo
- __u16 bcdDevice_hi
- Define low and high ends of the range of the
vendor-assigned product version number - Expressed in binary-coded decimal (BCD)
- __u8 bDeviceClass
- __u8 bDeviceSubClass
- __u8 bDeviceProtocol
- Define the class, subclass, and protocol of the
device
63What Devices Does the Driver Support?
- __u8 bInterfaceClass
- __u8 bInterfaceSubClass
- __u8 bInterfaceProtocol
- Class, subclass, and protocol of the individual
interface - kernel_ulong_t driver_info
- Used to differentiate different devices in the
probe callback function
64What Devices Does the Driver Support?
- To initialize usb_device_id, use the following
macros - USB_DEVICE(vendor, product)
- Creates a usb_device_id that can be used to match
only the specified vendor and product IDs - USB_DEVICE_VER(vendor, product, lo, hi)
- Creates a usb_device_id that can be used to match
only the specified vendor and product IDs within
a version range - USB_DEVICE_INFO(class, subclass, protocol)
- Creates a usb_device_id that can be used to match
a specific class of USB devices
65What Devices Does the Driver Support?
- USB_INTERFACE_INFO(class, subclass, protocol)
- Creates a usb_device_id that can be used to match
a specific class of USB interfaces - Example
- / table of devices that work with this driver /
- static struct usb_device_id skel_table
- USB_DEVICE(USB_SKEL_VENDOR_ID,
USB_SKEL_PRODUCT_ID) , - / Terminating entry /
-
- / allow user-space tools to figure out what
devices this driver can control / - MODULE_DEVICE_TABLE(usb, skel_table)
66Registering a USB Driver
- The main structure for a USB driver is struct
usb_driver - Important fields
- struct module owner
- Set to THIS_MODULE to track the reference count
of the module owning this driver - const char name
- Points to a unique driver name
67Registering a USB Driver
- const struct usb_device_id id_table
- Pointer to the list of supported USB devices
- If you want your driver always be called for
every USB device, create an entry that sets only
the driver_info field - static struct usb_device_id usb_ids
- .driver_info 42,
-
68Registering a USB Driver
- int (probe) (struct usb_interface intf,
- const struct usb_device_id id)
- Called when the USB core thinks it has a struct
usb_interface that this driver can handle - The USB driver should initialize the usb
interface and return 0, or return a negative
error number on failure - void (disconnect) (struct usb_interface intf)
- Called when the usb_interface has been removed
from the system, or when the driver is being
unloaded
69Registering a USB Driver
- To create a struct usb_driver, only five fields
need to be initialized - static struct usb_driver skel_driver
- .owner THIS_MODULE,
- .name "skeleton",
- .id_table skel_table,
- .probe skel_probe,
- .disconnect skel_disconnect,
-
70Registering a USB Driver
- To register a USB driver call usb_register_driver
- Example
- static int __init usb_skel_init(void)
- int result
- / register this driver with the USB subsystem
/ - result usb_register(skel_driver)
- if (result)
- err("usb_register failed. Error number d",
result) - return result
-
71Registering a USB Driver
- To unload a USB driver call usb_deregister
- Example
- static void __exit usb_skel_exit(void)
- / deregister this driver with the USB
subsystem / - / invokes disconnect() within usb_deregister()
/ - usb_deregister(skel_driver)
-
72Probe and Disconnect in Detail
- Called in the context of the USB hub kernel
thread - Sleep is allowed
- However, should do most of the work when the
device is opened by a user - USB core handles addition and removal of USB
devices in a single thread - A slow device driver can slow down USB device
detection
73Probe and Disconnect in Detail
- Probe function should
- Initialize local structures that it might use to
manage the USB device - Save any information that it needs to the local
structure - Detect endpoint address and buffer sizes
- Example usb/usb-skeleton.c
74Probe and Disconnect in Detail
- static int skel_prob(struct usb_interface
interface, - const struct usb_device_id
id) - struct usb_skel dev NULL
- struct usb_host_interface iface_desc
- struct usb_endpoint_descriptor endpoint
- size_t buffer_size
- int i
- int retval -ENOMEM
- dev kmalloc(sizeof(struct usb_skel),
GFP_KERNEL) - if (dev NULL)
- err(Out of memory)
- goto error
-
- memset(dev, 0x00, sizeof(dev))
- kref_init(dev-gtkref)
75Probe and Disconnect in Detail
- dev-gtudev usb_get_dev(interface_to_usbdev(inte
rface)) - dev-gtinterface interface
- / set up the endpoint information /
- / use only the first bulk-in and bulk-out
endpoints / - iface_desc interface-gtcur_altsetting
- for (i 0 i lt iface_desc-gtdesc.bNumEndpoints
i) - endpoint iface_desc-gtendpointi.desc
- if (!dev-gtbulk_in_endpointAddr
- (endpoint-gtbEndpointAddress USB_DIR_IN)
- ((endpoint-gtbmAttributes
USB_ENDPOINT_XFERTYPE_MASK) - USB_ENDPOINT_XFER_BULK))
- / we found a bulk in endpoint /
-
76Probe and Disconnect in Detail
- / we found a bulk in endpoint /
- buffer_size endpoint-gtwMaxPacketSize
- dev-gtbulk_in_size buffer_size
- dev-gtbulk_in_endpointAddr
endpoint-gtbEndpointAddress - dev-gtbulk_in_buffer kmalloc(buffer_size,
GFP_KERNEL) - if (!dev-gtbulk_in_buffer)
- err("Could not allocate bulk_in_buffer")
- goto error
-
-
- if (!dev-gtbulk_out_endpointAddr
- !(endpoint-gtbEndpointAddress
USB_DIR_IN) - ((endpoint-gtbmAttributes
USB_ENDPOINT_XFERTYPE_MASK) - USB_ENDPOINT_XFER_BULK))
- / we found a bulk out endpoint /
-
77Probe and Disconnect in Detail
- / we found a bulk out endpoint /
- dev-gtbulk_out_endpointAddr
endpoint-gtbEndpointAddress -
-
- if (!(dev-gtbulk_in_endpointAddr
- dev-gtbulk_out_endpointAddr))
- err("Could not find both bulk-in and bulk-out
endpoints") - goto error
-
- / save our data pointer in this interface
device / - usb_set_intfdata(interface, dev)
-
Use usb_get_intfdata(interface) to retrieve dev
78Probe and Disconnect in Detail
- / we can register the device now, as it is
ready / - retval usb_register_dev(interface,
skel_class) - if (retval)
- err(Not able to get a minor for this
device.) - usb_set_intfdata(interface, NULL)
- goto error
-
- return 0
- error
- if (dev)
- kref_put(dev-gtkref, skel_delete)
- return retval
Need to call usb_register_dev() instead of
usb_register() for input, tty, video USB devices
that are not associated with predefined types
Call usb_put_dev(), free bulk_in_buffer and dev
79Probe and Disconnect in Detail
- The definition of skel_class
- static struct usb_class_driver skel_class
- .name "usb/skeld",
- .fops skel_fops,
- .mode S_IFCHRS_IRUSRS_IWUSRS_IRGRPS_IWGRP
S_IROTH, - .minor_base USB_SKEL_MINOR_BASE,
-
- The definition of skel_fops
- static struct file_operations skel_fops
- .owner THIS_MODULE,
- .read skel_read,
- .write skel_write,
- .open skel_open,
- .release skel_release,
The start of the assigned minor range for this
driver
80Probe and Disconnect in Detail
- The disconnect function
- static void skel_disconnect(struct usb_interface
interface) - struct usb_skel dev
- int minor interface-gtminor
- / prevent skel_open() from racing
skel_disconnect() / - lock_kernel()
- dev usb_get_intfdata(interface)
- usb_set_intfdata(interface, NULL)
- / give back our minor /
- usb_deregister_dev(interface, skel_class)
- unlock_kernel()
- / decrement our usage count /
- kref_put(dev-gtkref, skel_delete)
-
The big kernel lock
All in-transit urbs are canceled by the USB core
before disconnect() is called no need to call
usb_kill_urb()
81Submitting and Controlling an Urb
- static ssize_t skel_write(struct file file,
- const char __user
user_buffer, - size_t count, loff_t
ppos) - struct usb_skel dev
- int retval 0
- struct urb urb NULL
- char buf NULL
- if (count 0) goto exit
- dev (struct usb_skel )file-gtprivate_data
- / create a urb and its buffer copy the data
to the urb / - urb usb_alloc_urb(0, GFP_KERNEL)
- if (!urb)
- retval -ENOMEM
- goto error
-
Initialized in skel_open()
82Submitting and Controlling an Urb
- buf usb_buffer_alloc(dev-gtudev, count,
GFP_KERNEL, - urb-gttransfer_dma)
- if (!buf)
- retval -ENOMEM
- goto error
-
- if (copy_from_user(buf, user_buffer, count))
- retval -EFAULT
- goto error
-
- / initialize the urb properly /
- usb_fill_bulk_urb(urb, dev-gtudev,
- usb_sndbulkpipe(dev-gtudev,
dev-gtbulk_out_endpointAddr), - buf, count, skel_write_bulk_callback,
dev) - urb-gttransfer_flags URB_NO_TRANSFER_DMA_MAP
83Submitting and Controlling an Urb
- / send the data out the bulk port /
- retval usb_submit_urb(urb, GFP_KERNEL)
- if (retval)
- err("s - failed submitting write urb, error
d", - __FUNCTION__, retval)
- goto error
-
- / release our reference to this urb, the USB
core will - eventually free it entirely /
- usb_free_urb(urb)
- exit
- return count
-
84Submitting and Controlling an Urb
- error
- usb_buffer_free(dev-gtudev, count, buf,
urb-gttransfer_dma) - usb_free_urb(urb)
- kfree(buf)
- return retval
85Probe and Disconnect in Detail
- The callback (complete) function
- static void skel_write_bulk_callback(struct urb
urb, - struct
pt_regs regs) - / in interrupt context /
- / sync/async unlink faults aren't errors /
- if (urb-gtstatus !(urb-gtstatus -ENOENT
- urb-gtstatus -ECONNRESET
- urb-gtstatus
-ESHUTDOWN)) - dbg("s - nonzero write bulk status received
d", - __FUNCTION__, urb-gtstatus)
-
- / free up our allocated buffer /
- usb_buffer_free(urb-gtdev, urb-gttransfer_buffer_l
ength, - urb-gttransfer_buffer,
urb-gttransfer_dma) -
86USB Transfers Without Urbs
- usb_bulk_msg
- Creates a USB bulk urb and sends it to the
specified device - Waits for it to complete before returning to the
caller - int usb_bulk_msg(struct usb_device usb_dev,
- unsigned int pipe, void data,
int len, - int actual_length, int
timeout) - timeout
- in jiffies
- Set to 0 to wait until the message to complete
87USB Transfers Without Urbs
- Exceptions
- Cannot be called from within interrupt context
- Cannot be called with a spinlock held
- Cannot be cancelled by any other function
- The disconnect call needs to wait for
usb_bulk_msg to complete before allowing itself
to be unloaded
88USB Transfers Without Urbs
- Example
- static ssize_t skel_read(struct file file,
- char __user buffer,
size_t count, - loff_t ppos)
- struct usb_skel dev
- int retval 0
- dev (struct usb_skel )file-gtprivate_data
- / do a blocking bulk read to get data from the
device / - retval usb_bulk_msg(dev-gtudev,
- usb_rcvbulkpipe(dev-gtudev, dev-gtbulk_in_endpoi
ntAddr), - dev-gtbulk_in_buffer, min(dev-gtbulk_in_size,
count), - count, HZ10)
-
89USB Transfers Without Urbs
- / if successful read, copy the data to user
space / - if (!retval)
- if (copy_to_user(buffer, dev-gtbulk_in_buffer,
count)) - retval -EFAULT
- else
- retval count
-
- return retval
-
90usb_control_msg
- Works just like the usb_bulk_msg
- Allows a driver to send and receive USB control
messages - int usb_control_msg(struct usb_device dev,
- unsigned int pipe, __u8
request, - __u8 requesttype, __u16
value, - __u16 index, void data,
__u16 size, - int timeout)
- Returns the number of bytes transferred on
success, or a negative error number - Same restrictions as usb_bulk_msg
91Other USB Data Functions
- Cannot be called from within interrupt context or
with a spinlock held - int usb_get_descriptor(struct usb_device dev,
- unsigned char type,
- unsigned char index,
- void buf, int size)
- int usb_get_string(struct usb_device dev,
- unsigned short langid,
unsigned char index, - void buf, int size)