input type类型_设备树下的input子系统
更多文章請(qǐng)關(guān)注公眾號(hào) :麻瓜技術(shù)閑談
input 就是輸入的意思,因此 input 子系統(tǒng)就是管理輸入的子系統(tǒng),和 pinctrl 和 gpio 子系統(tǒng)一樣,都是 Linux 內(nèi)核針對(duì)某一類設(shè)備而創(chuàng)建的框架。比如按鍵輸入、鍵盤、鼠標(biāo)、觸摸屏等等這些都屬于輸入設(shè)備,不同的輸入設(shè)備所代表的含義不同,按鍵和鍵盤就是代表按鍵信息,鼠標(biāo)和觸摸屏代表坐標(biāo)信息,因此在應(yīng)用層的處理就不同,對(duì)于驅(qū)動(dòng)編寫(xiě)者而言不需要去關(guān)心應(yīng)用層的事情,我們只需要按照要求上報(bào)這些輸入事件即可。為此 input子系統(tǒng)分為 input 驅(qū)動(dòng)層、input 核心層、input 事件處理層,最終給用戶空間提供可訪問(wèn)的設(shè)備節(jié)點(diǎn),input 子系統(tǒng)框架如圖 58.1.1.1 所示:
圖 58.1.1.1 中左邊就是最底層的具體設(shè)備,比如按鍵、USB 鍵盤/鼠標(biāo)等,中間部分屬于Linux 內(nèi)核空間,分為驅(qū)動(dòng)層、核心層和事件層,最右邊的就是用戶空間,所有的輸入設(shè)備以文件的形式供用戶應(yīng)用程序使用。可以看出 input 子系統(tǒng)用到了我們前面講解的驅(qū)動(dòng)分層模型,我們編寫(xiě)驅(qū)動(dòng)程序的時(shí)候只需要關(guān)注中間的驅(qū)動(dòng)層、核心層和事件層,這三個(gè)層的分工如下: 驅(qū)動(dòng)層:輸入設(shè)備的具體驅(qū)動(dòng)程序,比如按鍵驅(qū)動(dòng)程序,向內(nèi)核層報(bào)告輸入內(nèi)容。 核心層:承上啟下,為驅(qū)動(dòng)層提供輸入設(shè)備注冊(cè)和操作接口。通知事件層對(duì)輸入事件進(jìn)行處理。 事件層:主要和用戶空間進(jìn)行交互。
input 驅(qū)動(dòng)編寫(xiě)流程
1767 struct class input_class = { 1768 .name = "input", 1769 .devnode = input_devnode, 1770 }; ...... 2414 static int __init input_init(void) 2415 { 2416 int err; 2418 err = class_register(&input_class); 2419 if (err) { 2420 pr_err("unable to register input_dev classn"); 2421 return err; 2422 } 2423 2424 err = input_proc_init(); 2425 if (err) 2426 goto fail1; 2427 2428 err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0), 2429 INPUT_MAX_CHAR_DEVICES, "input"); 2430 if (err) { 2431 pr_err("unable to register char major %d",INPUT_MAJOR); 2432 goto fail2; 2433 } 2434 2435 return 0; 2436 2437 fail2: input_proc_exit(); 2438 fail1: class_unregister(&input_class); 2439 return err; 2440 }1、注冊(cè) input_dev 在使用 input 子系統(tǒng)的時(shí)候我們只需要注冊(cè)一個(gè) input 設(shè)備即可,input_dev 結(jié)構(gòu)體表示 input 設(shè)備,此結(jié)構(gòu)體定義在 include/linux/input.h 文件中,定義如下(有省略):
示例代碼 58.1.2.2 input_dev 結(jié)構(gòu)體 121 struct input_dev { 122 const char *name; 123 const char *phys; 124 const char *uniq; 125 struct input_id id; 126 127 unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)]; 128 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)]; /* 相對(duì)坐標(biāo)的位圖 */ 132 unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; /* 絕對(duì)坐標(biāo)的位圖 */ 133 unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)]; /* 雜項(xiàng)事件的位圖 */ 134 unsigned long ledbit[BITS_TO_LONGS(LED_CNT)]; /*LED 相關(guān)的位圖 */ 135 unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];/* sound 有關(guān)的位圖 */ 136 unsigned long ffbit[BITS_TO_LONGS(FF_CNT)]; /* 壓力反饋的位圖 */ 137 unsigned long swbit[BITS_TO_LONGS(SW_CNT)]; /*開(kāi)關(guān)狀態(tài)的位圖 */ ...... 189 bool devres_managed; 190 };第 129 行,evbit 表示輸入事件類型,可選的事件類型定義在 include/uapi/linux/input.h 文件 中,事件類型如下:
示例代碼 58.1.2.3 事件類型 #define EV_SYN 0x00 /* 同步事件 */ #define EV_KEY 0x01 /* 按鍵事件 */ #define EV_REL 0x02 /* 相對(duì)坐標(biāo)事件 */ #define EV_ABS 0x03 /* 絕對(duì)坐標(biāo)事件 */ #define EV_MSC 0x04 /* 雜項(xiàng)(其他)事件 */ #define EV_SW 0x05 /* 開(kāi)關(guān)事件 */ #define EV_LED 0x11 /* LED */ #define EV_SND 0x12 /* sound(聲音) */ #define EV_REP 0x14 /* 重復(fù)事件 */ #define EV_FF 0x15 /* 壓力事件 */ #define EV_PWR 0x16 /* 電源事件 */ #define EV_FF_STATUS 0x17 /* 壓力狀態(tài)事件 */比如本章我們要使用到按鍵,那么就需要注冊(cè) EV_KEY 事件,如果要使用連按功能的話還需要注冊(cè) EV_REP 事件。繼續(xù)回到示例代碼 58.1.2.2 中,第 129 行~137 行的 evbit、keybit、relbit 等等都是存放不同事件對(duì)應(yīng)的值。比如我們本章要使用按鍵事件,因此要用到 keybit,keybit 就是按鍵事件使用的位圖,Linux 內(nèi)核定義了很多按鍵值,這些按鍵值定義在include/uapi/linux/input.h 文件中,按鍵值如下: 示例代碼 58.1.2.4 按鍵值
215 #define KEY_RESERVED 0 216 #define KEY_ESC 1 217 #define KEY_1 2 218 #define KEY_2 3 219 #define KEY_3 4 220 #define KEY_4 5 221 #define KEY_5 6 222 #define KEY_6 7 223 #define KEY_7 8 224 #define KEY_8 9 225 #define KEY_9 10 226 #define KEY_0 11 ...... 794 #define BTN_TRIGGER_HAPPY39 0x2e6 795 #define BTN_TRIGGER_HAPPY40 0x2e72、上報(bào)輸入事件 當(dāng)我們向 Linux 內(nèi)核注冊(cè)好 input_dev 以后還不能高枕無(wú)憂的使用 input 設(shè)備,input 設(shè)備都是具有輸入功能的,但是具體是什么樣的輸入值 Linux 內(nèi)核是不知道的,我們需要獲取到具體的輸入值,或者說(shuō)是輸入事件,然后將輸入事件上報(bào)給 Linux 內(nèi)核。比如按鍵,我們需要在按鍵中斷處理函數(shù),或者消抖定時(shí)器中斷函數(shù)中將按鍵值上報(bào)給 Linux 內(nèi)核,這樣 Linux 內(nèi)核才能獲取到正確的輸入值。不同的事件,其上報(bào)事件的 API 函數(shù)不同,我們依次來(lái)看一下一些常用的事件上報(bào) API 函數(shù)。 首先是 input_event 函數(shù),此函數(shù)用于上報(bào)指定的事件以及對(duì)應(yīng)的值,函數(shù)原型如下:
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)函數(shù)參數(shù)和返回值含義如下: dev:需要上報(bào)的 input_dev。 type: 上報(bào)的事件類型,比如 EV_KEY。 code:事件碼,也就是我們注冊(cè)的按鍵值,比如 KEY_0、KEY_1 等等。 value:事件值,比如 1 表示按鍵按下,0 表示按鍵松開(kāi)3、代碼示例
和按鍵中斷程序類似設(shè)備樹(shù)下的中斷,唯一不同的是在keyio_init函數(shù)里申請(qǐng)完中斷后要申請(qǐng)輸入事件、注冊(cè)輸入設(shè)備
/* 申請(qǐng) input_dev */keyinputdev.inputdev = input_allocate_device();keyinputdev.inputdev->name = KEYINPUT_NAME;keyinputdev.inputdev->evbit[0] = BIT_MASK(EV_KEY) |BIT_MASK(EV_REP);input_set_capability(keyinputdev.inputdev, EV_KEY, KEY_0);/* 注冊(cè)輸入設(shè)備 */ret = input_register_device(keyinputdev.inputdev);if (ret) {printk("register input device failed!rn");return ret;}timer_function定時(shí)器功能函數(shù)里改為上報(bào)按鍵事件
if(value == 0){ /* 按下按鍵 *//* 上報(bào)按鍵值 *///input_event(dev->inputdev, EV_KEY, keydesc->value, 1);input_report_key(dev->inputdev, keydesc->value, 1);/*1,按下*/input_sync(dev->inputdev);} else { /* 按鍵松開(kāi) *///input_event(dev->inputdev, EV_KEY, keydesc->value, 0);input_report_key(dev->inputdev, keydesc->value, 0);input_sync(dev->inputdev);} 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的input type类型_设备树下的input子系统的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 用[bx+idata]的方式进行数组的处
- 下一篇: java信息管理系统总结_java实现科