我们下面通过自己编译个最简单的按键输入程序,来学习和理解input子系统。
程序的功能就是一个单独的按键,按下后产生中断并执行相应的程序,代码如下:
#include<linux/init.h>
#include<linux/module.h>
#include<asm/uaccess.h>
#include<linux/fs.h>
#include<linux/cdev.h>
#include<linux/device.h>
#include<asm/io.h>
#include<linux/kernel.h>
#include<linux/errno.h>
#include<linux/poll.h>
#include<linux/interrupt.h>
#include<linux/input.h>
#include<linux/irq.h>
#include<asm/irq.h>
#include<asm-arm/arch-s3c2410/regs-gpio.h> //S3C2410_GPF0_EINT
#include<asm/hardware.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Daisy");
MODULE_DESCRIPTION("This is my input button driver for daisy");
#define DEVICE_NAME "button_daisy"
static struct input_dev *button_dev;
static irqreturn_t button_interrupt(int irq, void* dummy)
{
printk("button_interrupt\n");
input_report_key(button_dev, BTN_0, 1);
input_sync(button_dev);
return IRQ_HANDLED;
}
static int __init input_button_init(void)
{
printk("input_button_init\n");
int err;
s3c2410_gpio_cfgpin(S3C2410_GPF0, S3C2410_GPF0_EINT0);
set_irq_type(IRQ_EINT0, IRQ_TYPE_EDGE_FALLING);
if (request_irq(IRQ_EINT0, button_interrupt, IRQF_DISABLED, "button_daisy", NULL))
{
printk("Can't request irq\n");
return -EBUSY;
}
button_dev = input_allocate_device();
if(!button_dev)
{
printk("input dev alloc err\n");
err = -ENOMEM;
goto err_free_irq;
}
button_dev->evbit[0] = BIT(EV_KEY);
button_dev->keybit[BIT_WORD(BTN_0)] = BIT(BTN_0);
err = input_register_device(button_dev);
if (err)
{
printk("fail to register input device\n");
goto err_free_dev;
}
err_free_irq:
free_irq(IRQ_EINT0, button_interrupt);
err_free_dev:
input_free_device(button_dev);
return err;
}
static void input_button_exit(void)
{
printk("input_button_exit\n");
input_free_device(button_dev);
free_irq(IRQ_EINT0, button_interrupt);
}
module_init(input_button_init);
module_exit(input_button_exit);
说明:
1、如果注册中断request_irq不清楚,可以看这篇转载的文章:
http://blog.csdn.net/daisy_chenting/article/details/6948159
2、对于input子系统的使用,首先就是
button_dev = input_allocate_device();
接着设置一些button_dev的参数,我们先来看struct input_dev这个结构体:
struct input_dev {
/* private: */
void *private;/* do not use */
/* public: */
const char *name;
const char *phys;
const char *uniq;
struct input_id id;
unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; //产生或接受什么样的事件的指示位,这里用到的就是EV_KEY,在//ADC中,就用到了EV_SYN、EV_KEY、EV_ABS。
unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; //产生或接受什么样的按键代码
unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];
unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
unsigned int keycodemax;
unsigned int keycodesize;
void *keycode;
int (*setkeycode)(struct input_dev *dev, int scancode, int keycode);
int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);
struct ff_device *ff;
unsigned int repeat_key;
struct timer_list timer;
int sync;
int abs[ABS_MAX + 1];
int rep[REP_MAX + 1];
unsigned long key[BITS_TO_LONGS(KEY_CNT)];
unsigned long led[BITS_TO_LONGS(LED_CNT)];
unsigned long snd[BITS_TO_LONGS(SND_CNT)];
unsigned long sw[BITS_TO_LONGS(SW_CNT)];
int absmax[ABS_MAX + 1];
int absmin[ABS_MAX + 1];
int absfuzz[ABS_MAX + 1];
int absflat[ABS_MAX + 1];
int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev);
int (*flush)(struct input_dev *dev, struct file *file);
int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
struct input_handle *grab;
spinlock_t event_lock;
struct mutex mutex;
unsigned int users;
int going_away;
struct device dev;
union {/* temporarily so while we switching to struct device */
struct device *dev;
} cdev;
struct list_headh_list;
struct list_headnode;
};
初始化的最后一步就是input_register_device(button_dev)把自己的input设备注册进input子系统。
下面的文章将会继续介绍Input子系统的其他部分,从而对input子系统的整体有一个全面的认识。
input子系统——linux驱动学习笔记(一)
最新推荐文章于 2022-11-29 16:59:58 发布