". / drivers/usb/usb-skeleton.c" is a template program provided by the kernel to USB device driver developers for mass storage of USB devices. The program is not long, but it has strong versatility and is very classic. A thorough understanding of this file can help us better understand the USB subsystem and USB device driver framework, and write a better USB mass storage device driver.
Before matching
Since it is a USB device-driven template, it is necessary to construct a usb_driver object and register it in the kernel.
650 static struct usb_driver skel_driver = { 651 .name = "skeleton", 652 .probe = skel_probe, 653 .disconnect = skel_disconnect, 654 .suspend = skel_suspend, 655 .resume = skel_resume, 656 .pre_reset = skel_pre_reset, 657 .post_reset = skel_post_reset, 658 .id_table = skel_table, 659 .supports_autosuspend = 1, 660 }; 661 662 module_usb_driver(skel_driver);
The domain of this object has been explained in the previous article. Here, our main concern is skel_table, which determines which device the driver matches. From the following definition, it can be seen that the driver matches according to device.
30 static const struct usb_device_id skel_table[] = { 31 { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, 32 { } /* Terminating entry */ 33 }; 34 MODULE_DEVICE_TABLE(usb, skel_table);
After matching
Resource class
Next, look at the driver's definition of resource class, which is the link of the whole driver and manages the resources shared by the functions and interfaces of the whole driver. It has to be said that this annotation is really a rare detail in the kernel. skeleton is mainly for mass storage devices, so its resource object encapsulates a lot of buffer information VS interrupt devices as long as one. One urb can solve the problem of data transmission
49 struct usb_skel { 50 struct usb_device *udev; /* the usb device for this device */ 51 struct usb_interface *interface; /* the interface for this device */ 52 struct semaphore limit_sem; /* limiting the number of writes in progress 53 struct usb_anchor submitted; /* in case we need to retract our submission 54 struct urb *bulk_in_urb; /* the urb to read data with */ 55 unsigned char *bulk_in_buffer; /* the buffer to receive data */ 56 size_t bulk_in_size; /* the size of the receive buffer */ 57 size_t bulk_in_filled; /* number of bytes in the buffer */ 58 size_t bulk_in_copied; /* already copied to user space */ 59 __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ 60 __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ 61 int errors; /* the last request tanked */ 62 bool ongoing_read; /* a read is going on */ 63 spinlock_t err_lock; /* lock for errors */ 64 struct kref kref; 65 struct mutex io_mutex; /* synchronize I/O with disconnect */ 66 wait_queue_head_t bulk_in_wait; /* to wait for an ongoing read */ 67 };
struct usb_skel
--50-->Driving operation usb_device object
--51-->Driving operation usb_interface object, Both are device information., VS i2c-s3c2410.c By putting the device information in the ___________ probe Copy it out to save it in the driver resource object, That's the same idea here.. struct usb_interface->dev Domain to usb_skel And other interface functions, Amount to struct device Domain to s3c24xx_i2c And other interface functions, They all flow through various interface functions.
--54-->Used urb object
--55-->Used to receive data. buf Pointer
--56-->Identify the domain of the length of the data to be received
--57-->Domains that identify how much valid data is in the current buffer
--58-->Identify how many data domains the current buffer has been copied to. skeleton It does not empty the buffer, but uses various length representations to determine how much has been occupied. It does not matter whether the parts exceeding the length are cleared or not. The relationship between them is shown below.
--59-->bulk Input Endpoint of Equipment
--60-->bulk Output Point of Equipment
--62-->Device readable marker,0 Represents readable, 1 represents unreadable
--64-->kref For kernel reference counting
usb_skeleton also encapsulates a to_skel_dev with reference to the existing to_platform_device structure in the kernel, which is worth learning from.
68 #define to_skel_dev(d) container_of(d, struct usb_skel, kref)
probe
After the match is successful, it's time to ask probe to play according to the routine.
490 static int skel_probe(struct usb_interface *interface, 491 const struct usb_device_id *id) 492 { 493 struct usb_skel *dev; 494 struct usb_host_interface *iface_desc; 495 struct usb_endpoint_descriptor *endpoint; 496 size_t buffer_size; 497 int i; 498 int retval = -ENOMEM; 499 500 /* allocate memory for our device state and initialize it */ 501 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 506 kref_init(&dev->kref); 507 sema_init(&dev->limit_sem, WRITES_IN_FLIGHT); 508 mutex_init(&dev->io_mutex); 509 spin_lock_init(&dev->err_lock); 510 init_usb_anchor(&dev->submitted); 511 init_waitqueue_head(&dev->bulk_in_wait); 512 513 dev->udev = usb_get_dev(interface_to_usbdev(interface)); 514 dev->interface = interface; 515 516 /* set up the endpoint information */ 517 /* use only the first bulk-in and bulk-out endpoints */ 518 iface_desc = interface->cur_altsetting; 519 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { 520 endpoint = &iface_desc->endpoint[i].desc; 521 522 if (!dev->bulk_in_endpointAddr && 523 usb_endpoint_is_bulk_in(endpoint)) { 524 /* we found a bulk in endpoint */ 525 buffer_size = usb_endpoint_maxp(endpoint); 526 dev->bulk_in_size = buffer_size; 527 dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; 528 dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); 534 dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL); 540 } 542 if (!dev->bulk_out_endpointAddr && 543 usb_endpoint_is_bulk_out(endpoint)) { 544 /* we found a bulk out endpoint */ 545 dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; 546 } 547 } 553 554 /* save our data pointer in this interface device */ 555 usb_set_intfdata(interface, dev); 556 557 /* we can register the device now, as it is ready */ 558 retval = usb_register_dev(interface, &skel_class); 566 567 /* let the user know what node this device is now attached to */ 568 dev_info(&interface->dev, 569 "USB Skeleton device now attached to USBSkel-%d", 570 interface->minor); 571 return 0; 578 } 579
skel_probe
--501-->Apply for space for resource objects, Pay attention to the writing here.: dev = kzalloc(sizeof(*dev), GFP_KERNEL);
--506-->Initialization usb_skel->kref
--507-->Initialization usb_skel->limit_sem
--508-->Initialization usb_skel->io_mutex);
--509-->Initialization usb_skel->err_lock);
--510-->Initialization usb_skel->submitted);
--511-->Initialization usb_skel->bulk_in_wait
--513-->Initialization usb_skel->udev,To be matched usb_device Address Storage
--514-519-->Initialization usb_skel Other domains of objects.
--555-->Hide our resource objects interface->dev->p->driver_data in
--558-->Register one usb_device Object to the kernel, apply for a secondary device number, and create device files, ==>intf->usb_dev = device_create(usb_class->class, &intf->dev,MKDEV(USB_MAJOR, minor), class_driver,"%s", temp);
Through the above analysis, we find a difference between skeleton and usbmouse: skeleton constructs usb_class_driver object and registers a USB device with usb_register_dev. As an input subsystem, usbmouse only needs input_register(input_dev) instead of USB device registration. The reason for this difference is that skeleton is for bulk urb device, while USBM is for bulk urb device. Ouse is for interrupt urb devices. For bulk devices, we will read and write devices, not just read and write operations, so in bulk urb device driver to achieve the corresponding set of operation methods and bind to the device file to register with the kernel, this work is done by usb_register_dev. To use this function, we need to construct a usb_class_driver object, the most important of which is skel_fops discussed in this section. This domain is also struct file_operations type, and all implementation of read and write methods are registered in this domain.
Since fops is mentioned, we are mainly concerned with the implementation of three methods: open, read and write. Considering that read and write are similar in operation logic, this article only discusses open and read.
open
83 static int skel_open(struct inode *inode, struct file *file) 84 { 85 struct usb_skel *dev; 86 struct usb_interface *interface; 87 int subminor; 88 int retval = 0; 89 90 subminor = iminor(inode); 91 92 interface = usb_find_interface(&skel_driver, subminor); 100 dev = usb_get_intfdata(interface); 106 retval = usb_autopm_get_interface(interface); 110 /* increment our usage count for the device */ 111 kref_get(&dev->kref); 112 113 /* save our object in the file's private structure */ 114 file->private_data = dev; 115 117 return retval; 118 }
skel_open()
--90-->from inode Get the secondary device number in
--92-->according to skel_driver Object and Subdevice Number Acquisition usb_interface Object, so far the device has been found
--100-->from interface->dev->p->driver_data Gets the address of the resource object in the probe--555--Hidden here
--110-->Reference Count Plus One
--114-->The key is to hide the address of the previously acquired resource object in file->private_data In this way, in all of the cdev Resource objects can be used between interfaces, and resource object addresses can be hidden to interface In order to usb_driver The idea of flow between interface functions is the same.
read
Open the device, then you can read and write. skeleton's key function calls for read operations are as follows. We analyze them in turn according to the call tree.
skel_read()
skel_do_read_io(dev, count)
usb_fill_bulk_urb(...);
usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL);
The first is skel_read(), which is a function called back when the application layer reads the device. It attempts to implement the function of copying the appropriate data to the application layer if there is data in the kernel buffer, and calling skel_do_read_io to request data from the device if there is no data in the kernel buffer.
226 static ssize_t skel_read(struct file *file, char *buffer, size_t count, 227 loff_t *ppos) 228 { 229 struct usb_skel *dev; 230 int rv; 231 bool ongoing_io; 232 233 dev = file->private_data; 255 if (ongoing_io) { 256 /* nonblocking IO shall not wait */ 257 if (file->f_flags & O_NONBLOCK) { 258 rv = -EAGAIN; 259 goto exit; 260 } 265 rv = wait_event_interruptible(dev->bulk_in_wait, (!dev->ongoing_read)); 266 if (rv < 0) 267 goto exit; 268 } 269 270 /* errors must be reported */ 271 rv = dev->errors; 272 if (rv < 0) { 273 /* any error is reported once */ 274 dev->errors = 0; 275 /* to preserve notifications about reset */ 276 rv = (rv == -EPIPE) ? rv : -EIO; 277 /* report it */ 278 goto exit; 279 } 286 if (dev->bulk_in_filled) { 287 /* we had read data */ 288 size_t available = dev->bulk_in_filled - dev->bulk_in_copied; 289 size_t chunk = min(available, count); 290 291 if (!available) { 296 rv = skel_do_read_io(dev, count); 297 if (rv < 0) 298 goto exit; 299 else 300 goto retry; 301 } 307 if (copy_to_user(buffer, 308 dev->bulk_in_buffer + dev->bulk_in_copied, 309 chunk)) 310 rv = -EFAULT; 311 else 312 rv = chunk; 313 314 dev->bulk_in_copied += chunk; 320 if (available < count) 321 skel_do_read_io(dev, count - chunk); 322 } else { 323 /* no data in the buffer */ 324 rv = skel_do_read_io(dev, count); 325 if (rv < 0) 326 goto exit; 327 else 328 goto retry; 329 } 330 exit: 331 mutex_unlock(&dev->io_mutex); 332 return rv; 333 }
skel_read()
--233-->They're all routines. First hide them in file_private_data Out of the resource objects
--255-268-->Readable markers in resource objects, when unreadable, judge IO Whether blocking is allowed, if not returned directly,Allow blocking to use the waiting queue header in the resource object to join the waiting queue,Used is interruptible Versions wait,If the process of sleep is interrupted and awakened, then rv==-1,The function returns directly.
--286-->There is only one case of execution to this line: the device is readable! If the buffer is full, execute the first block, otherwise execute the following block
--288-->Buffer full time, Get the size of the copiable data.
--289-->The smaller of the copiable size and the expected copy size. chunk
--291-->Copiable data is 0, and usb_skel->bulk_in_filled Placed in order to enter here, So there's only one case.: The data in the buffer has been copied out
--292-->Now that the data has been copied, call skel_do_read_io Initiate request
--300-->Request data, device feedback, but no data, retry
307-->From the Kernel Buffer usb_skel->bulk_in_buffer + usb_skel->bulk_in_copied start(Is the first address of the remaining unprinted data)Copy chunk byte Data to Application Layer
--314-->To update usb_skel->bulk_in_copied Value
--320-->If the size of the data can be copied<Expected copy size, So obviously just now. chunk=availible, All data has been copied to the application layer, But it can not meet the needs of application layer., call skel_do_read_io To continue requesting data from equipment, Of course, The size of the request is an unsatisfactory part, Namely count-chunk --324-->usb_skel->bulk_in_filled Not positioned, Represents that there is no data in the kernel buffer, call skel_do_read_io Request data, Of course, The size of the request is the total data, Namely count
As I said earlier, if the buffer can not meet the needs of the application layer, the following function will be called to request data from bulk usb device. After obtaining the data, the data will be placed in the buffer and the corresponding flag position will be 1/0.
189 static int skel_do_read_io(struct usb_skel *dev, size_t count) 190 { 191 int rv; 193 /* prepare a read */ 194 usb_fill_bulk_urb(dev->bulk_in_urb,dev->udev,usb_rcvbulkpipe(dev->udev,dev->bulk_in_endpointAddr),dev->bulk_in_buffer, min(dev->bulk_in_size, count),skel_read_bulk_callback,dev); 204 dev->ongoing_read = 1; 206 207 /* submit bulk in urb, which means no data to deliver */ 208 dev->bulk_in_filled = 0; 209 dev->bulk_in_copied = 0; 210 211 /* do it */ 212 rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL); 223 return rv; 224 }
skel_do_read_io()
--194-->towards usb Core submission urb, Target resources dev Hide in urb->context In the middle urb Parametric incoming callback function, and usb_fill_int_urb difference, usb_fill_bulk_urb When registering, you need to sum the size of the buffer header address and the requested data urb Bind to submit together, Only in this way can we know where to go. bulk Size of data requested by the device, bulk You don't know where to put it until the device has data returned..
--204-->take usb_skel->ongoing_read Set 1, Represents that there is no data to read
--208-->take usb_skel->bulk_in_filled Set 0, Represents that the kernel buffer has no data to read
--209-->take usb_skel->bulk_in_copied Set 0, Represents that no data has been copied
--212-->After getting ready, command usb Core sending urb
When the request is sent, the usb bus will wait for the feedback from the device. When the device has feedback, it will call back the registration function of urb. Let's see what this callback function does.
163 static void skel_read_bulk_callback(struct urb *urb) 164 { 165 struct usb_skel *dev; 166 167 dev = urb->context; 168 169 spin_lock(&dev->err_lock); 170 /* sync/async unlink faults aren't errors */ 181 dev->bulk_in_filled = urb->actual_length; 183 dev->ongoing_read = 0; 184 spin_unlock(&dev->err_lock); 185 186 wake_up_interruptible(&dev->bulk_in_wait); 187 }
skel_read_bulk_callback
--167-->Tricks, Put out the resource objects first
--181-->The length of data that will represent device feedback urb->actual_length Assign to usb_skel->bulk_in_filled, Represents that the buffer has data
--183-->take usb_skel->ongoing_read Set 0, Represents readable!
--186-->The process of waking up and falling asleep because there is no data to read
Analyzing this, the application layer can get data from USB mass storage device by usb_skeleton driver!!!! The idea of writing data is the same, so I won't talk about it here.
The use of locks
In addition to clever buffer management, usb_skeleton.c's use of concurrency control technology is also worth learning. When constructing usb_skel, the driver uses semaphore, spinlock and mutex, three commonly used concurrency control lock mechanisms. Next, we discuss how the kernel bulls use these technologies in different application scenarios.
semaphore
Semaphore is a process unit. Its typical feature is that when a process can't get semaphore, it will fall asleep and give up CPU, so semaphore can't be used in interrupt context. In usb_skeleton.c, semaphore is used in the following scenarios
335 static void skel_write_bulk_callback(struct urb *urb) 336 { 358 up(&dev->limit_sem); 359 } 361 static ssize_t skel_write(struct file *file, const char *user_buffer, 362 size_t count, loff_t *ppos) 363 { 376 /* 377 * limit the number of URBs in flight to stop a user from using up all 378 * RAM 379 */ 380 if (!(file->f_flags & O_NONBLOCK)) { 381 if (down_interruptible(&dev->limit_sem)) { 382 retval = -ERESTARTSYS; 383 goto exit; 384 } 385 } else { 386 if (down_trylock(&dev->limit_sem)) { 387 retval = -EAGAIN; 388 goto exit; 389 } 390 } 467 return retval; 468 }
spinlock
When critical resources are not available, the process using spinlock will not fall asleep, but be busy, so spinlock can be used in interrupt context, but if resources are not available and CPU is not sold, system resources will be wasted, so the critical area protected by spinlock can not be too long. usb_skeleton uses spinlock mainly in the following scenarios
226 static ssize_t skel_read(struct file *file, char *buffer, size_t count, 227 loff_t *ppos) 228 { 250 retry: 251 spin_lock_irq(&dev->err_lock); 252 ongoing_io = dev->ongoing_read; 253 spin_unlock_irq(&dev->err_lock); 332 return rv; 333 }
mutex
Mutex is only used to ensure mutual exclusion. When trylock is not used, like semaphore, it falls asleep when lock is not available. usb_skeleton uses mutex in the following scenarios
226 static ssize_t skel_read(struct file *file, char *buffer, size_t count, 227 loff_t *ppos) 228 { 239 /* no concurrent readers */ 240 rv = mutex_lock_interruptible(&dev->io_mutex); 330 exit: 331 mutex_unlock(&dev->io_mutex); 332 return rv; 333 }