完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
对于输入类设备如键盘、鼠标、触摸屏之类的Linux驱动,内核提供input子系统,使得这类设备的处理变得非常便捷。总体上来讲,input子系统由三部分组成: 事件驱动<——>input核心<——>设备驱动。 其中事件驱动负责与用户程序打交道,诸如设备节点/dev之类的,都由他负责,我们在写驱动时就不用实现这个了;设备驱动负责与硬件设备打交道,这里的交互很简单,只需要读取相关硬件的数据,然后抛给input核心就可以了; 举个例子,以按键key为例,定义了设备设备号、按键值,配置管脚和中断方式,然后申请中断。在中断服务函数中,读取对应管脚值,用input_report函数发送给input核心,并用input_sync通知发送结束即可。另外,在模块初始化时,定义一个input_dev的结构体,这个input_dev是input子系统设备驱动端的核心数据结构,由于输入设备多种多样,就是通过这个结构体告诉核心你的输入设备类型。 其中的两个重要成员,这些宏具体在linux/input.h中定义。 一个是,evbit,代表事件类型的指示位,常用的如 EV_SYN 0x00 同步事件 EV_KEY 0x01 按键事件 EV_REL 0x02 相对坐标 EV_ABS 0x03 绝对坐标 EV_MSC 0x04 其它 EV_LED 0x11 LED EV_SND 0x12 声音 EV_REP 0x14 Repeat EV_FF 0x15 力反馈 EV_PWR 电源 EV_FF_STATUS 状态 另一个是keybit,代表键值代码 其他的还有 relbit 相对定位 ab***it 绝对定位 mscbit Mouse Systems Corporation,大意是一些厂商使用了5字节的串口鼠标协议,但微软使用了一种三字节协议,于是厂商造串口鼠标时,让设备有两种工作模式,一种是MSC模式,一种是微软的模式 ledbit 键盘指示灯事件的指示位 sndbit 键盘发出声音的指示位 ffbit force feedback,强制反馈设备 swbit switch,设备切换时产生的事件 下面就分别给出驱动代码和测试程序,以供参考。 驱动代码: #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // 定义key对应的GPIO #define GPF0 (S3C2410_GPF(0)) #define GPF1 (S3C2410_GPF(1)) #define GPF2 (S3C2410_GPF(2)) #define GPF4 (S3C2410_GPF(4)) #define KEY_NUM 4 struct input_dev *key_dev; static struct key_info { int irq_no; int pin; int pin_setting; int key_no; char *name; }key_info_tab[KEY_NUM]= { {IRQ_EINT0,GPF0,S3C2410_GPF0_EINT0,1,"key_1"}, {IRQ_EINT1,GPF1,S3C2410_GPF1_EINT1,2,"key_2"}, {IRQ_EINT2,GPF2,S3C2410_GPF2_EINT2,3,"key_3"}, {IRQ_EINT4,GPF4,S3C2410_GPF4_EINT4,4,"key_4"}, }; // 中断处理程序 static irqreturn_t hq_eint_key(int irq,void *dev_id) { if(irq==17) { input_report_key(key_dev,KEY_1,s3c2410_gpio_getpin(GPF1)); } else if(irq==48) { input_report_key(key_dev,KEY_4,s3c2410_gpio_getpin(GPF4)); } else if(irq==18) { input_report_key(key_dev,KEY_2,s3c2410_gpio_getpin(GPF2)); } else if(irq==16) { input_report_key(key_dev,KEY_0,s3c2410_gpio_getpin(GPF0)); } input_sync(key_dev);input_sync(key_dev); return IRQ_HANDLED; } // 打开设备 static int hq_key_open(struct input_dev *dev) { int i; int err=0; for(i=0;i err=request_irq(key_info_tab.irq_no,hq_eint_key,IRQF_SAMPLE_RANDOM,key_info_tab.name,(void *)(&key_info_tab)); if(err) { return -1; } return 0; } // 关闭设备 static void hq_key_release(struct input_dev *dev) { int i; for(i=0;i free_irq(key_info_tab.irq_no,(void *)(&key_info_tab)); } } //模块初始化 static int __init hq_key_init(void) { int err; key_dev=input_allocate_device(); if(!key_dev){ return -ENOMEM; } set_bit(EV_KEY,key_dev->evbit); set_bit(KEY_1,key_dev->keybit); set_bit(KEY_2,key_dev->keybit); set_bit(KEY_3,key_dev->keybit); set_bit(KEY_4,key_dev->keybit); key_dev->name="input_key_demo"; key_dev->dev.init_name="input_key"; key_dev->open=hq_key_open; key_dev->close=hq_key_release; err=input_register_device(key_dev); if(err){ return err; } return 0; } // 模块卸载 static void __exit hq_key_exit(void) { input_unregister_device(key_dev); } MODULE_AUTHOR("www.embedhq.org"); MODULE_LICENSE("Dual BSD/GPL"); module_init(hq_key_init); module_exit(hq_key_exit); 测试程序: #include #include #include #include #include int main(void ) { int fd; int key_value,i=0,count; struct input_event ev_key; fd=open("/dev/input/event0",0666); if(fd<0){ perror("open device"); exit(1); } while(1){ count=read(fd,&ev_key,sizeof(struct input_event)); for(i=0;i<(int)count/sizeof(struct input_event);i++) { if(EV_KEY==ev_key.type) { int num=ev_key.code%10-1; printf("type:%d,code:%d ,value:%dn key%d pressed!n",ev_key.type,ev_key.code,ev_key.value,num); } if(EV_SYN==ev_key.type) printf("syn eventn"); } } close(fd); return 0; } |
|
相关推荐
1个回答
|
|
学习学习
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
883 浏览 0 评论
AI模型部署边缘设备的奇妙之旅:如何在边缘端部署OpenCV
3025 浏览 0 评论
tms320280021 adc采样波形,为什么adc采样频率上来波形就不好了?
1409 浏览 0 评论
2039 浏览 0 评论
1574 浏览 0 评论
75142 浏览 21 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 17:35 , Processed in 0.674441 second(s), Total 70, Slave 54 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号