900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > USB鼠标驱动源代码分析

USB鼠标驱动源代码分析

时间:2018-12-25 20:48:39

相关推荐

USB鼠标驱动源代码分析

学了URB,试着去分析了一下USB鼠标驱动源代码,更好去理解URB处理流程。

/** $Id: usbmouse.c,v 1.15 2001/12/27 10:37:41 vojtech Exp $** Copyright (c) 1999-2001 Vojtech Pavlik** USB HIDBP Mouse support*//** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License, or* (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA** Should you need to contact me, the author, you can do so either by* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic*/#include <linux/kernel.h>#include <linux/slab.h>#include <linux/module.h>#include <linux/init.h>#include <linux/usb/input.h>#include <linux/hid.h>/** Version Information*/#define DRIVER_VERSION "v1.6"#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"#define DRIVER_DESC "USB HID Boot Protocol mouse driver"#define DRIVER_LICENSE "GPL"MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE(DRIVER_LICENSE);struct usb_mouse {char name[128];char phys[64];struct usb_device *usbdev;//usb设备struct input_dev *dev;//输入设备struct urb *irq;//USB 请求块signed char *data;dma_addr_t data_dma;};/*一个urb完成时被调用的完成处理函数*/static void usb_mouse_irq(struct urb *urb){struct usb_mouse *mouse = urb->context;signed char *data = mouse->data;struct input_dev *dev = mouse->dev;int status;/*urb处理完成后,状态判断*/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(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);resubmit:/*提交下一次URB*/status = usb_submit_urb (urb, GFP_ATOMIC);if (status)err ("can't resubmit intr, %s-%s/input0, status %d",mouse->usbdev->bus->bus_name,mouse->usbdev->devpath, status);}static int usb_mouse_open(struct input_dev *dev){struct usb_mouse *mouse = input_get_drvdata(dev);/*当鼠标打开时,提交URB*/mouse->irq->dev = mouse->usbdev;if (usb_submit_urb(mouse->irq, GFP_KERNEL))return -EIO;return 0;}static void usb_mouse_close(struct input_dev *dev){struct usb_mouse *mouse = input_get_drvdata(dev);/*鼠标关闭,取消urb,终止urb的生命周期*/usb_kill_urb(mouse->irq);}/*usb设备检测函数*/static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id){struct usb_device *dev = interface_to_usbdev(intf);struct usb_host_interface *interface;struct usb_endpoint_descriptor *endpoint;struct usb_mouse *mouse;struct input_dev *input_dev;int pipe, maxp;int error = -ENOMEM;/*获 取 当 前 接 口 设 置*/interface = intf->cur_altsetting;/* 根 据 HID 规 范 鼠 标 只 有 一 个 的 端 点*/if (interface->desc.bNumEndpoints != 1)return -ENODEV;/* 获 取 0号 端 点*/endpoint = &interface->endpoint[0].desc;/* 根 据 HID 规 范, 鼠 标 的 唯 一 的 端 点 是中 断 端 点*/if (!usb_endpoint_is_int_in(endpoint))return -ENODEV;/*产生中断管道,这个urb要被发送到的usb设备的特定端点*/pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);/*返回端点能够传送数据包的最大长度,鼠标返回最大数据包为4*/maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));/*创建输入型设备,鼠标属于输入设备*/mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL);input_dev = input_allocate_device();if (!mouse || !input_dev)goto fail1;/*申请空间用于数据传输,data为用户空间的地址*/mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma);if (!mouse->data)goto fail1;//分配 URB(USB请求块)mouse->irq = usb_alloc_urb(0, GFP_KERNEL);if (!mouse->irq)goto fail2;mouse->usbdev = dev;mouse->dev = input_dev;if (dev->manufacturer)strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name));if (dev->product) {if (dev->manufacturer)strlcat(mouse->name, " ", sizeof(mouse->name));strlcat(mouse->name, dev->product, sizeof(mouse->name));}if (!strlen(mouse->name))snprintf(mouse->name, sizeof(mouse->name),"USB HIDBP Mouse %04x:%04x",le16_to_cpu(dev->descriptor.idVendor),le16_to_cpu(dev->descriptor.idProduct));/* usb_make_path -- returns stable device path in the usb tree */usb_make_path(dev, mouse->phys, sizeof(mouse->phys));strlcat(mouse->phys, "/input0", sizeof(mouse->phys));/*字符设备初始化*/input_dev->name = mouse->name;input_dev->phys = mouse->phys;usb_to_input_id(dev, &input_dev->id);input_dev->dev.parent = &intf->dev;/*设置输入事件*/input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);input_dev->relbit[0] |= BIT(REL_WHEEL);/*设置输入设备的私有数据*/input_set_drvdata(input_dev, mouse);input_dev->open = usb_mouse_open;//打开设备:提交URBinput_dev->close = usb_mouse_close;/*初始化中断URB,从pipe获取数据存放到data中,usb_mouse_irq:这个urb完成时被调用的完成处理函数,bInterval应当被调度的间隔*/usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,(maxp > 8 ? 8 : maxp),usb_mouse_irq, mouse, endpoint->bInterval);mouse->irq->transfer_dma = mouse->data_dma;mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;/*注册输入设备*/error = input_register_device(mouse->dev);if (error)goto fail3;/*把已经初始化的usb_mouse保存到usb_interface中*/usb_set_intfdata(intf, mouse);return 0;fail3:usb_free_urb(mouse->irq);fail2:usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);fail1:input_free_device(input_dev);kfree(mouse);return error;}static void usb_mouse_disconnect(struct usb_interface *intf){struct usb_mouse *mouse = usb_get_intfdata (intf);/*设置usb_interface的私有数据为null*/usb_set_intfdata(intf, NULL);if (mouse) {usb_kill_urb(mouse->irq);/*取消urb,终止urb的生命周期*/input_unregister_device(mouse->dev);//注销输入设备usb_free_urb(mouse->irq);//释放urbusb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);kfree(mouse);}}/*创建一个匹配接口制定类型的usb_device_id结构体实例*/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 */};MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);static struct usb_driver usb_mouse_driver = {.name= "usbmouse",/*驱动名称*/.probe= usb_mouse_probe,/*探测函数*/.disconnect= usb_mouse_disconnect,/*断开函数*/.id_table= usb_mouse_id_table,/*这个驱动所支持的USB设备列表*/};static int __init usb_mouse_init(void){int retval = usb_register(&usb_mouse_driver);if (retval == 0)info(DRIVER_VERSION ":" DRIVER_DESC);return retval;}static void __exit usb_mouse_exit(void){usb_deregister(&usb_mouse_driver);}module_init(usb_mouse_init);module_exit(usb_mouse_exit);

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。