为linux添加自己的USB驱动

来源:互联网 发布:天翼网络对讲机 编辑:程序博客网 时间:2024/04/29 17:20
转载自 http://blog.csdn.net/cricketol/article/details/5919771

本来想为mini2440添加自己的USB驱动,然后通过手柄做一些控制,结果一开始就遇到自己写的驱动被抢占了,google了几天未果,在csdn发了一个求助帖(http://topic.csdn.net/u/20100926/15/b5c7fc3b-e4f9-4843-89d2-b88ea484b9f3.html?34584),deep_pro兄提供了一个方法,借助这个方法我打开了胜利之门。

 

1、驱动编写不用多说,不会的参照usb-skeleton.c。我的模块名是joystick,所以编译后的模块是joystick.ko。

 

2、安装模块。

insmod&dmesg发现自己驱动的probe没有被调用,下面被抢占的输出:

usb 5-1.4: new low speed USB device using uhci_hcd and address 6
usb 5-1.4: New USB device found, idVendor=0e8f, idProduct=0002
usb 5-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 5-1.4: Product: BETOP USB GAMEPAD
usb 5-1.4: Manufacturer: GreenAsia Inc.   
input: GreenAsia Inc. BETOP USB GAMEPAD as /devices/pci0000:00/0000:00:1d.0/usb5/5-1/5-1.4/5-1.4:1.0/input/input12
generic-usb 0003:0E8F:0002.0004: input,hidraw1: USB HID v1.10 Joystick [GreenAsia Inc. BETOP USB GAMEPAD] on usb-0000:00:1d.0-1.4/input0

 

之后deep_pro提供了一个方法(http://hi.baidu.com/deep_pro/blog/item/415ec217bdead20c4b90a77d.html),找到抢占设备的模块是usbhid,如果禁用此模块的话插入别的usbhid设备也用不了了,比如鼠标和键盘,所以只能让该模块忽略掉特定的设备,于是就开始读内核源码。刚开始我钻到了死角,一直在内核源码树下drivers/hid目录下找,把所有关于GREENASIA和PANTHERLORD的#define都注释了,还是未能解决,后来step out and look back,整理一下思路,钻到drivers/hid/usbhid里面找(之前也进去过,只是没怎么研究),用过函数嵌套关系一层一层回溯,终于到了顶点,在usbhid/hid-core.c里面的usbhid_probe(这是usbhid模块的probe函数)发现,如果不为设备调用hid_add_device,那该设备就不被usbhid模块抢占,所以我在usbhid模块的probe函数开头加了一段过滤代码,问题就解决了。

 

修改后的代码:

 

[cpp] view plaincopy
  1. static struct usb_device_id ignored_list[] = {  
  2.     {USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0002)},  
  3.     { },  
  4. };  
  5. static int is_ignored_device(unsigned short idVendor, unsigned short idProduct)  
  6. {  
  7.     int index;  
  8.     for(index = 0;ignored_list[index].idVendor;index++)  
  9.     {  
  10.         if((ignored_list[index].idVendor == idVendor) && (ignored_list[index].idProduct == idProduct))  
  11.             return 1;  
  12.     }  
  13.     return 0;  
  14. }  
  15. static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id)  
  16. {  
  17.     struct usb_host_interface *interface = intf->cur_altsetting;  
  18.     struct usb_device *dev = interface_to_usbdev(intf);  
  19.     struct usbhid_device *usbhid;  
  20.     struct hid_device *hid;  
  21.     unsigned int n, has_in = 0;  
  22.     size_t len;  
  23.     int ret;  
  24.     dbg_hid("HID probe called for ifnum %d/n",  
  25.             intf->altsetting->desc.bInterfaceNumber);  
  26.     //ignore the device should not be handled by usbhid module  
  27.     if(is_ignored_device(dev->descriptor.idVendor, dev->descriptor.idProduct))  
  28.     {  
  29.         printk("*** Device ignored ***/n");  
  30.         printk("VendorID = %04X, ProductID = %04X/n", dev->descriptor.idVendor, dev->descriptor.idProduct);  
  31.         printk("%s/n", dev->manufacturer);  
  32.         printk("%s/n", dev->product);  
  33.         //printk("%s/n", );  
  34.         printk("**********************/n");  
  35.         return -ENODEV;  
  36.     }  
  37.     for (n = 0; n < interface->desc.bNumEndpoints; n++)  
  38.         if (usb_endpoint_is_int_in(&interface->endpoint[n].desc))  
  39.             has_in++;  
  40.     if (!has_in) {  
  41.         dev_err(&intf->dev, "couldn't find an input interrupt "  
  42.                 "endpoint/n");  
  43.         return -ENODEV;  
  44.     }  
  45.     hid = hid_allocate_device();  
  46.     if (IS_ERR(hid))  
  47.         return PTR_ERR(hid);  
  48.     usb_set_intfdata(intf, hid);  
  49.     hid->ll_driver = &usb_hid_driver;  
  50.     hid->hid_output_raw_report = usbhid_output_raw_report;  
  51.     hid->ff_init = hid_pidff_init;  
  52. #ifdef CONFIG_USB_HIDDEV  
  53.     hid->hiddev_connect = hiddev_connect;  
  54.     hid->hiddev_disconnect = hiddev_disconnect;  
  55.     hid->hiddev_hid_event = hiddev_hid_event;  
  56.     hid->hiddev_report_event = hiddev_report_event;  
  57. #endif  
  58.     hid->dev.parent = &intf->dev;  
  59.     hid->bus = BUS_USB;  
  60.     hid->vendor = le16_to_cpu(dev->descriptor.idVendor);  
  61.     hid->product = le16_to_cpu(dev->descriptor.idProduct);  
  62.     hid->name[0] = 0;  
  63.     if (intf->cur_altsetting->desc.bInterfaceProtocol ==  
  64.             USB_INTERFACE_PROTOCOL_MOUSE)  
  65.         hid->type = HID_TYPE_USBMOUSE;  
  66.     if (dev->manufacturer)  
  67.         strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));  
  68.     if (dev->product) {  
  69.         if (dev->manufacturer)  
  70.             strlcat(hid->name, " "sizeof(hid->name));  
  71.         strlcat(hid->name, dev->product, sizeof(hid->name));  
  72.     }  
  73.     if (!strlen(hid->name))  
  74.         snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",  
  75.              le16_to_cpu(dev->descriptor.idVendor),  
  76.              le16_to_cpu(dev->descriptor.idProduct));  
  77.     usb_make_path(dev, hid->phys, sizeof(hid->phys));  
  78.     strlcat(hid->phys, "/input"sizeof(hid->phys));  
  79.     len = strlen(hid->phys);  
  80.     if (len < sizeof(hid->phys) - 1)  
  81.         snprintf(hid->phys + len, sizeof(hid->phys) - len,  
  82.              "%d", intf->altsetting[0].desc.bInterfaceNumber);  
  83.     if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)  
  84.         hid->uniq[0] = 0;  
  85.     usbhid = kzalloc(sizeof(*usbhid), GFP_KERNEL);  
  86.     if (usbhid == NULL) {  
  87.         ret = -ENOMEM;  
  88.         goto err;  
  89.     }  
  90.     hid->driver_data = usbhid;  
  91.     usbhid->hid = hid;  
  92.     ret = hid_add_device(hid);  
  93.     if (ret) {  
  94.         if (ret != -ENODEV)  
  95.             dev_err(&intf->dev, "can't add hid device: %d/n", ret);  
  96.         goto err_free;  
  97.     }  
  98.     return 0;  
  99. err_free:  
  100.     kfree(usbhid);  
  101. err:  
  102.     hid_destroy_device(hid);  
  103.     return ret;  
  104. }  

 

ignored_list和is_ignored_device是我自己添加的。


重新编译usbhid模块和joystick模块,安装,插入手柄,输出如下:

usb 1-1: new low speed USB device using s3c2410-ohci and address 11

usb 1-1: New USB device found, idVendor=0e8f, idProduct=0002

usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0

usb 1-1: Product: BETOP USB GAMEPAD

usb 1-1: Manufacturer: GreenAsia Inc.   

usb 1-1: configuration #1 chosen from 1 choice

*** Device ignored ***

VendorID = 0E8F, ProductID = 0002

GreenAsia Inc.   

BETOP USB GAMEPAD

**********************

*************** Probe for joystick. ****************

bNumEndpoints: 1

direction: (81)Endpoint type: intterupt

MaxPacketSize: 8


嘿嘿,自己驱动的probe函数被调用了,接着就可以和设备通信了,至于怎么通信,还是看usb-skeleton.c
原创粉丝点击