USB设备驱动程序(四)

来源:互联网 发布:c 程序员招聘要求 编辑:程序博客网 时间:2024/06/05 11:47

首先分析usb_mouse_init,通过usb_register(&usb_mouse_driver)注册驱动程序,probe函数调用1.先插设备后安装驱动,USB core会遍历所有系统中已存在的USB设备,然后看usb_mouse_id_table, /* 所能支持设备列表 */有无系统支持的设备如果有则调用probe函数,2.先装驱动后装鼠标,USB core发现新的设备进来,会寻找有无能处理设备的驱动,找到后调用probe()

static struct usb_device_id usb_mouse_id_table [] = {

{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,

USB_INTERFACE_PROTOCOL_MOUSE) },

{ } /* Terminating entry */

};//驱动支持USB鼠标这一类设备。

 注册分析完后,分析probe函数(驱动找到USB鼠标后做的事情),

static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)

先interface = intf->cur_altsetting;/* 获取当前接口设置 */

然后检测接口描述符有多少endpoint    if (interface->desc.bNumEndpoints != 1)

通过检测取出端点描述符,endpoint = &interface->endpoint[0].desc;

 

判断端点是不是为输入型的中断端点(访问鼠标希望从鼠标中读到数据)

if (!usb_endpoint_is_int_in(endpoint))

 

产生中断管道,驱动程序buffer和端点之间虚拟通道 

usb_rcvintpipe(dev, endpoint->bEndpointAddress);

 

创建输入型设备,因为USB驱动从总线描述设备,从功能上有输入型、网络型、字符等设备,总线驱动包含功能驱动,鼠标是输入设备,所以要创建输入型设备。

input_dev = input_allocate_device();

 

分配数组buffer,从鼠标端点获取数据,存放进buffer

/* 申请内存空间用于数据传输,data 为指向该空间的地址*/

mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma);

 

准备工作完成后,开始围绕urb工作。

mouse->irq = usb_alloc_urb(0, GFP_KERNEL);  /* 分配URB */

第一个参数为0,表明中断传输,不设置等时包

 

获取USBSysfs文件系统名字,然后添加上名字"/input0"。

usb_make_path(dev, mouse->phys, sizeof(mouse->phys));

strlcat(mouse->phys, "/input0", sizeof(mouse->phys));

 

输入型设备初始化时需要指明设备支持哪些操作,例如按键、绝对坐标、左右键………

所支持的操作信息。

input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);

input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |

BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);

input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);

input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |

BIT_MASK(BTN_EXTRA);

input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);

 

制定打开、关闭函数

input_dev->open = usb_mouse_open;

input_dev->close = usb_mouse_close;

 

接下来有回到URB下来了,使用usb_fill_int_urb初始化URBendpoint->bInterval表示每个多长时间提交一次URB

usb_fill_int_urb (mouse->irq, dev, pipe, mouse->data,

 (maxp > 8 ? 8 : maxp),

 usb_mouse_irq, mouse, endpoint->bInterval);

urb初始化结束后,将URB提交给USB CORE,但是这里并没有提交过程,它在打开时候提交。因为不打开设备,就不用设备,不提交就不会有数据传输,只有当使用才要求提交URBUSB CORE,然后交给HOST_DRIVER,从USB鼠标拿到数据,在pipe拿到数据放在mouse->data,过程结束后调用usb_mouse_irq函数。

static int usb_mouse_open(struct input_dev *dev)

{

struct usb_mouse *mouse = input_get_drvdata(dev);

mouse->irq->dev = mouse->usbdev;

if (usb_submit_urb(mouse->irq, GFP_KERNEL))

return -EIO;

return 0;

}

 

 

 

通过urb->status判断URB传输是否成功,0正确继续执行,错误时不会执行。

switch (urb->status) {

case 0: /* success */

break;

case -ECONNRESET: /* unlink */

case -ENOENT:

case -ESHUTDOWN:

return;

/* -EPIPE:  should clear the halt */

default: /* error */

goto resubmit;

}

 

正确时报告鼠标按键情况,使用input_report_key()报告信息,使用input_sync表明报告完毕

input_report_key(dev, BTN_LEFT,   data[0] & 0x01);

input_report_key(dev, BTN_RIGHT,  data[0] & 0x02);

input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);

input_report_key(dev, BTN_SIDE,   data[0] & 0x08);

input_report_key(dev, BTN_EXTRA,  data[0] & 0x10);

 

input_report_rel(dev, REL_X,     data[1]);

input_report_rel(dev, REL_Y,     data[2]);

input_report_rel(dev, REL_WHEEL, data[3]);

 

input_sync(dev);

结束之后还要继续传输,又一次提交URB

status = usb_submit_urb (urb, GFP_ATOMIC);

关闭设备时usb_kill_urb

程序由两部分组成,一部分是USB部分,一部分是input部分,USB部分体现总线,围绕urb分析创建、分配、初始化、提交、后续处理,input体现功能部分。

0 0
原创粉丝点击