IMX257 USB鼠标驱动程序编写

2024-08-14  

SB驱动程序包括为USB总线驱动程序以及USB设备驱动程序.

USB总线驱动程序的功能是:

    1.识别

    2.找到匹配的设备驱动程序

    3.提供USB读写函数(不知道数据的含义)

USB设备驱动程序功能是: 分析USB的数据,上报相应的事件

 

今天,我们来实现一个USB鼠标的设备驱动程序,让鼠标的左键模拟为键盘的L键,鼠标的右键模拟为键盘的S键,鼠标的中键模拟为键盘的ENTER键,接下来我们先来实现一个简单程序,让操作系统找到USB鼠标.

 

一.简单的USB鼠标设备驱动程序

1.分配/注册一个USB结构体usb_driver

如图所示,定义一个usb_driver结构体,里面分别有三个函数:

usb_mouse_key_probe usb鼠标探测函数

usb_mouse_key_disconnect  usb鼠标移出函数

usb_mouse_key_id_table    里面包含了usb鼠标的协议等信息

接下来分别实现上面的三个函数:

如图所示:我们现在先不做什么复杂的操作,知识简单的让它打印信息.

 

2.注册一个USB结构体usb_driver

3.调试:

make menuconfig去除自带的鼠标驱动程序:

1. make menuconfig 去掉原来鼠标的驱动程序

--> Device Drivers

--> HID Device

<>USB Human Interface Device(full HID) support

2. make uImage 使用新的内核启动

3. insmod usb_mouse_key.ko

4. 在开发板上接入和拔除USB设备

 

插入鼠标:打印出found usbmouse!

拔出鼠标:打印出disconnect usbmouse!

 

附上驱动程序1如下:


 1 /*drivers/hid/usbhid/usbmouse.c

 2  */

 3 #include

 4 #include

 5 #include

 6 #include

 7 #include

 8 #include

 9 

10 static struct usb_device_id usb_mouse_key_id_table [] = {

11     { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID      /*usb接口描述符的类为HID*/

12             , USB_INTERFACE_SUBCLASS_BOOT,            /*子类为BOOT*/

13         USB_INTERFACE_PROTOCOL_MOUSE) },             /*协议为MOUSE*/

14     /*{USB_DEVICE(vend,prod)} //若要自定义驱动支持某一款usb,在此处填充 */    

15     { }    /* Terminating entry */

16 };

17 

18 static int usb_mouse_key_probe(struct usb_interface *intf, const struct usb_device_id *id)

19 {

20     printk('<0>found usbmouse !n');

21 

22     return 0;

23 }

24 

25 static void usb_mouse_key_disconnect(struct usb_interface *intf)

26 {

27     printk('<0>disconnect usbmouse !n');

28 }

29 

30 

31 //1. 分配/设置/注册一个USB结构体usb_driver

32 static struct usb_driver usb_mouse_key_driver = {

33     .name        = 'usb_mouse_key',

34     .probe        = usb_mouse_key_probe,

35     .disconnect    = usb_mouse_key_disconnect,

36     .id_table    = usb_mouse_key_id_table,

37 };

38 

39 static int usb_mouse_key_init(void){

40 

41 

42     /*2.注册USB结构体*/

43     usb_register(&usb_mouse_key_driver);

44 

45     return 0;

46 }

47 

48 static void usb_mouse_key_exit(void){

49 

50     //卸载USB结构体

51     usb_deregister(&usb_mouse_key_driver);

52 }

53 

54 module_init(usb_mouse_key_init);

55 module_exit(usb_mouse_key_exit);

56 

57 MODULE_LICENSE('GPL');

58 

59 

60 /*

61 测试:

62 1. make menuconfig 去掉原来鼠标的驱动程序

63     --> Device Drivers

64         --> HID Device

65         <>USB Human Interface Device(full HID) support

66 2. make uImage 使用新的内核启动

67 3. insmod usb_mouse_key.ko

68 4. 在开发板上接入和拔除USB设备

69 

70 */


二.打印出USB鼠标的硬件信息.


1.usb_device 结构体


struct usb_device {

    int         devnum;

    char       devpath [16];

    u32        route;

    enum     usb_device_state    state;

    enum     usb_device_speed    speed;

    struct     usb_tt    *tt;

    int         ttport;

    unsigned int toggle[2];

    struct     usb_device *parent;

    struct     usb_bus *bus;

    struct     usb_host_endpoint ep0;

    struct     device dev;

    struct     usb_device_descriptor descriptor;   //硬件的信息

    struct     usb_host_config *config;

    struct     usb_host_config *actconfig;

    struct     usb_host_endpoint *ep_in[16];

    struct     usb_host_endpoint *ep_out[16];

    char      **rawdescriptors;

    unsigned short bus_mA;

    u8        portnum;

    u8        level;

    unsigned can_submit:1;

    unsigned discon_suspended:1;

    unsigned persist_enabled:1;

    unsigned have_langid:1;

    unsigned authorized:1;

    unsigned authenticated:1;

    unsigned wusb:1;

    int string_langid;


    /* static strings from the device */

    char *product;

    char *manufacturer;

    char *serial;

    struct list_head filelist;


#ifdef CONFIG_USB_DEVICE_CLASS

    struct device *usb_classdev;

#endif

#ifdef CONFIG_USB_DEVICEFS

    struct dentry *usbfs_dentry;

#endif

    int maxchild;

    struct usb_device *children[USB_MAXCHILDREN];

    int pm_usage_cnt;

    u32 quirks;

    atomic_t urbnum;

    unsigned long active_duration;


#ifdef CONFIG_PM

    struct delayed_work autosuspend;

    struct work_struct autoresume;

    struct mutex pm_mutex;

    unsigned long last_busy;

    int autosuspend_delay;

    unsigned long connect_time;

    unsigned auto_pm:1;

    unsigned do_remote_wakeup:1;

    unsigned reset_resume:1;

    unsigned autosuspend_disabled:1;

    unsigned autoresume_disabled:1;

    unsigned skip_sys_resume:1;

#endif


    struct wusb_dev *wusb_dev;

    int slot_id;

};   


2.struct usb_device_descriptor结构体


在这个结构体里面包含了鼠标的硬件信息.


 1 /* USB_DT_DEVICE: Device descriptor */

 2 struct usb_device_descriptor {

 3     __u8 bLength;

 4     __u8 bDescriptorType;

 5     __le16 bcdUSB;

 6     __u8 bDeviceClass;

 7     __u8 bDeviceSubClass;

 8     __u8 bDeviceProtocol;

 9     __u8 bMaxPacketSize0;

10     __le16 idVendor;

11     __le16 idProduct;

12     __le16 bcdDevice;

13     __u8 iManufacturer;

14     __u8 iProduct;

15     __u8 iSerialNumber;

16     __u8 bNumConfigurations;

17 } __attribute__ ((packed));


3.在上面程序的基础上,我们在probe函数中打印出上面结构体的信息,如下图所示:

4.测试

如下图所示,正常的打印出了鼠标的硬件ID号

附上驱动程序2如下:

 1 /*drivers/hid/usbhid/usbmouse.c

 2  */

 3 #include

 4 #include

 5 #include

 6 #include

 7 #include

 8 #include

 9 

10 static struct usb_device_id usb_mouse_key_id_table [] = {

11     { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID      /*usb接口描述符的类为HID*/

12             , USB_INTERFACE_SUBCLASS_BOOT,            /*子类为BOOT*/

13         USB_INTERFACE_PROTOCOL_MOUSE) },             /*协议为MOUSE*/

14     /*{USB_DEVICE(vend,prod)} //若要自定义驱动支持某一款usb,在此处填充 */    

15     { }    /* Terminating entry */

16 };

17 

18 static int usb_mouse_key_probe(struct usb_interface *intf, const struct usb_device_id *id)

19 {

20     struct usb_device *dev = interface_to_usbdev(intf);    //获取USB的接口,设备描述符,在.usb_device_descriptor里面就包含的设备的ID号等信息。

21     printk('<0>found usbmouse !n');

22     

23     printk('<0>USB接口信息如下:n');

24     printk('bcdUSB = %xn',dev->descriptor.bcdUSB);

25     printk('VID = 0x%xn',dev->descriptor.idVendor);

26     printk('PID = 0x%xn',dev->descriptor.idProduct);

27 

28     return 0;

29 

30 }

31 

32 static void usb_mouse_key_disconnect(struct usb_interface *intf)

33 {

34     printk('<0>disconnect usbmouse !n');

35 }

36 

37 

38 //1. 分配/设置/注册一个USB结构体usb_driver

39 static struct usb_driver usb_mouse_key_driver = {

40     .name        = 'usb_mouse_key',

41     .probe        = usb_mouse_key_probe,

42     .disconnect    = usb_mouse_key_disconnect,

43     .id_table    = usb_mouse_key_id_table,

44 };

45 

46 static int usb_mouse_key_init(void){

47 

48 

49     /*2.注册USB结构体*/

50     usb_register(&usb_mouse_key_driver);

51 

52     return 0;

53 }

54 

55 static void usb_mouse_key_exit(void){

56 

57     //卸载USB结构体

58     usb_deregister(&usb_mouse_key_driver);

59 }

60 

61 module_init(usb_mouse_key_init);

62 module_exit(usb_mouse_key_exit);

63 

64 MODULE_LICENSE('GPL');

65 

66 

67 /*

68 测试:

69 1. make menuconfig 去掉原来鼠标的驱动程序

70     --> Device Drivers

71         --> HID Device

72         <>USB Human Interface Device(full HID) support

73 2. make uImage 使用新的内核启动

74 3. insmod usb_mouse_key.ko

75 4. 在开发板上接入和拔除USB设备

76 

77 */

三.获取鼠标的硬件信息

1.定义一个input_dev结构体,设置产生的事件类型,如图所示

2.定义urb(usb请求块usb request block)结构体,设置数据传输三要素,然后提交urb,如图所示

实现上面定义的usb_mouse_key_irq完成查询函数,当usb数据读取成功时,就会自动进入usb_mouse_key_irq函数中

如图所示,这个函数中,由于各个厂家的鼠标的数据定义可能不一样,所以,此处我们先打印测试,分别按下鼠标的左右中键,以及移动鼠标,测试鼠标数据的函数

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。