MTK 平台Android系统遥控器映射关系

本文详细介绍了MTK平台Android系统中遥控器按键映射的过程,从应用层的键值到Linux内核中的键值,再到红外键值(物理键值),并提供了遥控器映射关系图及常见问题解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MTK 平台Android系统遥控器映射关系


 在我们工作中,经常要去适配遥控器的工作,但是大部时候我们是移植其他工程上的代码来修改,可能对Android系统中的按键关系有些不清楚,下面以MTK平台为例,介绍下Android系统中按键映射关系(以应用层的KEYCODE_POWER键为例)。

我们先从上往下看

第一、应用的按键值。

第一,   在应用上我们按遥控器Power按键,会抛出26,这个按键值的定义在(/framework/base/core/android/view/KeyEvent.java)文件中,如下:

  public static final int KEYCODE_POWER = 26; (向应用层的抛上的键值就是26)

 

第二、应用层与Android系统映射关系

 应用上的这个按键值会与Android系统中的键值相对应起来,

对应关系在(/framework/native/include/input/KeycodelLables.h)文件中

如下:

static const KeycodeLabel KEYCODES[] = {

    {"SOFT_LEFT", 1 },

    {"SOFT_RIGHT", 2 },

    {"HOME", 3 },

    {"BACK", 4 },

    {"CALL", 5 },

    {"ENDCALL", 6 },

    { "0",7 },

    { "1",8 },

    { "2",9 },

    { "3",10 },

    { "4",11 },

    { "5",12 },

    { "6",13 },

    { "7",14 },

    { "8",15 },

    { "9",16 },

    {"STAR", 17 },

    {"POUND", 18 },

    {"DPAD_UP", 19 },

    {"DPAD_DOWN", 20 },

    {"DPAD_LEFT", 21 },

    {"DPAD_RIGHT", 22 },

    {"DPAD_CENTER", 23 },

    {"VOLUME_UP", 24 },

    {"VOLUME_DOWN", 25 },

    { "POWER", 26 }, (POWER是android系统定义的宏,26表示应用层上的键值)

..........

};

 

同时系统里面有个遥控器资源文件(/framework/base/core/res/res/values/attrs.xml),这个文件里面按键关系跟上面的KeycodelLables.h文件关系是一致的。

如下:

<attr name="keycode">

        <enumname="KEYCODE_UNKNOWN" value="0" />

        <enumname="KEYCODE_SOFT_LEFT" value="1" />

        <enumname="KEYCODE_SOFT_RIGHT" value="2" />

        <enumname="KEYCODE_HOME" value="3" />

        <enumname="KEYCODE_BACK" value="4" />

        <enumname="KEYCODE_CALL" value="5" />

        <enumname="KEYCODE_ENDCALL" value="6" />

   

        ……………………………………………………

…………………………………………………………………………

        <enumname="KEYCODE_VOLUME_DOWN" value="25" />

        <enumname="KEYCODE_POWER" value="26" />

        <enumname="KEYCODE_CAMERA" value="27" />

        <enumname="KEYCODE_CLEAR" value="28" />

        <enumname="KEYCODE_A" value="29" />

       

        ………………………………………………………………

……………………………………………………………………………………

    </attr>

 

 

第三步、Android系统按键跟Linux内核中键值的映射关系

涉及到文件(framework/base/data/keyboards/Vendor_000b_Product_000b.kl

文件格式如下:

 

key 116 POWER WAKE (116表示Linux 里面的键值,POWER表示 android 系统的键值)

key 60 SETTINGS

key 172 HOME

key 139 MENU

key 14 BACK

 

key 103 DPAD_UP

key 105 DPAD_LEFT

key 106 DPAD_RIGHT

key 108 DPAD_DOWN

key 28 DPAD_CENTER

 

key 113 VOLUME_MUTE

key 114 VOLUME_DOWN

key 115 VOLUME_UP

 

#red

key 64 F6

#green

key 65 F7

#yellow

key 66 F8

#blue

key 67 F9

 

key 104 PAGE_UP

key 109 PAGE_DOWN

 

key 87 CHANNEL_UP

key 88 CHANNEL_DOWN

 

key 164 MEDIA_PLAY_PAUSE

 

key 2 1

key 3 2

key 4 3

key 5 4

key 6 5

key 7 6

key 8 7

key 9 8

key 10 9

key 11 0

 

# (*) (#)

key 522 STAR

key 523 POUND

 

Linux中的键值定义

(/mediate/platform/mt8127/include/linux/input.h

#define KEY_END 107

#define KEY_DOWN 108

#define KEY_PAGEDOWN 109

#define KEY_INSERT 110

#define KEY_DELETE 111

#define KEY_MACRO 112

#define KEY_MUTE 113

#define KEY_VOLUMEDOWN 114

#define KEY_VOLUMEUP 115

#define KEY_POWER 116 /* SC System Power Down*/

#define KEY_KPEQUAL 117

#define KEY_KPPLUSMINUS 118

#define KEY_PAUSE 119

#define KEY_SCALE 120 /* AL Compiz Scale(Expose) */

 

第四步、Liunx中键值与红外键值(物理键值)映射关系

(涉及到文件:/mediate/platform/mt8127/kernel/drivers/ir/mtk_ir_cus_nec.h)

// this table is used in normal mode, fornormal_boot

static struct rc_map_table mtk_nec_table[] ={

 {0xdc,KEY_POWER},

 //{0x98, KEY_F3}, //sound track

 {0x9c, KEY_MUTE}, //mute

 {0x8d, KEY_F2},//setting

 //{0xd6, KEY_F5},//refresh

 

 {0xcd, KEY_F6}, //red

 {0x91, KEY_F7}, //green

 {0x83, KEY_F8}, //yellow

 {0xc3, KEY_F9}, //blue

 

 {0x88, KEY_HOMEPAGE},

 {0x82, KEY_MENU},

 {0xc5, KEY_BACKSPACE},

 

 {0xca, KEY_UP},

 {0xd2, KEY_DOWN},

 {0x99, KEY_LEFT},

 {0xc1, KEY_RIGHT},

 {0xce, KEY_ENTER},

 

 

 {0x95, KEY_PLAYPAUSE},

 {0x80, KEY_VOLUMEUP},

 {0x81, KEY_VOLUMEDOWN},

 

 {0xdd, KEY_PAGEUP},

 {0x8c, KEY_PAGEDOWN},

 

 {0x85, KEY_F11},

 {0x86, KEY_F12},

 

 {0x87, KEY_0},

 {0x92, KEY_1},

 {0x93, KEY_2},

 {0xcc, KEY_3},

 {0x8e, KEY_4},

 {0x8f, KEY_5},

 {0xc8, KEY_6},

 {0x8a, KEY_7},

 {0x8b, KEY_8},

 {0xc4, KEY_9},

 

 {0xda, KEY_NUMERIC_STAR},//*

 {0xd0, KEY_NUMERIC_POUND},//#

};

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

第五、遥控器映射关系图

前面四大步骤已经介绍了,大概关系如下图

 

第六步、如何快速更改的遥控器按键值

 上述五大步骤主要涉及到的是遥控器的映射关系,但是在我们实际修改遥控中,涉及到的修改主要是:

 修改物理键值(mtk_ir_cus_nes.h),和kl文件中的遥控器按键的映射关系值

一般我们的遥控器的的协议是NEC,需要修改的主要是物理按键和用户码,

物理键值和用户码,一般都会给出的。如果没有给出,我们可以通过遥控器内核打印来查看相应的物理键值和用户码

 

第七步 常见问题

 

1、厂商给的用户码和物理键值不对

答:通过遥控器的内核打印可以找到相应按键的物理键值和遥控器的用户码

2、 Kl文件书写问题

答: 当我们新的遥控添加进去后,发现部分按键操作不对。但是查找映射关系,都是对的。这个时候,我们需要查看下我们添加的kl文件是否加载上

解决方法,通过dumpsys命令来查看新加的kl文件是否加载进去,如果没有,说明新增的kl文件书写有问题,这个时候需要我们自己去一个个排查

 

3、Android如何加载遥控器kl文件

答:kl文件命令是有要求的,

Vendor_000b_Product_000b.kl 这个文件的命名规则是:

 红蓝色分别是VID和PID

如: kernel/ drivers/input/keyboard/atkbd.c键盘驱动中定义了 input_dev->id.vendor = 0×0001; input_dev->id.product = 0×0001;,那么与之对应的配置名为Vendor_0001_Product_0001.kl

 

MTK平台涉及到到的文件如下:

\mediatek\platform\mt8127\kernel\drivers\ir\mtk_ir_core.cmtk_ir_core.h

 

#define IR_BUS  BUS_HOST

#define IR_VERSION 11

#define IR_PRODUCT 11

#define IR_VENDOR 11

 

 

\mediatek\platform\mt8127\kernel\drivers\ir\mtk_ir_core.cmtk_ir_core.c

 

 

static int  mtk_ir_core_probe(struct platform_device*pdev)

{

 struct mtk_ir_core_platform_data *pdata =pdev->dev.platform_data;

 struct rc_dev *rcdev = NULL ;

 int ret = 0;

 

 /* id = -1, it is the mtk_ir_dev_parent,

    only for registerlirc_driver and begin mtk_ir_input_thread,

    bause lirc_driverand mtk_ir_input_thread  are for all devices*/

    if (-1 ==pdev->id)

    {  

       mtk_ir_core_create_attr(&(pdev->dev));// create device attribute

       ret =mtk_ir_lirc_register(&(pdev->dev));

    if (ret)

    {

   IR_LOG_ALWAYS("mtk_ir_lirc_register fail ret(%d) !!!\n",ret);

    }

    return ret;

    }

  

 /* register really ir device nec or rc5 orrc6 ....*/

 ASSERT(pdata != NULL);

 ASSERT(pdata->init_hw != NULL);

 ASSERT(pdata->uninit_hw != NULL);

 ASSERT(pdata->p_map_list != NULL);

 ASSERT(pdata->ir_hw_decode != NULL);

 

 platform_device_unregister(mtk_rc_core.dev_current);// first unregister old device

 ret = pdata->init_hw(); // init this  ir's  hw

 if (ret)

 {

  IR_LOG_ALWAYS(" fail to init_hw forir_dev(%s) ret = %d!!!\n",

               pdata->input_name, ret);

  goto err_init_hw;  

 }

 rcdev = rc_allocate_device(); // alloc rcdevice and rc->input

 if (!rcdev) {

  ret = -ENOMEM;

  IR_LOG_ALWAYS("rc_allocate_devicefail\n");

  goto err_allocate_device;

 }

   

 rcdev->driver_type = RC_DRIVER_SCANCODE;

 rcdev->allowed_protos =pdata->p_map_list->map.rc_type;

 rcdev->input_name = pdata->input_name;// /proc/bus/input/devices

 rcdev->input_id.bustype = BUS_HOST;

 rcdev->input_id.version = IR_VERSION;

 rcdev->input_id.product= IR_PRODUCT;

 rcdev->input_id.vendor= IR_VENDOR; 

 rcdev->driver_name = MTK_IR_DRIVER_NAME;

 rcdev->map_name =pdata->p_map_list->map.name;

    

 ret = rc_register_device(rcdev);

 if (ret < 0) {

  

  IR_LOG_ALWAYS( "failed to register rcdevice for ir_dev(%s) ret(%d)!!!\n",

                  pdata->input_name, ret);

  goto err_register_rc_device;

 }

 rc_set_keypress_timeout(pdata->i4_keypress_timeout);

 clear_bit(EV_MSC,rcdev->input_dev->evbit);

 clear_bit(MSC_SCAN,rcdev->input_dev->mscbit);

 #if MTK_IRRX_AS_MOUSE_INPUT

 mtk_rc_core.p_devmouse =mtk_ir_mouse_register_input(pdev);

 if (NULL == mtk_rc_core.p_devmouse)

 {

  IR_LOG_ALWAYS("fail to registerir_mouse device(%s)\n",pdata->mousename);

  goto err_register_mousedev;

  

 }

 #endif

 mtk_rc_core.rcdev = rcdev;

 mtk_rc_core.dev_current = pdev; 

     

 ret =mtk_ir_core_register_swirq(IRQF_TRIGGER_LOW);   

 if (ret)

 { 

  goto err_request_irq;

 }

 if (g_ir_timer.function == NULL)

 {

       init_timer(&g_ir_timer);

     g_ir_timer.function = mtk_ir_timer_function;

     g_ir_timer.expires = jiffies + TIMER_PERIOD;

     add_timer(&g_ir_timer);

 }

 return 0;

 

err_request_irq:

 rc_unregister_device(rcdev);

 rcdev = NULL;

err_register_mousedev:

err_register_rc_device:

 rc_free_device(rcdev);

 rcdev = NULL;

 mtk_rc_core.rcdev = NULL; 

err_allocate_device: 

   pdata->uninit_hw();

err_init_hw:

 

 return ret;

}

 

 

 

 

 

<think>嗯,用户想了解红外遥控器按键对应的键值获取方法。从用户的问题和提供的引用材料来看,用户应该是个开发者或者技术爱好者,正在做红外遥控相关的开发工作。 用户可能正在开发一个需要接收红外遥控输入的Android应用或Linux程序,遇到了键值映射的问题。深层需求可能是想实现自定义遥控功能,或者调试现有设备的红外接收问题。 这个问题涉及硬件和软件多个层面,需要分步骤解释。首先从硬件原理开始,红外信号经过接收头转换成电信号,然后由红外解码器解析成原始编码。这个原始编码就是最底层的键值表示,不同厂商的编码格式可能不同,比如NEC、RC5等。 在Linux环境下,用户可以通过串口或hidraw设备读取原始编码。引用2中的代码展示了在Linux下通过串口读取红外键值的方法,关键是要打开正确的设备节点,读取二进制数据后转换成十六进制表示。这里需要提醒用户注意设备节点的权限问题,以及原始编码的解析方法。 在Android环境下会更复杂些,系统已经内置了红外解码功能。引用1和3提到Android TV有专门的红外解码器,会将原始编码映射成系统标准的按键码。用户可以通过查看系统日志获取键值映射信息,或者修改映射表文件。引用3特别说明了Android的按键码定义在InputEventLabels.h和Keycodes.h中,这对开发者很有帮助。 用户可能还会遇到不同遥控器编码不同的问题,所以需要说明如何记录和学习新的遥控器键值。最后要提醒用户注意不同系统的差异,以及原始编码到系统键值的转换过程。 考虑到用户的技术背景,回答应该包含具体的技术实现细节,比如代码示例和系统文件路径。同时要强调调试技巧,因为实际开发中键值获取经常遇到问题。最后可以建议用户结合具体平台选择合适的方法,毕竟Linux和Android的实现方式差异很大。</think>要获取红外遥控器按键对应的键值,需要根据目标平台Android或Linux)采取不同的方法,核心是捕获原始红外编码并将其映射为标准键值。以下是具体方法: ### 一、通用原理 红外遥控器按键会发射独特的红外脉冲序列(如NEC、RC-5等协议)。接收设备(红外接收头)将其转换为电信号,**红外解码器**(硬件或软件)解析出原始编码值(Raw Code)。该原始编码需**通过映射表**转换为系统可识别的标准键值(如KEY_ENTER)。 ### 二、获取方法分平台 #### 1. **Linux系统** * **步骤1:读取原始红外编码** * 设备节点:通常为`/dev/lirc0`, `/dev/hidrawX` 或串口设备(如引用[2]中的`SERIALPORT_NAME`)。 * 代码示例(C语言): ```c #include <fcntl.h> #include <unistd.h> #define SERIALPORT_NAME "/dev/ttyUSB0" // 根据实际设备修改 u8 get_ir_key() { int fd = open(SERIALPORT_NAME, O_RDONLY); if (fd < 0) { perror("open IR device"); return 0xFF; } unsigned char buffer[32]; int len = read(fd, buffer, sizeof(buffer) - 1); close(fd); if (len > 0) { buffer[len] = '\0'; return buffer[0]; // 返回第一个字节(实际解析需根据协议) } return 0xFF; // 错误码 } ``` * **步骤2:映射原始编码到键值** * 创建**映射表**:将读取的原始编码(如`0xA1`)映射为Linux输入子系统键值(如`KEY_POWER`)。 * 工具:使用`ir-keytable`命令加载自定义映射表: ```bash sudo ir-keytable -c -p RC-5 -w /etc/rc_keymaps/my_remote ``` (`my_remote`文件定义 `0xA1 KEY_POWER` 等映射关系)。 #### 2. **Android系统** * **步骤1:获取系统层原始编码** * **查看内核日志**:按遥控器按键,通过`adb shell dmesg | grep -i "ir"` 或 `adb logcat | grep -i "ir"` 查找原始编码输出。 * **分析输入事件**:使用`adb shell getevent -l`,按遥控键观察输出(如 `event1: EV_KEY KEY_VOLUMEUP DOWN`),此处`KEY_VOLUMEUP`已是映射后的键值。 * **步骤2:修改/确认键值映射** * **映射文件位置**:`/system/usr/keylayout/Vendor_XXXX_Product_XXXX.kl`(`XXXX`为遥控器USB VID/PID)。 * **修改映射**:需Root权限,编辑`.kl`文件,将原始扫描码(`scancode`)关联到标准Android键值(定义在`Keycodes.h`[^3]),如: ``` key 0x5A KEY_MUTE ``` * **添加新设备**:若系统未自动识别,需在`/system/usr/keylayout/`下新增对应的`.kl`文件。 * **步骤3:应用层获取键值** * 在Activity中重写`onKeyDown()`方法: ```java @Override public boolean onKeyDown(int keyCode, KeyEvent event) { Log.d("IR_KEY", "KeyCode: " + keyCode); // 输出键值(如KEYCODE_VOLUME_UP=24) return super.onKeyDown(keyCode, event); } ``` ### 三、调试与学习工具 1. **红外编码嗅探器**:使用Arduino + IR接收头(如VS1838)配合`IRrecvDump`示例代码直接捕获原始协议类型和十六进制编码。 2. **Android App**:安装`KeyEvent Display`等应用,实时显示按键的KeyCode和扫描码。 ### 注意事项 1. **协议差异**:不同遥控器使用不同协议(NEC/Sony/RC6),需确认解码器支持。 2. **系统权限**:Linux访问设备节点/Android修改系统文件均需Root权限。 3. **映射表一致性**:确保`.kl`文件中的扫描码与驱动上报的原始编码匹配[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值