加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

Linux input子系統(tǒng)(一)初識(shí)

05/03 08:50
4058
閱讀需 14 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

哈嘍,大家好,我是LittleG。

如果將 Linux 比作一個(gè)人,那么Linux input子系統(tǒng)就好比我們的眼睛,手,腳,以及到大腦的神經(jīng)網(wǎng)絡(luò),可以通過(guò)它們獲取和傳遞信息,感知外圍世界?;氐?Linux/Android 世界,像手機(jī)設(shè)備中,按鍵、觸摸屏、各種sensor,數(shù)據(jù)流一般也是走的input子系統(tǒng)上報(bào)給上層的,所以學(xué)習(xí)和理解input子系統(tǒng)很重要。

正文

#include <linux/input.h>

在這個(gè)文件中,我們可以找到這個(gè)結(jié)構(gòu)體:

描述一個(gè)輸入事件
/*
 * The event structure itself
 */
struct input_event {
    struct timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
};

先來(lái)解讀下這個(gè)結(jié)構(gòu)體的含義:

struct timeval結(jié)構(gòu)體在time.h中的定義為:

struct timeval
{
    __time_t tv_sec; /* Seconds. */
    __suseconds_t tv_usec; /*Microseconds. */
};

【time】域的 tv_sec 為Epoch到創(chuàng)建struct timeval時(shí)的秒數(shù),tv_usec為微秒數(shù),即秒后面的零頭。

【type】域顯示了被報(bào)告事件的類型,例如,一個(gè) key press或者 button press, relative motion(比如移動(dòng)鼠標(biāo) ) 或者 absolute motion(比如移動(dòng)游戲桿 ); 常用的事件類型 type有 EV_KEY , EV_REL , EV_ABS , EV_SYN ;分別對(duì)應(yīng)keyboard事件,相對(duì)事件,絕對(duì)事件,同步事件;EV_SYN 則表示一組完整事件已經(jīng)完成,需要處理;

【code】域根據(jù)type的不同而含義不同,上報(bào)是哪一個(gè)key或者哪一個(gè)坐標(biāo)軸在被操作; 例如,type為 EV_KEY 時(shí),code表示鍵盤(pán)code或者鼠標(biāo)Button值;type為 EV_REL 時(shí),code表示操作的是哪個(gè)坐標(biāo)軸,如:REL_X,REL_Y (因?yàn)槭髽?biāo)有x,y兩個(gè)軸向,所以一次鼠標(biāo)移動(dòng),會(huì)產(chǎn)生兩個(gè)input_event);type為 EV_ABS 時(shí),code表示絕對(duì)坐標(biāo)軸向。

【value】域也是根據(jù)type的不同而含義不同,上報(bào)現(xiàn)在的狀態(tài)或者運(yùn)動(dòng)情況是什么。例如:type為EV_KEY時(shí),value:0表示按鍵抬起,1表示按鍵按下;(4表示持續(xù)按下等?)type為EV_REL時(shí),value: 表明移動(dòng)的值和方向(正負(fù)值);type為EV_ABS時(shí),value: 表示絕對(duì)位置;

那么,最主要的事件有以下三種:相對(duì)事件(鼠標(biāo)),絕對(duì)事件(觸摸屏),鍵盤(pán)事件。

例如:

我們說(shuō)鼠標(biāo),我們?cè)谝苿?dòng)鼠標(biāo)的時(shí)候鼠標(biāo)就是一個(gè)相對(duì)事件,所以type的類型也就是底層上報(bào)給用戶的事件為相對(duì)事件類型,那么code表示的就是相對(duì)于鼠標(biāo)當(dāng)前的位置的X或者Y的坐標(biāo),value也就是相對(duì)于當(dāng)前的位置偏移多少。

事件類型(type)在 input.h 主要有以下:

/*
 * Event types
 */
 
#define EV_SYN          0x00 ? ? //同步事件,就是將結(jié)果上報(bào)給系統(tǒng)的過(guò)程
#define EV_KEY          0x01 ? ? //按鍵事件,如 KEY_VOLUMEDOWN 事件
#define EV_REL          0x02 ? ? //相對(duì)事件, 如鼠標(biāo)上報(bào)的坐標(biāo)
#define EV_ABS          0x03 ? ? //絕對(duì)事件,如觸摸屏上報(bào)的坐標(biāo)
#define EV_MSC          0x04 ? ? //其它
#define EV_SW           0x05 ? ? //
#define EV_LED          0x11 ? ? //LED
#define EV_SND          0x12 ? ? //聲音
#define EV_REP          0x14 ? ? //Repeat
#define EV_FF           0x15 ? ? //力反饋
#define EV_PWR          0x16 ? ? //電源
#define EV_FF_STATUS     0x17 ? ? //狀態(tài)
#define EV_MAX          0x1f
#define EV_CNT          (EV_MAX+1)

以鼠標(biāo)為例,涉及鼠標(biāo)的事件讀取/控制相關(guān)的code有:

/*
 * Relative axes
 */
//在這里,我們暫時(shí)只會(huì)用來(lái)REL_X和REL_Y這兩個(gè)參數(shù)
#define REL_X           0x00 ?  //相對(duì)X坐標(biāo)
#define REL_Y           0x01 ?  //相對(duì)Y坐標(biāo)
#define REL_Z           0x02 ?  //相對(duì)Z坐標(biāo)
#define REL_RX          0x03
#define REL_RY          0x04
#define REL_RZ          0x05
#define REL_HWHEEL      0x06
#define REL_DIAL        0x07
#define REL_WHEEL       0x08
#define REL_MISC        0x09
#define REL_MAX         0x0f
#define REL_CNT         (REL_MAX+1)

最后value,就是選擇具體的type、具體的code以后所反應(yīng)出來(lái)的值,鼠標(biāo)就是相對(duì)于當(dāng)前X或者相對(duì)于當(dāng)前Y的值。

接下來(lái),我們來(lái)看一下如何來(lái)讀取鼠標(biāo)事件,寫(xiě)一段代碼測(cè)試一下:

#include <stdio.h>
#include <linux/input.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
/*
struct input_event {
 ? ? ? ?struct timeval time;
 ? ? ? ?__u16 type;
 ? ? ? ?__u16 code;
 ? ? ? ?__s32 value;
};
*/
/*
Event types
#define EV_SYN ? ? ? ? ? ? ? ?  0x00
#define EV_KEY ? ? ? ? ? ? ? ?  0x01
#define EV_REL ? ? ? ? ? ? ? ?  0x02
#define EV_ABS ? ? ? ? ? ? ? ?  0x03
*/
/*
 Relative axes
#define REL_X ? ? ? ? ? ? ? ? ? 0x00
#define REL_Y ? ? ? ? ? ? ? ? ? 0x01
#define REL_Z ? ? ? ? ? ? ? ? ? 0x02
#define REL_RX ? ? ? ? ? ? ? ?  0x03
#define REL_RY ? ? ? ? ? ? ? ?  0x04
#define REL_RZ ? ? ? ? ? ? ? ?  0x05
#define REL_HWHEEL ? ? ? ? ? ?  0x06
#define REL_DIAL ? ? ? ? ? ? ?  0x07
#define REL_WHEEL ? ? ? ? ? ? ? 0x08
#define REL_MISC ? ? ? ? ? ? ?  0x09
#define REL_MAX ? ? ? ? ? ? ? ? 0x0f
#define REL_CNT ? ? ? ? ? ? ? ? (REL_MAX+1)
*/
 
//event8  mouse
//event9  keyboard
int main(void)
{
    //1、定義一個(gè)結(jié)構(gòu)體變量用來(lái)描述input事件
    struct input_event event_mouse ;
    //2、打開(kāi)input設(shè)備的事件節(jié)點(diǎn)  我的電腦鼠標(biāo)事件的節(jié)點(diǎn)是event3
    int fd = open("/dev/input/event3",O_RDWR);
    int value ;
    int type ;
    int buffer[10]={0};
    if(-1 == fd){
        printf("open mouse event fair!n");
        return -1 ;
    }   
    while(1){
        //3、讀事件
        read(fd ,&event_mouse ,sizeof(event_mouse));
        //4、判斷事件類型,并打印鍵碼
        switch(event_mouse.type){
            case EV_SYN:
             ? ? printf("sync!n");
             ? ? break ;
            case EV_REL:
            //鼠標(biāo)事件,XY相對(duì)位移
            //code表示相對(duì)位移X或者Y,當(dāng)判斷是X時(shí),打印X的相對(duì)位移value
            //當(dāng)判斷是Y時(shí),打印Y的相對(duì)位移value
            if(event_mouse.code == REL_X){ 
             ? ? printf("event_mouse.code_X:%dn",event_mouse.code);    
             ? ? printf("event_mouse.value_X:%dn",event_mouse.value);  
            }
            if(event_mouse.code == REL_Y){
             ? ? printf("event_mouse.code_Y:%dn",event_mouse.code);    
             ? ? printf("event_mouse.value_Y:%dn",event_mouse.value);  
            }
            defalut:
            break ;
        }
    }   
    return 0 ;
}

附:在Linux系統(tǒng)下通過(guò)如下命令可以看到所有的input設(shè)備

cat /proc/bus/input/devices

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="qpnp_pon"
P: Phys=qpnp_pon/input0
S: Sysfs=/devices/platform/soc/c440000.qcom,spmi/spmi-0/spmi0-00/c440000.qcom,spmi:qcom,pm8150@0:qcom,power-on@800/input/input0
U: Uniq=
H: Handlers=event0 cpufreq
B: PROP=0
B: EV=3

B: KEY=600000000000000 0 14000000000000 0

............

I: Bus=0018 Vendor=0000 Product=0000 Version=0000
N: Name="light"
P: Phys=
S: Sysfs=/devices/virtual/input/input3
U: Uniq=
H: Handlers=event3
B: PROP=0
B: EV=5

B: REL=3

......

I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="gpio-keys"
P: Phys=gpio-keys/input0
S: Sysfs=/devices/platform/soc/soc:gpio_keys/input/input6
U: Uniq=
H: Handlers=event6 cpufreq
B: PROP=0
B: EV=3
B: KEY=8000000000000 0

下期見(jiàn)~

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
HFBR-1414Z 1 Broadcom Limited Transmitter, 792nm Min, 865nm Max, 160Mbps, ST Connector, DIP, Panel Mount, Through Hole Mount, ROHS COMPLIANT PACKAGE
$27.48 查看
ABS07AIG-32.768KHZ-9-T 1 Abracon Corporation CRYSTAL 32.768KHZ 9PF SMD

ECAD模型

下載ECAD模型
暫無(wú)數(shù)據(jù) 查看
TLP185(SE(T 1 Toshiba America Electronic Components NPN-OUTPUT DC-INPUT OPTOCOUPLER,1-CHANNEL,3.75KV ISOLATION,SO

ECAD模型

下載ECAD模型
$0.21 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

記錄和分享C/C++、Linux、ARM、Android、IoT相關(guān)知識(shí)。技術(shù)相伴于生活和成長(zhǎng),愿你我永為少年,心中有火,眼中有光,始保熱情。