[Linux]usb驱动程序

[Linux]usb驱动程序

个人博客https://aeneag.xyz/

艾恩凝

2021/7/1

usb framework

usb1.png

code

  1
  2#include <linux/kernel.h>
  3#include <linux/slab.h>
  4#include <linux/module.h>
  5#include <linux/init.h>
  6#include <linux/usb/input.h>
  7#include <linux/hid.h>
  8
  9static struct input_dev *uk_dev;
 10static char *usb_buf;
 11static dma_addr_t usb_buf_phys;
 12static int len;
 13static struct urb *uk_urb;
 14
 15
 16static struct usb_device_id usb_mouse_as_key_id_table [] = {
 17	{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
 18		USB_INTERFACE_PROTOCOL_MOUSE) },
 19	//{USB_DEVICE(0x1234,0x5678)},
 20	{ }	/* Terminating entry */
 21};
 22static void usb_mouse_as_key_irq(struct urb *urb)
 23{
 24	static unsigned char pre_val;
 25
 26#if 0
 27	int i;
 28	static int cnt = 0;
 29	printk("data cnt %d: ", ++cnt);
 30	for (i = 0; i < len; i++)
 31	{
 32		printk("%02x ", usb_buf[i]);
 33	}
 34	printk("\n");
 35#endif
 36	/* USB鼠标数据含义
 37	 * data[0]: bit0-左键, 1-按下, 0-松开
 38	 *			bit1-右键, 1-按下, 0-松开
 39	 *			bit2-中键, 1-按下, 0-松开 
 40	 *
 41	 */
 42	if ((pre_val & (1<<0)) != (usb_buf[0] & (1<<0)))
 43	{
 44		/* 左键发生了变化 */
 45		input_event(uk_dev, EV_KEY, KEY_L, (usb_buf[0] & (1<<0)) ? 1 : 0);
 46		input_sync(uk_dev);
 47	}
 48
 49	if ((pre_val & (1<<1)) != (usb_buf[0] & (1<<1)))
 50	{
 51		/* 右键发生了变化 */
 52		input_event(uk_dev, EV_KEY, KEY_S, (usb_buf[0] & (1<<1)) ? 1 : 0);
 53		input_sync(uk_dev);
 54	}
 55
 56	if ((pre_val & (1<<2)) != (usb_buf[0] & (1<<2)))
 57	{
 58		/* 中键发生了变化 */
 59		input_event(uk_dev, EV_KEY, KEY_ENTER, (usb_buf[0] & (1<<2)) ? 1 : 0);
 60		input_sync(uk_dev);
 61	}
 62
 63	pre_val = usb_buf[0];
 64
 65	/* 重新提交urb */
 66	usb_submit_urb(uk_urb, GFP_KERNEL);
 67
 68
 69}
 70static int usb_mouse_as_key_probe(struct usb_interface *intf, const struct usb_device_id *id)
 71{
 72	//printk("found usb_mouse!!!\n");
 73	struct usb_device *dev = interface_to_usbdev(intf);
 74	struct usb_host_interface *interface;
 75	struct usb_endpoint_descriptor *endpoint;
 76	int pipe;
 77
 78
 79	/* a. 分配一个input_dev */
 80	uk_dev = input_allocate_device();
 81
 82	/* b. 设置 */
 83	/* b.1 能产生哪类事件 */
 84	set_bit(EV_KEY, uk_dev->evbit);
 85	set_bit(EV_REP, uk_dev->evbit);
 86
 87	/* b.2 能产生哪些事件 */
 88	set_bit(KEY_L, uk_dev->keybit);
 89	set_bit(KEY_S, uk_dev->keybit);
 90	set_bit(KEY_ENTER, uk_dev->keybit);
 91
 92
 93	/* c. 注册 */
 94	input_register_device(uk_dev);
 95
 96	/* d. 硬件相关操作 */
 97	/* 数据传输3要素: 源,目的,长度 */
 98	/* 源: USB设备的某个端点 */
 99	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
100	/* 长度: */
101	len = endpoint->wMaxPacketSize;
102	/* 目的: */
103	usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);
104
105	/* 使用"3要素" */
106	/* 分配usb request block */
107	uk_urb = usb_alloc_urb(0, GFP_KERNEL);
108	/* 使用"3要素设置urb" */
109	usb_fill_int_urb(uk_urb, dev, pipe, usb_buf, len, usb_mouse_as_key_irq, NULL, endpoint->bInterval);
110	uk_urb->transfer_dma = usb_buf_phys;
111	uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
112
113	/* 使用URB */
114	usb_submit_urb(uk_urb, GFP_KERNEL);
115
116
117
118
119}
120static void usb_mouse_as_key_disconnect(struct usb_interface *intf)
121{
122	struct usb_device *dev = interface_to_usbdev(intf);
123
124	//printk("disconnect usbmouse!\n");
125	usb_kill_urb(uk_urb);
126	usb_free_urb(uk_urb);
127
128	usb_buffer_free(dev, len, usb_buf, usb_buf_phys);
129	input_unregister_device(uk_dev);
130	input_free_device(uk_dev);
131}
132
133/* setting usb driver*/
134static struct usb_driver usb_mouse_as_key_driver = {
135	.name		= "usb_mouse_as_key_",
136	.probe		= usb_mouse_as_key_probe,
137	.disconnect	= usb_mouse_as_key_disconnect,
138	.id_table	= usb_mouse_as_key_id_table,
139};
140
141static int usb_mouse_as_key_init(void){
142	usb_register(&usb_mouse_as_key_driver);
143	return 0;
144}
145
146static void usb_mouse_as_key_exit(void){
147	usb_deregister(&usb_mouse_as_key_driver);
148}
149
150
151module_init(usb_mouse_as_key_init);
152module_exit(usb_mouse_as_key_exit);
153MODULE_AUTHOR("https://aeneag.xyz");
154MODULE_VERSION("0.1");
155MODULE_DESCRIPTION("S3C2440 Mouse Driver");
156MODULE_LICENSE("GPL");

end

总的来说就是了解学习usb相关的驱动基本概念,多注重注重理解,这个程序是用了鼠标模拟按键通过usb设备来实现。

艾恩凝

写于大连

2021/7/1

catalogue

[Linux]驱动系列目录


    


公众号'艾恩凝'
个人公众号
个人微信
个人微信
    吾心信其可行,
          则移山填海之难,
                  终有成功之日!
                                  ——孙文
    评论
    0 评论
avatar

取消