liunx驱动----USB驱动
现象:把usb设备接入电脑
1.Windows发现设备
2.跳出一个对话框提示安装驱动程序
问1:既然没有驱动程序,为什么了够知道是什么驱动了??
答1:Windows里面已经有了usb总线驱动程序,接入usb设备后,是“总线驱动程序知道”是什么驱动。提示安装设备驱动程序
usb总线驱动程序负责识别USB设备,给usb设备找到对应的驱动程序
问2.usb设备种类多,为什么接入电脑就能够识别出来了?
答2.PC和USB设备都的遵守一些规范。
比如:USB接入电脑后PC机会发出,读取设备类型的命令(描述符)。然后USB设备就回答给PC机(描述符)。
问3.PC机上接有非常多的USB设备,怎么分辨?
答3.接在USB总线上的每个USB设备都有自己的编号(地址)PC机想访问某个USB设备的时候,发出的信息都有对方的编号(地址)
问4.USB设备刚接入PC的时候还没有编号,那么PC怎么把分配的编号告诉
答4.新接入的USB设备的默认编号为0,在没有分配新的编号前。PC使用0编号和USB通讯。
问5.为什么一接入USB设备,PC机就能发现USB设备
答5.PC的USB口内部。D-和D+接了下拉电阻,没有接入USB的时候为低电平,USB设备的USB口内部,D-或D+接了上啦电阻,接入时就有一个硬件的信号通知PC机有USB设备接入。
其它概念:
1.USB是主从设备(主从结构)
所有的USB传输都是从USB主机发起的。USB设备没有主动通知USB主机的能力。
例子:USB鼠标滑动一下立刻产生数据,但是它没有能力通知PC机来读数据,只能被动的等待PC机来读取数据
2.USB的传输类型
a.控制传输:可靠,时间有保证,比如USB设备的识别过程
b.批量传输:可靠,时间没有保证,U盘
c.中断传输:可靠,实时,USB鼠标
d.实时传输:不可靠,实时,USB摄像头
3.USB传输的对象:端点(endpoint)
读写U盘,可以细化为:把数据写到u盘的端点1,从u盘的端点2读出数据
除了端点0以外,每个端点只支持一个方向的数据传输。
端点0用于控制传输,既能输出也能输入
4.每一个端点都有传输类型,传输方向。
5.术语里,程序里说的输入(IN)输出(OUT)。都是基于USB主机的立场说的。
比如说对于鼠标,数据是从鼠标传输到PC机的。对应的端点称为“输出端点”
USB驱动
设备驱动: 1.知道数据的含义。
USB总线驱动程序(的作用)----> 1.识别设备
2.找到并安装对应的USB设备驱动
3.提供USB读写函数
硬件: USB主机控制器
USB驱动程框架:
APP:
---------------------------------------------
USB设备驱动程序
内核--------------------------------------
USB总线驱动程序
---------------------------------------------
USB主机控制器
硬件 ---------------------
USB设备
/*****************************USB总线驱动程序****************************************/
USB设备驱动程序编写:
1.分配/设置usb_derver结构体
.id_table 表示支持哪些usb设备
.probe
.disconnect
2.注册
测试:
1.make munconfig 去掉内核中原来的usb鼠标驱动
-> Device Drivers
-> HID Devices
< > USB Human Interface Device (full HID) support
2.make uImage 并使用新的内核启动
使用新内核启动:nfs 30000000 192.168.1.102:/home/book/work/nfs_root/first_fs/uImage_nohid; 30000000
挂接根文件系统:mount -t nfs -o nolock,vers=2 192.168.1.102:/home/book/work/nfs_root/first_fs /mut
3.insmod usbmonus_as_key.ko
实验1:
目的:通过控制台将数据数据移动按下数据打印出来。
步骤1:得到 usb_host_interface 结构体
interface = intf->cur_altsetting;//interface结构体
步骤2:获取端点描述符
endpoint = &interface->endpoint[0].desc;//端点描述符
步骤3://1.分配一个input_dev 结构体
uk_dev = input_allocate_device();
步骤4:设置uk_dev结构体
步骤5:注册input_dev结构体
步骤6:硬件相关的操作 (使用usb总线设备驱动来收发数据)
//数据传输的三要素: 源 、目的、长度
//源:USB的某个端点
代码分为:
usbmouse_as_key_probe函数(初始化需要操作鼠标的设置)
usbmouse_as_key_irq函数(当鼠标有数据变化时将调用这个函数)
usbmouse_as_key_disconnect函数(鼠标的断开处理函数)
usbmouse_as_key_probe代码如下:
static int usbmouse_as_key_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
/*打印厂家Id设备ID*/ struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
int pipe; interface = intf->cur_altsetting;//interface结构体 endpoint = &interface->endpoint[].desc;//端点描述符
#if 0
struct usb_device *dev = interface_to_usbdev(intf);//通过 interface_to_usbdev接口函数得到 usb_device id
printk("bcd_USB = %x\n",dev->descriptor.bcdUSB);
printk("vid = 0x%x\n",dev->descriptor.idVendor);
printk("pid = 0x%x\n",dev->descriptor.idProduct);
printk("found usbmonuse!\n");
#endif //1.分配一个input_dev 结构体
uk_dev = input_allocate_device(); //2.设置分配的这个结构体
//2.1能产生那类事件
set_bit(EV_KEY, uk_dev->evbit);//设置能够产生按键类事件uk_dev->evbit是表示能够产生那类事件
set_bit(EV_REP, uk_dev->evbit);//设置能够产生重复类事件uk_dev->evbit是表示能够产生那类事件
//2.2能产生哪些事件
set_bit(KEY_L,uk_dev->keybit);//通过设置uk_dev->keybit 实现产生一个KEY_L的事件 (相当于按键按下 L 键)
set_bit(KEY_S,uk_dev->keybit);//通过设置uk_dev->keybit 实现产生一个KEY_S的事件 (相当于按键按下 S 键)
set_bit(KEY_ENTER,uk_dev->keybit);//通过设置uk_dev->keybit 实现产生一个KEY_ENTER的事件 (相当于按键按下 ENTER 键)
//3.注册input_dev结构体
input_register_device(uk_dev);
//4.硬件相关的操作 (使用usb总线设备驱动来收发数据)
//数据传输的三要素: 源 、目的、长度
//源:USB的某个端点
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); //长度:
len =endpoint->wMaxPacketSize;//长度等于端点描述符的wMaxPacketSize(最大包大小) //目的:使用usb_buffer_alloc分配一个数据缓冲区
usb_buf=usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_pyhs); //使用三要素 usb requset block
uk_urb = usb_alloc_urb(, GFP_KERNEL); //使用三要素 设置usb requset block
/* usb请求块, */
usb_fill_int_urb(uk_urb, dev, pipe, usb_buf, len, usbmouse_as_key_irq, NULL, endpoint->bInterval);
uk_urb->transfer_dma = usb_buf_pyhs;//设置usb传输的目的 的物理地址
uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;//设置标记 //使用urb
usb_submit_urb (uk_urb, GFP_KERNEL);//提交数据 提交urb
return ;
}
usbmouse_as_key_irq代码如下:(当鼠标数据发生变化时执行此函数)
static void usbmouse_as_key_irq(struct urb *urb)
{
int i;
static int cnt=;
/*将鼠标数据打印出来*/
printk("usb data %d: ",++cnt);
for(i=;i<len;i++)
{
printk("%02x ",usb_buf[i]);
}
printk("\n");
//重新提交urb
usb_submit_urb (uk_urb, GFP_KERNEL);//提交数据 提交urb
}
usbmouse_as_key_disconnect代码如下:其实就是usbmouse_as_key_probe的逆向操作
static void usbmouse_as_key_disconnect(struct usb_interface *intf)
{
struct usb_device *dev = interface_to_usbdev(intf); //printk("dsiconnect usbmonuse!\n");
usb_kill_urb (uk_urb);//清除urb
usb_free_urb(uk_urb);//释放urb
usb_buffer_free(dev,len,usb_buf,usb_buf_pyhs);//去除 usb_buf
input_unregister_device(uk_dev);
input_free_device(uk_dev);
}
测试步骤:
1、insmod usbmonus_as_key.ko 挂载驱动
2、ls /dev/event* 查看事件

3、移动或者按下鼠标
数据1:按键值
数据2:x方向位移 数据
数据3:y方向位移 数据
数据4:滚轮数据


实验2:
目的:使用鼠标上的按键实现 L S 和ENTER 键值 在控制台上输出
通过实验一,已经将鼠标数据读了出来,所以要实现按键的话只关心第一个数据就可以了
所以只需要修改usbmouse_as_key_disconnect
static void usbmouse_as_key_irq(struct urb *urb)
{
static int pre_val;//用来保存上次的数据 #if 0
int i;
static int cnt=; /*将鼠标数据打印出来*/
printk("usb data %d: ",++cnt);
for(i=;i<len;i++)
{
printk("%02x ",usb_buf[i]);
}
printk("\n");
#endif /*
* USB鼠标数据含义
* data[0]:bit0-左键 1-按下 0-松开
* bit1-右键 1-按下 0-松开
* bit2-中键 1-按下 0-松开
*/
if((pre_val & (<<)) != (usb_buf[] & (<<)))
{
//左键发生了变化
input_event(uk_dev,EV_KEY,KEY_L,(usb_buf[] & (<<))? : );//使用input_event上报按键事件
input_sync(uk_dev);//同步信号
}
if((pre_val & (<<)) != (usb_buf[] & (<<)))
{
//右键发生了变化
input_event(uk_dev,EV_KEY,KEY_S,(usb_buf[] & (<<))? : );//使用input_event上报按键事件
input_sync(uk_dev);//同步信号
}
if((pre_val & (<<)) != (usb_buf[] & (<<)))
{
//中键发生了变化
input_event(uk_dev,EV_KEY,KEY_ENTER,(usb_buf[] & (<<))? : );//使用input_event上报按键事件
input_sync(uk_dev);//同步信号
}
pre_val = usb_buf[];
//重新提交urb
usb_submit_urb (uk_urb, GFP_KERNEL);//提交数据 提交urb
}
使用/dev/tty1 测试:

使用hexdump /dev/event1 测试:

liunx驱动----USB驱动的更多相关文章
- 【驱动】USB驱动实例·串口驱动·键盘驱动
Preface USB体系支持多种类型的设备. 在 Linux内核,所有的USB设备都使用 usb_driver结构描述. 对于不同类型的 USB设备,内核使用传统的设备驱动模型建立设备驱动 ...
- 【驱动】USB驱动实例·串口驱动·键盘驱动【转】
转自:http://www.cnblogs.com/lcw/p/3159370.html Preface USB体系支持多种类型的设备. 在 Linux内核,所有的USB设备都使用 usb_drive ...
- usb驱动开发24之接口驱动
从第一节我们已经知道,usb_generic_driver在自己的生命线里,以一己之力将设备的各个接口送给了linux的设备模型,让usb总线的match函数,也就是usb_device_match, ...
- Linux内核USB驱动【转】
本文转载自:http://www.360doc.com/content/12/0321/14/8363527_196286673.shtml 注意,该文件是2.4的内核的驱动源文件,并不保证在2.6内 ...
- USB驱动开发大全【转】
本文转载自:http://www.360doc.com/content/12/0504/19/8363527_208666082.shtml 编写USB驱动程序步骤:1所有usb驱动都必须创建主要结构 ...
- usb驱动开发15之设备生命线
总算是进入了HCD的片儿区,既然来到一个片区,怎么都要去拜会一下山头几个大哥吧.,先回忆一些我们怎么到这里的?给你列举一个调用函数过程usb_control_msg->usb_internal_ ...
- usb驱动开发14之设备生命线
直接看代码吧. /*-------------------------------------------------------------------*/ /** * usb_submit_urb ...
- usb驱动开发12之设备生命线
函数usb_control_msg完成一些初始化后调用了usb_internal_control_msg之后就free urb.剩下的活,全部留给usb_internal_control_msg去做了 ...
- usb驱动开发10之usb_device_match
在第五节我们说过会专门分析函数usb_device_match,以体现模型的重要性.同时,我们还是要守信用的. 再贴一遍代码,看代码就要不厌其烦. static int usb_device_matc ...
随机推荐
- [LeetCode] Ambiguous Coordinates 模糊的坐标
We had some 2-dimensional coordinates, like "(1, 3)" or "(2, 0.5)". Then, we re ...
- [LeetCode] N-ary Tree Preorder Traversal N叉树的前序遍历
Given an n-ary tree, return the preorder traversal of its nodes' values. For example, given a 3-ary ...
- js的作用域题
---恢复内容开始--- 1. var a = 12 function fn() { console.log(a) var a = 45; console.log(a) } fn() 2. funct ...
- C++———库函数cstring及string方法解读
1.string与cstring区别 <string>是C++标准库头文件.包含了拟容器class std::string的声明(不过class string事实上只是basic_stri ...
- iOS 如何查看APP的jetsamEvent日志
1.如何在iPhone上查看 设置-通用-分析-分析数据- JetsamEvent+日志 打头的系统日志. 2.如何在Mac 上查看此类分析日志 1.手机链接MAC 2.打开iTunes,点开手机图标 ...
- python 数据分析算法(决策树)
决策树基于时间的各个判断条件,由各个节点组成,类似一颗树从树的顶端,然后分支,再分支,每个节点由响的因素组成 决策树有两个阶段,构造和剪枝 构造: 构造的过程就是选择什么属性作为节点构造,通常有三种节 ...
- check failed status == cudnn_status_success (4 vs. 0) cudnn_status_internal_error
Check failed: error == cudaSuccess (30 vs. 0) unknown error 这个有可能是显存不足造成的,或者网络参数不对造成的 check failed ...
- Nginx 安装后 相关错误解决
1,安装 https://blog.csdn.net/wxyjuly/article/details/79443432 nobody 改为了 www /configure --user=www --g ...
- 【QT】Pycharm add QT Desinger
1. https://www.cnblogs.com/dalanjing/p/6978373.html -m PyQt5.uic.pyuic $FileName$ -o $FileNameWitho ...
- 使用jEnv在Mac/Linux环境配置多版本Java
jEnv 是什么? 先来看一下官方介绍 jEnv is a command line tool to help you forget how to set the JAVA_HOME environm ...