您的位置 首页 FPGA

需求了解Linux input子系统编程、剖析与模板的原理

需要了解Linux input子系统编程、分析与模板的原理-输入核心层主要提供一些API供设备驱动层调用,通过这些API设备驱动层上报的数据就可以传递到事件处理层,

输入设备都有共性:中止驱动+字符IO,根据分层的思维,Linux内核将这些设备的公有的部分提取出来,根据cdev供给接口,规划了输入子系统,一切运用输入子系统构建的设备都运用主设备号13,一同输入子系统也支撑主动创立设备文件,这些文件选用堵塞的IO读写方法,被创立在”/dev/input/”下。如下图所示。内核中的输入子系统自底向上分为设备驱动层,输入中心层,事情处理层。因为每种输入的设备上报的事情都各有不同,所以为了应用层能够很好辨认上报的事情,内核中也为应用层封装了规范的接口来描绘一个事情,这些接口在”/include/upai/linux/input”中。

设备驱动层是详细硬件相关的完结,也是驱动开发中首要完结的部分,

输入中心层首要供给一些API供设备驱动层调用,经过这些API设备驱动层上报的数据就能够传递到事情处理层,

事情处理层担任创立设备文件以及将上报的事情传递到用户空间,

input的运用

input目标描绘了一个输入设备,包含它可能上报的事情,这些事情运用位图来描绘,内核供给的相应的东西协助咱们构建一个input目标,咱们能够参阅内核文档”Documentation/input/input-programming.txt”,里边关于input子系统的运用有详细的描绘。

//input设备目标121 struct input_dev {122 const char *name;129 unsigned long evbit[BITS_TO_LONGS(EV_CNT)];130 unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];131 unsigned long relbit[BITS_TO_LONGS(REL_CNT)];132 unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];133 unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];134 unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];135 unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];136 unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];137 unsigned long swbit[BITS_TO_LONGS(SW_CNT)];155 162 unsigned long key[BITS_TO_LONGS(KEY_CNT)];163 unsigned long led[BITS_TO_LONGS(LED_CNT)];164 unsigned long snd[BITS_TO_LONGS(SND_CNT)];165 unsigned long sw[BITS_TO_LONGS(SW_CNT)];166 172 struct input_handle __rcu *grab;179 180 struct device dev;181 182 struct list_head h_list;183 struct list_head node;190 };

struct input_dev
–122–> 这个name不是设备名,input子系统的设备名在子系统源码中指定的,不是这。
–129–> 设备支撑的输入事情位图,EV_KEY,EV_REL, etc
–130–> 关于按键事情,设备支撑的输入子事情位图
–132–> 关于相对坐标事情,设备支撑的相对坐标子事情位图
–133–> 关于肯定坐标事情,设备支撑的肯定坐标子事情位图
–134–> 稠浊设备的支撑的子事情位图
–180–>表明这是一个device。
–182–>h_list是用来链接相关handle的链表
–183–>node用来链接其他input_dev的链表

分配/开释

//drivers/input/input.c//创立一个input目标struct input_dev *input_allocate_device(void);//开释一个input目标void input_free_device(struct input_dev *dev);

初始化

初始化一个input目标是运用input子系统编写驱动的首要作业,内核在头文件”include/uapi/linux/input.h”中规则了一些常见输入设备的常见的输入事情,这些宏和数组便是咱们初始化input目标的东西。这些宏一同用在用户空间的事情解析和驱动的事情注册,能够看作是驱动和用户空间的通信协议,所以了解其间的含义十分重要。在input子系统中,每一个事情的产生都运用事情(type)->子事情(code)->值(value)三级来描绘,比方,按键事情->按键F1子事情->按键F1子事情触发的值是高电平1。留意,事情和子事情和值是相得益彰的,只要注册了事情EV_KEY,才能够注册子事情BTN_0,也只要这样做才是有含义的。
下面便是内核约好的事情类型,对应应用层的事情目标的type域

下面这些是按键子事情的类型,能够看到对PC键值的界说

除了对常用的事情进行描绘,内核相同供给了东西将这些事情正确的填充到input目标中描绘事情的位图中。

//第一种//这种方法十分适宜一同注册多个事情button_dev->evbit[0] = BIT_MASK(EV_KEY); button_dev->keybit[BIT_WORD(BTN_0|BTN_1)] = BIT_MASK(BTN_0|BTN_1);

//第二种//一般用于只注册一个事情set_bit(EV_KEY,button_dev.evbit);set_bit(BTN_0,button_dev.keybit);

注册/刊出

初始化好了一个input目标,接下来就需求将其注册到内核

//注册input目标到内核int input_register_device(struct input_dev *dev);//从内核刊出一个input目标void input_unregister_device(struct input_dev *dev);

驱动层陈述事情

在适宜的机遇(因为输入终究是中止表明的,所以一般在驱动的中止处理函数中)驱动能够将注册好的事情上报,且能够一同上报多个事情,下面是内核供给的API

//上报指定的事情+子事情+值void input_event(struct input_dev *dev,unsigned int type,unsigned int code,int value);//上报键值void input_report_key(struct input_dev *dev,unsigned int code,int value);//上报肯定坐标void input_report_abs(struct input_dev *dev,unsigned int code,int value);//陈述同步事情void input_report_rel(struct input_dev *dev,unsigned int code,int value);//同步一切的上报void input_sync(struct input_dev *dev);

上报事情有2点需求留意:

report函数们并不会真的上报,仅仅预备上报,sync才会真的将刚刚report的事情真的上报搭input中心

input中心会进行判决再上报的事情处理层,所以关于按键事情,一定要先报1再报0(或许反过来),不能只report 1或0, 这样中心会认为是一个事情被误触发了屡次而只上报一次,尽管咱们真的按下了屡次。

应用层解析

事情处理层终究会将驱动sync一次时一切report的事情组织成一个struct input_value[]的形式上签到应用层,在应用层从相应的设备文件中获取上报的事情的时分,需求留意:

收到数组元素的数量会比底层多一个空元素,类似于写of_device_id[]时终究的空元素,这点应用层在解析的时分需求留意。

事情处理层并不会缓存收到的事情,如果有新的事情到来,即便旧的事情没有被读取,也会被掩盖,所以应用程序需求及时读取。

前文现已说过,”include/uapi/linux/input.h”中的宏是应用层和驱动层共用的通信协议,所以应用层在解析收到的struct input_value目标的时分,只需求”include “即可运用其间的宏。

/* * The event structure itself */struct input_event { struct TImeval TIme; __u16 type; __u16 code; __s32 value;};

input剖析

上文现已说过,input子系统运用三层结构来完结驱动事情到应用层的传递。详细的,这三个层次每一个层次都由一条结构体链表组成,在设备驱动层,中心结构体是input_dev;在input中心层,是input_handle;在事情处理层,是input_handler。内核经过链表和指针将三者结合到一同,终究完结了input_dev和input_handler的多对多的映射联系,这种联系可用下图简略描绘。

模板

下面的这个模板首要运用input子系统上报按键事情,然后在应用层读取。

input按键设备驱动

/{
           key@26{
                      compaTIble = “xj4412,key”;
                      interrupt-parent = <&gpx1>;
                      interrupts = <2 2>;
           };
};

static struct input_dev *button_dev;static int button_irq;static int irqflags;static irqreturn_t button_interrupt(int irq, void *dummy){ input_report_key(button_dev, BTN_0, 0); input_report_key(button_dev, BTN_0, 1); input_sync(button_dev); return IRQ_HANDLED;} static int button_init(void){ request_irq(button_irq, button_interrupt,irqflags, “button”, NULL)) ; button_dev = input_allocate_device(); button_dev->name = “button”; button_dev->evbit[0] = BIT_MASK(EV_KEY); button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); input_register_device(button_dev); return 0;}static int button_exit(void){ input_free_device(button_dev); free_irq(button_irq, button_interrupt); return 0; }static int key_probe(struct platform_device *pdev){ struct resource *irq_res; irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if(irq_res){ button_irq = irq_res->start; irqflags = irq_res->flags & IRQF_TRIGGER_MASK; }else{ return -EINVAL; } return button_init();}staTIc int key_remove(struct platform_device *dev){ return button_exit();}struct of_device_id of_tbl[] = { {.compatible = “xj4412,key”,}, {},};MODULE_DEVICE_TABLE(of, of_tbl);struct platform_driver key_drv = { .probe = key_probe, .remove = key_remove, .driver.name = “keydrv”, .driver.of_match_table = of_tbl,};module_platform_driver_register(key_drv);MODULE_LICENSE(“GPL”);

应用层获取键值

#include struct input_event { struct timeval time; unsigned short type; unsigned short code; int value;};int main(int argc, char * const argv[]){ int fd = 0; struct input_event event[3] = {0}; //3!!!,驱动上传了2个事情,第三个用来装空元素 int ret = 0; fd = open(argv[1],O_RDONLY); while(1){ ret = read(fd,&event,sizeof(event)); printf(“ret:%d,val0:%d,val1:%d,val12:%d\n”,ret,event[0].value,event[1].value,event[2].value); //2!!!,终究一个是空 sleep(1); } return 0;}
 

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/fpga/99871.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部