嵌入式开发记录-day38 USB鼠标驱动
1、usbmouse.c 在目录drivers\hid\usbhid下
驱动入口
int retval = usb_register(&usb_mouse_driver);
驱动结构体
// 这个结构体中包含有很多函数,但是这四个是必须的 static struct usb_driver usb_mouse_driver = { .name = "usbmouse", // 驱动名称 .probe = usb_mouse_probe, // USB设备初始化,设备如果成功,会自动执行到这里 .disconnect = usb_mouse_disconnect, // USB断开,释放URB等操作 .id_table = usb_mouse_id_table, // 用于匹配USB的协议 以进入probe中 };
2、初始化probe的match条件
在前面一直强调要在驱动源码中写入idProduct和idVendor,这样才能 进入probe,严格说来这是不严谨的,甚至可以说是错误的。 •
在移植大型USB驱动的时候,对驱动工程师来说,的确是只需要添加 idProduct和idVendor,但是match匹配的时候,不一定需要匹配这两个 参数,而要根据实际代码来分析。 –
具体是如何匹配的,USB从机设备驱动工程师需要根据USB协议来配置对 应的参数。 •
但是有一点作者可以保证,在移植大型USB驱动的时候,一般是要修 改或者添加idProduct和idVendor这两个参数,如果匹配的时候使用其 它参数,目前作者没有发现需要修改的。 •
这两个参数是作者移植大型驱动的过程中总结出来的,目前还没发现 任何一本书上这样写,也没有发现任何博客这样写。但是实践发现就 是这样。
3、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> #define DRIVER_VERSION "v1.6" #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" #define DRIVER_DESC "USB HID Boot Protocol mouse driver" #define DRIVER_LICENSE "GPL" MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE(DRIVER_LICENSE); static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id) { printk("usb mouse probe!\n"); return 0; // 需要有返回值,否则会出现问题 } static void usb_mouse_disconnect(struct usb_interface *intf) { printk("usb mouse disconnect!\n"); } 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 */ }; MODULE_DEVICE_TABLE (usb, usb_mouse_id_table); 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) { return usb_register(&usb_mouse_driver); } static void __exit usb_mouse_exit(void) { usb_deregister(&usb_mouse_driver); } module_init(usb_mouse_init); module_exit(usb_mouse_exit);
4、在测试之前需要
Device Drivers ---> – HID Devices ---> – USB Human Interface Device (full HID) support(去掉)去掉鼠标之前的驱动
5、USB的设备信息
usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id) --->struct usb_interface *intf --->struct usb_interface {
/* array of alternate settings for this interface,* stored in no particular order */
struct usb_host_interface *altsetting;
struct usb_host_interface *cur_altsetting; /* the currentl active alternate setting */.....}--->struct usb_host_interface *altsetting--->
struct usb_host_interface {
struct usb_interface_descriptor desc; /* array of desc.bNumEndpoint endpoints associated with this interface setting. these will be in no particular order.*/
struct usb_host_endpoint *endpoint;...}
struct usb_device *dev = interface_to_usbdev(intf);--->struct usb_device-->struct usb_device_descriptor descriptor; // 包含有USB的设备描述符,包含产品ID和厂商ID
6、初始化probe的分析和验证
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 */
};
#define USB_INTERFACE_CLASS_HID 3
#define USB_INTERFACE_SUBCLASS_BOOT 1
#define USB_INTERFACE_PROTOCOL_MOUSE 2
probe在验证的时候,并不是简单匹配ID那么简单;
7、urb的使用周期为 –
1、申请urb,初始化urb,提交urb,完成urb,注销urb和释放urb
struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags) //
static inline void usb_fill_int_urb(struct urb *urb,struct usb_device *dev,unsigned int pipe,void *transfer_buffer,
int buffer_length,usb_complete_t complete_fn,void *context,int interval) //
int usb_submit_urb(struct urb *urb, gfp_t mem_flags) //
// 用于传输数据
input_report_key(dev, BTN_LEFT, data[0] & 0x01);
input_report_rel(dev, REL_X, data[1]);