• 正文
    • 實(shí)現(xiàn)原理
  • 推薦器件
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

Linux input子系統(tǒng)(二)uinput 原理和用途

2024/05/11
4872
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

哈嘍,大家好,我是程序員秘書(shū)LittleG。

前言

uinputUserspace Input,uinput 的實(shí)現(xiàn)是基于 Linux input子系統(tǒng)(Input Subsystem),允許用戶空間程序創(chuàng)建虛擬的輸入設(shè)備并向內(nèi)核發(fā)送輸入事件,比如鍵盤(pán)敲擊、鼠標(biāo)移動(dòng)等,就像這些事件來(lái)自真實(shí)的物理設(shè)備一樣。對(duì)于開(kāi)發(fā)自定義輸入設(shè)備驅(qū)動(dòng)、自動(dòng)化測(cè)試、游戲控制模擬以及各種人機(jī)交互實(shí)驗(yàn)等場(chǎng)景非常有用。

可能的使用場(chǎng)景有:

自動(dòng)化測(cè)試:模擬用戶操作,如點(diǎn)擊、滑動(dòng)等,進(jìn)行UI自動(dòng)化測(cè)試。在自動(dòng)化測(cè)試過(guò)程中,可以模擬用戶的輸入操作來(lái)測(cè)試軟件的功能。

自定義輸入設(shè)備:為沒(méi)有驅(qū)動(dòng)支持的新奇設(shè)備創(chuàng)建虛擬驅(qū)動(dòng)。

游戲控制模擬:模擬游戲手柄或其他特殊控制器。一些游戲玩家可能會(huì)使用腳本來(lái)自動(dòng)執(zhí)行一些復(fù)雜的操作。

輔助工具開(kāi)發(fā):如屏幕鍵盤(pán)、宏命令工具等。實(shí)現(xiàn)一些輔助工具(如屏幕閱讀器、殘疾人輔助工具等)可能需要模擬輸入設(shè)備來(lái)與操作系統(tǒng)或其他應(yīng)用程序進(jìn)行交互。

uinput的使用場(chǎng)景非常廣泛,包括但不限于以上場(chǎng)景。下面就學(xué)習(xí)看下原理和如何使用。

實(shí)現(xiàn)原理

uinput?通過(guò)在內(nèi)核和用戶空間之間創(chuàng)建一個(gè)特殊的設(shè)備文件(通常是?/dev/uinput)來(lái)工作。用戶空間程序可以打開(kāi)這個(gè)文件,并向其中寫(xiě)入數(shù)據(jù)來(lái)模擬輸入事件。這些數(shù)據(jù)會(huì)被內(nèi)核的輸入子系統(tǒng)接收,并像真實(shí)的輸入設(shè)備產(chǎn)生的事件一樣進(jìn)行處理。

具體來(lái)說(shuō),uinput?的實(shí)現(xiàn)包括以下幾個(gè)步驟:

創(chuàng)建 uinput 設(shè)備:用戶空間程序通過(guò)?ioctl?調(diào)用?UINPUT_CREATE_DEVICE?請(qǐng)求來(lái)創(chuàng)建一個(gè)?uinput?設(shè)備。這個(gè)請(qǐng)求需要指定模擬的輸入設(shè)備的類型和屬性。

設(shè)置輸入事件:用戶空間程序通過(guò)寫(xiě)入?/dev/uinput?設(shè)備文件來(lái)設(shè)置要模擬的輸入事件。這些事件可以是鍵盤(pán)按鍵、鼠標(biāo)移動(dòng)、觸摸屏觸摸等。

啟用 uinput 設(shè)備:在設(shè)置完所有需要的輸入事件后,用戶空間程序通過(guò)?ioctl?調(diào)用?UINPUT_START_DEVICE?請(qǐng)求來(lái)啟用?uinput?設(shè)備。此時(shí),內(nèi)核的輸入子系統(tǒng)會(huì)開(kāi)始處理這些模擬的輸入事件。

發(fā)送輸入事件:一旦?uinput?設(shè)備被啟用,用戶空間程序就可以通過(guò)寫(xiě)入?/dev/uinput?設(shè)備文件來(lái)發(fā)送輸入事件了。這些事件會(huì)被內(nèi)核的輸入子系統(tǒng)接收,并像真實(shí)的輸入設(shè)備產(chǎn)生的事件一樣進(jìn)行處理。

銷毀 uinput 設(shè)備:當(dāng)用戶空間程序不再需要模擬輸入設(shè)備時(shí),它可以通過(guò)?ioctl?調(diào)用?UINPUT_DESTROY_DEVICE?請(qǐng)求來(lái)銷毀?uinput?設(shè)備。

補(bǔ)充說(shuō)明

關(guān)于配置設(shè)備屬性
在創(chuàng)建虛擬設(shè)備之前,需要通過(guò)ioctl調(diào)用配置設(shè)備的各種屬性,比如設(shè)備名稱、ID(廠商ID、產(chǎn)品ID、版本等)、支持的事件類型(EV_KEY、EV_REL、EV_ABS等)和具體的事件代碼(如BTN_LEFT、KEY_A、REL_X等)。

關(guān)于發(fā)送事件
一旦設(shè)備被創(chuàng)建,就可以通過(guò)寫(xiě)入input_event結(jié)構(gòu)體到文件描述符來(lái)模擬輸入事件。每個(gè)事件包括類型(EV_KEY、EV_REL等)、代碼(按鍵、軸等)、值(按鍵狀態(tài)、移動(dòng)距離等)以及一個(gè)同步事件(EV_SYN)來(lái)標(biāo)記事件包的結(jié)束。

使用舉例

下面是一個(gè)簡(jiǎn)單的使用例子,通過(guò)uinput創(chuàng)建虛擬鍵盤(pán)并發(fā)送一次鍵擊事件:

#include <fcntl.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include <stdio.h>
#include <unistd.h>

int main() {
    int fd;
    struct uinput_user_dev uidev;
    struct input_event ev;

    /* 打開(kāi)uinput設(shè)備 */
    fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
    if (fd < 0) {
        perror("Error opening /dev/uinput");
        return 1;
    }

    /* 配置虛擬設(shè)備 */
    memset(&uidev, 0, sizeof(uidev));
    strncpy(uidev.name, "Virtual Keyboard", UINPUT_MAX_NAME_SIZE);
    uidev.id.bustype = BUS_USB;
    uidev.id.vendor = 0x1234;
    uidev.id.product = 0x5678;
    uidev.id.version = 1;

    /* 設(shè)置支持的事件類型 */
    ioctl(fd, UI_SET_EVBIT, EV_KEY);
    ioctl(fd, UI_SET_KEYBIT, KEY_A);

    /* 創(chuàng)建虛擬設(shè)備 */
    write(fd, &uidev, sizeof(uidev));
    ioctl(fd, UI_DEV_CREATE);

    /* 發(fā)送按鍵事件 */
    memset(&ev, 0, sizeof(ev));
    ev.type = EV_KEY;
    ev.code = KEY_A;
    ev.value = 1; // 按下
    write(fd, &ev, sizeof(ev));

    ev.value = 0; // 抬起
    write(fd, &ev, sizeof(ev));

    /* 發(fā)送同步事件 */
    memset(&ev, 0, sizeof(ev));
    ev.type = EV_SYN;
    ev.code = SYN_REPORT;
    ev.value = 0;
    write(fd, &ev, sizeof(ev));

    /* 銷毀設(shè)備 */
    ioctl(fd, UI_DEV_DESTROY);
    close(fd);

    return 0;
}

說(shuō)明:以上代碼中,創(chuàng)建了一個(gè)名為"Virtual Keyboard"的虛擬鍵盤(pán)設(shè)備,發(fā)送了一個(gè)"A"鍵的按下與釋放事件,并在最后銷毀了虛擬設(shè)備。

注意,調(diào)試運(yùn)行時(shí),可能會(huì)存在相應(yīng)的權(quán)限問(wèn)題,可以使用root登錄運(yùn)行或chmod修改/dev/uinput權(quán)限。

下期見(jiàn)~

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
DP83867IRRGZR 1 Texas Instruments Industrial temperature, robust gigabit Ethernet PHY transceiver 48-VQFN -40 to 85

ECAD模型

下載ECAD模型
$59.73 查看
SN74LVC1G14DCKRE4 1 Texas Instruments Single 1.65-V to 5.5-V inverter with Schmitt-Trigger inputs 5-SC70 -40 to 125

ECAD模型

下載ECAD模型
$0.41 查看
HFBR-5911LZ 1 Avago Technologies FIBER OPTIC TRANSCEIVER, 830-860nm, 1250Mbps(Tx), 1250Mbps(Rx), THROUGH HOLE MOUNT, LC CONNECTOR, ROHS COMPLIANT PACKAGE
$54.7 查看

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫(xiě)文章/發(fā)需求
立即登錄