入力サブシステム

入力サブシステム フレームワークの概要

入力サブシステムは、入力デバイス (キーボード、マウス、タッチ スクリーンなど) のイベント フローを管理するための Linux カーネルのフレームワークです。入力デバイスは、物理デバイスまたはソフトウェアでシミュレートされたデバイスです。Linux では、すべての入力デバイスは入力イベント ストリームとして表され、入力サブシステムによって読み取られてユーザー空間に渡されます。

Input サブシステムは、次のコア機能を提供します。

接收和处理输入事件:输入子系统负责接收并处理来自输入设备的输入事件。输入事件包括按键、鼠标移动、滚轮滚动、触摸屏触摸等。

事件过滤和处理:输入子系统支持事件过滤和处理。例如,可以禁用鼠标滚轮,或者将按键事件映射到其他键。

事件传递到用户空间:输入子系统将事件传递到用户空间,以便应用程序可以响应用户的输入。

设备节点的创建:输入子系统为每个输入设备创建一个设备节点,应用程序可以使用设备节点访问输入设备的事件流。

以下は、Input サブシステムのスケルトンです。

输入设备驱动程序:输入设备驱动程序负责接收来自硬件或软件的输入事件,并将事件传递给输入子系统。输入设备驱动程序通常在内核中作为模块编译,可以在系统启动时加载。输入设备驱动程序需要实现input_dev结构体,并使用input_register_device函数注册设备。

输入子系统核心:输入子系统核心负责管理输入设备和事件流。它包括输入事件的处理、过滤和传递到用户空间的代码。

应用程序:应用程序可以使用读取输入设备节点的方式来访问输入设备的事件流。当输入事件发生时,应用程序可以从输入设备节点中读取事件,并对其进行处理。

设备节点:输入子系统为每个输入设备创建一个设备节点。应用程序可以使用读取设备节点的方式来访问输入设备的事件流。

入力サブシステムは、アプリケーション開発者が入力デバイスを簡単に操作できるようにするツールと API も提供します。たとえば、libinput は、さまざまな入力デバイスからのイベントの処理を容易にするユーザー空間ライブラリです。または、入力デバイスのテストとデバッグに使用できる evtest などのコマンドライン ツールもあります。

サンプルデモ

以下は、デバイス ツリーとアプリケーション層インターフェイスを含む、GPIO ボタンを使用する入力デバイス ドライバーの例です。

ドライバーコード (input-gpio-keys.c):

#include <linux/input.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>

#define DRIVER_NAME "input-gpio-keys"

static struct input_dev *input_dev;
static int gpio_pin;
static int gpio_irq;

static irqreturn_t input_gpio_isr(int irq, void *dev_id)
{
    
    
    int val = gpio_get_value(gpio_pin);
    input_event(input_dev, EV_KEY, KEY_ENTER, val);
    input_sync(input_dev);
    return IRQ_HANDLED;
}

static int input_gpio_probe(struct platform_device *pdev)
{
    
    
    struct device_node *np = pdev->dev.of_node;
    const char *name = np->name;
    int ret;

    ret = of_property_read_u32(np, "gpio-pin", &gpio_pin);
    if (ret) {
    
    
        dev_err(&pdev->dev, "Failed to read gpio-pin property\n");
        return ret;
    }

    gpio_request(gpio_pin, name);
    gpio_direction_input(gpio_pin);
    gpio_irq = gpio_to_irq(gpio_pin);

    ret = request_irq(gpio_irq, input_gpio_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, name, NULL);
    if (ret < 0) {
    
    
        dev_err(&pdev->dev, "Failed to request IRQ: %d\n", ret);
        return ret;
    }

    input_dev = input_allocate_device();
    if (!input_dev) {
    
    
        dev_err(&pdev->dev, "Failed to allocate input device\n");
        return -ENOMEM;
    }

    input_dev->name = name;
    input_dev->id.bustype = BUS_HOST;
    input_dev->evbit[0] = BIT_MASK(EV_KEY);
    input_dev->keybit[BIT_WORD(KEY_ENTER)] = BIT_MASK(KEY_ENTER);

    ret = input_register_device(input_dev);
    if (ret) {
    
    
        dev_err(&pdev->dev, "Failed to register input device\n");
        input_free_device(input_dev);
        return ret;
    }

    dev_info(&pdev->dev, "Initialized input-gpio-keys driver\n");
    return 0;
}

static int input_gpio_remove(struct platform_device *pdev)
{
    
    
    input_unregister_device(input_dev);
    free_irq(gpio_irq, NULL);
    gpio_free(gpio_pin);
    return 0;
}

static const struct of_device_id input_gpio_of_match[] = {
    
    
    {
    
     .compatible = "input-gpio-keys" },
    {
    
    },
};
MODULE_DEVICE_TABLE(of, input_gpio_of_match);

static struct platform_driver input_gpio_driver = {
    
    
    .driver = {
    
    
        .name = DRIVER_NAME,
        .of_match_table = input_gpio_of_match,
    },
    .probe = input_gpio_probe,
    .remove = input_gpio_remove,
};

module_platform_driver(input_gpio_driver);

MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("GPIO input driver");
MODULE_LICENSE("GPL");

デバイス ツリー コード (input-gpio-keys.dts):

/dts-v1/;
#include "gpio-keys.dtsi"

/ {
    
    
    compatible = "raspberrypi,3-model-b", "brcm,bcm2837";
    model = "Raspberry Pi 3 Model B";
    aliases {
    
    
        gpio_keys0 = &gpio_keys;
    };
};

&gpio {
    
    
    gpio_keys {
    
    
        compatible = "input-gpio-keys";
        gpios = <&gpio 17 >;
    gpio-pin = <17>;
    linux,keycode = <28>;
    debounce-interval = <50>;
};

アプリケーション層コード:

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

#define DEVICE_NAME "/dev/input/by-path/platform-input-gpio-keys-event"

int main(int argc, char **argv)
{
    
    
    int fd;
    struct input_event ev;

    fd = open(DEVICE_NAME, O_RDONLY);
    if (fd < 0) {
    
    
        printf("Failed to open device\n");
        return -1;
    }

    printf("Press Ctrl-C to exit\n");
    while (1) {
    
    
        read(fd, &ev, sizeof(ev));
        if (ev.type == EV_KEY && ev.code == KEY_ENTER) {
    
    
            printf("Button state: %d\n", ev.value);
        }
    }

    close(fd);
    return 0;
}

おすすめ

転載: blog.csdn.net/qq_31057589/article/details/130412131