您的位置:首页 > 其它

学习笔记:音频之耳机按键事件上报流程

2017-11-01 15:09 731 查看
(本文仅用于本人学习记录,仅供参考)

耳机按键检测到动作后事件上报,涉及到输入子系统。

Input_report_key(cod3034x->input,jd->button,1) //向输入子系统报告产生按键事件
|-- input_event(dev,EV_KEY,code,!!value)
|-- is_event_supported(type,dev->evbit,EV_MAX)
|-- input_handle_event(dev,type,code,value)
|-- input_get_disposition(dev,type,code,&value)
|-- input_pass_values(dev,dev->vals,dev->num_vals)
|-- input_to_handler(handle,vals,count)


Input_sync(cod3034x->input);//通知接收者,一个报告发送完毕。

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


Input_report_key函数的参数1是产生事件的输入设备,参数2是产生的事件,参数3是事件的值。

注:C语言中的感叹号(!)是逻辑运算操作符,经过该操作符运算后的值只有2种情况,要么为1,即True,要么为0,即False。在进行逻辑运算时,所有非0的值都会被认为是 True,而只有 0 值会被认为是False。所以对变量进行2次非运算(!!)就能将其转化成 1 或者0,且变量原本的逻辑值保持不变。

void input_event(struct input_dev *dev,unsigned int type,unsigned int code,int value)
{
unsigned long flag;
if(is_event_supported(type,dev->evbit,EV_MAX))
{
input_handle_event(dev,type,code,value);
}
}


input_event函数的参数1是input_device设备,参数2是事件的类型,参数3是产生的事件,参数4是事件的值。该函数里面用到了is_event_supported()函数,用于检查输入设备是否支持该事件。支持返回1,不支持返回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_HANDLERS)
{
struct input_value *v;
v=&dev->vals[dev->num_vals++];
v->type=type;
v->code=code;
v->value=value;
}
input_pass_values(dev,dev->vals,dev->num_vals);
}


input_handle_event函数向输入子系统传送事件信息,参数1是输入设备input_dev,参数2是事件类型,参数3是键码,参数4是键值。input_get_disposition()确定事件的处理方式,返回值主要有以下几种:

INPUT_IGNORE_EVENT:表示忽略事件,不进行处理。

INPUT_PASS_TO_HANDLERS:表示事件交给handler处理。

INPUT_PASS_TO_DEVICE:表示将事件交给input_dev处理。

INPUT_PASS_TO_ALL:表示将事件交给handler和 input_dev共同处理。

static void input_pass_values(struct input_dev *dev,struct input_value *vals,unsigned int count)
{
struct input_handle *handle;
struct input_value *v;

handle=rcu_dereference(dev->grab);
if(handle)
count=input_to_handler(handle,vals,count);
else
list_for_each_entry_rcu(handle,&dev->h_list,d_node)
if(handle->open)
{
count=input_to_handler(handle,vals,count);
if(!count)
break;
}
}


input_pass_values()函数用于确定input_dev的handler,并通过input_to_handler()调用handler的event函数。在上述代码中,rcu_dereference(),该接口用来获取RCU protected pointer。reader要访问RCU保护的共享数据,当然要获取RCU protected pointer,然后通过该指针进行dereference的操作。dev->grab是强制为input device的handler,如果rcu_dereference()函数返回值不为空,说明有为input_device强制指定handler,就直接调用handler的event函数。如果为NULL,表示没有为input_device强制指定handler,就会通过遍历input device->h_list上的handle成员。如果该handle被打开,表示该设备已经被一个用户进程使用,就会调用与输入设备对应的handler的event函数。

注:只有在handle被打开的情况下才会接收到事件,这就是说,只有设备被用户程序使用时,才有必要向用户空间导出信息。

static unsigned int input_to_handler(struct input_handle *handle,struct input_value *vals,unsigned int count)
{
struct input_handler *handler=handle->handler;
struct input_value *end=vals;
struct input_value *v;
if(handler->filter)
{
for(v=vals;v!=vals+count;v++)
{
if(handler->filter(handle,v->type,v->code,v->value))
continue;
if(end!=v)
*end=*v;
end++;
}
count=end-vals;
}
if(!count)
return 0;
if(handler->events)
handler->event(handle,vals,count);
else if(handler->event)
for(v=vals;v!=vals+count;v++)
handler->event(handle,v->type,v->code,v->value);
return count;
}


首先通过所有过滤器传递事件,然后,如果事件未被过滤掉,则通过所有打开的句柄。该函数被调用,而dev-> event_lock被禁止并且中断被禁用。

[samsung][Z205]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: