在我们平常的TV,商显,等电子类产品很多是需要遥控器操作的。首先遥控器也是一款标准的设备驱动,一起分享一下M平台遥控器驱动。
设备树
在配置文件m7221_an.dts,中定义了遥控器设备
ir {
compatible = "mstar-ir";
};
这里只配置遥控器设备驱动的名称。
注册驱动
通过设备驱动的名称,可以找到平台驱动code。
static struct platform_driver Mstar_ir_driver = {
.probe = mstar_ir_drv_probe,
.remove = mstar_ir_drv_remove,
.suspend = mstar_ir_drv_suspend,
.resume = mstar_ir_drv_resume,
.driver = {
#if defined(CONFIG_OF)
.of_match_table = mstarir_of_device_ids,
#endif
.name = "Mstar-ir",
.owner = THIS_MODULE,
.bus = &platform_bus_type,
}
};
static int __init mstar_ir_drv_init_module(void)
{
int ret = 0;
// 注册平台驱动
ret = platform_driver_register(&Mstar_ir_driver);
if (ret)
{
IRDBG_ERR("Register Mstar IR Platform Driver Failed!");
}
#ifdef CONFIG_MIRC_INPUT_DEVICE
#if(CONFIG_IR_KEYMAP_MSTAR_NEC)
init_key_map_mstar_tv();
init_key_map_cultraview_tv();
#endif
#if(CONFIG_IR_KEYMAP_TCL_RCA)
init_key_map_tcl_tv();
#endif
#if(CONFIG_IR_KEYMAP_TCL)
init_key_map_tcl_tv();
#endif
#if(CONFIG_IR_KEYMAP_CHANGHONG)
init_key_map_changhong_tv();
#endif
#if(CONFIG_IR_KEYMAP_HISENSE)
init_key_map_hisense_tv();
#endif
#if (CONFIG_IR_KEYMAP_HAIER)
init_key_map_haier_tv();
#endif
#if(CONFIG_IR_KEYMAP_KONKA)
init_key_map_konka_tv();
#endif
#if(CONFIG_IR_KEYMAP_SKYWORTH)
init_key_map_skyworth_tv();
#endif
#if(CONFIG_IR_KEYMAP_PANASONIC_7051)
init_key_map_p7051_stb();
#endif
#if(CONFIG_IR_KEYMAP_KATHREIN)
init_key_map_rc6_kathrein();
#endif
#if(CONFIG_IR_KEYMAP_RC5)
init_key_map_rc5_tv();
#endif
#if(CONFIG_IR_KEYMAP_METZ)
init_key_map_metz_rm18();
init_key_map_metz_rm19();
#endif
#endif
return ret;
}
注册完设备驱动之后,紧接着有注册了多款遥控器,最终通过MIRC_Map_Register将按键映射表添加到链表keymap_list中,
方便后面通过scancode 寻找keycode。
设备探测
/**===============end IR ATTR Functions ==================**/
static int mstar_ir_drv_probe(struct platform_device *pdev)
{
int ret=0;
if (!(pdev->name) || strcmp(pdev->name,"Mstar-ir")|| pdev->id!=0)
{
ret = -ENXIO;
}
IRDev.u32IRFlag = 0;
ret = mstar_ir_cdev_init();
if (ret < 0)
{
IRDBG_ERR("mstar_ir_cdev_init Failed! \n");
}
ret = mstar_ir_creat_sysfs_attr(pdev);
if (ret < 0)
{
IRDBG_ERR("mstar_ir_creat_sysfs_attr Failed! \n");
}
ret = mstar_ir_register_device(pdev);
if (ret < 0)
{
IRDBG_ERR("mstar_ir_register_device Failed! \n");
}
pdev->dev.platform_data=&IRDev;
mstar_ir_customer_config();
#ifdef CONFIG_MIRC_INPUT_DEVICE
mstar_ir_init(0);
IRDev.u32IRFlag |= (IRFLAG_IRENABLE|IRFLAG_HWINITED);
#endif
return ret;
}
mstar_ir_cdev_init 创建字符设备,mstar_ir_creat_sysfs_attr创建硬件设备驱动信息,mstar_ir_register_device 注册遥控器设备,mstar_ir_customer_config设置客户配置,mstar_ir_init 设置遥控器解码方式,注册中断。
注册设备
int mstar_ir_register_device(struct platform_device *pdev)
{
struct mstar_ir_dev *dev = NULL;
int ret;
#ifdef CONFIG_MIRC_INPUT_DEVICE
int i = 0;
#endif
//1. alloc struct ir_dev
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
//2. init locks
spin_lock_init(&dev->keylock);
spin_lock_init(&irq_read_lock);
mutex_init(&dev->lock);
mutex_lock(&dev->lock);
//3. init other args
dev->priv = &IRDev;
//4. init readfifo & sem & waitqueue
ret= kfifo_alloc(&dev->read_fifo,MAX_IR_DATA_SIZE,GFP_KERNEL);
if (ret<0)
{
IRDBG_ERR("ERROR kfifo_alloc!\n");
goto out_dev;
}
sema_init(&dev->sem, 1);
init_waitqueue_head(&dev->read_wait);
#ifdef CONFIG_MIRC_INPUT_DEVICE
//5. alloc struct input_dev
dev->input_dev = input_allocate_device();
if (!dev->input_dev)
{
ret = -ENOMEM;
goto out_kfifo;
}
input_set_drvdata(dev->input_dev, dev);
dev->input_name = MSTAR_IR_DEVICE_NAME;
dev->input_phys = "/dev/ir";
dev->driver_name = MSTAR_IR_DRIVER_NAME;
dev->map_num = NUM_KEYMAP_MSTAR_TV; //default :mstar keymap
//6. init®ister input device
dev->input_dev->id.bustype = BUS_I2C;
dev->input_dev->id.vendor = INPUTID_VENDOR;
dev->input_dev->id.product = INPUTID_PRODUCT;
dev->input_dev->id.version = INPUTID_VERSION;
set_bit(EV_KEY, dev->input_dev->evbit);
set_bit(EV_REP, dev->input_dev->evbit);
set_bit(EV_MSC, dev->input_dev->evbit);
set_bit(MSC_SCAN, dev->input_dev->mscbit);
dev->input_dev->dev.parent = &(pdev->dev);
dev->input_dev->phys = dev->input_phys;
dev->input_dev->name = dev->input_name;
for (i = 0; i<KEY_CNT; i++)
{
__set_bit(i, dev->input_dev->keybit);
}
__clear_bit(BTN_TOUCH,dev->input_dev->keybit);// IR device without this case
ret = input_register_device(dev->input_dev);
#endif
//7. register IR Data ctrl
ret = MIRC_Data_Ctrl_Init(dev);
if (ret < 0)
{
IRDBG_ERR("Init IR Raw Data Ctrl Failed!\n");
goto out_unlock;
return -EINVAL;
}
IRDev.pIRDev= dev;
mutex_unlock(&dev->lock);
return 0;
out_unlock:
mutex_unlock(&dev->lock);
#ifdef CONFIG_MIRC_INPUT_DEVICE
input_unregister_device(dev->input_dev);
dev->input_dev = NULL;
#endif
out_kfifo:
kfifo_free(&dev->read_fifo);
out_dev:
kfree(dev);
return ret;
}
- 创建锁
- 创建read fifo
- 创建wiatqueue
- 创建sme
- 创建,注册输入设备,input_allocate_device,input_register_device
设置vendor id , product id 分别为0x3697,0x0001,这一步是所有输入设
备。通过cat /proc/bus/input/devices,dumpsys input 指令查看注册的
所有输入设备,touch ,ir,mouse,keypad等等 - MIRC_Data_Ctrl_Init注册IR 数据kthread线程MIRC_Data_Ctrl_Thread
从kfifo中获取原始的按键数据
设置遥控器配置
#define NUM_KEYMAP_MSTAR_TV 0x807F
#define NUM_KEYMAP_CULTRAVIEW_TV 0x41FB
#define NUM_KEYMAP_HHT_TV 0x03FF
#define NUM_KEYMAP_TCL_TV 0x00F0
#define NUM_KEYMAP_CHANGHONG_TV 0x40BF
#define NUM_KEYMAP_HISENSE_TV 0x00BF
#define NUM_KEYMAP_HAIER_TV 0x1818
#define NUM_KEYMAP_KONKA_TV 0x0002
#define NUM_KEYMAP_SKYWORTH_TV 0x0E0E
#define NUM_KEYMAP_P7051_STB 0x484E5958
#define NUM_KEYMAP_KATHREIN_TV 0x8046
#define NUM_KEYMAP_TCL_RCA_TV 0xF000
#define NUM_KEYMAP_RC5_TV 0x0008
#define NUM_KEYMAP_METZ_RM18_TV 0x0609
#define NUM_KEYMAP_METZ_RM19_TV 0x0708
#define IR_SUPPORT_NUM 2
//Add & Modify Customer IR with Differ Headcode Here
static IR_Profile_t ir_config[IR_SUPPORT_NUM]=
{
// {IR_TYPE_NEC,NUM_KEYMAP_MSTAR_TV,0}, // Mstar IR customer code
{IR_TYPE_NEC,NUM_KEYMAP_HHT_TV,0}, // hht IR customer code
{IR_TYPE_NEC,NUM_KEYMAP_CULTRAVIEW_TV,0}, // cultraview IR customer code
//{IR_TYPE_TOSHIBA,NUM_KEYMAP_SKYWORTH_TV,0}, //skyworth toshiba ir
//{IR_TYPE_NEC,NUM_KEYMAP_CHANGHONG_TV,0}, // changhong_RL78B /Toshiba CT-90436 IR customer code
//{IR_TYPE_NEC,NUM_KEYMAP_HISENSE_TV,0}, // Hisense IR customer code
//{IR_TYPE_RCA,NUM_KEYMAP_TCL_RCA_TV,0}, // TCL RCA customer code
//{IR_TYPE_P7051,NUM_KEYMAP_P7051_STB,0}, // Panasonic 7051 IR customer code
//{IR_TYPE_RC5,NUM_KEYMAP_RC5_TV,0}, // RC5 customer code
//{IR_TYPE_RC6,NUM_KEYMAP_KATHREIN_TV,0}, //Kathrein RC6 customer code
//{IR_TYPE_KONKA,NUM_KEYMAP_KONKA_TV,2},
};
static void mstar_ir_customer_config(void)
{
MIRC_Set_IRDBG_Level(ir_dbglevel);
MIRC_Set_IRSpeed_Level(ir_speed);
MIRC_IRCustomer_Config(ir_config,IR_SUPPORT_NUM);
return ;
}
配置遥控器的打印级别,速率,支持的遥控器的协议和头码。
设置中断
static void mstar_ir_init(int bResumeInit)
{
int ret = 0;
struct mstar_ir_dev *dev = IRDev.pIRDev;
//Prevent residual value exist in sw fifo when system wakeup from standby status
REG(REG_IR_CTRL) &= (0xFF00); //disable IR ctrl regs
REG(REG_IR_SEPR_BIT_FIFO_CTRL) &= (0xFF); //disable IR FIFO settings
if(NULL == dev)
return ;
switch(dev->ir_mode)
{
case IR_TYPE_FULLDECODE_MODE:
{
mstar_ir_hw_fulldecode_config();
}
break;
case IR_TYPE_RAWDATA_MODE :
{
mstar_ir_hw_rawdecode_config();
}
break;
case IR_TYPE_HWRC5_MODE :
{
mstar_ir_hw_rc5decode_config();
}
break;
case IR_TYPE_HWRC5X_MODE :
{
mstar_ir_hw_rc5decode_config();
}
break;
case IR_TYPE_HWRC6_MODE :
{
mstar_ir_hw_rc6decode_config();
}
break;
case IR_TYPE_SWDECODE_MODE :
{
mstar_ir_sw_decode_config();
}
break;
default:
IRDBG_INFO("No IR Mode Support!\n");
break;
}
if ((!bResumeInit) &&(ir_irq_sel ==0xFF))
{
ir_irq_enable = 0;
if((dev->ir_mode == IR_TYPE_HWRC5_MODE)||(dev->ir_mode == IR_TYPE_HWRC5X_MODE)||(dev->ir_mode == IR_TYPE_HWRC6_MODE))
{
......
}
else
{
ret = request_irq(INT_NUM_IR_ALL, _MDrv_IR_ISR, SA_INTERRUPT, "IR", &IRDev);
ir_irq_sel = 0;
}
......
}
return ;
}
根据配置的遥控器解码方式,做好寄存器配置;接着request_irq(INT_NUM_IR_ALL, _MDrv_IR_ISR, SA_INTERRUPT, “IR”, &IRDev);申请中断。
中断处理
irqreturn_t _MDrv_IR_ISR(int irq, void *dev_id)
{
IRModHandle *mstar_dev = dev_id;
int ret = 0;
if (NULL == mstar_dev)
return -EINVAL;
if(mstar_dev->pIRDev->ir_mode == IR_TYPE_FULLDECODE_MODE)
ret = mstar_ir_isr_getdata_fulldecode(mstar_dev);
else if(mstar_dev->pIRDev->ir_mode == IR_TYPE_RAWDATA_MODE)
ret = mstar_ir_isr_getdata_rawdecode(mstar_dev);
else
{
spin_lock(&irq_read_lock);
while ( ((REG(REG_IR_SHOT_CNT_H_FIFO_STATUS) & IR_FIFO_EMPTY) != IR_FIFO_EMPTY))
{
ret = mstar_ir_isr_getdata_swdecode(mstar_dev);
if(ret < 0)
{
spin_unlock(&irq_read_lock);
return IRQ_HANDLED;
}
REG(REG_IR_FIFO_RD_PULSE) |= 0x0001;
}
spin_unlock(&irq_read_lock);
}
if(ret >= 0)
MIRC_Data_Wakeup(mstar_dev->pIRDev);
return IRQ_HANDLED;
}
中断触发后,获取按键值数据,然后写进fifo,最后唤醒线程。
下面以IR_TYPE_FULLDECODE_MODE 说明
int mstar_ir_isr_getdata_fulldecode(IRModHandle *mstar_dev)
{
int ret = 0;
u8 u8Ir_Index = 0;
u8 u8Keycode = 0;
u8 u8Repeat = 0;
u32 u32IRSpeed = 0;
if(REG(REG_IR_SHOT_CNT_H_FIFO_STATUS) & IR_FIFO_EMPTY)
{
return -1;
}
DEFINE_IR_RAW_DATA(ev);
u8Keycode = REG(REG_IR_CKDIV_NUM_KEY_DATA) >> 8;
u8Repeat = (REG(REG_IR_SHOT_CNT_H_FIFO_STATUS) & IR_RPT_FLAG)? 1 : 0;
u8Ir_Index = REG(REG_IR_SHOT_CNT_H_FIFO_STATUS) & 0x40? 1 : 0;//IR remote controller TX1 send flag
REG(REG_IR_FIFO_RD_PULSE) |= 0x0001;
// duration = head code | keyCode
ev.duration = (u32IRHeaderCode[u8Ir_Index]<<8) | u8Keycode;
ev.pulse = u8Repeat;
IRDBG_INFO(" u8Ir_Index = %d\n",u8Ir_Index);
IRDBG_INFO("[Full Decode] Headcode =%x Key =%x\n",u32IRHeaderCode[u8Ir_Index],u8Keycode);
mstar_dev->pIRDev->map_num = mstar_dev->pIRDev->support_ir[u8Ir_Index].u32HeadCode;
u32IRSpeed = mstar_dev->pIRDev->support_ir[u8Ir_Index].u32IRSpeed;
if(u8Repeat)
{
if (((u32IRSpeed != 0)&&( u8RepeatCount < (u32IRSpeed - 1)))
|| ((u32IRSpeed == 0)&&(u8RepeatCount < mstar_dev->pIRDev->speed)))
{
u8RepeatCount ++;
mstar_ir_nec_clearfifo();
return -1;
}
}
else
{
u8RepeatCount = 0;
}
ret = MIRC_Data_Store(mstar_dev->pIRDev, &ev);
if (ret < 0)
{
IRDBG_ERR("Store IR data Error!\n");
}
mstar_ir_nec_clearfifo();
return ret;
}
int MIRC_Data_Store(struct mstar_ir_dev *dev, struct ir_raw_data *ev)
{
if (!dev->raw)
return -EINVAL;
// 按键数据写入fifo
if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
return -ENOMEM;
return 0;
}
void MIRC_Data_Wakeup(struct mstar_ir_dev *dev)
{
unsigned long flags;
if (!dev->raw)
return;
spin_lock_irqsave(&dev->raw->lock, flags);
wake_up_process(dev->raw->thread);
spin_unlock_irqrestore(&dev->raw->lock, flags);
}
唤醒线程MIRC_Data_Ctrl_Thread往fifo 读取数据,接着解析。
数据解析
中断回调收取原始数据,转发值fifo 后,线程从fifo 读取数据并解析数据
static int MIRC_Data_Ctrl_Thread(void *data)
{
struct ir_raw_data ev;
struct ir_raw_data_ctrl *raw = (struct ir_raw_data_ctrl *)data;
int retval;
int get_scancode;
while (!kthread_should_stop())
{
get_scancode = 0;
spin_lock_irq(&raw->lock);
retval = kfifo_len(&raw->kfifo);
if (retval < sizeof(ev))
{
set_current_state(TASK_INTERRUPTIBLE);
if (kthread_should_stop())
set_current_state(TASK_RUNNING);
spin_unlock_irq(&raw->lock);
schedule();
continue;
}
// 获取fifo 的数据
retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev));
spin_unlock_irq(&raw->lock);
mutex_lock(&ir_decoder_lock);
// 软解吗
if(raw->dev->ir_mode == IR_TYPE_SWDECODE_MODE) //sw decoder
{
struct ir_decoder_handler *handler;
IRDBG_MSG("shotcount[ %5d %d ]\n",ev.duration, ev.pulse);
list_for_each_entry(handler, &ir_decoder_list, list){
if(handler->decode(raw->dev, ev) > 0){
get_scancode = 1;
break;
}
}
}
else //hw decoder 硬解码
{
raw->this_sc.scancode = ev.duration;
raw->u8RepeatFlag = ev.pulse;
get_scancode = 1;
IRDBG_MSG("keycode =%x repeatflag =%d \n",raw->this_sc.scancode,raw->u8RepeatFlag);
}
if (get_scancode)
{
//diff protocol
if(raw->u8RepeatFlag == 1)
{
eventtimeout = IR_DEFAULT_TIMEOUT;
}
else
{
eventtimeout = IR_FIRST_REPEAT_TIMEOUT;
}
_ulLastKeyPresentTime = MIRC_Get_System_Time();
if(raw->dev->filter_flag == 0)
{
#ifdef CONFIG_MIRC_INPUT_DEVICE
//diff protocol
if (raw->this_sc.scancode_protocol!= raw->prev_sc.scancode_protocol)
{
//if before timeout send keyup + keydown
if (time_after_eq((raw->keyup_jiffies+msecs_to_jiffies(eventtimeout)),jiffies))
{
MIRC_Keyup(raw->dev);
}
IRDBG_INFO("[2]========= Down First!\n");
MIRC_Keydown(raw->dev, raw->this_sc.scancode);//first keydown
}
else// same protocol
{
if (raw->this_sc.scancode != raw->prev_sc.scancode)// diff key press
{
//if before timeout send keyup + keydown
if (time_after_eq((raw->keyup_jiffies+msecs_to_jiffies(eventtimeout)),jiffies))
{
MIRC_Keyup(raw->dev);
}
IRDBG_INFO("[1]========= Down First!\n");
MIRC_Keydown(raw->dev, raw->this_sc.scancode);//first keydown
}
else
{
if((raw->u8RepeatFlag == 0)&& (!raw->dev->keypressed ))// press the same fast
{
MIRC_Keydown(raw->dev, raw->this_sc.scancode);
}
else
{
IRDBG_INFO("========= Repeat!\n");
}
}
}
}
del_timer(&(raw->timer_keyup));
raw->timer_keyup.expires = jiffies + msecs_to_jiffies(eventtimeout);
raw->keyup_jiffies = jiffies;
raw->timer_keyup.data = (unsigned long)raw->dev;
add_timer(&(raw->timer_keyup));
#else
// for DFB polling read /dev/ir
if (down_trylock(&raw->dev->sem)==0)
{
IRDBG_INFO("scancode =%x \n",raw->this_sc.scancode);
if (kfifo_in(&raw->dev->read_fifo, &raw->this_sc.scancode, sizeof(u32)) != sizeof(u32))
{
up(&raw->dev->sem);
mutex_unlock(&ir_decoder_lock);
return -ENOMEM;
}
up(&raw->dev->sem);
wake_up_interruptible(&raw->dev->read_wait);
}
#endif
//record IR last scancode
raw->prev_sc.scancode_protocol = raw->this_sc.scancode_protocol;
raw->prev_sc.scancode = raw->this_sc.scancode;
raw->this_sc.scancode_protocol = 0;
raw->this_sc.scancode = 0x0;
raw->u8RepeatFlag = 0;
}
mutex_unlock(&ir_decoder_lock);
}
return 0;
}
MIRC_Keydown 解析分发数据
void MIRC_Keydown(struct mstar_ir_dev *dev, int scancode)
{
unsigned long flags;
u32 keycode = MIRC_Keycode_From_Map(dev->map_num, scancode);
if (keycode == KEY_RESERVED)
{
IRDBG_ERR("Key Map Match scancode Failed!\n");
return ;
}
spin_lock_irqsave(&dev->keylock, flags);
MIRC_Do_Keydown(dev, scancode, keycode);
spin_unlock_irqrestore(&dev->keylock, flags);
}
MIRC_Keycode_From_Map从注册key map 链表keymap_list 中遍历,去匹配遥控器头码。
static u32 MIRC_Keycode_From_Map(u32 keymapnum,u32 scancode)
{
struct key_map_list *map = NULL;
u32 keycode = KEY_RESERVED;
u8 i=0;
bool match_flag = false;
spin_lock(&key_map_lock);
list_for_each_entry(map, &keymap_list, list)
{
if (((scancode>>8) == map->map.headcode) || (keymapnum == map->map.headcode))
{
IRDBG_INFO("[Match] Keymap Name: %s\n",map->map.name);
match_flag = true;
break;//find IR map
}
}
if (match_flag)
{
......
}
spin_unlock(&key_map_lock);
return keycode;
}
MIRC_Do_Keydown 拼接成标注的输入事件,通过/dev/input/eventX
发往上层。
static void MIRC_Do_Keydown(struct mstar_ir_dev *dev, int scancode,u32 keycode)
{
bool new_event = !dev->keypressed ||
dev->last_scancode != scancode;
if (new_event && dev->keypressed)
MIRC_Do_Keyup(dev, false);
input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode);
if (new_event && keycode != KEY_RESERVED) {
/* Register a keypress */
dev->keypressed = true;
dev->last_scancode = scancode;
dev->last_keycode = keycode;
input_report_key(dev->input_dev, keycode, 1);
}
input_sync(dev->input_dev);
}
例如home键
添加一款遥控器
ir_config.h
ir_common.h
mstar_ir.h
keymap-cultraview-tv.c,定义key_map_table ,添加scancode,和keycode 的映射。
#include <linux/kernel.h>
#include <linux/module.h>
#include "../ir_core.h"
#include "../ir_common.h"
static struct key_map_table cultraview_tv[] = {
// 2nd IR controller.
{ 0xfb82, KEY_POWER },
{ 0xfb9b, KEY_CHANNELUP },
{ 0xfb8f, KEY_CHANNELDOWN },
{ 0xfb97, KEY_MENU },
.........
{ 0xfbFC, KEY_POWER2 },
};
static struct key_map_list cultraview_tv_map = {
.map = {
.scan = cultraview_tv,
.size = ARRAY_SIZE(cultraview_tv),
.name = NAME_KEYMAP_CULTRAVIEW_TV,
.headcode = NUM_KEYMAP_CULTRAVIEW_TV,
}
};
int init_key_map_cultraview_tv(void)
{
return MIRC_Map_Register(&cultraview_tv_map);
}
EXPORT_SYMBOL(init_key_map_cultraview_tv);
void exit_key_map_cultraview_tv(void)
{
MIRC_Map_UnRegister(&cultraview_tv_map);
}
EXPORT_SYMBOL(exit_key_map_cultraview_tv);
mdrv_ir.c 添加key code 与字符串的映射,getevent -l 时,可以正确知道底层映射关系
static const str2key_map_t str2key_map[] =
{
{ "KEY_POWER", KEY_POWER },
{ "KEY_MUTE", KEY_MUTE },
{ "KEY_HOME", KEY_HOME },
{ "KEY_ENTER", KEY_ENTER },
{ "KEY_UP", KEY_UP },
{ "KEY_DOWN", KEY_DOWN },
{ "KEY_LEFT", KEY_LEFT },
{ "KEY_RIGHT", KEY_RIGHT },
{ "KEY_BACK", KEY_BACK},
{ "KEY_MENU", KEY_MENU },
......
}
mstar_ir.c 注册新增key map
static int __init mstar_ir_drv_init_module(void)
{
int ret = 0;
......
init_key_map_cultraview_tv();
......
return ret;
}
static void __exit mstar_ir_drv_exit_module(void)
{
......
exit_key_map_cultraview_tv();
}
添加说明:
- 遥控器头码要正确;
- 注意key_map_table 中的scancode 中前面8位为headcode ,scancode
为后面8位,keycode 是值在
vendor\mstar\kernel\linaro\include\uapi\linux\input-event-codes.h中定
义,getevent 无打印响应时,就有key map 没有配置正确; - getevnet 收到按键的信息之后,就需要在android层映射keycode 到应用
层的keyevent code
例如kl 文件第一列是keycode 的值(十进制),第二列则是对应frameworks\native\include\android\keycodes.h 文件中的枚举去掉AKEYCODE_前缀之后的字符串。注意kl 文件中如果有定义的配置找不到
就有可能是按键不响应,或者到没有使用配置的kl文件,而使用了系统默认Generic.kl. - IR调试方法,echo 4 > ./sys/bus/platform/drivers/Mstar-ir/ir/IRDebug
打开IR模块驱动打印,记得printk 节点也要为7。