学习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");

				
时间: 2024-10-05 08:11:09

学习Linux下s3c2440的USB鼠标驱动笔记的相关文章

Linux下adb驱动问题Linux下使用手机USB调试模式连接ADB进行Android程序的调试

Linux 下adb 驱动问题 Linux下使用手机USB调试模式连接ADB进行Android程序的调试,配置驱动没有Windows来的直观. 具体步骤首先确认手机连接上电脑,lsusb查看下设备记录. [email protected]:~$ lsusb Bus 007 Device 009: ID 18d1:4e12 Bus 007 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 006 Device 001: ID 1d

转 学习linux下的c/c++编程

http://blog.csdn.net/byxdaz/article/details/3959680 1,先有linux环境搭minGW和cygwin都有点麻烦,最最简单的办法还是装个真正的linux,用虚拟机也好,在网络上的另一台机器也好.这样不仅快,而且你有了真正的环境.2.会C/C++语言(估计你会的)3.入门阶段熟悉gcc命令行,最基本的参数,如,-g,-W,-O,-o,-c 建议看man gcc(很大找想要的)4.编译第一个helloworld程序: 基本命令 gcc hellowo

Linux下安装Android的adb驱动-解决不能识别的问题

Linux下安装Android的adb驱动-解决不能识别的问题 20141011更新: 老方法对我当时使用的一款设备一直都没有出现问题,最后遇到小米手机还有Android4.4版本的系统都会每次出现error: insufficient permissions for device问题,老方法的最后也说了这个问题的解决方法是什么.大意就是adb服务得以root用户身份启动,比较靠谱的方法是添加或者修改/etc/udev/rules.d/51-android.rules文件,内容如下: SUBSY

linux下minicom和USB转串口

minicom是linux下串口通信的软件,它的使用完全依靠键盘的操作,虽然没有"超级终端"那么易用,但是使用习惯之后读者将会体会到它的高效与便利,下面将讲解minicom的安装和配置. 一.安装minicom: 使用以下命令:# sudo apt-get install minicom ubuntu 现在做的真是没话说,相当的实用和智能啊,把相关的依赖包(lrzsz)都相互关联并且安装上去了.但是如果使用ubuntu  8.10以前的版本可能就要单独安装lrzsz软件包了(lrzsz

linux 下手动编译安装无线网卡驱动

//先参照 <本地yum源安装GCC >安装好gcc hp的笔记本上安装了CentOS6.3,没有安装无线网卡驱动,安装这个驱动,在Google上找了好多资料,最后终于解决了这个问题.在这里做点记录,希望也能帮到别人. 我的机子是32位,CentOS的内核版本是2.6.32-279.19.1.el6.i686,下载的无线网卡驱动是hybrid-portsrc_x86_32-v5_100_82_112.tar.gz 下面是具体的步骤 一:确定无线网卡的型号,驱动下载 第一步要确定机子的无线网卡型

开启Ubuntu Linux下VirtualBox访问USB功能

解决方法如下: 1.增加用户组usbfs sudo groupadd usbfs 2.查看usbfs用户组的gid cat /etc/group | grep usbfs usbfs:x:1002: 3.把当前用户增加到usbfs组 sudo gedit /etc/group 把 usbfs:x:1002: 修改为 usbfs:x:1002:joson(joson改为自己的用户名) 开启Ubuntu Linux下VirtualBox访问USB功能

Linux USB 驱动开发—— USB 鼠标驱动注解及测试

参考2.6.14版本中的driver/usb/input/usbmouse.c.鼠标驱动可分为几个部分:驱动加载部分.probe部分.open部分.urb回调函数处理部分. 一.驱动加载部分 static int __init usb_mouse_init(void) { int retval = usb_register(&usb_mouse_driver);//注册鼠标驱动 if (retval == 0) info(DRIVER_VERSION ":" DRIVER_DE

Linux USB 驱动开发实例(二)—— USB 鼠标驱动注解及测试

参考2.6.14版本中的driver/usb/input/usbmouse.c.鼠标驱动可分为几个部分:驱动加载部分.probe部分.open部分.urb回调函数处理部分. 一.驱动加载部分 [cpp] view plain copy static int __init usb_mouse_init(void) { int retval = usb_register(&usb_mouse_driver);//注册鼠标驱动 if (retval == 0) info(DRIVER_VERSION 

Linux下安装android手机ADB驱动

本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020 在Linux下开发安卓,少不了要用到真机进行调试,测试,所以首先要保证Linux能驱动你的手机,驱动安装步骤如下: 安装步骤: 1. 检测你的Linux是否能驱动你的手机 如果你已经下载sdk,但未加入环境变量,那么你可以进入sdk目录下的platform-tools文件夹下找到adb,比如我的adb目录为/home/jesson/develop/adt-bundle-linu