为linux添加自己的USB驱动
2010-10-03 15:28
429 查看
本来想为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函数开头加了一段过滤代码,问题就解决了。
修改后的代码:
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
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函数开头加了一段过滤代码,问题就解决了。
修改后的代码:
static struct usb_device_id ignored_list[] = { {USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0002)}, { }, }; static int is_ignored_device(unsigned short idVendor, unsigned short idProduct) { int index; for(index = 0;ignored_list[index].idVendor;index++) { if((ignored_list[index].idVendor == idVendor) && (ignored_list[index].idProduct == idProduct)) return 1; } return 0; } static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_host_interface *interface = intf->cur_altsetting; struct usb_device *dev = interface_to_usbdev(intf); struct usbhid_device *usbhid; struct hid_device *hid; unsigned int n, has_in = 0; size_t len; int ret; dbg_hid("HID probe called for ifnum %d/n", intf->altsetting->desc.bInterfaceNumber); //ignore the device should not be handled by usbhid module if(is_ignored_device(dev->descriptor.idVendor, dev->descriptor.idProduct)) { printk("*** Device ignored ***/n"); printk("VendorID = %04X, ProductID = %04X/n", dev->descriptor.idVendor, dev->descriptor.idProduct); printk("%s/n", dev->manufacturer); printk("%s/n", dev->product); //printk("%s/n", ); printk("**********************/n"); return -ENODEV; } for (n = 0; n < interface->desc.bNumEndpoints; n++) if (usb_endpoint_is_int_in(&interface->endpoint .desc)) has_in++; if (!has_in) { dev_err(&intf->dev, "couldn't find an input interrupt " "endpoint/n"); return -ENODEV; } hid = hid_allocate_device(); if (IS_ERR(hid)) return PTR_ERR(hid); usb_set_intfdata(intf, hid); hid->ll_driver = &usb_hid_driver; hid->hid_output_raw_report = usbhid_output_raw_report; hid->ff_init = hid_pidff_init; #ifdef CONFIG_USB_HIDDEV hid->hiddev_connect = hiddev_connect; hid->hiddev_disconnect = hiddev_disconnect; hid->hiddev_hid_event = hiddev_hid_event; hid->hiddev_report_event = hiddev_report_event; #endif hid->dev.parent = &intf->dev; hid->bus = BUS_USB; hid->vendor = le16_to_cpu(dev->descriptor.idVendor); hid->product = le16_to_cpu(dev->descriptor.idProduct); hid->name[0] = 0; if (intf->cur_altsetting->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) hid->type = HID_TYPE_USBMOUSE; if (dev->manufacturer) strlcpy(hid->name, dev->manufacturer, sizeof(hid->name)); if (dev->product) { if (dev->manufacturer) strlcat(hid->name, " ", sizeof(hid->name)); strlcat(hid->name, dev->product, sizeof(hid->name)); } if (!strlen(hid->name)) snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x", le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct)); usb_make_path(dev, hid->phys, sizeof(hid->phys)); strlcat(hid->phys, "/input", sizeof(hid->phys)); len = strlen(hid->phys); if (len < sizeof(hid->phys) - 1) snprintf(hid->phys + len, sizeof(hid->phys) - len, "%d", intf->altsetting[0].desc.bInterfaceNumber); if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) hid->uniq[0] = 0; usbhid = kzalloc(sizeof(*usbhid), GFP_KERNEL); if (usbhid == NULL) { ret = -ENOMEM; goto err; } hid->driver_data = usbhid; usbhid->hid = hid; ret = hid_add_device(hid); if (ret) { if (ret != -ENODEV) dev_err(&intf->dev, "can't add hid device: %d/n", ret); goto err_free; } return 0; err_free: kfree(usbhid); err: hid_destroy_device(hid); return ret; }
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
相关文章推荐
- 为linux添加自己的USB驱动
- Linux-2.6.22.6 内核移植--添加USB设备驱动
- linux-2.6.35内核移植—USB驱动的添加
- 如何在Linux下添加自己的驱动
- linux gspca usb摄像头驱动添加对新型号的详细移植步骤
- 在linux内核文件中添加自己的驱动,添加自己的linux驱动,编译自己的linux驱动程序方法和例子图文
- 如何在Linux下添加自己的驱动
- 在linux内核文件中添加自己的驱动,添加自己的linux驱动,编译自己的linux驱动程序方法和例子图文
- 如何在Linux下添加自己的驱动
- linux gspca usb摄像头驱动添加对新型号的详细移植步骤
- 如何在linux下添加自己的设备驱动
- ARM9开发板FL2440移植Linux-3.0内核————添加USB驱动
- Linux下的硬件驱动——USB设备(上)(驱动配置部分)
- Linux下的USB总线驱动 mouse
- linux 中添加自己的库路径的方法 cannot open shared object file: No such file or directory
- 在menuconfig 菜单中添加自己编写的驱动选项
- 自己实现linux串口驱动
- ARM-Linux S5PV210 UART驱动(6)----platform device的添加
- Linux-USB Gadget : Part 5: 测试 PXA UDC 驱动
- Linux下的硬件驱动——USB设备(上)(驱动配置部分)