0

0

Linux输入子系统简介

WBOY

WBOY

发布时间:2024-02-13 13:09:12

|

1019人浏览过

|

来源于良许Linux教程网

转载

linux输入子系统是一组驱动程序,它支持linux系统上的所有输入设备,包括键盘、鼠标、触摸屏、手写板、游戏手柄等。输入子系统的核心是input模块,它负责在两类模块之间传递事件:

  • 设备驱动模块:这些模块与硬件通信(例如通过USB),并向input模块提供事件(按键、鼠标移动等)。
  • 事件处理模块:这些模块从input模块获取事件,并通过各种接口将它们传递到需要的地方(例如内核、GPM、X等)。

在本文中,我们将介绍Linux输入子系统的基本概念和结构,以及一些常用的命令和工具。我们将使用Ubuntu 20.04作为示例系统,但是这些内容也适用于其他Linux发行版。

Linux输入子系统简介

驱动层

将底层的硬件输入转化为统一事件形式,想输入核心(Input Core)汇报。

输入子系统核心层

它承上启下为驱动层提供输入设备注册与操作接口,如:input_register_device;通知事件处理层对事件进行处理;在/Proc下产生相应的设备信息。

事件处理层

主要是和用户空间交互(Linux中在用户空间将所有的设备都当作文件来处理,由于在一般的驱动程序中都有提供fops接口,以及在/dev下生成相应的设备文件nod,这些操作在输入子系统中由事件处理层完成)。

设备描述

input_dev结构是实现设备驱动核心工作:向系统报告按键、触摸屏等输入事件(event,通过input_event结构描述),不再需要关心文件操作接口。驱动报告事件经过inputCore和Eventhandler到达用户空间。

注册输入设备函数:

SmartB2B行业电子商务
SmartB2B行业电子商务

SmartB2B 是一款基于PHP、MySQL、Smarty的B2B行业电子商务网站管理系统,系统提供了供求模型、企业模型、产品模型、人才招聘模型、资讯模型等模块,适用于想在行业里取得领先地位的企业快速假设B2B网站,可以运行于Linux与Windows等多重服务器环境,安装方便,使用灵活。 系统使用当前流行的PHP语言开发,以MySQL为数据库,采用B/S架构,MVC模式开发。融入了模型化、模板

下载
int input_register_device(struct input_dev *dev)

注销输入设备函数:

void input_unregister_device(struct input_dev *dev)

驱动实现——初始化(事件支持)set_bit()告诉input输入子系统支持哪些事件,哪些按键。例如:

set_bit(EV_KEY,button_dev.evbit)  (其中button_dev是struct input_dev类型)

struct input_dev****中有两个成员为:
**1)**evbit事件类型(包括EV_RST,EV_REL,EV_MSC,EV_KEY,EV_ABS,EV_REP等)。
**2)**keybit按键类型(当事件类型为EV_KEY时包括BTN_LEFT,BTN_0,BTN_1,BTN_MIDDLE等)。

驱动实现——报告事件用于报告EV_KEY,EV_REL,EV_ABS事件的函数分别为:

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)

驱动实现——报告结束input_sync()同步用于告诉input core子系统报告结束,触摸屏设备驱动中,一次点击的整个报告过程如下:

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);//同步结束

实例分析(按键中断程序):

//按键初始化
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);
}

总结:input子系统仍然是字符设备驱动程序,但是代码量减少很多,****input子系统只需要完成两个工作:初始化和事件报告(这里在linux****中是通过中断来实现的)。

实例

#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");

在本文中,我们学习了Linux输入子系统的基本概念和结构,以及一些常用的命令和工具。我们了解了如何查看和控制输入设备的属性和状态,以及如何使用evtest和libinput工具来测试和调试输入设备。我们还学习了如何使用udev规则来自定义输入设备的行为和配置。

Linux输入子系统是一个强大而灵活的框架,它可以让你更好地管理和使用你的输入设备。通过使用Linux输入子系统,你可以提高你的工作效率和用户体验。我们建议你在使用Linux系统时,经常使用Linux输入子系统来优化你的输入设备。

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

989

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

50

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

207

2025.12.29

点击input框没有光标怎么办
点击input框没有光标怎么办

点击input框没有光标的解决办法:1、确认输入框焦点;2、清除浏览器缓存;3、更新浏览器;4、使用JavaScript;5、检查硬件设备;6、检查输入框属性;7、调试JavaScript代码;8、检查页面其他元素;9、考虑浏览器兼容性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

180

2023.11.24

磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

1345

2023.06.21

如何安装LINUX
如何安装LINUX

本站专题提供如何安装LINUX的相关教程文章,还有相关的下载、课程,大家可以免费体验。

698

2023.06.29

linux find
linux find

find是linux命令,它将档案系统内符合 expression 的档案列出来。可以指要档案的名称、类别、时间、大小、权限等不同资讯的组合,只有完全相符的才会被列出来。find根据下列规则判断 path 和 expression,在命令列上第一个 - ( ) , ! 之前的部分为 path,之后的是 expression。还有指DOS 命令 find,Excel 函数 find等。本站专题提供linux find相关教程文章,还有相关

293

2023.06.30

linux修改文件名
linux修改文件名

本专题为大家提供linux修改文件名相关的文章,这些文章可以帮助用户快速轻松地完成文件名的修改工作,大家可以免费体验。

773

2023.07.05

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

7

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 6.3万人学习

Git 教程
Git 教程

共21课时 | 2.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号