linux驱动开发扩展--输入设备驱动层源码分析

arch/arm/mach-s5pv210/button-x210.c

static int __init s3c_button_init(void)
{   
	platform_device_register(&s3c_device_button);       

	return platform_driver_register(&s3c_button_device_driver);
}

static void __exit s3c_button_exit(void)
{
	platform_driver_unregister(&s3c_button_device_driver);
	platform_device_unregister(&s3c_device_button);   
}

module_init(s3c_button_init);
module_exit(s3c_button_exit);
static struct platform_driver s3c_button_device_driver = {
	.probe		= s3c_button_probe,
	.remove		= s3c_button_remove,
	.suspend	= s3c_button_suspend,
	.resume		= s3c_button_resume,
	.driver		= {
		.name	= "s3c-button",
		.owner	= THIS_MODULE,
	}
};


static struct platform_device s3c_device_button = {
	.name	= "s3c-button",
	.id		= -1,
};

这里不做过多解释,请参考platform平台总线工作原理

s3c_button_probe

/* gph0_1 (power) */
ret = gpio_request(S5PV210_GPH0(1), "GPH0");
if(ret)
	printk("button-x210: request gpio GPH0(1) fail");
s3c_gpio_setpull(S5PV210_GPH0(1), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PV210_GPH0(1), S3C_GPIO_SFN(0));
s3c_button_history[0] = gpio_get_value(S5PV210_GPH0(1));
...

 申请按键所对应的gpio并进行配置

input = input_allocate_device();
	if(!input) 
		return -ENOMEM;
static struct input_dev * input;

调用核心层提供的接口input_allocate_device为struct input_dev类型的变量input分配内存并进行一些泛型初始化

set_bit(EV_KEY, input->evbit);

for(i = 0; i < MAX_BUTTON_CNT; i++)
	set_bit(s3c_Keycode[i], input->keybit);
static int s3c_Keycode[MAX_BUTTON_CNT] = {KEY_POWER, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_A, KEY_B};

 设置设备所支持的事件类型EV_KEY和其对应支持的code,这里没有调用核心层分析中讲过的input_set_capability接口

    input->name = "s3c-button";
	input->phys = "s3c-button/input0";

	input->id.bustype = BUS_HOST;
	input->id.vendor = 0x0001;
	input->id.product = 0x0001;
	input->id.version = 0x0100;

    input->keycode = s3c_Keycode;

一些成员初始化

    if(input_register_device(input) != 0)
	{
		printk("s3c-button input register device fail!!\n");

		input_free_device(input);
		return -ENODEV;
	}

调用核心层提供的接口input_register_device向核心层注册input device

    /* Scan timer init */
	init_timer(&timer);
	timer.function = s3cbutton_timer_handler;

	timer.expires = jiffies + (HZ/100);
	add_timer(&timer);
static struct timer_list timer;

 初始化并启动一个内核定时器,该定时器到时后会去执行s3cbutton_timer_handler函数,定时时间为jiffies + (HZ/100)为10ms。

该定时器的作用主要是定时去轮训检测按键的gpio的电平是否被按下

s3cbutton_timer_handler

按键没有被按下:

input_report_key(input, s3c_Keycode[0], 0); 

按键被按下:

input_report_key(input, s3c_Keycode[0], 1);
mod_timer(&timer,jiffies + HZ/100);

内核定时器为单次定时器,需要更新定时器重新设置计时时间

input_report_key

该函数定义在include/linux/input.h文件中,主要用于上报按键事件。

static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
{
	input_event(dev, EV_KEY, code, !!value);
}

static inline void input_report_rel(struct input_dev *dev, unsigned int code, int value)
{
	input_event(dev, EV_REL, code, value);
}

static inline void input_report_abs(struct input_dev *dev, unsigned int code, int value)
{
	input_event(dev, EV_ABS, code, value);
}
...

类似的input_report_rel函数和input_report_abs函数等,其内部都是调用了input_event函数,只是参数不同

 input_event
    input_handle_event
        input_pass_event
            handle->handler->event

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值