怎么写usb驱动( 三 )


或者查看厂商的USB设备的手册也能得到 , 在我机器上运行lsusb是这样的结果:Bus 004 Device 001: ID 0000:0000 Bus 003 Device 002: ID 1234:2345 Abc Corp. Bus 002 Device 001: ID 0000:0000 Bus 001 Device 001: ID 0000:0000 得到这两个值后把它定义到程序里就可以了 。注册USB驱动程序:所 有的USB驱动程序都必须创建的结构体是struct usb_driver 。
这个结构体必须由USB驱动程序来填写 , 包括许多回调函数和变量 , 它们向USB核心代码描述USB驱动程序 。创建一个有效的 struct usb_driver结构体 , 只须要初始化五个字段就可以了 , 在框架程序中是这样的:static struct usb_driver skel_driver = { .owner = THIS_MODULE, .name = "skeleton", .probe = skel_probe, .disconnect = skel_disconnect, .id_table = skel_table , }; 探测和断开:当 一个设备被安装而USB核心认为该驱动程序应该处理时 , 探测函数被调用 , 探测函数检查传递给它的设备信息 , 确定驱动程序是否真的适合该设备 。
当驱动程序因 为某种原因不应该控制设备时 , 断开函数被调用 , 它可以做一些清理工作 。探测回调函数中 , USB驱动程序初始化任何可能用于控制USB设备的局部结构体 , 它 还把所需的任何设备相关信息保存到一个局部结构体中 , 提交和控制urb:当驱动程序有数据要发送到USB设备时(大多数情况是在驱动程序的写函数中) , 要分配一个urb来把数据传输给设备: /* 创建一个urb , 并且给它分配一个缓存*/ urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { retval = -ENOMEM; goto error; } 当urb被成功分配后 , 还要创建一个DMA缓冲区来以高效的方式发送数据到设备 , 传递给驱动程序的数据要复制到这块缓冲中去: buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma); if (!buf) { retval = -ENOMEM; goto error; } if (copy_from_user(buf, user_buffer, count)) { retval = -EFAULT; goto error; } 当数据从用户空间正确复制到局部缓冲区后 , urb必须在可以被提交给USB核心之前被正确初始化: /* 初始化urb */ usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), buf, count, skel_write_bulk_callback, dev); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 然后urb就可以被提交给USB核心以传输到设备了: /* 把数据从批量OUT端口发出 */ retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) { err("%s - failed submitting write urb, error %d", __FUNCTION__, retval); goto error; } 当urb被成功传输到USB设备之后 , urb回调函数将被USB核心调用 , 在我们的例子中 , 我们初始化urb , 使它指向skel_write_bulk_callback函数 , 以下就是该函数:static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs) { struct usb_skel *dev; dev = (struct usb_skel *)urb->context; if (urb->status && !(urb->status == -ENOENT || urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) { dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); } /* 释放已分配的缓冲区 */ usb_buffer_free(urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); } 有时候USB驱动程序只是要发送或者接收一些简单的数据 , 驱动程序也可以不用urb来进行数据的传输 , 这是里涉及到两个简单的接口函数:usb_bulk_msg和usb_control_msg  , 在这个USB框架程序里读操作就是这样的一个应用:/* 进行阻塞的批量读以从设备获取数据 */ retval = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), dev->bulk_in_buffer, min(dev->bulk_in_size, count), &count, HZ*10); /*如果读成功 , 复制到用户空间 */ if (!retval) { if (copy_to_user(buffer, dev->bulk_in_buffer, count)) retval = -EFAULT; else retval = count; } usb_bulk_msg接口函数的定义如下:int usb_bulk_msg(struct usb_device *usb_dev,unsigned int pipe,void *data,int len, 。