時(shí)間:2015-06-28 00:00:00 來(lái)源:IT貓撲網(wǎng) 作者:網(wǎng)管聯(lián)盟 我要評(píng)論(0)
參考2.6.14版本中的driver/usb/input/usbmouse.c。鼠標(biāo)驅(qū)動(dòng)可分為幾個(gè)部分:驅(qū)動(dòng)加載部分、probe部分、open部分、urb回調(diào)函數(shù)處理部分。
下文陰影部分為注解。
一、??? 驅(qū)動(dòng)加載部分
static int __init usb_mouse_init(void)
{
int retval = usb_register(&usb_mouse_driver);//注冊(cè)鼠標(biāo)驅(qū)動(dòng)
if (retval == 0)
info(DRIVER_VERSION ":" DRIVER_DESC);
return retval;
}
其中usb_mouse_driver的定義為:
static struct usb_driver usb_mouse_driver = {
.owner? = THIS_MODULE,
.name? = "usbmouse",
.probe? = usb_mouse_probe,
.disconnect??? = usb_mouse_disconnect,
.id_table??? = usb_mouse_id_table,
};
如果注冊(cè)成功的話(huà),將會(huì)調(diào)用usb_mouse_probe。那么什么時(shí)候才算注冊(cè)成功呢?
和其它驅(qū)動(dòng)注冊(cè)過(guò)程一樣,只有在其對(duì)應(yīng)的"總線(xiàn)"上發(fā)現(xiàn)匹配的"設(shè)備"才會(huì)調(diào)用probe??偩€(xiàn)匹配的方法和具體總線(xiàn)相關(guān),如:platform_bus_type中是判斷驅(qū)動(dòng)名稱(chēng)和平臺(tái)設(shè)備名稱(chēng)是否相同;那如何確認(rèn)usb總線(xiàn)的匹配方法呢?
Usb設(shè)備是注冊(cè)在usb_bus_type總線(xiàn)下的。查看usb_bus_type的匹配方法。
struct bus_type usb_bus_type = {
.name =? "usb",
.match =??? usb_device_match,
.hotplug =??? usb_hotplug,
.suspend =??? usb_generic_suspend,
.resume =??? usb_generic_resume,
};
其中usb_device_match定義了匹配方法
static int usb_device_match (struct device *dev, struct device_driver *drv)
{
struct usb_interface *intf;
struct usb_driver *usb_drv;
const struct usb_device_id *id;
/* check for generic driver, which we don't match any device with */
if (drv == &usb_generic_driver)
return 0;
intf = to_usb_interface(dev);
usb_drv = to_usb_driver(drv);
id = usb_match_id (intf, usb_drv->id_table);
if (id)
return 1;
return 0;
}
可以看出usb的匹配方法是usb_match_id (intf, usb_drv->id_table),也就是說(shuō)通過(guò)比對(duì)"dev中intf信息"和"usb_drv->id_table信息",如果匹配則說(shuō)明驅(qū)動(dòng)所對(duì)應(yīng)的設(shè)備已經(jīng)添加到總線(xiàn)上了,所以接下了就會(huì)調(diào)用drv中的probe方法注冊(cè)u(píng)sb設(shè)備驅(qū)動(dòng)。
usb_mouse_id_table的定義為:
static struct usb_device_id usb_mouse_id_table[] = {
{ USB_INTERFACE_INFO(3, 1, 2) },
{ }????? /* Terminating entry */
};
#define USB_INTERFACE_INFO(cl,sc,pr) \
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, \
.bInterfaceClass = (cl), \
.bInterfaceSubClass = (sc), \
.bInterfaceProtocol = (pr)
鼠標(biāo)設(shè)備遵循USB人機(jī)接口設(shè)備(HID),在HID規(guī)范中規(guī)定鼠標(biāo)接口類(lèi)碼為:
接口類(lèi):0x03
接口子類(lèi):0x01
接口協(xié)議:0x02
這樣分類(lèi)的好處是設(shè)備廠(chǎng)商可以直接利用標(biāo)準(zhǔn)的驅(qū)動(dòng)程序。除了HID類(lèi)以外還有Mass storage、printer、audio等
#define USB_DEVICE_ID_MATCH_INT_INFO \
(USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_INT_PROTOCOL)
匹配的過(guò)程為:
usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
{
struct usb_host_interface *intf;
struct usb_device *dev;
/* proc_connectinfo in devio.c may call us with id == NULL. */
if (id == NULL)
return NULL;
intf = interface->cur_altsetting;
dev = interface_to_usbdev(interface);
/* It is important to check that id->driver_info is nonzero,
since an entry that is all zeroes except for a nonzero
id->driver_info is the way to create an entry that
indicates that the driver want to examine every
device and interface. */
for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
id->driver_info; id++) {
if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
continue;
/* No need to test id->bcdDevice_lo != 0, since 0 is never
greater than any unsigned number. */
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
(id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
(id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
(id->bDeviceClass != dev->descriptor.bDeviceClass))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
(id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
(id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
continue;
//接口類(lèi)
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
(id->bInterfaceClass != intf->desc.bInterfaceClass))
continue;
//接口子類(lèi)
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
(id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
continue;
//遵循的協(xié)議
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
(id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
continue;
return id;
}
return NULL;
}
從中可以看出,只有當(dāng)設(shè)備的接口類(lèi)、接口子類(lèi)、接口協(xié)議匹配鼠標(biāo)驅(qū)動(dòng)時(shí)鼠標(biāo)驅(qū)動(dòng)才會(huì)調(diào)用probe方法。
二、probe部分
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;
int pipe, maxp;
char path[64];
interface = intf->cur_altsetting;
/* 以下是網(wǎng)絡(luò)的一段對(duì)cur_altsettin的解釋?zhuān)旅婢徒杌ǐI(xiàn)佛。usb 設(shè)備有一個(gè)configuration 的概念,表示配置,一個(gè)設(shè)備可以有多個(gè)配置,但只能同時(shí)激活一個(gè),如:一些設(shè)備可以下載固件,或可以設(shè)置不同的全局模式,就像手機(jī)可以被設(shè)定為靜音模式或響鈴模式一樣。而這里又有一個(gè)setting,咋一看有些奇怪,這兩個(gè)詞不是一回事嗎.還是拿我們最熟悉的手機(jī)來(lái)打比方,configuration 不說(shuō)了,setting,一個(gè)手機(jī)可能各種配置都確定了,是振動(dòng)還是鈴聲已經(jīng)確定了,各種功能都確定了,但是聲音的大小還可以變吧,通常手機(jī)的音量是一格一格的變動(dòng),大概也就5,6 格,那么這個(gè)可以算一個(gè)setting 吧.這里cur_altsetting 就是表示的當(dāng)前的這個(gè)setting,或者說(shuō)設(shè)置??梢圆榭丛a中usb_interface 結(jié)構(gòu)定義的說(shuō)明部分。從說(shuō)明中可以看到一個(gè)接口可以有多種setting*/
if (interface->desc.bNumEndpoints != 1)
return -ENODEV;
/*根據(jù)HID規(guī)則,期望鼠標(biāo)只有一個(gè)端點(diǎn)即中
關(guān)鍵詞標(biāo)簽:Linux,USB鼠標(biāo)驅(qū)動(dòng)
相關(guān)閱讀
熱門(mén)文章 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程 Tomcat9.0如何安裝_Tomcat9.0環(huán)境變量配置方法 多種操作系統(tǒng)NTP客戶(hù)端配置 Linux操作系統(tǒng)修改IP
人氣排行 Linux下獲取CPUID、硬盤(pán)序列號(hào)與MAC地址 dmidecode命令查看內(nèi)存型號(hào) linux tc實(shí)現(xiàn)ip流量限制 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程 linux下解壓rar文件 lcx.exe、nc.exe、sc.exe入侵中的使用方法 Ubuntu linux 關(guān)機(jī)、重啟、注銷(xiāo) 命令 查看linux服務(wù)器硬盤(pán)IO讀寫(xiě)負(fù)載