USB驱动程序之鼠标用做键盘

原创 2017年03月20日 23:14:24

我们还是接着来看看我们的例子程序 usbmouse.c


这里它接着判断了他是不是鼠标,

得到它的usb_host_interface,interface=intf->cur_alsetting就是当前接口的设置



这里有个接口描述符,我们来看看接口描述符


接口描述符里面有个__u8  bNumEndpoints端点的个数

这个端点的个数是除了端点0之外还有多少个端点


这里首先判断如果除了端点0之外,端点个数不是1的话就返回错误,不是我能够支持的设备

如果只有一个端点,那就把这个端点放到endpoint这个数组里面,这个并不是端点0,而是除了端点0之外第一个端点

得到一个端点描述符

if(!usb_endpoint_is_int_in(endpoint))这个是指如果他不是中断类似的端点,不是输入端点,注意了我们这里输入输出是站在主机的角度说的,站在主机角度,我们的鼠标是输入设备,数据是输入给主机的。如果不是输入类型端点,中断类型端点,就返回一个错误。这个怎么回事呢,怎么知道你是不是中断输入端点呢,端点描述符里面不是有个属性吗,属性里面就是表示它是什么类型的,方向。


我们在我们自己的程序里就不做判断了,我们回到我们的主题,我们就认为就是一个鼠标,



我们硬件相关的操作要用到USB总线驱动程序里面的读写函数

我们只需要记住数据传输3要素,把这个三要素找出就可以实现这一点

1.源   在我们这里是USB设备的某个端点


这个就是源

我们来看看usb_rcvintpipe这个宏


这个源是个整数,pipe_interrupt是指中断类型端点,USB_DIR_IN是端点的方向。我们进入__create_pipe(dev,endpoint)这个宏


devnum是设备的地址,endpoint是端点的地址也是端点编号


2.目的

我们从USB设备里面读数据,读到哪里去,肯定读到缓冲区,但这个缓冲区肯定不能用kmallioc函数,

用这函数

返回一个void* 是个虚拟地址

最后一个参数是指的物理地址


3.长度就是我们的端点描述符最大包大小


使用我们三要素

怎么用呢,看一下我们的例子


分配一个urb urb是什么意思呢,就是USB请求快的意思 usb request block

然后使用这个3要素设置我们的urb  来看我们的例子程序




看看这个函数原型


第一个参数是urb,第二个参数是设备,第三个参数是源,第四个参数是目的,第五个参数是长度 ,第6个参数是完成函数,第7个参数是给那个完成函数用的,我们不需要,第8个参数是查询的频率。

我们前面说过usb设备不能打断主机控制器,只能让主机控制器查询,不断的去查询,等有数据之后才能中断CPU。当它得到数据之后,总线驱动程序就会调用这个complete_fn这个函数,查询多频繁呢就是int interval 。

端点描述符里面有个binterval就是的



我们USB主机控制器,得到数据之后是往某个地方写,但是我们主机控制器没那么聪明,所以我们要告诉它,例子里面


第一句就是告诉物理地址,下面一句是设置某些标记


我们构造了URB 就要使用urb

怎么使用urb


使用usb_submit_urb提交urb



usb鼠标数据含义

我们前面说框架的时候说过,USB设备驱动程序知道数据的含义,USB总线驱动程序提供识别设备,给设备找到驱动,提供读写函数,但是不知道数据的含义。这些数据需要由设备驱动程序来解析,


data[0] bit 0表示左键,1表示按下,0表示松开

     bit 1表示右键,1表示按下,0表示松开

     bit  2表示中键    1表示按下,0表示松开



代码如下

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/hid.h>


static struct input_dev *usb_key;
static char * usb_buf;
static dma_addr_t usb_buf_phys;
static int len;
static struct urb *uk_urb;
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) },
{ } /* Terminating entry */
};


static void usbmouse_as_key_irq(struct urb *urb)
{
static unsigned char pre_val;
/* USB鼠标数据含义
* data[0]: bit0-左键, 1-按下, 0-松开
*          bit1-右键, 1-按下, 0-松开
*          bit2-中键, 1-按下, 0-松开 
*/
if((pre_val & (1<<0)) != (usb_buf[0] & (1<<0)))
{
//左键发生了变化
input_event(usb_key, EV_KEY, KEY_L, (usb_buf[0] & (1<<0)) ? 1 : 0);
input_sync(usb_key);
}
if ((pre_val & (1<<1)) != (usb_buf[0] & (1<<1)))
{
/* 右键发生了变化 */
input_event(usb_key, EV_KEY, KEY_S, (usb_buf[0] & (1<<1)) ? 1 : 0);
input_sync(usb_key);
}
if ((pre_val & (1<<2)) != (usb_buf[0] & (1<<2)))
{
/* 中键发生了变化 */
input_event(usb_key, EV_KEY, KEY_ENTER, (usb_buf[0]  & (1<<2)) ? 1 : 0);
input_sync(usb_key);
}

pre_val = usb_buf[0];


/* 重新提交urb */
usb_submit_urb(uk_urb, GFP_KERNEL);
}


static int usbmouse_as_key_probe(struct usb_interface *intf, const struct usb_device_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;


endpoint = &interface->endpoint[0].desc;
/*a.分配一个input_device结构体*/
usb_key=input_allocate_device();
/*b.设置*/
/*b.1能产生哪类事件*/
//能够产生按键类事件
set_bit(EV_KEY,usb_key->evbit);
set_bit(EV_REP,usb_key->evbit);//能够产生重复类事件,就是只我们按下一个字母不动就会不断的打印出来


/*b.2能产生这类事件的哪些事件*/
set_bit(KEY_L,usb_key->keybit);
set_bit(KEY_S,usb_key->keybit);
set_bit(KEY_ENTER,usb_key->keybit);


/*c.注册*/
input_register_device(usb_key);
/*d.硬件相关的操作*/
/*数据传输3要素 源,目的,长度*/
/*1.源 :USB设备的某个端点*/
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);


//长度 等于端点描述符的最大包大小
len=endpoint->wMaxPacketSize;


/*2.目的 */
usb_buf = usb_alloc_coherent(dev,len, GFP_ATOMIC, &usb_buf_phys);


//使用三要素
/*分配一个urb usb request block*/
uk_urb= usb_alloc_urb(0, GFP_KERNEL);
//使用3要素设置这个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;
//使用URB
usb_submit_urb(uk_urb, GFP_KERNEL);


return 0;
}


static void usbmouse_as_key_disconnect(struct usb_interface *intf)
{
struct usb_device *dev = interface_to_usbdev(intf);
usb_kill_urb(uk_urb);
usb_free_urb(uk_urb);
usb_free_coherent(dev, len, usb_buf, usb_buf_phys);
input_unregister_device(usb_key);
input_free_device(usb_key);




}
/*1.分配/设置usb_driver*/
static struct usb_driver usbmouse_as_key_driver = {
.name = "usbmouse_as_key",
.probe = usbmouse_as_key_probe,
.disconnect = usbmouse_as_key_disconnect,
.id_table = usbmouse_as_key_id_table,
};
static int usbmouse_as_key_init(void)
{
/*2.注册usb_driver结构体*/
usb_register(&usbmouse_as_key_driver);
return 0;
}

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);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("EIGHT");


测试结构如下图







USB驱动程序之USB设备驱动程序2鼠标用作键盘学习笔记

1、usbmouse.c (1)在这个probe函数后判断是不是一个鼠标,先得到usb_host_interface结构体,除了端点0外,端点个数如果不是1,返回错误,表示不是自己能支持的设备。如果只...
  • qingkongyeyue
  • qingkongyeyue
  • 2016年12月03日 10:49
  • 613

让Thinkpad USB键盘支持小红帽中键滚轮的方法(ThinkPad USB Keyboard with TrackPoint)

Thinkpad键盘是非常好用的一款键盘,体验和传统的Thinkpad笔记本键盘一样,而且还支持小红帽(Trackpoint,指点杆)。 小红帽在使用上双手不需要离开键盘,甚至不用移动手掌位...
  • jaketseng
  • jaketseng
  • 2013年05月15日 15:19
  • 4964

Android/Linux USB HID驱动(即USB鼠标USB键盘等驱动)相关文件

1、USB HID HID:Human Interface Devices的缩写,即人体学输入设备或人体学接入设备。USB HID则为USB人体学输入设备,最典型的是USB鼠标和USB键盘。 2...
  • lindonghai
  • lindonghai
  • 2016年02月22日 11:01
  • 3039

编写Linux下的USB键盘驱动(附源码)

摘自:http://tech.techweb.com.cn/thread-383835-1-1.html   1.   指定USB键盘驱动所需的头文件: 1 t! q5 f( V4 ~9 V...
  • li_qcxy
  • li_qcxy
  • 2012年11月19日 12:46
  • 2247

Linux2.6.34下 USB驱动(U盘\USB鼠标、键盘)

由于Linux中对USB的驱动已经非常完善,这里只需要按照以下配置  就可以了,配置完后重新编译内核烧到开发板上 1、修改make menuconfig        System Type ...
  • xdw1985829
  • xdw1985829
  • 2011年08月13日 19:18
  • 5180

内核编译图文教程,usb键盘鼠标篇

CONFIG_INPUT_MOUSEDEV CONFIG_INPUT_EVDEV Hardware I/O ports什么都不用选 CONFIG_USB_HID To compile this...
  • sitelist
  • sitelist
  • 2015年02月10日 13:44
  • 1391

禁用USB口导致键盘鼠标不能使用

iamlaosong文 为安全起见,内网PC一律封USB口,技术人员操作时采用在BIOS中禁用USB设备,结果导致那些接USB键盘鼠标的PC都不能用了,连重回BIOS都不行,因为键盘不起作用了。 ...
  • iamlaosong
  • iamlaosong
  • 2017年06月01日 12:46
  • 932

关于USBHID协议以及鼠标键盘描述符的解释

一.HID设备识别 前面有提到关于SCSI协议的USB设备实现。现在来谈谈USBHID设备。HID全称Human Interface Device。HID协议里增加了HID描述符和报告描述符,以及特定...
  • jiujiujiuqiuqiuqiu
  • jiujiujiuqiuqiuqiu
  • 2015年08月04日 15:35
  • 3107

Linux USB 鼠标驱动程序详解 这个好

 USB 总线引出两个重要的链表! 一个 USB 总线引出两个重要的链表,一个为 USB 设备链表,一个为 USB 驱动链表。设备链表包含各种系统中的USB 设备以及这些设备的所有接口,驱...
  • u012075739
  • u012075739
  • 2014年04月17日 16:58
  • 2176

基于STM32处理器的USB HID模拟鼠标键盘(2) - 实现键盘鼠标功能

由于在报告描述符中使用了两个Report ID,分别是0x01和0x02,前者是键盘的报告描述符的报告ID,后者是鼠标的报告ID,HID的键盘和鼠标发送的数据格式参考文档: http://linfe...
  • tq384998430
  • tq384998430
  • 2016年11月28日 10:42
  • 3768
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:USB驱动程序之鼠标用做键盘
举报原因:
原因补充:

(最多只允许输入30个字)