linux usb 输入到文件,Linux下USB 输入子系统的学习(以鼠标驱动为例)

Linux下USB 输入子系统的学习(以鼠标驱动为例)usb 1-1.2: new low speed USB device using musb_hdrc and address 3

usb 1-1.2: Product: USB Optical Mouse

input: USB HID v1.11 Mouse [USB Optical Mouse] on usb-musb_hdrc-1.2

//drivers/usb/input/hid-core.c

>hid_probe()

{

printk(": USB HID v%x.%02x %s [%s] on %s\n",

hid->version >> 8, hid->version & 0xff, c, hid->name, path);

}

//drivers/input/mouse/sermouse.c---->sermouse_connect()

printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys);

/proc/bus/input # cat devices

I: Bus=0003 Vendor=0461 Product=4d15 Version=0200

N: Name="USB Optical Mouse"

P: Phys=usb-musb_hdrc-1.1/input0

H: Handlers=mouse1

B: EV=f

B: KEY=70000 0 0 0 0 0 0 0 0

B: REL=103

B: ABS=100 0

驱动层负责和底层的硬件设备打交道,

将底层硬件对用户输入的响应转换为标准的输入事件以后再向上发送给Input Core。

驱动层通过调用Input_register_device函数和

Input_unregister_device函数来向输入子系统中注册和注销输入设备---

/drivers/us/input/usbmouse.c

usb_mouse_probe->

input_register_device(&mouse->dev)>

usb_mouse_disconnect>

input_unregister_device(&mouse->dev);

usb_mouse_irq()>

input_report_key>

input_event>//drivers/input/input.c

input_sync>//每次终端数据发送完成后都会跟随发送一个同步事件,便与鼠标、按键数据及时更新到响应的全局变量

//输入子系统层的操作--drivers/input/input.c

open /dev/input/mouse0>

mousedev_open()> //drivers/input/mousedev.c /*打开鼠标类输入设备*/

input_open_device()>

input_handle->dev->open>

//驱动层物理设备的操作---drivers/usb/input/usbmouse.c

usb_mouse_open()

注册Input Handler

驱动层只是把输入设备注册到输入子系统中,在驱动层的代码中本身并不创建设备结点。

应用程序用来与设备打交道的设备结点的创建由Event Handler层调用Input core中的函数来实现。

而在创建具体的设备节点之前,Event Handler层需要先注册一类设备的输入事件处理函数及相关接口

static int __init mousedev_init(void){//注册输入事件处理、连接、断开、设备(文件)操作函数input_register_handler(&mousedev_handler);//创建输入设备节点devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");}

static struct input_handler mousedev_handler = {

.event =    mousedev_event,//REL(相对坐标)、按键、ABS(绝对坐标)、SYNC等事件处理

.connect =    mousedev_connect,

.disconnect =    mousedev_disconnect,

.fops =        &mousedev_fops,//鼠标打开、poll、读写等操作

.minor =    MOUSEDEV_MINOR_BASE,

.name =        "mousedev",

.id_table =    mousedev_ids,

};

下面集中分析mousedev_event事件处理:分析数据事件结构体linux/input.h中有定义,这个文件还定义了标准按键的编码等struct input_event {struct timeval time;  //按键时间__u16 type; //类型,在下面有定义__u16 code; //要模拟成什么按键__s32 value;//是按下还是释放};

code:

件的代码.如果事件的类型代码是EV_KEY,该代码code为设备键盘代码.代码植0~127为键盘上的按键代码,0x110~0x116

为鼠标上按键代码,其中0x110(BTN_ LEFT)为鼠标左键,0x111(BTN_RIGHT)为鼠标右键,0x112(BTN_

MIDDLE)为鼠标中键.其它代码含义请参看include/linux/input.h文件. 如果事件的类型代码是EV_REL,code值表示轨迹的类型.如指示鼠标的X轴方向REL_X(代码为0x00),指示鼠标的Y轴方向REL_Y(代码为0x01),指示鼠标中轮子方向REL_WHEEL(代码为0x08).

type:

EV_SYN,同步事件

EV_KEY,键盘

EV_REL,相对坐标

EV_ABS,绝对坐标

value:

事件的值.如果事件的类型代码是EV_KEY,当按键按下时值为1,松开时值为0;如果事件的类型代码是EV_ REL,value的正数值和负数值分别代表两个不同方向的值.

mousedev_event()

{

//以相对坐标移动事件为例:case EV_REL:

mousedev_rel_event(mousedev, code, value);

break;

}

mousedev_rel_event(struct mousedev *mousedev, unsigned int code, int value)

{

//code区分X Y 轴、滚轮移动

//value代表正负移动量

switch (code) {

case REL_X:    mousedev->packet.dx += value; break;

case REL_Y:    mousedev->packet.dy -= value; break;

case REL_WHEEL:    mousedev->packet.dz -= value; break;

}

}

分析mousedev中的packet:struct mousedev_hw_data {int dx, dy, dz;int x, y;int abs_event;unsigned long buttons;};

struct mousedev_hw_data packet;

更新mousedev中的packet数据,然后触摸屏输入、鼠标输入分别使用touch、EV_SYN方式调用mousedev_notify_readers()将其更新到mousedev_list中,这就是为什么每次按键、移动事件都跟随一个同步事件的原因

//屏幕分辨率的设置:

#ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X

#define CONFIG_INPUT_MOUSEDEV_SCREEN_X    1024

#endif

#ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_Y

#define CONFIG_INPUT_MOUSEDEV_SCREEN_Y    768

#endif

其他参考链接:http://blog.csdn.net/wind20/archive/2008/04/25/2327510.aspx

http://blog.csdn.net/chenzhixin/archive/2008/03/12/2173530.aspx

测试应用程序代码:

#include #include #include #include #include #define USB_MOUSE   ("/dev/input/mouse0")

struct pollfd  mypoll;

int main(int argc,  char *argv[])

{

int mouseFd;

struct input_event buff;

if ((mouseFd = open(USB_MOUSE, O_RDONLY)) == -1) {

printf("Failed to open /dev/input/mouse0\n");

return -1;

}

mypoll.fd =  mouseFd;

mypoll.events = POLLIN;

while(1)

{

if(poll( &mypoll, 1, 10) > 0)

{

unsigned char data[4] ={0};

/*

data的数据格式:

data0:00xx 1xxx   ----低三位是按键值---左中右分别为01 02 04, 第4/5位分别代表x、y移动方向,右上方x/y>0,左下方xy<0

data1:取值范围-127~127,代表x轴移动偏移量

data2:取值范围-127~127,代表y轴移动偏移量

*/

usleep(50000);

read(mouseFd, data, 4); //MOUSEDEV_EMUL_PS2方式每次采样数据为3个字节,多读不会出错,只返回成功读取的数据数

printf("mouse data=%02x%02x%02x%02x\n", data[0],data[1], data[2], data[3]);

}

}

close(mouseFd);

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值