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

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

Linux USB鼠標驅(qū)動注解及測試

時間:2015-06-28 00:00:00 來源:IT貓撲網(wǎng) 作者:網(wǎng)管聯(lián)盟 我要評論(0)

  參考2.6.14版本中的driver/usb/input/usbmouse.c。鼠標驅(qū)動可分為幾個部分:驅(qū)動加載部分、probe部分、open部分、urb回調(diào)函數(shù)處理部分。

  下文陰影部分為注解。

  一、??? 驅(qū)動加載部分

  static int __init usb_mouse_init(void)

  {

  int retval = usb_register(&usb_mouse_driver);//注冊鼠標驅(qū)動

  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,

  };

  如果注冊成功的話,將會調(diào)用usb_mouse_probe。那么什么時候才算注冊成功呢?

  和其它驅(qū)動注冊過程一樣,只有在其對應(yīng)的"總線"上發(fā)現(xiàn)匹配的"設(shè)備"才會調(diào)用probe。總線匹配的方法和具體總線相關(guān),如:platform_bus_type中是判斷驅(qū)動名稱和平臺設(shè)備名稱是否相同;那如何確認usb總線的匹配方法呢?

  Usb設(shè)備是注冊在usb_bus_type總線下的。查看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),也就是說通過比對"dev中intf信息"和"usb_drv->id_table信息",如果匹配則說明驅(qū)動所對應(yīng)的設(shè)備已經(jīng)添加到總線上了,所以接下了就會調(diào)用drv中的probe方法注冊usb設(shè)備驅(qū)動。

  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)

  鼠標設(shè)備遵循USB人機接口設(shè)備(HID),在HID規(guī)范中規(guī)定鼠標接口類碼為:

  接口類:0x03

  接口子類:0x01

  接口協(xié)議:0x02

  這樣分類的好處是設(shè)備廠商可以直接利用標準的驅(qū)動程序。除了HID類以外還有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)

  匹配的過程為:

  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;

  //接口類

  if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&

  (id->bInterfaceClass != intf->desc.bInterfaceClass))

  continue;

  //接口子類

  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;

  }

  從中可以看出,只有當設(shè)備的接口類、接口子類、接口協(xié)議匹配鼠標驅(qū)動時鼠標驅(qū)動才會調(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ò)的一段對cur_altsettin的解釋,下面就借花獻佛。usb 設(shè)備有一個configuration 的概念,表示配置,一個設(shè)備可以有多個配置,但只能同時激活一個,如:一些設(shè)備可以下載固件,或可以設(shè)置不同的全局模式,就像手機可以被設(shè)定為靜音模式或響鈴模式一樣。而這里又有一個setting,咋一看有些奇怪,這兩個詞不是一回事嗎.還是拿我們最熟悉的手機來打比方,configuration 不說了,setting,一個手機可能各種配置都確定了,是振動還是鈴聲已經(jīng)確定了,各種功能都確定了,但是聲音的大小還可以變吧,通常手機的音量是一格一格的變動,大概也就5,6 格,那么這個可以算一個setting 吧.這里cur_altsetting 就是表示的當前的這個setting,或者說設(shè)置??梢圆榭丛a中usb_interface 結(jié)構(gòu)定義的說明部分。從說明中可以看到一個接口可以有多種setting*/

  if (interface->desc.bNumEndpoints != 1)

  return -ENODEV;

  /*根據(jù)HID規(guī)則,期望鼠標只有一個端點即中

關(guān)鍵詞標簽:Linux,USB鼠標驅(qū)動

相關(guān)閱讀

文章評論
發(fā)表評論

熱門文章 安裝紅帽子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客戶端配置 多種操作系統(tǒng)NTP客戶端配置 Linux操作系統(tǒng)修改IP Linux操作系統(tǒng)修改IP

相關(guān)下載

    人氣排行 Linux下獲取CPUID、硬盤序列號與MAC地址 dmidecode命令查看內(nèi)存型號 linux tc實現(xiàn)ip流量限制 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程 linux下解壓rar文件 lcx.exe、nc.exe、sc.exe入侵中的使用方法 Ubuntu linux 關(guān)機、重啟、注銷 命令 查看linux服務(wù)器硬盤IO讀寫負載