linux下无线鼠标驱动执行流程

操作系统: debian 7.4(linux 3.2.54)

硬件: 一个无线鼠标、一个有线鼠标

从淘宝上花了15块钱买了个无线鼠标,很好奇它的驱动程序是如何执行的。

首先执行下面命令来捕获uevent事件:

sudo udevadm monitor

然后插入和移除再插入无线鼠标的nano接收器(为了完整的查看信息才操作这么多次),可以在控制台下查看到下面的信息:

$ sudo udevadm monitor
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent
KERNEL[22375.667072] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1 (usb)KERNEL[22375.667421] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0 (usb)KERNEL[22375.667470] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/0003:1D57:0016.0006 (hid)KERNEL[22375.668613] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input9 (input)KERNEL[22375.668769] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input9/mouse0 (input)KERNEL[22375.668899] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input9/event0 (input)KERNEL[22375.669151] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/0003:1D57:0016.0006/hidraw/hidraw0 (hidraw)UDEV  [22375.693845] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1 (usb)UDEV  [22375.701112] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0 (usb)UDEV  [22375.714647] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input9 (input)UDEV  [22375.716553] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input9/mouse0 (input)UDEV  [22375.719153] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/0003:1D57:0016.0006 (hid)UDEV  [22375.719712] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/0003:1D57:0016.0006/hidraw/hidraw0 (hidraw)UDEV  [22375.729434] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input9/event0 (input)KERNEL[22456.752414] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input9/mouse0 (input)UDEV  [22456.752961] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input9/mouse0 (input)KERNEL[22456.776217] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input9/event0 (input)UDEV  [22456.776626] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input9/event0 (input)KERNEL[22456.785326] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input9 (input)KERNEL[22456.785501] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/0003:1D57:0016.0006/hidraw/hidraw0 (hidraw)KERNEL[22456.785523] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/0003:1D57:0016.0006 (hid)KERNEL[22456.785541] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0 (usb)KERNEL[22456.785616] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1 (usb)UDEV  [22456.786670] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input9 (input)UDEV  [22456.786699] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/0003:1D57:0016.0006/hidraw/hidraw0 (hidraw)UDEV  [22456.786842] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/0003:1D57:0016.0006 (hid)UDEV  [22456.786940] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0 (usb)UDEV  [22456.794130] remove   /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1 (usb)KERNEL[22562.038737] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1 (usb)KERNEL[22562.039577] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0 (usb)KERNEL[22562.039748] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/0003:1D57:0016.0007 (hid)KERNEL[22562.040809] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input10 (input)KERNEL[22562.040953] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input10/mouse0 (input)KERNEL[22562.041206] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input10/event0 (input)KERNEL[22562.041400] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/0003:1D57:0016.0007/hidraw/hidraw0 (hidraw)UDEV  [22562.070879] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1 (usb)UDEV  [22562.077647] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0 (usb)UDEV  [22562.084927] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/0003:1D57:0016.0007 (hid)UDEV  [22562.086144] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/0003:1D57:0016.0007/hidraw/hidraw0 (hidraw)UDEV  [22562.089305] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input10 (input)UDEV  [22562.089350] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input10/mouse0 (input)UDEV  [22562.089384] add      /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input10/event0 (input)

输出信息中add对应行是插入时候产生的uevent,remove对应行是移除nano接收器时产生的uevent。

最后一次插入时在/sys文件夹下添加了很多目录,可以用下面命令查看:

$ cat /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input10/mouse0/device/id/vendor
1d57
$ cat /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input10/mouse0/device/id/product
0016

这与lsusb命令获取的信息一致:

$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 002: ID 1a40:0101 Terminus Technology Inc. 4-Port HUB
Bus 001 Device 010: ID 1d57:0016 Xenta
Bus 002 Device 002: ID 046d:c05a Logitech, Inc. Optical Mouse M90
Bus 003 Device 002: ID 413c:2003 Dell Computer Corp. Keyboard
Bus 001 Device 007: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)

$ lsusb -s 001:010 -v

Bus 001 Device 010: ID 1d57:0016 Xenta Couldn‘t open device, some information will be missingDevice Descriptor:  bLength                18  bDescriptorType         1  bcdUSB               2.00  bDeviceClass            0 (Defined at Interface level)  bDeviceSubClass         0   bDeviceProtocol         0   bMaxPacketSize0         8  idVendor           0x1d57 Xenta  idProduct          0x0016   bcdDevice           11.10  iManufacturer           1   iProduct                2   iSerial                 0   bNumConfigurations      1  Configuration Descriptor:    bLength                 9    bDescriptorType         2    wTotalLength           34    bNumInterfaces          1    bConfigurationValue     1    iConfiguration          0     bmAttributes         0xa0      (Bus Powered)      Remote Wakeup    MaxPower              100mA    Interface Descriptor:      bLength                 9      bDescriptorType         4      bInterfaceNumber        0      bAlternateSetting       0      bNumEndpoints           1      bInterfaceClass         3 Human Interface Device      bInterfaceSubClass      1 Boot Interface Subclass      bInterfaceProtocol      2 Mouse      iInterface              0         HID Device Descriptor:          bLength                 9          bDescriptorType        33          bcdHID               1.10          bCountryCode            0 Not supported          bNumDescriptors         1          bDescriptorType        34 Report          wDescriptorLength      65         Report Descriptors:            ** UNAVAILABLE **      Endpoint Descriptor:        bLength                 7        bDescriptorType         5        bEndpointAddress     0x81  EP 1 IN        bmAttributes            3          Transfer Type            Interrupt          Synch Type               None          Usage Type               Data        wMaxPacketSize     0x0008  1x 8 bytes        bInterval               2

这个nano接收器的vendorID和productID分别是0x1d57和0x0016。

执行dmesg查看插入nano接收器的输入信息:

 dmesg | tail -n 15
[22375.556155] usb 1-1.1: new full-speed USB device number 9 using ehci_hcd
[22375.666762] usb 1-1.1: New USB device found, idVendor=1d57, idProduct=0016
[22375.666769] usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[22375.666773] usb 1-1.1: Product: HID Wireless Mouse
[22375.666777] usb 1-1.1: Manufacturer: HID Wireless Mouse
[22375.668566] input: HID Wireless Mouse HID Wireless Mouse as /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input9
[22375.668979] generic-usb 0003:1D57:0016.0006: input,hidraw0: USB HID v1.10 Mouse [HID Wireless Mouse HID Wireless Mouse] on usb-0000:00:1d.7-1.1/input0
[22456.751805] usb 1-1.1: USB disconnect, device number 9
[22561.928127] usb 1-1.1: new full-speed USB device number 10 using ehci_hcd
[22562.038482] usb 1-1.1: New USB device found, idVendor=1d57, idProduct=0016
[22562.038489] usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[22562.038493] usb 1-1.1: Product: HID Wireless Mouse
[22562.038497] usb 1-1.1: Manufacturer: HID Wireless Mouse
[22562.040767] input: HID Wireless Mouse HID Wireless Mouse as /devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1.1/1-1.1:1.0/input/input10
[22562.041276] generic-usb 0003:1D57:0016.0007: input,hidraw0: USB HID v1.10 Mouse [HID Wireless Mouse HID Wireless Mouse] on usb-0000:00:1d.7-1.1/input0

只有最后7行输出信息与最后一次插入nano接收器有关。

下面获取当前linux的内核源码,我使用的是debian 7.4,使用下面命令查看内核信息:

[email protected]:~/soft/mini2440/linux-2.6.32.2$ uname -a
Linux debian 3.2.0-4-686-pae #1 SMP Debian 3.2.54-2 i686 GNU/Linux

当前内核版本是linux 3.2.54, 因为我已经下载了3.2.57的内核,就直接使用该版本的内核源代码(这两个版本源码差别很小,我只是查看源代码,所以就不想重新下载了)。

如果没有内核源代码,可以参考我的博文《编译debian内核》下载内核源码。

内核源代码下载后,执行解压缩,然后进入该文件夹.

鼠标属于hid(human interface device),而nano接收器使用了usb口,所以其对应驱动所在位置很可能是在drivers/hid或者drivers/usb下。

为了确保能找到所有相关代码,我在drivers文件夹执行搜索:

$ find drivers/ -name ‘*.[ch]‘ -exec grep -rnHi ‘full-speed‘ {} \; | grep USB
drivers/usb/usb-common.c:23:        [USB_SPEED_FULL] = "full-speed",

可以看到该行源代码位于usb_speed_string。在vim下执行"make cscope"、"cs add cscope.out"、"cs f s usb_speed_string"可以搜索到所有使用usb_speed_string的代码。

其中最可能相关联的是hub_port_init函数中调用usb_speed_string的代码。

而hub_port_init又被hub_port_connect_change函数所调用。

当前情况下是将nano接收器插入到usb口,确实满足port连接状况改变的情况。

继续查找信息,使用下面命令:

$ find drivers/ -name ‘*.[ch]‘ -exec grep -rnHi ‘idVendor=‘ {} \;
drivers/usb/core/hub.c:1783:    dev_info(&udev->dev, "New USB device found, idVendor=%04x, idProduct=%04x\n",

该行代码位于annouce_device函数,annouce_device函数内容如下:

1 static void announce_device(struct usb_device *udev)
1782 {
1783     dev_info(&udev->dev, "New USB device found, idVendor=%04x, idProduct=%04x\n",
1784         le16_to_cpu(udev->descriptor.idVendor),
1785         le16_to_cpu(udev->descriptor.idProduct));
1786     dev_info(&udev->dev,
1787         "New USB device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
1788         udev->descriptor.iManufacturer,
1789         udev->descriptor.iProduct,
1790         udev->descriptor.iSerialNumber);
1791     show_string(udev, "Product", udev->product);
1792     show_string(udev, "Manufacturer", udev->manufacturer);
1793     show_string(udev, "SerialNumber", udev->serial);
1794 }

而annouce_device被usb_new_device调用,usb_new_device又被hub_port_connect_change函数所调用。

倒数第二行的输出信息中不容易用grep搜索到,直接搜索最后一行输出信息中的"generic-usb":

$ find drivers/ -name ‘*.[ch]‘ -exec grep -rnHi ‘generic-usb‘ {} \;
drivers/hid/usbhid/hid-core.c:1477:    .name = "generic-usb",

这行输出信息很可能是初始化hid(对应于hid_init函数)时得到的输出信息。

稍微整理一下代码的执行流程(参考《essential linux device drivers》)。

usb代码架构中包含有三个重要的组成部分:usbcore, usb host controller driver, usb client driver.

其中usb host controller driver是比较靠近内核的一部分功能,此处不需要考虑。

usbcore中创建了一个khubd线程(位于usb_hub_init函数中)监控端口(port)的状态,当端口(port)状态改变时,会调用hub_port_connect_change函数。

hub_port_connect_change中调用hub_port_init对port进行初始化(包括获取设备描述符,这样能得到所有该设备相关信息),

然后调用usb_new_device调用device_add添加新的usb设备(此处即nano接收器)。

device_add添加该设备(nano接收器)时,主要是创建设备和sysfs文件夹以及添加相应的设备驱动,

中间经过漫长的调用(具体执行过程比较复杂,我还没有好好分析)后会执行hid_bus_match对总线匹配,

匹配成功后执行hid_device_probe->hid_hw_start->hid_connect输出信息。

我手中还有个有线鼠标,插入该鼠标得到的输出信息如下:

[ 7029.876038] usb 2-2: new low-speed USB device number 3 using uhci_hcd
[ 7030.051078] usb 2-2: New USB device found, idVendor=046d, idProduct=c05a
[ 7030.051085] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 7030.051090] usb 2-2: Product: USB Optical Mouse
[ 7030.051093] usb 2-2: Manufacturer: Logitech
[ 7030.067358] input: Logitech USB Optical Mouse as /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/input/input7
[ 7030.067521] generic-usb 0003:046D:C05A.0004: input,hidraw0: USB HID v1.11 Mouse [Logitech USB Optical Mouse] on usb-0000:00:1d.0-2/input0

从输出信息上看,二者输出信息是相当类似的,其驱动执行过程也应该大致相似。

在写博客之前,我猜想无线鼠标可能会用到和有线鼠标不同的驱动程序,但是从整个分析过程看来二者用的驱动程序基本上是差不多的(都是用到usbcore和usbhid)。

linux下无线鼠标驱动执行流程

时间: 2024-11-07 11:52:54

linux下无线鼠标驱动执行流程的相关文章

debian下使用dynamic printk分析usb转串口驱动执行流程

看了一篇文章<debug by printing>,文中提到了多种通过printk来调试驱动的方法,其中最有用的就是"Dynamic debugging". “Dynamic debugging"的官方文档:http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/dynamic-debug-howto.txt?id=HEAD "Dyanmic de

Linux下adb驱动问题Linux下使用手机USB调试模式连接ADB进行Android程序的调试

Linux 下adb 驱动问题 Linux下使用手机USB调试模式连接ADB进行Android程序的调试,配置驱动没有Windows来的直观. 具体步骤首先确认手机连接上电脑,lsusb查看下设备记录. [email protected]:~$ lsusb Bus 007 Device 009: ID 18d1:4e12 Bus 007 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 006 Device 001: ID 1d

linux下shell脚本执行方法及exec和source命令

exec和source都属于bash内部命令(builtins commands),在bash下输入man exec或man source可以查看所有的内部命令信息. bash shell的命令分为两类:外部命令和内部命令.外部命令是通过系统调用或独立的程序实现的,如sed.awk等等.内部命令是由特殊的文件格式(.def)所实现,如cd.history.exec等等. 在说明exe和source的区别之前,先说明一下fork的概念. fork是linux的系统调用,用来创建子进程(child

Linux下spi驱动开发

转载至:http://www.embedu.org/Column/Column367.htm 作者:刘洪涛,华清远见嵌入式学院讲师. 一.概述 基于子系统去开发驱动程序已经是linux内核中普遍的做法了.前面写过基于I2C子系 统的驱动开发.本文介绍另外一种常用总线SPI的开发方法.SPI子系统的开发和I2C有很多的相似性,大家可以对比学习.本主题分为两个部分叙述,第一 部分介绍基于SPI子系统开发的理论框架:第二部分以华清远见教学平台FS_S5PC100上的M25P10芯片为例(内核版本2.6

Linux下C语言执行过程(预处理,编译,汇编,链接,执行)

1.C语言的执行过程包括5个步骤:分别是:预处理,编译,汇编,链接,执行 第一步:编写C源代码,截图如下: 2.预处理,命令为:gcc -E variable.c -o variable.i(这步的作用是文件的展开和宏替换),生成的文件类型是.i类型的. 3.编译:命令为:gcc -S variable.i -o variable.s,这里的.s文件就成了会变语言,截图如下: 4.汇编,命令是:gcc -c variable.s -o variable.o,截图如下: 5,链接:命令:gcc -

Linux下设置定期执行脚本

下面针对的是非ubuntu环境,会在文章末尾介绍ubuntu的一些区别. 在Linux下,经常需要定期的执行一些脚本从而来实现一些功能. 在Linux下我们用crontab来实现定期的执行脚本这个功能,下面就介绍一下crontab的使用.以及我遇到的一些问题 一. crontab的使用说明 1. crond 是linux用来定期执行程序的命令.当安装完成操作系统之后,默认便会启动此任务调度命令.crond命令每分钟会定期检查是否有要执行的工作,如果有要执行的工作便会自动执行该工作.而linux任

arch linux下nvidia 驱动死机问题

好长一段时间了,自从某次arch滚动升级nvidia驱动后,就频繁的Xorg死掉.一直没能解决,只好换用nouveau.nouveau一般使用问题到不大,但是前几天nouveau升级后,也开始抽筋. 于是又尝试换回nvidia的专有驱动,死机情况依然未解.偶然在死机后,用ssh连接上后用dmesg抓到一个错误: NVRM: GPU at 0000:01:00.0 Has Fallen Off The Bus 一番搜索,找到这篇文章: http://www.cyberciti.biz/faq/de

Linux下多命令执行

Linux下多命令执行: 1.执行多条命令,不确保每条执行成功. 多条命令之间用分号(;)隔开,比如:command1 || command2 || command3 三条命令中都会执行,不确保每条命令执行成功. 2.执行多条命令,遇到执行失败的命令之后,停止后续命令执行.多条命令之间做逻辑与(&&)操作,比如:command1 && command2 && command3 三条命令中有一个失败则停止后续命令执行. 3.执行多条命令,遇到执行成功的命令之后

(转)linux下编译驱动

参考: 1,linux下编译运行驱动 http://blog.csdn.net/zeroboundary/article/details/9294715 2,A Simple Driver for Linux OShttp://www.codeproject.com/Articles/112474/A-Simple-Driver-for-Linux-OS (转)linux下编译驱动