我们先来看代码:
/*
* drivers\hid\usbhid\usbmouse.c
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/hid.h>
/* 关于这个结构体我们在注释1里面会有分析 */
static struct usb_device_id usb_mouse_id_table [] = {
{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
USB_INTERFACE_PROTOCOL_MOUSE) },
{ } /* Terminating entry */
};
/* 匹配时会调用这个函数 */
static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
printk("found usbmouse!\n");
printk("bcdUSB = %x\n", dev->descriptor.bcdUSB);
printk("VID = 0x%x\n", dev->descriptor.idVendor);
printk("PID = 0x%x\n", dev->descriptor.idProduct);
return 0;
}
/* 拔出时会自动调用这个函数 */
static void usb_mouse_disconnect(struct usb_interface *intf)
{
printk("disconnect usbmouse!\n");
}
static struct usb_driver usb_mouse_driver = {
.name = "usbmouse",
.probe = usb_mouse_probe,
.disconnect = usb_mouse_disconnect,
.id_table = usb_mouse_id_table,
};
static int __init usb_mouse_init(void)
{
int retval = usb_register(&usb_mouse_driver);
//注册
return retval;
}
static void __exit usb_mouse_exit(void)
{
usb_deregister(&usb_mouse_driver);
//卸载
}
module_init(usb_mouse_init);
module_exit(usb_mouse_exit);
MODULE_LICENSE("GPL");
注释1:
上一节里我们已经知道,插上usb设备后会读取设备的信息,然后根据读取的设备的信息我们来判断驱动与设备是否匹配。下面我们开始来分析:
首先找到
USB_INTERFACE_INFO的定义:
#define USB_INTERFACE_INFO(cl,sc,pr) \
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \
.bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO:表示要匹配接口信息
bInterfaceClass = (cl),:表示接口的类必须是USB_INTERFACE_CLASS_HID
.bInterfaceSubClass = (sc),:表示子类必须是USB_INTERFACE_SUBCLASS_BOOT
.bInterfaceProtocol = (pr):表示协议必须是USB_INTERFACE_PROTOCOL_MOUSE
一旦匹配就调用probe函数了
关于本程序我们来总结一下:
当插入USB设备时,会根据usb_mouse_driver 里的id.table去判断驱动与设备是否匹配,如果匹配,就会调用probe函数,在这个函数里面我们打印出了设备的一些信息,这些信息已经被内核读了出来。当拔出设备时会调用disconnect函数。其实这个机制就和平台总线设备驱动机制相似,只不过
平台总线设备驱动机制的匹配比较容易,只需要设备名与驱动名相同就可以,但是usb总线驱动相对要复杂了,上面已经讲过了。
测试:
1. make menuconfig去掉原来的USB鼠标驱动
-> Device Drivers
-> HID Devices
<> USB Human Interface Device (full HID) support
2. make uImage 并使用新的内核启动
3. insmod usbmouse_as_key.ko
4. 在开发板上接入、拔出USB鼠标
5. 打印出如下信息:
# usb 1-1: new low speed USB device using s3c2410-ohci and address 2
usb 1-1: configuration #1 chosen from 1 choice
found usbmouse!
bcdUSB = 110
VID = 0x93a
PID = 0x2510
usb 1-1: USB disconnect, address 2
disconnect usbmouse!
这里面有些信息是内核打印的