日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux 输入子系统原理理解(原创)

發(fā)布時(shí)間:2023/12/10 linux 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux 输入子系统原理理解(原创) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

linux????輸入子系統(tǒng)原理理解(原創(chuàng))

以前學(xué)了單獨(dú)的按鍵設(shè)備驅(qū)動(dòng)以及鼠標(biāo)驅(qū)動(dòng),實(shí)際上,在linux中實(shí)現(xiàn)這些設(shè)備驅(qū)動(dòng),有一種更為推薦的方法,就是input輸入子系統(tǒng)。平常我們的按鍵,觸摸屏,鼠標(biāo)等輸入型設(shè)備都可以利用input接口來簡化驅(qū)動(dòng)程序并實(shí)現(xiàn)設(shè)備驅(qū)動(dòng)。

輸入子系統(tǒng)原理

linux輸入子系統(tǒng)的體系結(jié)構(gòu)可以分為三個(gè)層面,分別為:驅(qū)動(dòng)層、輸入核心層、事件處理層,三個(gè)有點(diǎn)類似PHP的MVC模式,意思就是每個(gè)層次只是負(fù)責(zé)單獨(dú)的一個(gè)功能,無需參與其他的功能,有點(diǎn)類似函數(shù)的封裝,好了,廢話不多說,三個(gè)層面具體的功能如下:

(1)驅(qū)動(dòng)層:將底層的硬件輸入轉(zhuǎn)化為統(tǒng)一的事件類型,向輸入核心(input?core)匯報(bào)0,簡單來說,驅(qū)動(dòng)層就是負(fù)責(zé)匯報(bào)事情。

(2)輸入核心層:為驅(qū)動(dòng)層提供輸入設(shè)備的注冊和操作接口。

比如:?1.?用input_register_device函數(shù)對設(shè)備進(jìn)行注冊;

2.?通知事件處理層對事件進(jìn)行處理;

3.?在/proc下產(chǎn)生相應(yīng)的設(shè)備信息。

(3)事件處理層:主要作用就是與用戶空間進(jìn)行交互。包含提供驅(qū)動(dòng)程序的fops接口,在/dev下生成相應(yīng)的設(shè)備文件節(jié)點(diǎn)nod等功能。

?

總的來說,歸納一下上面的一大段內(nèi)容:

一個(gè)事件,如鼠標(biāo)移動(dòng),鍵盤按下事件,首先通過?
?驅(qū)動(dòng)層Driver -->?輸入核心層 InputCore-->事件處理層Event handler-->用戶空間userspace的順序來完成事件的響應(yīng)。

?

設(shè)備描述

Input設(shè)備用input_dev結(jié)構(gòu)體來描述。

在input子系統(tǒng)實(shí)現(xiàn)設(shè)備驅(qū)動(dòng)程序中,驅(qū)動(dòng)的核心工作是向系統(tǒng)報(bào)告按鍵,觸摸屏,鼠標(biāo)等事件,無須關(guān)心文件操作接口,因?yàn)檫@些接口是有事件處理層Event handler來實(shí)現(xiàn)的。

?

好了,原理講的差不多了,接下來講一下驅(qū)動(dòng)的實(shí)現(xiàn)

驅(qū)動(dòng)實(shí)現(xiàn)

1.事件支持

首先一個(gè)設(shè)備驅(qū)動(dòng),我們應(yīng)該通過set_bit()函數(shù)來告訴輸入子系統(tǒng)它支持哪些事件,哪些按鍵,例如:

Set_bit(EV_KEY,button_dev.evbit);????????????告訴輸入子系統(tǒng)支持按鍵的時(shí)間

Struct?input_dev中有兩個(gè)成員:

??????Evbit:?事件類型

??????Keybit:?按鍵類型

?

事件類型:

??????EV_RST????????????reset????????????? ? ? ?EV_KEY????????????按鍵

??????EV_REL????????????相對坐標(biāo)? ? ?EV_ABS? ? ??絕對坐標(biāo)

??????EV_MSC????????????其他??????????????????EV_LEC????????????LED

??????EV_SND????????????聲音????????????? ? ? ?EV_REP????????????repeat

??????EV_FF????????????力反饋

但事件類型為EV_KEY時(shí),還需指明按鍵類型:

??????BTN_LEFT:??????鼠標(biāo)左鍵????????????BTN_0:數(shù)字0鍵

??????BTN_RIGHT:??????鼠標(biāo)右鍵????????????BTN_1:數(shù)字1鍵

??????BTN_MIDDLE:??????鼠標(biāo)中鍵

?

2.報(bào)告事件

當(dāng)事件真的發(fā)生的時(shí)間,我們的驅(qū)動(dòng)層應(yīng)該向輸入核心層Input Core來報(bào)告EV_KEY,EV_REL,EV_ABS等事件,報(bào)告函數(shù)分別為:

Void input_report_key(struct input_dev *dev,unsigned int code, int value)

Void input_report_rel(struct input_dev *dev,unsigned int code, int value)

Void input_report_abs(struct input_dev *dev,unsigned int code, int value)

?

Code:?事件的代碼:如果事件類型是EV_KEY, 則該代碼則為設(shè)備的鍵盤代碼,例如鍵盤上按鍵代碼值為0~127?,鼠標(biāo)鍵代碼值為0x110 ~ 0x116?具體請參考include/linux/input.h文件

Value:事件的值。如果事件類型是EV_KEY,?按鍵按下時(shí)值為1,松開即為0

?

3.報(bào)告結(jié)束

Input_sync()用于告訴輸入核心層input core:此次報(bào)告已經(jīng)結(jié)束

?

例如,在觸摸屏設(shè)備驅(qū)動(dòng)中,一次點(diǎn)擊的整個(gè)報(bào)告事件過程如下:

Input_report_abs(input_dev, ABS_X, x);??????//報(bào)告X坐標(biāo)

Input_report_abs(input_dev, ABS_Y, y);??????//報(bào)告Y坐標(biāo)

Input_report_abs(input_dev, ABS_PRESSURE, 1);??????//報(bào)告事件類型為按下,且value值為1

Input_sync(input_dev);??????//報(bào)告完畢,同步事件

?

?

一個(gè)按鍵驅(qū)動(dòng)程序的局部函數(shù):

//在按鍵中斷中報(bào)告事件

Static?void buton_interrupt(int irq, void *dummy, struct pt_regs *fp)

{

??????//注意,此處所有的按鍵都要報(bào)告,無論是0號按鍵還是1號按鍵

??????Input_report_key(&button_dev, BTN_0, inb(BUTTON_PORT0));

Input_report_key(&button_dev, BTN_1, inb(BUTTON_PORT1));

??????Input_sync(&button_dev);??????//報(bào)告完畢,同步事件

??????//此時(shí),輸入核心層和事件處理層就會將收集的事件類型形成相應(yīng)的數(shù)據(jù),放到file operation?中和?buffer中,以用用戶空間讀取

}

?

//驅(qū)動(dòng)初始化函數(shù)

Static?int __init??button_init(void){

????????????//申請中斷,因?yàn)榘存I事件報(bào)告是在中斷中執(zhí)行

????????????If( request_irq(BUTTON_IRQ,button_interrupt, 0, “button”, NULL) )

????????????????? ????Return –EBUSY;

??????????? ?Set_bit(EV_KEY, button_dev.evbit);??//告訴輸入子系統(tǒng)支持EV_key事件
?????????????Set_bit(BTN_0, button_dev.keybit);? //告訴輸入子系統(tǒng)支持0號鍵
?????????????Set_bit(BTN_1, button_dev.keybit);? //告訴輸入子系統(tǒng)支持1號鍵

?????????????Input_register_device(&button_dev);????? //注冊input設(shè)備

}

?

?

應(yīng)用程序?qū)崿F(xiàn)

??????當(dāng)相應(yīng)的時(shí)間響應(yīng),用戶空間讀取事件是,所讀取到的是?input_event?結(jié)構(gòu)的信息,不再是一個(gè)單純的數(shù)字,

在input_event?結(jié)構(gòu)中,已經(jīng)包含?按鍵類型type,?按鍵鍵值code等信息。

用戶需要對input_event?進(jìn)行相應(yīng)的解析,獲得相應(yīng)的信息。
?

Struct???input_event??ev_key;??//聲明結(jié)構(gòu)體?

Button_fd = open(“/dev/event0”,O_RDWR);?

While(1){

??????Count = read(button_fd, &ev_key, sizeof( struct input_event ));

??????for( i=0; i<(int)count/sizeof( struct input_event ); i++ ){

????????????if(EV_KEY??==??ev_key.type)????????????//確定類型是否相同

????????????? ? ? ? ? ?printf(“type:%d, code:%d, value:%d \n”,ev_key.type,ev_key.code,ev_key.value);

????????????If(?EV_SYN == ev_key.type?)??

????????????? ? ? ? ? ?Printf(“syn event \n”);

}

}

Close(button_fd);

?

我們都在路上,有時(shí)苦有時(shí)甜,為此我送給自己以及相同愛好者們兩個(gè)字:堅(jiān)持 。
? ? ? ?一起加油!!!
? ? ? ?2015年1月16日?

轉(zhuǎn)載于:https://www.cnblogs.com/lihaiyan/p/4274456.html

總結(jié)

以上是生活随笔為你收集整理的Linux 输入子系统原理理解(原创)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。