Linux Input Device 介紹: APIs

news/2024/7/3 13:50:50

Linux Input Device 介紹: APIs

jollen 發表於 April 8, 2009 12:18 PM

Linux 的 Input Device 是重要的一個 subsystem,在進行實例介紹前,先大略了解一下相關的 API。

Linux Input Device

input.c是Linux的”input”驅動程式,主要支援鍵盤與滑鼠的輸入;input.c介面有趣的地方是採用了事件(event)的方式來處理輸入,以下是input.c介面重要的資料結構與函數:

* struct input_dev
* void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
* void input_register_device(struct input_dev *);
* void input_unregister_device(struct input_dev *);
* void input_register_handler(struct input_handler *);
* void input_unregister_handler(struct input_handler *);

Linux 的input機制可用來實作「虛擬鍵盤」或「虛擬滑鼠」,只要呼叫input_event()將輸入資料發佈給input handler即可。

struct input_dev是用來描述輸入事件的重要資料結構,其原型宣告如下:

struct input_dev {

void *private;

int number;
char *name;
unsigned short idbus;
unsigned short idvendor;
unsigned short idproduct;
unsigned short idversion;

unsigned long evbit[NBITS(EV_MAX)];
unsigned long keybit[NBITS(KEY_MAX)];
unsigned long relbit[NBITS(REL_MAX)];
unsigned long absbit[NBITS(ABS_MAX)];
unsigned long mscbit[NBITS(MSC_MAX)];
unsigned long ledbit[NBITS(LED_MAX)];
unsigned long sndbit[NBITS(SND_MAX)];
unsigned long ffbit[NBITS(FF_MAX)];
int ff_effects_max;

unsigned int keycodemax;
unsigned int keycodesize;
void *keycode;

unsigned int repeat_key;
struct timer_list timer;

int abs[ABS_MAX + 1];
int rep[REP_MAX + 1];

unsigned long key[NBITS(KEY_MAX)];
unsigned long led[NBITS(LED_MAX)];
unsigned long snd[NBITS(SND_MAX)];

int absmax[ABS_MAX + 1];
int absmin[ABS_MAX + 1];
int absfuzz[ABS_MAX + 1];
int absflat[ABS_MAX + 1];

int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev);
int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);
int (*erase_effect)(struct input_dev *dev, int effect_id);

struct input_handle *handle;
struct input_dev *next;
};

 

定義按鍵

我們可以設定struct input_dev裡的evbit欄位,來定義所要接受的輸入類型,目前共有8種輸入類型如下:

* EV_KEY:Keys and buttons(按鍵與按鈕)。
* EV_REL:Relative axes(相對座標)。
* EV_ABS:Absolute axes(絕對座標)。
* EV_MSC:Misc events(其它事件)。
* EV_LED:LEDs。
* EV_SND:Sounds(聲音輸入)。
* EV_REP:Autorepeat values(自動重覆數值)。
* EV_FF:Force feedback事件。

以下是一個範例,我們指定dev可接受EV_KEY事件:

dev.evbit[0] = BIT(EV_KEY);

evbit是一個陣列,每個元素可以索引一種輸入類型。每種輸入類型均可指定特定的輸入資料,例如:TAB鍵。指定方式是使用set_bit()或BIT巨集來設定每種輸入類型的陣列。以下是各輸入類型的欄位名稱:

* keybit[NBITS(KEY_MAX)]:Keys and buttons(按鍵與按鈕)。
* relbit[NBITS(REL_MAX)]:Relative axes(相對座標)。
* absbit[NBITS(ABS_MAX)]:Absolute axes(絕對座標)。
* mscbit[NBITS(MSC_MAX)]:Misc events(其它事件)。
* ledbit[NBITS(LED_MAX)]:LEDs。
* sndbit[NBITS(SND_MAX)]:Sounds(聲音輸入)。
* ffbit[NBITS(FF_MAX)]:Force feedback事件。

以下是使用set_bit()的範例:

* set_bit(KEY_UP, dev.keybit);
* set_bit(KEY_LEFT, dev.keybit);

或是使用BIT巨集也可以:

* keybit[0] = BIT(KEYUP) | BIT(KEY_LEFT);

input.h裡做位元運算的3個巨集如下:

* NBITS(x):計算要幾個陣列元素,才夠紀錄第x個位元。
* BIT(x):傳回單獨第x個位元為1時所代表的數值,例如:x=0時為0x1,x=1時為0x2,x=2時為0x4。
* LONG(x):第x個位元是屬於第幾個陣列元素(即索引值)。

我們先設定驅動程式能接受EV_KEY事件,然後指定EV_KEY事件的特定輸入值為KEY_UP與KEY_LEFT按鍵。不同事件的輸入資料定義,請參考input.h檔,例如以下是EV_KEY事件的按鍵1~按鍵9定義:

/*
* Keys and buttons
*/

#define KEY_1 2
#define KEY_2 3
#define KEY_3 4
#define KEY_4 5
#define KEY_5 6
#define KEY_6 7
#define KEY_7 8
#define KEY_8 9
#define KEY_9 10

設定好struct input_dev後再呼叫input_register_device()註冊至上層。當”input device”註冊至kernel後,當該input device被開啟時,便呼叫input device的open method;當input device關閉時,便呼叫input device的close method。
實作input device的open method時,若成功應傳回0,失敗的話則傳回任意的非零值;close method則不須傳回值。

Report 按鍵

使用者的按鍵往上層回報所使用的API如下:

* input_report_key(struct input_dev *dev, unsigned int code, int value);
* input_report_rel(struct input_dev *dev, unsigned int code, int value);
* input_report_abs(struct input_dev *dev, unsigned int code, int value);
* input_report_key與input_report_rel其實都是使用input_event()的巨集,input_event()的函數原型與參數說明如下:
* void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);

* @dev:指向input device的指標。
* @type:輸入類型(EV_KEY、EV_ABS等)。
* @code:輸入按鍵(例如EV_KEY的KEY_1)。
* @value:按鍵值。

Input Handler

任何的按鍵輸入,都應呼叫input_event()來將input event送到input.c,再由input.c分派事件(遶送)到每一個”input handler”。有註冊input handler的驅動程式,都能讀取輸入資料。

--jollen


http://www.niftyadmin.cn/n/3613032.html

相关文章

Android 如何破解兼容性困局

最新的消息表明,Android 手机的销售量超越 iPhone,虽然在整体市场占有率上,仍然不及竞争对手,但是却已经初现王者风范,一些文章也预测 Android 最终会稳坐智能手机第一把交椅。Android 的确是十分有潜力的,…

webpack学习路径(01.webpack的配置及使用)

对于webpack,我的理解是一种工具提供了友好的前端模块化开发的支持,可以解决代码压缩混淆,浏览器兼容性问题,以及提升性能等主要功能, 安装配置过程: 首先创建一个根目录(随便创建一个文件夹&…

C#中直接打印Report文件(rdlc)

Visual Studio自带的报表文件(rdlc,后面提到的报表,都指rdlc报表文件)虽然功能相对不是十分强大,但应付一般的报表要求也是绰绰有余了。关于rdlc报表的使用和设计方法,这里就不做讲解了,本文主要…

士农工商

中国古代,把商排在了最低等级,其实这是有道理的,商人是滋生腐败的源头,以盈利为目的的运营,只要没有很好的规范,即使牺牲了全世界,也会有人去做,这里的重点就是规范,不过…

vsCode自动修复规范报错的配置

1.先要安装Eslint 和Prettier - Code formatter插件 2.在settings-json中添加 (1) //Eslint插件的配置 “editor.codeActionsOnsave”:{ “source.fixAll”:true, }, (2) //prettier配置 “eslint.alwaysShowStatus”: true, &quo…

HDOJ 1181 HDU 1181 变形课 ACM 1181 IN HDU

MiYu原创, 转帖请注明 : 转载自 ______________白白の屋题目地址:http://acm.hdu.edu.cn/showproblem.php?pid1181 题目描述:代码变形课Time Limit: 2000/1000MS (Java/Others) Memory Limit: 131072/65536K (Java/Others)Total Submission(s): 2655Accepted Submission(s)…