《Linux总线、设备与驱动》USBHID设备驱动

转载 2016年06月01日 16:02:16

来源:http://blog.csdn.net/tankai19880619/article/details/17447791


说明:本分析基于mstar801平台Linux2.6.35.11内核,其他内核版本仅供参考。

一、HID虚拟总线驱动加载

drivers/hid/hid-core.c

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. module_init(hid_init);  
  2. static int __init hid_init(void){  
  3.   ret = bus_register(&hid_bus_type);  //注册HID虚拟总线  
  4.   ret = hidraw_init();  
  5. }  
  6. static struct bus_type hid_bus_type = {  
  7.   .name       = "hid",  
  8.   .match      = hid_bus_match,  
  9.   .probe      = hid_device_probe,  
  10.   .remove     = hid_device_remove,  
  11.   .uevent     = hid_uevent,  
  12. };  

二、USBHID驱动加载

USBHID驱动同时包含USB总线设备驱动和HID总线设备驱动。

drivers/hid/usbhid/hid-core.c

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static int __init hid_init(void){  
  2.   retval = hid_register_driver(&hid_usb_driver);  //注册HID总线设备驱动  
  3.   retval = usb_register(&hid_driver);  //注册USB总线设备驱动  
  4. }  
  5. module_init(hid_init);  
  6. static struct hid_driver hid_usb_driver = { //一般HID驱动都不实现probe方法  
  7.   .name = "generic-usb",  
  8.   .id_table = hid_usb_table,  
  9. };  
  10. static struct usb_driver hid_driver = {  //USB设备驱动方法  
  11.   .name =     "usbhid",  
  12.   .probe =    usbhid_probe,  
  13.   .disconnect =   usbhid_disconnect,  
  14.  #ifdef CONFIG_PM  
  15.   .suspend =  hid_suspend,  
  16.   .resume =   hid_resume,  
  17.   .reset_resume = hid_reset_resume,  
  18. #endif  
  19.   .pre_reset =    hid_pre_reset,  
  20.    .post_reset =   hid_post_reset,  
  21.   .id_table = hid_usb_ids,  
  22.   .supports_autosuspend = 1,  
  23. };  

三、USBHID设备探测

1.USB总线的设备探测并注册HID设备

USB设备发现机制看如下链接:

《Linux总线、设备与驱动》USB设备发现机制

drivers/hid/usbhid/hid-core.c

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id){  
  2.   hid = hid_allocate_device(); //申请HID设备  
  3.   hid->ll_driver = &usb_hid_driver; //重要!  
  4.   /* 
  5.   static struct hid_ll_driver usb_hid_driver = { 
  6.     .parse = usbhid_parse, 
  7.     .start = usbhid_start, 
  8.     .stop = usbhid_stop, 
  9.     .open = usbhid_open, 
  10.     .close = usbhid_close, 
  11.     .power = usbhid_power, 
  12.     .hidinput_input_event = usb_hidinput_input_event, 
  13.   }; 
  14.   */  
  15.   hid->hiddev_connect = hiddev_connect;  
  16.   hid->hiddev_disconnect = hiddev_disconnect;  
  17.   hid->hiddev_hid_event = hiddev_hid_event;  
  18.   hid->hiddev_report_event = hiddev_report_event;  
  19.   usb_make_path(dev, hid->phys, sizeof(hid->phys));  
  20.   strlcat(hid->phys, "/input"sizeof(hid->phys));  
  21.   if (len < sizeof(hid->phys) - 1)  
  22.     snprintf(hid->phys + len, sizeof(hid->phys) - len, "%d", intf->altsetting[0].desc.bInterfaceNumber);  
  23.   ret = hid_add_device(hid); //注册HID设备  
  24. }  
申请HID设备:

drivers/hid/hid-core.c

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. struct hid_device *hid_allocate_device(void){  
  2.   struct hid_device *hdev;  
  3.   device_initialize(&hdev->dev);  
  4.   hdev->dev.release = hid_device_release;  
  5.   hdev->dev.bus = &hid_bus_type;  
  6. }  
  7. static struct bus_type hid_bus_type = {  
  8.   .name       = "hid",  
  9.   .match      = hid_bus_match,  
  10.   .probe      = hid_device_probe,  
  11.   .remove     = hid_device_remove,  
  12.   .uevent     = hid_uevent,  
  13. };  

注册HID设备:

drivers/hid/hid-core.c

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int hid_add_device(struct hid_device *hdev){  
  2.   ret = device_add(&hdev->dev); //该函数的调用将导致总线对应match和probe的调用  
  3. }  

2.HID总线的设备探测

参考USB总线探测:http://blog.csdn.net/tankai19880619/article/details/11639185

drivers/hid/hid-core.c

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //HID总线match函数  
  2. static int hid_bus_match(struct device *dev, struct device_driver *drv){  
  3.   if (!hid_match_device(hdev, hdrv)) //匹配VID和PID  
  4.     return 0;  
  5.   if (!strncmp(hdrv->name, "generic-", 8)) //名字为generic-都匹配  
  6.     return !hid_match_id(hdev, hid_have_special_driver);  
  7. }  
  8. //HID总线的probe函数  
  9. static int hid_device_probe(struct device *dev){  
  10.   if (hdrv->probe) { //一般HID驱动都没有实现probe方法  
  11.     ret = hdrv->probe(hdev, id);  
  12.   } else { /* default probe */  
  13.      ret = hid_parse(hdev);  
  14.      /* 
  15.      include/linux/hid.h 
  16.      static inline int __must_check hid_parse(struct hid_device *hdev){ 
  17.        ret = hdev->ll_driver->parse(hdev); 
  18.        if (!ret) 
  19.          hdev->status |= HID_STAT_PARSED; 
  20.        return ret; 
  21.      } 
  22.      drivers/hid/usbhid/hid-core.c 
  23.      static int usbhid_parse(struct hid_device *hid){ 
  24.        ret = hid_parse_report(hid, rdesc, rsize); 
  25.      } 
  26.      */  
  27.      if (!ret)  
  28.        ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);  
  29.        /* 
  30.        include/linux/hid.h 
  31.        static inline int __must_check hid_hw_start(struct hid_device *hdev, 
  32. unsigned int connect_mask){ 
  33.          int ret = hdev->ll_driver->start(hdev); 
  34.          ret = hid_connect(hdev, connect_mask); 
  35.          if (ret) 
  36.            hdev->ll_driver->stop(hdev); 
  37.        } 
  38.        drivers/hid/usbhid/hid-core.c 
  39.        static int usbhid_start(struct hid_device *hid){ 
  40.    
  41.        } 
  42.        */  
  43.   }  
  44. }  
  45. int hid_connect(struct hid_device *hdev, unsigned int connect_mask){  
  46.   static const char *types[] = { "Device""Pointer""Mouse""Device",  
  47.     "Joystick""Gamepad""Keyboard""Keypad",  
  48.     "Multi-Axis Controller"  
  49.   };  
  50.   //HIDINPUT设备  
  51.   if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev,connect_mask & HID_CONNECT_HIDINPUT_FORCE))  
  52.     hdev->claimed |= HID_CLAIMED_INPUT;  
  53.   //HIDDEV设备  
  54.   if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect && !hdev->hiddev_connect(hdev,connect_mask & HID_CONNECT_HIDDEV_FORCE))  
  55.     hdev->claimed |= HID_CLAIMED_HIDDEV;  
  56.   //HIDRAW设备  
  57.   if ((connect_mask & HID_CONNECT_HIDRAW) && !hidraw_connect(hdev))  
  58.     hdev->claimed |= HID_CLAIMED_HIDRAW;  
  59. }  

四、具体设备驱动

1.HIDINPUT设备,如走2.4G的遥控器

drivers/hid/hid-input.c

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int hidinput_connect(struct hid_device *hid, unsigned int force){  
  2.   //申请设备  
  3.   input_dev = input_allocate_device();  
  4.   input_dev->event = hid->ll_driver->hidinput_input_event;  
  5.   input_dev->open = hidinput_open;  
  6.   input_dev->close = hidinput_close;  
  7.   input_dev->setkeycode = hidinput_setkeycode;  
  8.   input_dev->getkeycode = hidinput_getkeycode;  
  9.   input_dev->name = hid->name;  
  10.   for (i = 0; i < report->maxfield; i++)  
  11.     for (j = 0; j < report->field[i]->maxusage; j++)  
  12.       hidinput_configure_usage(hidinput, report->field[i],report->field[i]->usage + j);  
  13.   /* 
  14.   static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, 
  15.       struct hid_usage *usage){ 
  16.     switch (usage->hid & HID_USAGE_PAGE) { 
  17.       case HID_UP_KEYBOARD: 
  18.         set_bit(EV_REP, input->evbit); 
  19.         if ((usage->hid & HID_USAGE) < 256) { 
  20.           if (!hid_keyboard[usage->hid & HID_USAGE]) goto ignore; 
  21.             map_key_clear(hid_keyboard[usage->hid & HID_USAGE]); 
  22.             /* 
  23.             static const unsigned char hid_keyboard[256] = { 
  24.               0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 
  25.               50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3, 
  26.               4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26, 
  27.               27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, 
  28.               65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, 
  29.               105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 
  30.               72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, 
  31.               191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, 
  32.               115,114,unk,172,194,121,229, 89, 93,124, 92, 94, 95,unk,unk,unk, 
  33.               122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk, 
  34.               unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, 
  35.               unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk, 
  36.               unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, 
  37.               unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk, 
  38.               29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, 
  39.               150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk 
  40.             }; 
  41.             */  
  42.           } else  
  43.              map_key(KEY_UNKNOWN);  
  44.           break;  
  45.         }  
  46.       }  
  47.    }  
  48.   */  
  49.   //注册设备  
  50.   if (hidinput && input_register_device(hidinput->input))  
  51.     goto out_cleanup;  
  52. }  

2.HIDDEV设备

drivers/hid/usbhid/hiddev.c

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int hiddev_connect(struct hid_device *hid, unsigned int force){  
  2.   retval = usb_register_dev(usbhid->intf, &hiddev_class);  
  3. }  

3.HIDRAW设备,用来与设备做原始的通讯

这个驱动中不会解析任何数据,只是简单的将设备产生的数据传给应用层。

drivers/hid/hidraw.c

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int hidraw_connect(struct hid_device *hid){  
  2.   dev->dev = device_create(hidraw_class, &hid->dev, MKDEV(hidraw_major, minor), NULL, "%s%d""hidraw", minor);  
  3. }  

五、设备移除部分

1.USB总线设备移除触发USBHID中USB驱动部分调用

drivers/hid/usbhid/hid-core.c

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. retval = usb_register(&hid_driver);  
  2. static struct usb_driver hid_driver = {  
  3.   .disconnect =   usbhid_disconnect,  
  4. }  
  5. static void usbhid_disconnect(struct usb_interface *intf){  
  6.   hid_destroy_device(hid); //调用HID总线的设备注销函数  
  7. }  
2.HID总线驱动

drivers/hid/hid-core.c

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. void hid_destroy_device(struct hid_device *hdev){  
  2.   hid_remove_device(hdev);  
  3. }  
  4. static void hid_remove_device(struct hid_device *hdev){  
  5.   device_del(&hdev->dev);  
  6. }  
  7. //总线设备注销触发总线函数调用:  
  8. static struct bus_type hid_bus_type = {  
  9.   .remove     = hid_device_remove,  
  10. }  
  11. static int hid_device_remove(struct device *dev){  
  12.   if (hdrv) {  
  13.     if (hdrv->remove)  
  14.       hdrv->remove(hdev);  
  15.     else /* default remove */  
  16.       hid_hw_stop(hdev);  
  17.       /* 
  18.       include/linux/hid.h 
  19.       static inline void hid_hw_stop(struct hid_device *hdev){ 
  20.         hid_disconnect(hdev); 
  21.       } 
  22.       */  
  23.     hdev->driver = NULL;  
  24.   }  
  25. }  
  26. void hid_disconnect(struct hid_device *hdev){  
  27.   device_remove_bin_file(&hdev->dev, &dev_bin_attr_report_desc);  
  28.   if (hdev->claimed & HID_CLAIMED_INPUT)  
  29.     hidinput_disconnect(hdev); //HIDINPUT设备  
  30.   if (hdev->claimed & HID_CLAIMED_HIDDEV)  
  31.     hdev->hiddev_disconnect(hdev);  //HIDDEV设备  
  32.   if (hdev->claimed & HID_CLAIMED_HIDRAW)  
  33.     hidraw_disconnect(hdev);  //HIDRAW设备  
  34. }  

相关文章推荐

《Linux总线、设备与驱动》USB设备发现机制

一、USB总线驱动 kernel/drivers/usb/core/driver.c EXPORT_SYMBOL_GPL(usb_register_driver); EXPORT_SYMBOL_GP...

Linux下USB HID device driver研究

首先介绍HID: HID是Human Interface Devices的缩写.翻译成中文即为人机交互设备.这里的人机交互设备是一个宏观上面的概念,任何设备,只要符合HID spec,都可以称之为H...

Linux设备驱动之HID驱动

------------------------------------------ 本文系本站原创,欢迎转载! 转载请注明出处:http://ericxiao.cublog.cn/ ---...

如何在Linux下利用Libusb与HID USB设备通信!

由于公司的产品,导致我在Linux下写usb通信的代码出现了许多的问题,最后发现这些设备只能通过控制传输来操作设备,所以后面的问题就迎刃而解了。现在贴上当时在QT下写的代码,以防日后再碰到此类问题的时...

s3c2416 自定义hid设备通信

最近在研究hid通信,下面总结下供以后参考,同时也希望能给正在研究这个的同胞提供一些帮助。 有关自定义hid设备在linux内核源码下的Documentation/usb/gadget_hid.txt...

linux下自定义USB HID设备

http://blog.csdn.net/hclydao/article/details/16807085 http://blog.csdn.net/hclydao/article/details/...

在Linux 2.6环境下读写HID设备(USB Key)

Linux 2.6内核中包含了HID驱动,能够自动把USB Key等HID外设识别成“/dev/hiddev0”之类的设备。但是该驱动没有实现write接口,因此无法象Windows平台那样使用 Re...
  • acf
  • acf
  • 2010-03-30 11:27
  • 7699

Linux HID分析

Linux hid子系统实现原理以及访问方式
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)