linux系统弹出鼠标,driver: 浅析linux下鼠标驱动的实现

让我们来看看驱动源码:

============drivers/input/mouse/amimouse.c============

input_report_rel(amimouse_dev,REL_X,dx);

input_report_rel(amimouse_dev,REL_Y,dy);

input_report_key(amimouse_dev,BTN_LEFT,ciaa.pra&0x40);

input_report_key(amimouse_dev,BTN_MIDDLE,potgor&0x0100);

input_report_key(amimouse_dev,BTN_RIGHT,potgor&0x0400);

input_sync(amimouse_dev);//拷贝到open了的每个client的client->packets[16]环形缓冲区,每个应用程序在调用open时,mousedev_open都会调用kzalloc来申请一个独立的mousedev_client结构体,然后将该client挂接到mousedev->client_list链表,最后由mousedev_notify_readers向mousedev->client_list链表上挂接的每个client拷贝鼠标信息,最后wake_up唤醒read或poll.

============drivers/input/mousedev.c============

mousedev_read=>mousedev_packet=>如果dx,dy,dz同时都为0,说明鼠标停止了,那么client->ready=0;

mousedev_event(dev,EV_SYN,SYN_REPORT,0)=>mousedev_notify_readers=>如果dx,dy,dz有一个发生了移动或者鼠标按键上一次的按键不同,那么client->ready=1;拷贝数据到mousedev->client_list链表上挂接的每个client的环形缓冲区,最后调用wake_up_interruptible(&mousedev->wait);唤醒因为read或者poll操作而被pending住的应用程序,比如xWindows系统或者MiniGUI系统.

mousedev_write=>mousedev_generate_response=>向client->ps2[6]缓冲区填充数据,有效数据的个数为client->bufsiz,之后执行如下赋值client->buffer=client->bufsiz;让client->buffer等于client->ps2[6]数据缓冲区中有效数据的个数.

staticssize_t mousedev_read(structfile*file,char__user*buffer,

size_tcount,loff_t*ppos)

{

structmousedev_client*client=file->private_data;

structmousedev*mousedev=client->mousedev;

signedchardata[sizeof(client->ps2)];

intretval=0;

if(!client->ready&&!client->buffer&&mousedev->exist&&

(file->f_flags&O_NONBLOCK))

return-EAGAIN;

retval=wait_event_interruptible(mousedev->wait,

!mousedev->exist||client->ready||client->buffer);

//等待条件满足或者信号发生,client->ready和client->buffer都可以在调用wake_up_interruptible(&mousedev->wait)之后,因为为真,而继续往下执行.

if(retval)

returnretval;

if(!mousedev->exist)

return-ENODEV;

spin_lock_irq(&client->packet_lock);//禁止中断

if(!client->buffer&&client->ready){

mousedev_packet(client,client->ps2);

client->buffer=client->bufsiz;

}

if(count>client->buffer)

count=client->buffer;

memcpy(data,client->ps2+client->bufsiz-client->buffer,count);

//所以从这里可以看出,client->bufsiz为ps2[]数组有效数据索引的上限值,

//client->buffer为ps2[]数组索引的下限值

client->buffer-=count;//这样之后,再次执行read时,将会接续该buffer偏移位置继续读取.

spin_unlock_irq(&client->packet_lock);//打开中断

if(copy_to_user(buffer,data,count))//拷贝到用户空间

return-EFAULT;

returncount;

}

对于mouse和keyboard来说poll方法是同时处理多项输入的相当高效的信息处理方法,应用程序可以使用select或者poll甚至epoll来等待多个事件的发生,比如同时等待mouse和key的发生,然后来统一处理

staticunsignedintmousedev_poll(structfile*file,poll_table*wait)

{

structmousedev_client*client=file->private_data;

structmousedev*mousedev=client->mousedev;

poll_wait(file,&mousedev->wait,wait);

return((client->ready||client->buffer)?(POLLIN|POLLRDNORM):0)|

(mousedev->exist?0:(POLLHUP|POLLERR));

}

以上鼠标input事件和键盘的input时间基本一致,最后都是调用input_report_rel()、input_report_key()等,不同的是mousedev_event只有当调用input_sync才会发生向client的数据拷贝动作,而键盘的evdev_event的事件处理函数不管是什么信息都会执行如下遍历:

list_for_each_entry_rcu(client,&evdev->client_list,node)

evdev_pass_event(client,&event);

来完成向每个client数据buffer拷贝数据

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值