Android IR键值传递底层解析

主要通过两个文件来分析ir从linux到Android流程,基于mtk Android方案,这两个文件是ir_config.ini、Vendor_xxx_product_xxx.kl。
kernel
文章不是讲解驱动,所以只列出了ir的基本流程。
MTK为遥控器做了数据分离,可以通过ir_config.ini配置所需要的遥控器而不需要修改kernel。
ir作为input设备注册:

int mstar_ir_register_device(struct platform_device *pdev){
    ...
    dev->input_dev = input_allocate_device();//申请input dev
    ...
    dev->input_dev->id.vendor = INPUTID_VENDOR;
    dev->input_dev->id.product = INPUTID_PRODUCT;
    dev->input_dev->id.version = INPUTID_VERSION;
    ...
    ret = input_register_device(dev->input_dev);//注册input设备
}

linux有预先定义好的按键,定义在vim include/uapi/linux/input-event-codes.h中,在/drv/ir_mirc/ir_dynamic_config/input_keys_available.h中绑定key的name和input-event-code.h的映射值

#define KEYMAP_PAIR(x)      {#x,x} //{"KEY_DOWN",KEY_DOWN}
#define KEY_DOWN                108 //input-event-code.h
...
KEYMAP_PAIR(KEY_DOWN) //input_keys_available.h

根据ir_config.ini填充dev,具体解析ini文件是由ir_dynamic_config_main.c 来完成的:

static char *purelinux_config_file = "/config/ir_config.ini" //配置文件路径

加载key:

static void load_ir_config_thread(struct work_struct *work)

ir_config的结构如下:

//ir_config.ini
KEY_UP                  =       0x12       # up
KEY_DOWN                =       0x34       # down
KEY_LEFT                =       0x56       # left
KEY_RIGHT               =       0x78       # right
KEY_ENTER               =       0x90       # Enter
//ir_dynamic_config_main.c
//KEY_UP是name,0x12是遥控器实际键值,遍历IR_KeysList,获取键值
if (!strcmp(k->name, IR_KeysList[i].key))
{
	table->keycode = IR_KeysList[i].value;
}
//向设备中增加配置的按键信息
MIRC_IRCustomer_Add(curr_ir_profile);

申请中断:

ret = request_irq(INT_NUM_IR_ALL, _MDrv_IR_ISR, SA_INTERRUPT, "IR", &IRDev);

当操作遥控器时产生中断,中断函数会判断得到的数据是否符合配置的遥控器头码,并在按下和松开时report按键。发送按键则是依照input设备report流程调用input_report_key来发送按键。

Android
可以通过cat /proc/bus/input/devices来查看ir对应/dev/input下的哪个设备:

130|console:/ # cat /proc/bus/input/devices 
I: Bus=0018 Vendor=3697 Product=0001 Version=0001
P: Phys=/dev/ir
S: Sysfs=/devices/ir/input/input0
U: Uniq=
H: Handlers=kbd event0 mstar_ir 
B: PROP=0
B: EV=100013
B: KEY=ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffbff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe
B: MSC=10

以上信息显示ir对应/dev/input/event0,Vendor:3697,Product:0001,Version:0001,这些信息在Android绑定设备的时候都会用到。
Android通过启动InputReaderThread来读取按键消息,具体实现:

//frameworks/native/services/inputflinger/InputReader.cpp
bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}

在loopOnce中调用EventHub的getEvents方法来获取kernel的按键信息。
EventHub.cpp中会加入/dev/input的所有设备:

status_t EventHub::scanDirLocked(const char *dirname){
    ...
    //该函数会遍历/dev/input下所有设备文件,并添加到device list中
}
status_t EventHub::openDeviceLocked(const char *devicePath){
    ...
    //打开设备,并获取设备相关信息
   identifier.product = inputId.product;
   identifier.vendor = inputId.vendor;
   identifier.version = inputId.version;
   ... 
}

Vendor_xxx_Product_xxx.kl是什么时候起作用的呢?在openDeviceLocked打开设备的时候会绑定对应的kl文件

//EventHub.cpp
keyMapStatus = loadKeyMapLocked(device);
//Keyboard.cpp
status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier,   const String8& name) {
     String8 path(getPath(deviceIdentifier, name,             INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT));
     ...
     status_t status = KeyLayoutMap::load(path, &keyLayoutMap);
     ...
     keyLayoutFile.setTo(path);
     return OK;
}

如何确定kl文件的名称,上述loadKeyLayout函数中定义的getpath传入的name如果是空,就会调用getInputDeviceConfigurationFilePathByDeviceIdentifier函数根据获取到的设备信息来决定keylayout的路径:

 String8 versionPath(getInputDeviceConfigurationFilePathByName(
                     String8::format("Vendor_%04x_Product_%04x_Version_%04x",
                            deviceIdentifier.vendor, deviceIdentifier.product,
                            deviceIdentifier.version),
                    type));

确定了kl文件,接下来就是找到keycode对应Android的映射值。

void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
      int32_t usageCode)
status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t usageCode,
       int32_t* outKeyCode, uint32_t* outFlags)

该值就是对应KeyEvent.java里的值。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值