Rumah  >  Artikel  >  Tutorial sistem  >  Pengenalan kepada subsistem input Linux

Pengenalan kepada subsistem input Linux

WBOY
WBOYke hadapan
2024-02-13 13:09:12776semak imbas

Subsistem input Linux ialah satu set pemacu yang menyokong semua peranti input pada sistem Linux, termasuk papan kekunci, tetikus, skrin sentuh, tablet, pengawal permainan, dsb. Teras subsistem input ialah modul input, yang bertanggungjawab untuk menghantar peristiwa antara dua jenis modul:

  • Modul pemacu peranti: Modul ini berkomunikasi dengan perkakasan (cth. melalui USB) dan menyediakan acara (tekanan kekunci, pergerakan tetikus, dll.) ke modul input.
  • Modul pengendalian acara: Modul ini mendapatkan acara daripada modul input dan menghantarnya ke tempat yang diperlukan (cth. kernel, GPM, X, dll.) melalui pelbagai antara muka.

Dalam artikel ini, kami akan memperkenalkan konsep asas dan struktur subsistem input Linux, serta beberapa arahan dan alatan yang biasa digunakan. Kami akan menggunakan Ubuntu 20.04 sebagai sistem contoh, tetapi kandungannya juga digunakan untuk pengedaran Linux yang lain.

Pengenalan kepada subsistem input Linux

Lapisan pemandu

Tukar input perkakasan asas kepada borang acara bersatu dan laporkannya kepada Teras Input.

Masukkan lapisan teras subsistem

Ia menyediakan lapisan pemacu dengan pendaftaran peranti input dan antara muka operasi, seperti: input_register_device memberitahu lapisan pemprosesan acara untuk menjana maklumat peranti yang sepadan di bawah /Proc.

Lapisan pemprosesan acara

Terutamanya berinteraksi dengan ruang pengguna (dalam Linux, semua peranti dianggap sebagai fail dalam ruang pengguna. Memandangkan antara muka fops disediakan dalam pemacu umum dan anggukan fail peranti yang sepadan dijana di bawah /dev, operasi ini diselesaikan oleh pemprosesan acara lapisan dalam subsistem input).

Penerangan Peranti

Struktur input_dev adalah untuk melaksanakan kerja teras pemacu peranti: melaporkan tekanan kekunci, skrin sentuh dan peristiwa input lain (peristiwa, diterangkan melalui struktur input_event) kepada sistem dan tidak perlu lagi mengambil berat tentang antara muka operasi fail. Pemacu melaporkan peristiwa kepada ruang pengguna melalui inputCore dan Eventhandler.

Daftar fungsi peranti input:

int input_register_device(struct input_dev *dev)

Nyahdaftarkan fungsi peranti input:

void input_unregister_device(struct input_dev *dev)

Pelaksanaan pemacu - pemula (sokongan acara) set_bit() memberitahu subsistem input acara dan kekunci mana yang disokong. Contohnya:

set_bit(EV_KEY,button_dev.evbit)  (其中button_dev是struct input_dev类型)
Terdapat dua ahli dalam

struct input_dev****:
**1)** jenis acara evbit (termasuk EV_RST, EV_REL, EV_MSC, EV_KEY, EV_ABS, EV_REP, dsb.).
**2)**jenis kekunci keybit (termasuk BTN_LEFT, BTN_0, BTN_1, BTN_MIDDLE, dsb. apabila jenis acara ialah EV_KEY).

Pelaksanaan pemacu - melaporkan peristiwa Fungsi yang digunakan untuk melaporkan peristiwa EV_KEY, EV_REL, EV_ABS ialah:

void input_report_key(struct input_dev *dev,unsigned int code,int value)
void input_report_rel(struct input_dev *dev,unsigned int code,int value)
void input_report_abs(struct input_dev *dev,unsigned int code,int value)

Pelaksanaan pemacu - penyegerakan akhir input_sync() digunakan untuk memberitahu subsistem teras input bahawa laporan telah tamat Dalam pemacu peranti skrin sentuh, keseluruhan proses pelaporan satu klik adalah seperti berikut:

input_reprot_abs(input_dev,ABS_X,x);   //x坐标
input_reprot_abs(input_dev,ABS_Y,y);   // y坐标
input_reprot_abs(input_dev,ABS_PRESSURE,1);
input_sync(input_dev);//同步结束

Contoh analisis (program gangguan kunci):

//按键初始化
static int __init button_init(void)
{//申请中断
    if(request_irq(BUTTON_IRQ,button_interrupt,0,”button”,NUll))
        return –EBUSY;
    set_bit(EV_KEY,button_dev.evbit); //支持EV_KEY事件
    set_bit(BTN_0,button_dev.keybit); //支持设备两个键
    set_bit(BTN_1,button_dev.keybit); //
    input_register_device(&button_dev);//注册input设备
}
/*在按键中断中报告事件*/
Static void button_interrupt(int irq,void *dummy,struct pt_regs *fp)
{
    input_report_key(&button_dev,BTN_0,inb(BUTTON_PORT0));//读取寄存器BUTTON_PORT0的值
    input_report_key(&button_dev,BTN_1,inb(BUTTON_PORT1));
    input_sync(&button_dev);
}

Ringkasan: Subsistem input masih merupakan pemacu peranti aksara, tetapi jumlah kod jauh dikurangkan Subsistem ****input hanya perlu menyelesaikan dua tugas: pemulaan dan pelaporan peristiwa (di sini dalam linux*. *** Ini dicapai melalui gangguan).

Instance

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

struct input_dev *button_dev;
struct button_irq_desc {
    int irq;
    int pin;
    int pin_setting;
    int number;
    char *name;
};

/*定义一个结构体数组*/
static struct button_irq_desc button_irqs [] = {
    {IRQ_EINT8 , S3C2410_GPG0 , S3C2410_GPG0_EINT8 , 0, "KEY0"},
    {IRQ_EINT11, S3C2410_GPG3 , S3C2410_GPG3_EINT11 , 1, "KEY1"},
    {IRQ_EINT13, S3C2410_GPG5 , S3C2410_GPG5_EINT13 , 2, "KEY2"},
    {IRQ_EINT14, S3C2410_GPG6 , S3C2410_GPG6_EINT14 , 3, "KEY3"},
    {IRQ_EINT15, S3C2410_GPG7 , S3C2410_GPG7_EINT15 , 4, "KEY4"},
    {IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, 5, "KEY5"},
};

static int key_values = 0;
static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
    struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;
    int down;
    udelay(0);
/*获取按键值*/
down = !s3c2410_gpio_getpin(button_irqs->pin); //down: 1(按下),0(弹起)
if (!down) {
    /*报告事件*/
    key_values = button_irqs->number;
    //printk("====>rising key_values=%d\n",key_values);
    if(key_values==0)
        input_report_key(button_dev, KEY_1, 0);
    if(key_values==1)
        input_report_key(button_dev, KEY_2, 0);
    if(key_values==2)
        input_report_key(button_dev, KEY_3, 0);
    if(key_values==3)
        input_report_key(button_dev, KEY_4, 0);
    if(key_values==4)
        input_report_key(button_dev, KEY_5, 0);
    if(key_values==5)
        input_report_key(button_dev, KEY_6, 0);
    /*报告结束*/
    input_sync(button_dev);
    }
else {
    key_values = button_irqs->number;
    //printk("====>falling key_values=%d\n",key_values);
    if(key_values==0)
        input_report_key(button_dev, KEY_1, 1);
    if(key_values==1)
        input_report_key(button_dev, KEY_2, 1);
    if(key_values==2)
        input_report_key(button_dev, KEY_3, 1);
    if(key_values==3)
        input_report_key(button_dev, KEY_4, 1);
    if(key_values==4)
        input_report_key(button_dev, KEY_5, 1);
    if(key_values==5)
        input_report_key(button_dev, KEY_6, 1);
    input_sync(button_dev);
    }
    return IRQ_RETVAL(IRQ_HANDLED);
}
static int s3c24xx_request_irq(void)
{
    int i;
    int err = 0;
    for (i = 0; i if (button_irqs[i].irq continue;
        }
        /* IRQ_TYPE_EDGE_FALLING,IRQ_TYPE_EDGE_RISING,IRQ_TYPE_EDGE_BOTH */
        err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_BOTH,
        button_irqs[i].name, (void *)&button_irqs[i]);
        if (err)
            break;
    }
    /*错误处理*/
    if (err) {
        i--;
        for (; i >= 0; i--) {
            if (button_irqs[i].irq continue;
            }
            disable_irq(button_irqs[i].irq);
          free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
        }
        return -EBUSY;
    }
    return 0;
}
static int __init dev_init(void)
{
    /*request irq*/
    s3c24xx_request_irq();
    /* Initialise input stuff */
    button_dev = input_allocate_device();
    if (!button_dev) {
        printk(KERN_ERR "Unable to allocate the input device !!\n");
        return -ENOMEM;
    }
    button_dev->name = "s3c2440_button";
    button_dev->id.bustype = BUS_RS232;
    button_dev->id.vendor = 0xDEAD;
    button_dev->id.product = 0xBEEF;
    button_dev->id.version = 0x0100;

    button_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT(EV_SYN);
    //set_bit(EV_KEY, button_dev->evbit)//支持EV_KEY事件
    /*设置支持哪些按键*/
    set_bit(KEY_1, button_dev->keybit);
    set_bit(KEY_2, button_dev->keybit);
    set_bit(KEY_3, button_dev->keybit);
    set_bit(KEY_4, button_dev->keybit);
    set_bit(KEY_5, button_dev->keybit);
    set_bit(KEY_6, button_dev->keybit);
    //printk("KEY_RESERVED=%d ,KEY_1=%d",KEY_RESERVED,KEY_1);
    input_register_device(button_dev); //注册input设备

    printk ("initialized\n");

    return 0;
}

static void __exit dev_exit(void)
{
    int i;

    for (i = 0; i if (button_irqs[i].irq continue;
        }
        free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
    }

    input_unregister_device(button_dev);
}

module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Xie");

Dalam artikel ini, kami mempelajari konsep asas dan struktur subsistem input Linux, serta beberapa arahan dan alatan yang biasa digunakan. Kami mempelajari cara melihat dan mengawal sifat dan status peranti input dan cara menggunakan alat evtest dan libinput untuk menguji dan nyahpepijat peranti input. Kami juga mempelajari cara menggunakan peraturan udev untuk menyesuaikan gelagat dan konfigurasi peranti input.

Subsistem input Linux ialah rangka kerja yang berkuasa dan fleksibel yang membolehkan anda mengurus dan menggunakan peranti input anda dengan lebih baik. Dengan menggunakan subsistem input Linux, anda boleh meningkatkan produktiviti dan pengalaman pengguna anda. Kami mengesyorkan agar anda sering menggunakan subsistem input Linux untuk mengoptimumkan peranti input anda apabila menggunakan sistem Linux.

Atas ialah kandungan terperinci Pengenalan kepada subsistem input Linux. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:lxlinux.net. Jika ada pelanggaran, sila hubungi admin@php.cn Padam