IT貓撲網(wǎng):您身邊最放心的安全下載站! 最新更新|軟件分類(lèi)|軟件專(zhuān)題|手機(jī)版|論壇轉(zhuǎn)貼|軟件發(fā)布

您當(dāng)前所在位置: 首頁(yè)操作系統(tǒng)LINUX → Linux USB鼠標(biāo)驅(qū)動(dòng)注解及測(cè)試

Linux USB鼠標(biāo)驅(qū)動(dòng)注解及測(cè)試

時(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)閱讀

文章評(píng)論
發(fā)表評(píng)論

熱門(mén)文章 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程 Tomcat9.0如何安裝_Tomcat9.0環(huán)境變量配置方法 Tomcat9.0如何安裝_Tomcat9.0環(huán)境變量配置方法 多種操作系統(tǒng)NTP客戶(hù)端配置 多種操作系統(tǒng)NTP客戶(hù)端配置 Linux操作系統(tǒng)修改IP Linux操作系統(tǒng)修改IP

相關(guān)下載

    人氣排行 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ù)載