浅析Linux Input 子系统

本文详细介绍了Linux输入子系统的架构及工作原理,包括输入设备、事件处理层等关键概念,并提供了一个具体的输入设备驱动实现案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在android中,定时alarm功能是很常用的,现在来分析下怎么实现的,这里将采用自下而上的方式讲解。

输入子系统又叫input子系统。其构建非常灵活,只需要调用一些简单的函数,就可以将一个输入设备的功能呈现给应用程序。

Input子系统 主要有下面几个结构:

struct input_dev;         //表示一个输入设备,包含输入设备的一些相关信息(如支持的按键码,s设备的名称,设备支持的事件。)
        struct input_handler;         //表示对输入事件的具体处理。为输入设备的功能实现了一个接口。输入事件最终传递到handler处理。
        struct input_handle;         用来关联struct input_dev和struct input_handler

输入子系统由驱动层,输入子系统核心层(input core)和事件处理层(event handler) 3部分组成。一个输入事件,如键盘按键等通过驱动层-> 系统核心层->事件处理层->用户空间的顺序到达用户空间并传给应用程序使用。其中input core由内核源码下driver/input/input.c 及相关头文件实现。核心层对下提供了设备驱动的接口,对上提供了事件处理层的编程接口。输入子系统主要涉及上面三个结构体。

做linux驱动,一般用结构体来描述设备;我们需要做的是申请相应的结构体空间,然后填充相关结构体内成员;之后注册这个结构体;主要就这么三步;

1)  struct input_dev *input_dev;
2)input_dev = input_allocate_device();         //申请相应的结构体空间

        input_dev ->evbit[0] = 0xb;
        input_dev ->keybit[0xa] = 0x400;
        input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0);
        input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0);
        input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1, 0, 0);
        input_dev ->name = s3c2410ts_name;
        input_dev ->id.bustype = BUS_RS232;
        input_dev ->id.vendor = 0xDEAD;
        input_dev ->id.product = 0xBEEF;
        input_dev ->id.version = S3C2410TSVERSION;         //填充相关结构体内成员;

3)input_register_device(input_dev);        // 注册struct input_dev这个结构体

然后跟代码会发现注册input_dev,做了如下步骤;

input_register_device()
                -->input_attach_handler();
                        -->input_match_device();
                        -->handler->connect();

注册这个设备后,它回去找与它匹配的struct handler结构;找到之后调用struct handler的connect()方法;

简单的实例

  1. #include <linux/module.h> 
  2.         #include <linux/kernel.h> 
  3.         #include <linux/init.h> 
  4.         #include <linux/fs.h> 
  5.         #include <linux/cdev.h> 
  6.         #include <linux/irqreturn.h> 
  7.         #include <asm/io.h> 
  8.         #include <asm/irq.h>  
  9.         #include <linux/input.h> 
  10.         struct file_operations hello_fops = { 
  11.                 .owner = THIS_MODULE 
  12.         }; 
  13.                 static struct input_dev *button_dev; /*输入设备结构体*/  
  14.                 static irqreturn_t button_interrupt(int irq, void *dummy)  
  15.                 /*中断处理函数*/  
  16.                 {  
  17.                         input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & 1);  
  18.                         /*向输入子系统报告产生按键事件*/  
  19.                         input_sync(button_dev); /*通知接收者,一个报告发送完毕*/  
  20.                         return IRQ_HANDLED;  
  21.                 }  
  22.                 static int __init button_init(void) /*加载函数*/  
  23.                 {  
  24.                         int error; 
  25.                         int result; 
  26.                         dev = MKDEV (hello_major, hello_minor); 
  27.                         result = register_chrdev_region (dev, number_of_devices, "hello"); 
  28.                         if (result<0) { 
  29.                         printk (KERN_WARNING "hello: can't get major number %d\n", hello_major); 
  30.                         return result; 
  31.                         } 
  32.                         /* dynamic allocation */ 
  33.                         cdev_init (cdev, &hello_fops); 
  34.                         cdev->owner = THIS_MODULE
  35.                         result = cdev_add (cdev, dev, 1); 
  36.                         if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL))  
  37.                         /*申请中断处理函数*/  
  38.                         {  
  39.                                 /*申请失败,则打印出错信息*/  
  40.                                 printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_  
  41.                                 irq);  
  42.                                 return -EBUSY;  
  43.                         }  
  44.                         button_dev = input_allocate_device(); /*分配一个设备结构体*/  
  45.                         if (!button_dev) /*判断分配是否成功*/  
  46.                         {  
  47.                                 printk(KERN_ERR "button.c: Not enough memory\n");  
  48.                                 error = -ENOMEM;  
  49.                                 goto err_free_irq;  
  50.                         }  
  51.                         button_dev->evbit[0] = BIT_MASK(EV_KEY); /*设置按键信息*/  
  52.                         button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);  
  53.                         error = input_register_device(button_dev); /*注册一个输入设备*/  
  54.                         if (error)  
  55.                         {  
  56.                                 printk(KERN_ERR "button.c: Failed to register device\n");  
  57.                                 goto err_free_dev;  
  58.                         }  
  59.                         return 0;  
  60.                         err_free_dev: /*以下是错误处理*/  
  61.                                 input_free_device(button_dev);  
  62.                         err_free_irq:  
  63.                                 free_irq(BUTTON_IRQ, button_interrupt);  
  64.                         return error;  
  65.                 }  
  66.                 static void __exit button_exit(void) /*卸载函数*/  
  67.                 {  
  68.                         input_unregister_device(button_dev); /*注销按键设备*/  
  69.                         free_irq(BUTTON_IRQ, button_interrupt); /*释放按键占用的中断线*/  
  70.                 }  
  71.                 module_init(button_init);  
  72.                 module_exit(button_exit); 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值