"./drivers/usb/usb-skeleton.c" 是内核提供给 usb 设备驱动开发者的海量存储 usb 设备的模板程序, 程序不长, 通用性却很强,十分经典, 深入理解这个文件可以帮助我们更好的理解 usb 子系统以及 usb 设备驱动框架, 写出更好的 usb 海量存储设备驱动。
既然是一个 usb 设备驱动的模板,那么就少不了构造一个 usb_driver 对象并将其注册到内核中,
- 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);
关于这个对象的域,在上一篇已经解释了,这里,我们主要关心的是 skel_table,它决定了这个驱动匹配到哪个设备,从下面的定义可以看出,这个驱动是按照 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);
接下来,看一下这个驱动对于资源类的定义,这可是整个驱动程序的纽带,管理着整个驱动程序各个函数与接口共用的资源, 不得不说这个注释真的是内核中少有的详细, skeleton 主要是针对海量存储设备的, 所以其资源对象中封装了很多缓冲区的信息 VS 中断设备只要一个 urb 即可搞定数据传输问题
- 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
- };
usb_skeleton 还参考内核中已有的 to_platform_device 等结构封装了一个 to_skel_dev, 这种写法值得借鉴
- 68 #define to_skel_dev(d) container_of(d, struct usb_skel, kref)
匹配成功后,按照套路就该请 probe 上场了
- 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
通过上面的分析, 我们发现了一个 skeleton 和 usbmouse 不一样的地方: skeleton 构造了 usb_class_driver 对象并使用 usb_register_dev 注册一个 usb 设备, 而 usbmouse 作为 input 子系统, 仅需要 input_register(input_dev) 即可, 不用 usb 设备的注册问题, 产生这个差别的原因是 skeleton 是针对 bulk urb 设备的, 而 usbmouse 是针对 interrupt urb 设备的。对于 bulk 设备,我们会对设备进行读写操作,而不仅仅是读操作,所以在 bulk urb 设备驱动中要实现相应的操作方法集并绑定到设备文件一起注册到内核,这个工作就是由 usb_register_dev 来完成。为了使用这个函数,我们需要构造一个 usb_class_driver 对象,其中最重要的就是本节要讨论的 skel_fops 了。这个域也是 struct file_operations 类型的,所有的读写方法的实现都要注册到这个域中。
既然提到 fops,我们主要关心的就三个方法的实现: open, read 和 write,考虑到 read 和 write 在操作逻辑类似,所以本文只讨论 open 和 read
- 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 }
打开了设备,接下来就可以读写了,skeleton 中对于读操作的关键函数调用关系如下,我们依照这个调用树依次分析
首先是 skel_read(),这个函数是应用层读设备时回调的函数,它试图实现这样一个功能: 如果内核缓冲区有数据就将适当的数据拷贝给应用层, 如果没有就调用 skel_do_read_io 来向设备请求数据
- 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
- }
刚才也说了, 如果缓冲区不能满足应用层需求的时候, 就会调用下面这个函数向 bulk usb 设备请求数据, 得到数据后将数据放到缓冲区并将相应的标志位置 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
- }
请求被发出后, usb 总线就会静待设备的反馈, 设备有反馈后就会回调 urb 的注册函数, 我们看看这个回调函数都做了什么
- 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 }
分析到这里, 应用层就可以通过 usb_skeleton 驱动从 USB 海量存储设备中获取数据了!!! 写入数据的思路是一样的, 我这里就不罗嗦了.
除了对缓冲区管理的巧妙, usb_skeleton.c 中对于并发控制技术的使用也值得学习, 在构造资源对象 usb_skel 的时候, 这个驱动使用了 semaphore ,spinlock,mutex 三种常用的并发控制锁机制, 接下来我们讨论一下内核大牛们是如何在不同应用场景中使用这些技术的.
semaphore 是以进程为单位的, 其典型特点就是当一个进程不能获取信号量的时候, 会进陷入睡眠让出 CPU, 所以中断上下文不能使用 semaphore。在 usb_skeleton.c 中,semaphore 在如下场景中被使用
- 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 的进程不会陷入睡眠, 而是忙等,所以 spinlock 可以用在中断上下文,但是如果不能获取资源又不出让 CPU,会浪费系统资源,所以被 spinlock 保护的临界区不能太长。usb_skeleton 主要在以下场景中使用了 spinlock
- 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 只是用来保证互斥,在不使用 trylock 的时候,和 semaphore 一样会在得不到锁的时候进入睡眠。usb_skeleton 在以下场景中使用 mutex
- 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 }
来源: http://www.cnblogs.com/xiaojiang1025/p/6506116.html