【驱动】第6课、USB驱动之学习笔记

主   机:VMWare--Ubuntu-16.04.2-x64-100ask

开发板:Mini2440--256M NandFlash,   2M NorFlash,   64M SDRAM,   LCD-TD35;
    bootlorder:u-boot1.16,        Kernel:2.6.22.6;
编译器:arm-linux-gcc-3.4.5


目录:

编程

一、搭建usb总线设备驱动模型框架
二、加入对USB鼠标的厂家ID, 设备ID的打印
三、I.probe()函数 
  II.usbmouse_as_key_irq()函数
四、重做usbmouse_as_key_irq()函数

源码


【编程】
目的:用USB鼠标做按键,左键-'L',右键-'S',中键-'ENTER'。
步骤:
一、搭建usb总线设备驱动模型框架
目的:在开发板上接入、拔出USB鼠标并在终端打印USB鼠标插拔状态;
1. 分配一个usb_driver结构体:
static struct usb_driver usbmouse_as_key_driver = {
.id_table
.probe
.disconnect};
static struct usb_device_id usbmouse_as_key_id_table [] = {
{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
USB_INTERFACE_PROTOCOL_MOUSE) },};
static int usbmouse_as_key_probe(struct usb_interface *intf, const struct usb_device_id *id){printk("found usbmouse!\n");}
static void usbmouse_as_key_disconnect(struct usb_interface *intf){ printk("disconnect usbmouse!\n");}
2.配置结构体usb_driver;
3.注册结构体usb_driver;
usb_register(&usbmouse_as_key_driver);
static int usbmouse_as_key_init(void) {usb_register(&usbmouse_as_key_driver);}
static void usbmouse_as_key_exit(void) { usb_deregister(&usbmouse_as_key_driver);}
module_init(usbmouse_as_key_init);
module_exit(usbmouse_as_key_exit);

二、加入对USB鼠标的厂家ID, 设备ID的打印;
usbmouse_as_key_probe(struct usb_interface *intf, const struct usb_device_id *id){
struct usb_device *dev = interface_to_usbdev(intf);
printk("bcdUSB = %x\n", dev->descriptor.bcdUSB);
printk("VID = 0x%x\n", dev->descriptor.idVendor);
printk("PID = 0x%x\n", dev->descriptor.idProduct);
}
三、I.probe()函数: (在probe()函数中)加入以鼠标为输入设备的输入子系统;
1.分配一个input_dev;
2.配置该结构体;
3.注册该结构体;
4、硬件相关的操作;
4.1数据传输的三要素:源,长度,目的(地)。
a.源:USB设备的某个端点。int pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
b.长度:len = endpoint->wMaxPacketSize;
c.目的(地):从USB读出的数据存储到的缓冲区地址(虚拟地址),
usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys); //返回值是一个虚拟地址。
4.2(使用三要素)分配并初始化URB:
a.分配usb request block,即:uk_urb = usb_alloc_urb(0, GFP_KERNEL);
b.使用“三要素”设置/填充urb;
usb_fill_int_urb(uk_urb, dev, pipe, usb_buf, len, usbmouse_as_key_irq, NULL, endpoint->bInterval);
uk_urb->transfer_dma = usb_buf_phys;
uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
4.3提交URB;
usb_submit_urb(uk_urb, GFP_KERNEL);

II.usbmouse_as_key_irq()函数:在USB主机控制器得到数据并产生中断 usbmouse_as_key_irq(),在此中断中处理函数内处理中断;
1.打印从usb设备读到的数据:
for(i = 0; i < len; i++) printk("%02x ", usb_buf[i]);
2.重新提交URB:
usb_submit_urb(uk_urb, GFP_KERNEL);
四、重做usbmouse_as_key_irq()函数
1.提交USB鼠标按键数据
* 鼠标按键: usb_buf[0];
* 左键: bit0; 右键:bit1; 中键: bit2;
if((preval & (1<<0)) != (usb_buf[0] & (1<<0)))
{
input_event(uk_dev, EV_KEY, KEY_L, (usb_buf[0] & (1<<0)) ? 1 : 0);
input_sync(uk_dev);
}
2.重新提交URB:
usb_submit_urb(uk_urb, GFP_KERNEL);

【测试】
测试1th/2th:
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鼠标

测试3th:
1. insmod usbmouse_as_key.ko
2. ls /dev/event*
3. 接上USB鼠标
4. ls /dev/event*
5. 操作鼠标观察数据
问题1:122: warning: ISO C90 forbids mixed declarations and code
翻译:ISO C90禁止混合声明和代码
问题源码:
static void usbmouse_as_key_disconnect (struct usb_interface *intf)
{
printk("disconnect usbmouse!\n");
struct usb_device *dev = interface_to_usbdev(intf); //122行;
...
}

测试4th:
1. insmod usbmouse_as_key.ko
2. ls /dev/event*
3. 接上USB鼠标
4. ls /dev/event*
5. cat /dev/tty1 然后按鼠标键
6. hexdump /dev/event0

【源码】

源码:usbmouse_as_key.c

  1 /*
  2  * 2019-01-04
  3  * 功能: 用USB鼠标做按键;
  4  */
  5 #include <linux/kernel.h>
  6 #include <linux/slab.h>
  7 #include <linux/module.h>
  8 #include <linux/init.h>
  9 #include <linux/usb/input.h>
 10 #include <linux/hid.h>
 11 MODULE_LICENSE("GPL");
 12 
 13 static struct input_dev *uk_dev;
 14 static struct urb *uk_urb;
 15 static int len;                /* 数据长度 */
 16 static char *usb_buf;        /* 虚拟地址 */
 17 static dma_addr_t usb_buf_phys;    /* 物理地址 */
 18 
 19 /* usb鼠标中断处理函数 */
 20 static void usbmouse_as_key_irq(struct urb *urb)
 21 {
 22     static char preval;
 23     #if 0
 24     /* 1.打印从usb设备读到的数据 */
 25     static int cnt = 0;
 26     int i;
 27     printk("usbmouse data cnt %d:   ", ++cnt);
 28     for(i = 0; i < len; i++)
 29     {
 30         printk("%02x ", usb_buf[i]);
 31     }
 32     printk("\n");
 33     #endif
 34     /* 1.提交数据
 35      * 鼠标按键: usb_buf[0];
 36      * 左键: bit0; 右键:bit1; 中键: bit2;
 37      */
 38     /* 左键发生变化 */
 39     if((preval & (1<<0)) != (usb_buf[0] & (1<<0)))
 40     {
 41         input_event(uk_dev, EV_KEY, KEY_L, (usb_buf[0] & (1<<0)) ? 1 : 0);
 42         input_sync(uk_dev);
 43     }
 44     /* 右键发生变化 */
 45     if((preval & (1<<1)) != (usb_buf[0] & (1<<1)))
 46     {
 47         input_event(uk_dev, EV_KEY, KEY_S, (usb_buf[0] & (1<<1)) ? 1 : 0);
 48         input_sync(uk_dev);
 49     }
 50     /* 中键发生变化 */
 51     if((preval & (1<<2)) != (usb_buf[0] & (1<<2)))
 52     {
 53         input_event(uk_dev, EV_KEY, KEY_ENTER, (usb_buf[0] & (1<<2)) ? 1 : 0);
 54         input_sync(uk_dev);
 55     }
 56     preval = usb_buf[0];
 57     /* 2.重新提交uK_urb */
 58     usb_submit_urb(uk_urb, GFP_KERNEL);
 59 }
 60 static int usbmouse_as_key_probe (struct usb_interface *intf, const struct usb_device_id *id)
 61 {
 62     struct usb_device *dev = interface_to_usbdev(intf);
 63     struct usb_endpoint_descriptor *endpoint;
 64     struct usb_host_interface *hostintf;
 65     int pipe;
 66 
 67     hostintf = intf->cur_altsetting;
 68     if (hostintf->desc.bNumEndpoints != 1)
 69         return -ENODEV;
 70     endpoint = &hostintf->endpoint[0].desc;
 71     if (!usb_endpoint_is_int_in(endpoint))
 72         return -ENODEV;
 73     printk("found usbmouse!\n");
 74 
 75      #if 0
 76     printk("bcdUSB = 0X%04X\n", dev->descriptor.bcdUSB);
 77     printk("VID = 0X%04X\n", dev->descriptor.idVendor);
 78     printk("PID = 0X%04X\n", dev->descriptor.idProduct);
 79      #endif
 80     /* 1.分配一个input_dev结构体 */
 81     uk_dev = input_allocate_device();
 82     if(!uk_dev)
 83     {
 84         printk(KERN_ERR "Unable to allocate uk_dev input device!\n");
 85         goto err_fail1;
 86     }
 87      /* 2.配置该dev */
 88      /* 2.1配置该设备支持哪类事件 */
 89     set_bit(EV_KEY, uk_dev->evbit);
 90     set_bit(EV_REP, uk_dev->evbit);
 91     /* 2.2配置该设备支持哪些事件 */
 92     set_bit(KEY_L, uk_dev->keybit);
 93     set_bit(KEY_S, uk_dev->keybit);
 94     set_bit(KEY_ENTER, uk_dev->keybit);
 95     /* 3.注册该结构体 */
 96     if(input_register_device(uk_dev) < 0)
 97     {
 98         printk(KERN_ERR "Unable to register uk_dev input device!\n");
 99         goto err_fail2;
100     }
101     /* 4.硬件相关的配置 */
102     /* 4.1数据传输三要素: 数据源,目的地,长度 */
103     pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
104     len = endpoint->wMaxPacketSize;
105     usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);
106     if(!usb_buf)
107     {
108         printk(KERN_ERR "Unable to allocate usb_buf transfer buffer!\n");
109         goto err_fail3;
110     }
111     /* 4.2分配并初始化urb */
112     uk_urb = usb_alloc_urb(0, GFP_KERNEL);
113     if(!uk_urb)
114     {
115         printk(KERN_ERR "Unable to allocate uk_urb usb request block!\n");
116         goto err_fail4;
117     }
118     usb_fill_int_urb(uk_urb, dev, pipe, usb_buf, len, usbmouse_as_key_irq, 
119         NULL, endpoint->bInterval);
120     uk_urb->transfer_dma = usb_buf_phys;
121     uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
122     /* 4.3提交urb */
123     if(usb_submit_urb(uk_urb, GFP_KERNEL) < 0)
124     {
125         printk(KERN_ERR "Unable to submit uk_urb usb request block!\n");
126         goto err_fail5;
127     }
128  
129     return 0;
130  err_fail5:
131      usb_kill_urb(uk_urb);
132  err_fail4:
133      usb_free_urb(uk_urb);
134  err_fail3:
135      usb_buffer_free(dev, len, usb_buf, usb_buf_phys);
136  err_fail2:
137      input_unregister_device(uk_dev);
138  err_fail1:
139      input_free_device(uk_dev);
140     return -ENOMEM;
141 }
142 
143 static void usbmouse_as_key_disconnect (struct usb_interface *intf)
144 {
145     struct usb_device *dev = interface_to_usbdev(intf);
146 
147     printk("disconnect usbmouse!\n");
148     usb_kill_urb(uk_urb);
149      usb_free_urb(uk_urb);
150      usb_buffer_free(dev, len, usb_buf, usb_buf_phys);
151      input_unregister_device(uk_dev);
152      input_free_device(uk_dev);
153 }
154 
155 static struct usb_device_id usbmouse_as_key_id_table[] = {
156     {USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, \
157         USB_INTERFACE_PROTOCOL_MOUSE)},
158     //{USB_DEVICE(vend, prod)},
159     {},
160 };
161 
162 static struct usb_driver usbmouse_as_key_driver = {
163     .name = "usbmouse_as_key2",
164     .probe = usbmouse_as_key_probe,
165     .disconnect = usbmouse_as_key_disconnect,
166     .id_table = usbmouse_as_key_id_table,
167 };
168 
169 static int usbmouse_as_key_init(void)
170 {
171     int retval = usb_register(&usbmouse_as_key_driver);
172     if(retval < 0)
173     {
174         printk("Unable to register the usb_driver of usbmouse_as_key_driver!\n");
175     }
176     return retval;
177 }
178 static void usbmouse_as_key_exit(void)
179 {
180     usb_deregister(&usbmouse_as_key_driver);
181 }
182 
183 module_init(usbmouse_as_key_init);
184 module_exit(usbmouse_as_key_exit);

Makefile

 1 ifneq ($(KERNELRELEASE),)
 2     obj-m := usbmouse_as_key8.o
 3 else
 4     KERN_DIR ?= /home/book/workbook/mini2440/systems/linux-2.6.22.6
 5 
 6     PWD = $(shell pwd)
 7 all:
 8     $(MAKE) -C $(KERN_DIR) M=$(PWD) modules
 9 clean:
10     $(MAKE) -C $(KERN_DIR) M=$(PWD) modules clean
11     rm -rf modules.order
12 
13 endif

 

posted @ 2019-01-06 16:58  大秦长剑  阅读(444)  评论(0编辑  收藏  举报