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

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

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

哈嘍,大家好,我是程序員秘書LittleG。

前言

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

可能的使用場景有:

自動化測試:模擬用戶操作,如點擊、滑動等,進行UI自動化測試。在自動化測試過程中,可以模擬用戶的輸入操作來測試軟件的功能。

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

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

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

uinput的使用場景非常廣泛,包括但不限于以上場景。下面就學習看下原理和如何使用。

實現(xiàn)原理

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

具體來說,uinput?的實現(xiàn)包括以下幾個步驟:

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

設置輸入事件:用戶空間程序通過寫入?/dev/uinput?設備文件來設置要模擬的輸入事件。這些事件可以是鍵盤按鍵、鼠標移動、觸摸屏觸摸等。

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

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

銷毀 uinput 設備:當用戶空間程序不再需要模擬輸入設備時,它可以通過?ioctl?調(diào)用?UINPUT_DESTROY_DEVICE?請求來銷毀?uinput?設備。

補充說明

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

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

使用舉例

下面是一個簡單的使用例子,通過uinput創(chuàng)建虛擬鍵盤并發(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;

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

    /* 配置虛擬設備 */
    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;

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

    /* 創(chuàng)建虛擬設備 */
    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));

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

    return 0;
}

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

注意,調(diào)試運行時,可能會存在相應的權限問題,可以使用root登錄運行或chmod修改/dev/uinput權限。

下期見~

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風險等級 參考價格 更多信息
ABS09-32.768KHZ-9-T 1 Abracon Corporation CRYSTAL 32.7680KHZ 9PF SMD

ECAD模型

下載ECAD模型
$1.16 查看
74HC245PW,118 1 NXP Semiconductors 74HC(T)245 - Octal bus transceiver; 3-state TSSOP2 20-Pin
$0.56 查看
AT24C32E-SSHM-B 1 Atmel Corporation EEPROM, 4096X8, Serial, CMOS, PDSO8, 0.150 INCH, GREEN, PLASTIC, MS-012AA, SOIC-8
$0.68 查看

相關推薦