栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux input子系统上报键值失败问题

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux input子系统上报键值失败问题

昨天在做有关Linux input子系统实验的时候,被一个问题困扰了很久,到第二天才发现原因,最后的问题是一个小细节导致实验的失败。

当时的实验代码如下:

static int key_probe(struct platform_device *pdev)  // 按键初始化函数
{
    int ret = 0;
    



 

   //  申请input_dev 结构体内存
    keycdev.keyinputdev = devm_input_allocate_device(&pdev->dev);
    if(NULL == keycdev.keyinputdev){
        DEBUG_SFLR("devm_input_allocate_device
    keycdev.keyinputdev->name = "key_input_dev";
    //keycdev.keyinputdev->dev.parent = &pdev->dev;
    
    __set_bit(KEY_DOWN ,keycdev.keyinputdev->keybit);  // 设置按键键值为KEY_DOWN
    __set_bit(EV_KEY, keycdev.keyinputdev->evbit);     // 设置按键类型为EV_KEY

	// 注册inputdevice
    if(input_register_device(keycdev.keyinputdev)){
        DEBUG_SFLR("input_register_device errorrn" );
        ret = -1;
        goto end;
    }

    keycdev.key_timer.function = key_timer_func;
    keycdev.key_timer.data     = &keycdev;
    init_timer(&keycdev.key_timer);   // 初始化定时器
    
end:    
    return ret;

}

当时实验代码在定时器中断中上报键值
void key_timer_func(unsigned long arg)
{
	struct key_dev_type *pdata = (struct key_dev_type *)arg;
	int value = 0;
	value = gpio_get_value(pdata->gpio);
	if(0 == value)   // 当按键按下时上报事件
	{
		input_report_key(pdata->keyinputdev,KEY_0,0);  // 上报事件
		input_sync(pdata->keyinputdev);
	}

}

但是当把驱动加载到内核之后,按下按键内核并没有把键值上报到应用层。反复检查了很多遍都没有找到是什么问题。后来再次认真检查一遍,终于发现了问题所在。原来是在按键初始化函数中向内核注册的按键键值为KEY_DOWN,但是在定时器中断函数中向内核上报按键的键值却是KEY_0,这就导致了内核注册的键值与上报的键值不一致,导致上报失败

至于为什么当内核注册的按键键值与上报的键值不一致会导致上传失败,这需要在内核中找答案

static void input_handle_event(struct input_dev *dev,unsigned int type, unsigned int code, int value)
{
	int disposition;

	disposition = input_get_disposition(dev, type, code, &value);

	if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
		dev->event(dev, type, code, value);

	if (!dev->vals)
		return;

	if (disposition & INPUT_PASS_TO_HANDLERS) {
		struct input_value *v;

		if (disposition & INPUT_SLOT) {
			v = &dev->vals[dev->num_vals++];
			v->type = EV_ABS;
			v->code = ABS_MT_SLOT;
			v->value = dev->mt->slot;
		}

		v = &dev->vals[dev->num_vals++];
		v->type = type;
		v->code = code;
		v->value = value;
	}

	if (disposition & INPUT_FLUSH) {
		if (dev->num_vals >= 2)
			input_pass_values(dev, dev->vals, dev->num_vals);
		dev->num_vals = 0;
	} else if (dev->num_vals >= dev->max_vals - 2) {
		dev->vals[dev->num_vals++] = input_value_sync;
		input_pass_values(dev, dev->vals, dev->num_vals);
		dev->num_vals = 0;
	}

}


input_handle_event函数负责处理上报的内容,其中函数input_get_disposition负责检测键值的有效性

static int input_get_disposition(struct input_dev *dev,
			  unsigned int type, unsigned int code, int *pval)
{
	int disposition = INPUT_IGNORE_EVENT;
	int value = *pval;

	switch (type) {

	
	case EV_KEY:
		if (is_event_supported(code, dev->keybit, KEY_MAX)) {

			
			if (value == 2) {
				disposition = INPUT_PASS_TO_HANDLERS;
				break;
			}

			if (!!test_bit(code, dev->key) != !!value) {

				__change_bit(code, dev->key);
				disposition = INPUT_PASS_TO_HANDLERS;
			}
		}
		break;

	

	*pval = value;
	return disposition;
}

在input_get_disposition函数中我们选择EV_KEY来分析,在函数被执行时disposition预先被设置为INPUT_IGNORE_EVENT,也就是预先设置为忽略事件。is_event_supported负责判断上报的键值是否与内核注册的键值一致,如果一致就将disposition设置为INPUT_PASS_TO_HANDLERS并往后选择一个input事件处理层来处理事件,如果不相等就直接退出,不进行事件上报

所以这就是为什么当内核注册的按键键值与上报键值不一致时会导致数据没有上报的原因。最后将定时器中断函数中需要上报的键值修改为KEY_DOWN,与注册的键值一致就能上报成功

void key_timer_func(unsigned long arg)
{
	struct key_dev_type *pdata = (struct key_dev_type *)arg;
	int value = 0;
	value = gpio_get_value(pdata->gpio);
	if(0 == value)   // 当按键按下时上报事件
	{
		input_report_key(pdata->keyinputdev,KEY_DOWN);  // 上报事件
		input_sync(pdata->keyinputdev);
	}

}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/740634.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号