首页 > 代码库 > 学习Linux下s3c2440的USB鼠标驱动笔记
学习Linux下s3c2440的USB鼠标驱动笔记
USB驱动学习笔记: 2 1、ARM-Linux下USB驱动程序开发 3 1.1.1、linux下USB配置: 4 *********(MassStorage:存储设备)************************************ 5 -> Device Drivers 6 -> SCSI device support(通用设备) 7 -> SCSI disk support (磁盘支持) 8 -> SCSI device support(设备支持) 9 10 -> Device Drivers 11 -> USB support (USB设备) 12 -> USB device filesystem (USB设备文件系统) 13 -> OHCI HCD support (主要是非PC上的USB芯片) 14 -> USB Mass Storage support(USB大容量设备) 15 -> USB Monitor (USB 主设备) 16 17 -> File systems 18 -> DOS/FAT/NT Filesystems 19 -> MSDOS fs support 20 -> VFAT (Windows-95) fs support 21 22 -> Partition Types (分区类型) 23 -> PC BIOS (MSDOS partition tables) support 24 25 -> Native Language Suppor (本地语言设置) 26 -> Simplified Chinese charset (CP936, GB2312) 27 -> NLS UTF-8 28 29 make uImage (生成uImage) 30 测试 mount /dev/sda1 /mnt/ 31 32 *********(HID:人机接口(鼠标、键盘))******************************** 33 -> Device Drivers 34 HID Devices ---> 35 -> USB Human Interface Device (full HID) support 36 USB support ---> 37 -> Support for Host-side USB 38 make uImage (生成uImage) 39 测试 cat /dev/mouse1 40 41 *********(RNDIS:网卡)******************************** 42 43 -> Device Drivers x 44 -> USB support x 45 -> USB Gadget Support 46 <M> Support for USB Gadgets 47 <M> Ethernet Gadget (with CDC Et hernet support) x x 48 [*] RNDIS support (EXPERIMENTAL) (NEW) 49 编译内核模块 50 51 cp drivers/usb/gadget/_ether.ko /work/nfs_root/first_fs/ 52 cp /arch/arm/boot/uImage /work/nfs_root/new_uImage 53 54 *********(CDC-ACM:USB虚拟串口)******************************** 55 (未能识别USB driver)可能是没有配置USB设备 56 57 58 59 60 1.2.1、驱动程序编写 61 struct usb_driver { 62 const char *name; /*USB驱动名字*/ 63 int (*probe) (struct usb_interface *intf,const struct usb_device_id *id);/*USB core发现该驱动程序能够处理USB接口时,调用*/ 64 void (*disconnect) (struct usb_interface *intf);/*USB移除的时候调用*/ 65 const struct usb_device_id *id_table; /*该驱动程序支持哪些设备 idVendor(制造商ID) idProduct(产品id)*/ 66 }; 67 1.2.2、linux提供宏来定义 一种 设备 : 68 USB_DEVICE(vend,prod) 69 vend:USB Vendor ID 制造商ID 70 prod:USB Product ID 设备ID 71 72 1.2.3、linux提供宏来定义 一类 设备 : 73 USB_INTERFACE_INFO(cl,sc,pr) 74 cl:类 blnterfaceClass Value 75 sc:子类 blnterfaceSubClass value 76 pr:协议 blnterfaceProtocil Value 77 78 1.2.4、USB注册:传入一个参数usb_driver 79 static inline int usb_register(struct usb_driver *driver) 80 81 1.2.5、usb_device结构 82 int devnum; /* Address on USB bus */ 83 char devpath [16]; /* Use in messages: /port/port/... */ 84 enum usb_device_state state; /* configured, not attached, etc */ 85 enum usb_device_speed speed; /* high/full/low (or error) */ 86 struct usb_device_descriptor descriptor; /* Descriptor 设备描述符号*/ 87 struct usb_host_config *config; /* All of the configs */ 88 struct usb_config_descriptor desc; /*usb配置描述符*/ 89 struct usb_interface *interface[USB_MAXINTERFACES]; 90 ruct usb_host_interface *cur_altsetting; /* the currently 91 /*USB 接口描述符 一个[配置]包含一个或者多个接口,一个接口包含一个或者多个[设置] */ 92 struct usb_interface_descriptor desc; 93 struct usb_host_endpoint *endpoint; /*USB端点*/ 94 struct usb_endpoint_descriptor desc;/*USB 端点描述符 */ 95 96 1.3.1、URB(usb request block)请求块 ,承载USB之间的数据传输 97 98 ①URB处理流程: 99 1、USB设备驱动程序创建并初始化一个访问特点USB设备指定的端点的URB,并提交给USB Core 100 2、USB core提交该URB到USB主控制驱动程序 101 3、USB主控制器驱动程序根据该URB的描述信息,来访问USB设备 102 4、当访问设备结束后,USB主控制器驱动程序通知USB设备驱动(device)程序 103 104 ②创建urb的函数为: 105 struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags) 106 参数1:iso_packets:urb所含的等时数据包个数 107 参数2:mem_flags:内存分配标示 108 109 ③初始化urb函数为:interrupt 110 static inline void usb_fill_int_urb ( 111 struct urb *urb, //要初始化urb指针 112 struct usb_device *dev, //usb_device设备 113 unsigned int pipe, //要访问的端点所对应的管道,使用usb_sndintpipe()/usb_rcvintpipe() 114 void *transfer_buffer, //要传输数据的缓冲区 115 int buffer_length, //要传输数据的长度 116 usb_complete_t complete_fn, //当完成urb所请求的操作时候调用的回调函数 117 void *context, //通常取值为DEV 118 int interval //URB被调度的时间间隔 119 ); 120 问:何为管道? 121 答:管道:驱动程序的数据缓冲区与一个端点的连接,代表一个在两者之间要移动数据的能力。 122 123 批量urb:使用usb_fill_bulk_urb() 124 控制urb: 使用usb_control_urb() 125 等时urb没有像中断、控制、批量传输那样有URB初始化函数,我们只有手动初始化urb. 126 127 ④提交URB 128 在完成urb的创建和初始化后,URB就可以通过usb_smbmit_urb函数来提交给usb core 129 int usb_submit_urb(struct urb *urb, gfp_t mem_flags) 130 urb:指向URB的指针 131 mem_flags:内存分配标示,用于告知USB core如何分配内存换成区。 132 133 134 ⑤URB处理 以下三种情况被认为URB处理完成,调用complete_fn函数 135 1、URB成功发送给设备,并且设备返回正确,URB->status = 0 136 2、如果接收和发送发生错误时候 urb->status = error 137 3、urb被取消,就发生在驱动程序通过,usb_unlink_urb() / usb_kill_urb() 138
鼠标驱动程序:
1 #include <linux/kernel.h> 2 #include <linux/errno.h> 3 #include <linux/init.h> 4 #include <linux/slab.h> 5 #include <linux/module.h> 6 #include <linux/kref.h> 7 #include <asm/uaccess.h> 8 #include <linux/usb.h> 9 #include <linux/mutex.h> 10 #include <linux/hid.h> 11 #include <linux/input.h> 12 13 14 /*创建输入设备*/ 15 static struct input_dev *uk_dev; 16 static int len; 17 static char *usb_buf; 18 static dma_addr_t usb_data_dma; 19 static struct urb *uk_urb; 20 21 22 23 24 //usb支持的设备列表 25 static struct usb_device_id usbmouse_key_table [] = { 26 { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, 27 USB_INTERFACE_PROTOCOL_MOUSE) }, 28 //{USB_DEVICE(0x1234,0x5678)}, 29 { } /* Terminating entry */ 30 }; 31 32 static void usb_mouse_irq(struct urb *urb) 33 { 34 static unsigned char pre_val; 35 #if 0 36 int i; 37 char b[100]; 38 static int cnt = 0; 39 printk("data cnt %d: ", ++cnt); 40 for (i = 0; i < len; i++) 41 { 42 printk("%02x ", usb_buf[i]); 43 } 44 printk("\n"); 45 46 47 48 /* USB鼠标数据含义 49 * data[1]: bit0-左键, 1-按下, 0-松开 50 * bit1-右键, 1-按下, 0-松开 51 * bit2-中键, 1-按下, 0-松开 52 * 53 */ 54 // if ((pre_val & (1<<0)) != (usb_buf[1] & (1<<0))) 55 // { 56 // /* 左键发生了变化 */ 57 // input_event(uk_dev, EV_KEY, KEY_L, (usb_buf[1] & (1<<0)) ? 1 : 0); 58 // input_sync(uk_dev); 59 // } 60 61 // if ((pre_val & (1<<1)) != (usb_buf[1] & (1<<1))) 62 // { 63 // /* 右键发生了变化 */ 64 // input_event(uk_dev, EV_KEY, KEY_S, (usb_buf[1] & (1<<1)) ? 1 : 0); 65 // input_sync(uk_dev); 66 // } 67 68 // if ((pre_val & (1<<2)) != (usb_buf[1] & (1<<2))) 69 // { 70 // /* 中键发生了变化 */ 71 // input_event(uk_dev, EV_KEY, KEY_ENTER, (usb_buf[1] & (1<<2)) ? 1 : 0); 72 // input_sync(uk_dev); 73 // } 74 75 // pre_val = usb_buf[1]; 76 /* 重新提交urb */ 77 usb_submit_urb(uk_urb, GFP_KERNEL); 78 79 #else 80 81 switch (urb->status) { 82 case 0: /* success */ 83 break; 84 case -ECONNRESET: /* unlink */ 85 case -ENOENT: 86 case -ESHUTDOWN: 87 return; 88 /* -EPIPE: should clear the halt */ 89 default: /* error */ 90 goto resubmit; 91 } 92 93 input_report_key(uk_dev, BTN_LEFT, usb_buf[1] & 0x01); 94 input_report_key(uk_dev, BTN_RIGHT, usb_buf[1] & 0x02); 95 input_report_key(uk_dev, BTN_MIDDLE, usb_buf[1] & 0x04); 96 input_report_key(uk_dev, BTN_SIDE, usb_buf[1] & 0x08); 97 input_report_key(uk_dev, BTN_EXTRA, usb_buf[1] & 0x10); 98 99 input_report_rel(uk_dev, REL_X, usb_buf[3]); 100 input_report_rel(uk_dev, REL_Y, usb_buf[4]); 101 input_report_rel(uk_dev, REL_WHEEL, usb_buf[5]); 102 103 input_sync(uk_dev); 104 resubmit: 105 usb_submit_urb (urb, GFP_ATOMIC); 106 #endif 107 108 109 110 111 } 112 113 static int usbmouse_key_probe(struct usb_interface *intf, const struct usb_device_id *id) 114 { 115 struct usb_device *dev = interface_to_usbdev(intf); 116 struct usb_host_interface *interface; 117 struct usb_endpoint_descriptor *endpoint; 118 int pipe; 119 /*获取当前usb接口的设置*/ 120 interface = intf->cur_altsetting; 121 endpoint = &interface->endpoint[0].desc; 122 123 /* a. 分配一个input_dev */ 124 uk_dev = input_allocate_device(); 125 /* b. 设置 */ 126 /* b.1 能产生哪类事件 */ 127 set_bit(EV_KEY, uk_dev->evbit); 128 set_bit(EV_REL, uk_dev->evbit); 129 130 // /* b.2 能产生这类操作里的哪些事件: L,S,ENTER,LEFTSHIT */ 131 // set_bit(BTN_LEFT, uk_dev->keybit); 132 // set_bit(BTN_RIGHT, uk_dev->keybit); 133 // set_bit(BTN_MIDDLE, uk_dev->keybit); 134 135 // set_bit(REL_X,uk_dev->keybit); 136 // set_bit(REL_Y,uk_dev->keybit); 137 // set_bit(REL_WHEEL,uk_dev->keybit); 138 139 uk_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); 140 uk_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); 141 uk_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); 142 uk_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA); 143 uk_dev->relbit[0] |= BIT(REL_WHEEL); 144 145 /* c. 注册 */ 146 input_register_device(uk_dev); 147 148 /* d. 硬件相关操作 */ 149 /* 数据传输3要素: 源,目的,长度 */ 150 /* 源: USB设备的某个端点 */ 151 pipe = usb_rcvintpipe(dev,endpoint->bEndpointAddress); 152 /* 长度: */ 153 len = endpoint->wMaxPacketSize; 154 /* 目的: */ 155 usb_buf = usb_buffer_alloc(dev,len,GFP_ATOMIC,&usb_data_dma); 156 /* 使用"3要素" */ 157 /* 分配usb request block */ 158 uk_urb = usb_alloc_urb(0, GFP_KERNEL); 159 160 /* 使用"3要素设置urb" */ 161 usb_fill_int_urb(uk_urb, dev, pipe,usb_buf,len,usb_mouse_irq, NULL, endpoint->bInterval); 162 uk_urb->transfer_dma = usb_data_dma; 163 uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 164 165 /* 使用URB */ 166 usb_submit_urb(uk_urb, GFP_KERNEL); 167 168 169 printk("found usbmouse!\n"); 170 171 printk("bcdUSB = %x\n", dev->descriptor.bcdUSB); 172 printk("VID = 0x%x\n", dev->descriptor.idVendor); 173 printk("PID = 0x%x\n", dev->descriptor.idProduct); 174 175 return 0; 176 } 177 178 static void usbmouse_key_disconnect(struct usb_interface *interface) 179 { 180 struct usb_device *dev = interface_to_usbdev(interface); 181 182 printk("usbmouse_key_disconnect\n"); 183 input_unregister_device(uk_dev); 184 input_free_device(uk_dev); 185 usb_buffer_free(dev,len,usb_buf,usb_data_dma); 186 usb_kill_urb(uk_urb); 187 usb_free_urb(uk_urb); 188 189 } 190 191 MODULE_DEVICE_TABLE (usb, usbmouse_key_table); 192 193 /*usbmouse_key_probe usbmouse_key_disconnect 函数指针 194 *当设备与在id_table 中变量信息匹配时,此函数被调用 195 */ 196 static struct usb_driver usbmouse_key_driver = { 197 .name = "usbmouse_key", 198 .probe = usbmouse_key_probe, 199 .disconnect = usbmouse_key_disconnect, 200 .id_table = usbmouse_key_table, 201 202 }; 203 204 /* 205 *USB骨架 最基本的usb驱动模板 206 */ 207 static int __init usb_usbmouse_key_init(void) 208 { 209 int result; 210 211 printk("usb_usbmouse_key_init\n"); 212 213 /* register this driver with the USB subsystem */ 214 result = usb_register(&usbmouse_key_driver); 215 if (result) 216 err("usb_register failed. Error number %d", result); 217 218 return result; 219 } 220 221 static void __exit usb_usbmouse_key_exit(void) 222 { 223 printk("usb_usbmouse_key_exit\n"); 224 /* deregister this driver with the USB subsystem */ 225 usb_deregister(&usbmouse_key_driver); 226 } 227 228 module_init(usb_usbmouse_key_init); 229 module_exit(usb_usbmouse_key_exit); 230 MODULE_LICENSE("GPL");
学习Linux下s3c2440的USB鼠标驱动笔记
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。