不追求面面俱到,我也是行走在道路上,点到为止。本篇基于realtek TV方案分析。

简述:

我会从linux kernel 和 android 两个部分分析,在我看来这个两个部分就是从android 目录下的Generic.kl(或自定义kl) 分离开来的。

工作中会遇到的问题:

kernel:1、驱动已经添加OK,需要添加新的按键码

        android:2、添加一个新的android  keycode

  3、新输入设备如何选择相应的XXX.kl文件

  4、按键进入处理队列前会怎么走(interceptKeyBeforeQueueing)


——————————————————————————————————————————————————————————————————————

kernel:

——————————————————————————————————————————————————————————————————————

kernel总是那么专注,分析总是以module_init开始,以module_exit结束。

路径:linux-3.7.2\arch\arm\bsp-realtek\mach-rtd298x\Irrc.c

     module_init(ir_init_module);
     module_exit(ir_cleanup_module);

先来看ir_init_module:

|

venus_ir_input_init:设备文件初始化,其中 data->input_dev->name = "venus_IR_input"; 这个名字会用于android输入设备使用xxx.kl文件的名字

data->input_dev->keybit:输入子系统在发送按键前首先会检测要发送的按键值keycode,是否在keybit位图中有注册,所以

set_bit(rtk_mk5_tv_key_table.keys[i].keycode, data->input_dev->keybit);有注册的过程(问题1)

... ... ...

|

if(request_irq(IRQ_ISO, 
IR_interrupt_handler
IRQF_SHARED, 
"Venus_IR", 
IR_interrupt_handler)) {
printk(KERN_ERR "IR: cannot register IRQ %d\n", IRQ_ISO);
result = -EIO;
goto fail_alloc_irq;
}     : 这里的中断handler 是这个设备驱动真正做事的部分,中断到来,会读取相应寄存器的数据

while(examine_ir_avail(®Value, &irrp2Value, &dataRepeat) == 0) {
received = repeat_key_handle(regValue, irrp2Value, dataRepeat);
} // 检测数据是否有效,如果有效进去发键流程,调用输入子系统的

input_event()。


所以移植新的遥控器,首先要定义scancode: keycode的映射表,同时初始化时keycode的值要初始化到input_dev->keybit的映射位,

发键是更具scancode 找到对应的keycode ,然后调用input 子系统的接口input_event()发送出去。

——————————————————————————————————————————————————————————————————————

********

********


——————————————————————————————————————————————————————————————————————

android :

——————————————————————————————————————————————————————————————————————

添加新的遥控按键码涉及的文件有(xxx.kl(Generic.kl 属于系统自带不建议修改),KeycodeLabels.h,keycodes.h,attrs.xml,KeyEvent.java)

android 键盘的消息处理机制的技术分析已经很多,就不去分析这个类别直接的启动流程,已经读thread,分发thread是如何创建的了,InputReader.cpp的

InputReader::loopOnce()开始。


一、新设备的加入,映射解析相应的 .kl文件过程

mEventHub->getEvents :这个方法里会去读取一个按键,或检测是否有新的设备加入,下面来分析下。

EventHub::getEvents()——>EventHub::scanDevicesLocked()——>EventHub::scanDirLocked(DEVICE_PATH)  //DEVICE_PATH: 设备目录/dev/input

      ——>EventHub::openDeviceLocked(const char *devicePath)//这个里面首先会根据传入的设备文件路径,打开读取设备文件名,

  也就是之前kernel里设置的data->input_dev->name = "venus_IR_input";

/*loadConfigurationLocked(device)获取kl文件路径inputeDevice.cpp,getInputDeviceConfigurationFilePathByDeviceIdentifier

  通过查询 /system/usr/keylayout 目录查询venus_IR_input.kl 文件

*/

      ——>EventHub::loadKeyMapLocked(Device* device)——>device->keyMap.load(device->identifier, device->configuration)

      ——>keyboard.cpp,KeyMap::load()——>KeyMap::probeKeyMap()——>KeyMap::loadKeyLayout——>KeyLayoutMap.cpp 

 KeyLayoutMap::load()——> KeyLayoutMap::Parser::parse()——>KeyLayoutMap::Parser::parseKey()——>Keyboard.cpp, 

getKeyCodeByLabel()——>

lookupValueByLabel(label, KEYCODES) //KEYCODES正是我们在KeycodeLabels.h  这需要添加按键的table表,只有自定义的

 // xxx.kl 文件里的keycode 字符串在KEYCODES全部能找到,才会成功用到xxx.kl,否则会用Generic.kl


  /* // Try searching by device identifier.
    if (probeKeyMap(deviceIdenfifier, String8::empty())) {
        return OK;
    }

 
// Fall back on the Generic key map.
    // TODO Apply some additional heuristics here to figure out what kind of
  //      generic key map to use (US English, etc.) for typical external keyboards.
    if (probeKeyMap(deviceIdenfifier, String8("Generic"))) {
        return OK;
    }
*/

至此新设备xxx.kl的keylayout的文件已经映射完成。



二、 按键输入的调用流程。

看下InputReaderThread线程:


InputReader.cpp   InputReader::loopOnce() ——> //

InputReader::processEventsLocked()——>InputReader::processEventsForDeviceLocked()——>InputDevice::process——>KeyboardInputMapper::process

——>KeyboardInputMapper::process()——> getListener()->notifyKey()=InputDispatcher::notifyKey()——>NativeInputManager::interceptKeyBeforeQueueing()

——>PhoneWindowManager.java:interceptKeyBeforeQueueing()// 在新的keyevent加入处理队列之前,如果需要特殊处理可以在interceptKeyBeforeQueueing中过滤

     后面将新获取到的输入事件enqueueInboundEventLocked,并唤醒dispatch线程。


今天到此结束,InputDispatcherThread下回在研究

——————————————————————————————————————————————————————————————————————




更多相关文章

  1. Ubuntu Linux下安装JDK,Android(安卓)SDK,Android(安卓)Studio以
  2. 英特尔® Android* USB 驱动程序安装指南
  3. Android(安卓)Studio 学习笔记(一)环境搭建、文件目录等相关说明
  4. Android(安卓)Studio 学习笔记(一)环境搭建、文件目录等相关说明
  5. Android(安卓)读取app内json配置文件
  6. 【Android(安卓)开发入门】Android设备监视器之调试工具DDMS使用
  7. Android客户端性能参数监控
  8. android recovery模式及ROM制作
  9. NPM 和webpack 的基础使用

随机推荐

  1. android http中请求访问添加 cookie
  2. android 常用调用系统功能
  3. android 图片圆角 遮罩_安卓圆角、背景遮
  4. Android运行时动态全屏以及旋转屏幕时不
  5. android 弹悬浮窗
  6. 2012年第1周国内Android应用下载排行榜
  7. [Learn Android(安卓)Studio 汉化教程]第
  8. android系统核心机制 基础(09)Android(安卓
  9. 4.1 Android如何访问资源
  10. 利用GPS定位[android]