Mstar平台_遥控器驱动

IR框架分为四层:IR Driver层,IR core层, Decoder层, Keymap层。
iput_dev层 input_core层 input_handle层 映射层

红外遥控器驱动 类似于输入子系统中的 input_device层 硬件初始化,fops操作

IR Driver层: 需要实现IR Driver的一些init,interrupt处理,file_operations操作等。
IR core层:需要实现提供给decoder层,keymap层的相关接口,raw数据处理接口,input相关接口等。
Decoder层:需要实现不同protocols的解析函数。
Keymap层:需要实现针对不同IR的keymap映射关系。

这里我们根据公司的中性遥控器 为例

IR Driver层代码: kernel\mstar2\drv\ir_mirc\mstar_ir.c
IR CORE层代码: kernel\mstar2\drv\ir_mirc\ir_core.c
protocols: kernel\mstar2\drv\ir_mirc\protocols\ir-nec-decoder.c ==>nec解码 Decoder层
keymaps: kernel\mstar2\drv\ir_mirc\keymaps\keymap-mstar-tv.c ==>把按键的扫描值映射成keycode值 keycode值是上报给android层处理的

IR 的配置有两种:

  1. Ir_config.h 进行配置,在编译阶段配置好客户要使用的遥控器。 ==>我们公司是使用了这种配置方式
  2. Ir_config.ini进行配置,可以动态配置客户要使用的遥控器。
    两种配置方式可以单独配置使用,也可以同时配置使用。

1> 分析配置文件
文件路径: mstar2/drv/ir_mirc/lr_config.h

#ifndef _IR_CONFIG_H_
#define _IR_CONFIG_H_
#include "mstar_ir.h"		//==>这3个.h文件 前两个就是驱动文件的.h文件,ir_common.h文件是我们公司对应的配置文件之一 (定义了头码,解码类型...)
#include "ir_core.h"
#include "ir_common.h"

/****************** For Customer Config  Start [can modify by customers] ********************/
//Number of IR should this chip supported		该芯片应支持的IR数: ==>  表示该系统支持2款遥控器  
#define IR_SUPPORT_NUM 2

//Add & Modify Customer IR with Differ Headcode Here   在这里添加和修改不同头码的客户IR   ==> ir_config这个结构体中的成员就是一种遥控器的信息
static IR_Profile_t ir_config[IR_SUPPORT_NUM]=
{
	// {IR_TYPE_NEC,NUM_KEYMAP_MSTAR_TV,0},         // Mstar 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_NEC, NUM_KEYMAP_MSTAR_TV, 0},
	//{IR_TYPE_RC6,NUM_KEYMAP_KATHREIN_TV,0},       // Kathrein RC6 customer code
	//{IR_TYPE_KONKA,NUM_KEYMAP_KONKA_TV,2},
	{IR_TYPE_PANASONIC,NUM_KEYMAP_PANASONIC_TV,2},
};


//IR Debug level for customer setting
static IR_DBG_LEVEL_e ir_dbglevel = IR_DBG_ERR;

//IR Speed level for customer setting
static IR_SPEED_LEVEL_e ir_speed = IR_SPEED_FAST_H;

/****************** For Customer Config  End [can modify by customers] ********************/

#endif

代码分析 ir_config: 
//Description  of IR
typedef struct IR_Profile_s {
	IR_Type_e eIRType;			//协议类型
	u32 u32HeadCode;			//头码值
	u32 u32IRSpeed;				//遥控器灵敏度
}IR_Profile_t;

我们这里配置了两种遥控器{IR_TYPE_NEC, NUM_KEYMAP_MSTAR_TV, 0},  {IR_TYPE_PANASONIC,NUM_KEYMAP_PANASONIC_TV,2},
我们通常使用的是{IR_TYPE_NEC, NUM_KEYMAP_MSTAR_TV, 0}, 	即NEC编码协议
NUM_KEYMAP_MSTAR_TV值的来源
	|
mstar2/drv/ir_mirc/ir_common.h 文件中定义的  ==>3个头文件之一      ****************** 这就是我们在配置kernel 遥控器信息中的一个步骤
在ir_common.h中为了实现客户的定制化遥控器功能  我们通过宏来区分客户不同的NEC协议的头码

//每个宏定义对应一个客户遥控器
#define CUSTOMER_IR_MSTAR 0
#define CUSTOMER_IR_SYKJWB  1					//中性
#define CUSTOMER_IR_PROMETH_EN  2
#define CONFIG_CUSTOMER_VIEWSONIC  3
#define CONFIG_CUSTOMER_PROWISE  4
#define CONFIG_CUSTOMER_WJCIRTEXT  5

#define CUSTOMER_IR_SELECT  CONFIG_CUSTOMER_WJCIRTEXT //CUSTOMER_IR_MSTAR   最终宏 

//不同的客户有主见不同的NEC遥控器的头码
#if(CUSTOMER_IR_SELECT == CUSTOMER_IR_SYKJWB)
#define    NUM_KEYMAP_MSTAR_TV                   0x4040
#elif(CUSTOMER_IR_SELECT == CUSTOMER_IR_PROMETH_EN)
#define    NUM_KEYMAP_MSTAR_TV                0x01FE
#elif(CUSTOMER_IR_SELECT == CONFIG_CUSTOMER_VIEWSONIC )
#define    NUM_KEYMAP_MSTAR_TV                0x0000
#elif(CUSTOMER_IR_SELECT == CONFIG_CUSTOMER_PROWISE)
#define    NUM_KEYMAP_MSTAR_TV                  0x20DF
#elif(CUSTOMER_IR_SELECT == CONFIG_CUSTOMER_WJCIRTEXT)
#define    NUM_KEYMAP_MSTAR_TV                  0x4040
#else
#define    NUM_KEYMAP_MSTAR_TV                0x807F


代码分析: 配置IR debug 级别
//IR Debug level for customer setting
static IR_DBG_LEVEL_e ir_dbglevel = IR_DBG_ERR;
==> 默认设置成error打印 
关键点: 在IR驱动中 除了在_MDrv_IR_ISR中不能加log打印外,其他地方都能加log进行打印
修改打印级别的方法: *********** *****************
先找到存放打印级别的属性文件,这个属性文件是在 mstar_ir.c中实现的 mstar_ir_drv_probe() --> mstar_ir_creat_sysfs_attr() --> device_create_file(dev, &dev_attr_IRDebug) 
find / -name IRDebug  ==>先找到该属性文件的路径
echo 4 > xxx/IRDebug   ==>修改该属性文件的打印级别 
cat  xxx/IRDebug	  ==>查看属性文件的当前打印级别和支持的打印级别  
==> 其实这个实现方法 不就是printk中设置7个级别的打印方法吗?     
具体操作
IFP:/ #su
IFP:/ # find / -name IRDebug
/sys/devices/ir/IRDebug

IFP:/sys/devices/ir # ls
IRDebug   IRProtocols  driver           modalias  subsystem  
IREnable  IRSpeed      driver_override  of_node   uevent     
IREvent   IRTimeout    input            power  

开头是大写的文件都是通过函数mstar_ir_creat_sysfs_attr创建的

查看 打印级别
IFP:/sys/devices/ir # cat IRDebug                                              
Current Debug Level:  1

修改打印级别为 4
IFP:/sys/devices/ir #echo 4 > IRDebug

代码分析: 配置IR Speed
//IR Speed level for customer setting
static IR_SPEED_LEVEL_e ir_speed = IR_SPEED_FAST_H;  // IR_SPEED_FAST_H == 0  ==> 表示不会附带重复波形,按一下就发送一个波形
ir_speed:要设置的原因 ,因为不同的遥控器的灵敏度可能不同,也许你短按一下按键,发送出去的是好几个重复波形,如果不做处理会就会造成,我按一下,上层相应几下的情况
故需要设置这个属性来过滤附带的重复波形,   ir_speed = 2 ==> 过滤两个波形

2> 分析ir_driver驱动文件 mstar_ir.c

//驱动入口函数
module_init(mstar_ir_drv_init_module);

//加载函数
static int __init mstar_ir_drv_init_module(void)
{
	int ret = 0;
	ret = platform_driver_register(&Mstar_ir_driver);   //注册设备驱动  使用了platform框架来实现 input_dev层
	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();
#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
#if(CONFIG_IR_KEYMAP_PANASONIC)
	init_key_map_panasonic_tv();
#endif
#endif
	return ret;
}
==>
注册完设备驱动之后,紧接着有注册了多款遥控器,最终通过MIRC_Map_Register将按键映射表添加到链表keymap_list中,方便后面通过scancode 寻找keycode。
#ifdef CONFIG_MIRC_INPUT_DEVICE 这个宏=1 
==> kernel根目录下的 .config文件中有如下定义
#
# Mstar IR Config
#
# CONFIG_IR_DYNAMIC_CONFIG is not set
CONFIG_MIRC_INPUT_DEVICE=y   

除了直接修改.config文件外,还可以通过make menuconfig来修改配置
查看 ir_mirc目录下的Kconfig文件,内容如下
config MSTAR_IR_REFACTOR
tristate "Mstar IR Driver"
default y
help
	Mstar IR decoder driver function
menu "Mstar IR Config"
	depends on MSTAR_IR_REFACTOR
config IR_DYNAMIC_CONFIG
		depends on MIRC_INPUT_DEVICE
	tristate "load ir config(header,protocol,keymap) from /config/ir_config"
	default n						==> 对应CONFIG_IR_DYNAMIC_CONFIG is not set 
config MIRC_INPUT_DEVICE			
	bool "IR Key send to input subsystem"
	default y						==> 对应CONFIG_MIRC_INPUT_DEVICE=y
if MIRC_INPUT_DEVICE
source "drivers/mstar2/drv/ir_mirc/keymaps/Kconfig"
endif
endmenu

CONFIG_IR_KEYMAP_MSTAR_NEC这个宏 同理查看.config文件有如下定义
CONFIG_IR_KEYMAP_MSTAR_NEC=y
CONFIG_IR_KEYMAP_TCL_RCA=y
CONFIG_IR_KEYMAP_TCL=y
CONFIG_IR_KEYMAP_CHANGHONG=y
CONFIG_IR_KEYMAP_HISENSE=y
CONFIG_IR_KEYMAP_HAIER=y
CONFIG_IR_KEYMAP_KONKA=y
CONFIG_IR_KEYMAP_SKYWORTH=y
CONFIG_IR_KEYMAP_PANASONIC_7051=y
CONFIG_IR_KEYMAP_KATHREIN=y
CONFIG_IR_KEYMAP_RC5=y
CONFIG_IR_KEYMAP_METZ=y
CONFIG_IR_KEYMAP_PANASONIC=y
CONFIG_MSTAR_IOMAP=y

然后配置: 前面的ir_mirc目录下的Kconfig文件中说明如果对应CONFIG_MIRC_INPUT_DEVICE=y就执行mstar2/drv/ir_mirc/keymaps/Kconfig这个文件
mstar2/drv/ir_mirc/keymaps/Kconfig文件的内容
menu "Mstar IR Keymap Select"
depends on MIRC_INPUT_DEVICE
config IR_KEYMAP_MSTAR_NEC
	bool "Mstar NEC keymaps"
	default y
	help
	Mstar nec keymap
config IR_KEYMAP_TCL_RCA
	bool "TCL RCA keymaps"
	default y
	help
	TCL RCA keymaps
config IR_KEYMAP_TCL
	bool "TCL keymaps"
	default y
	help
	TCL tv keymaps
config IR_KEYMAP_CHANGHONG
	bool "Changhong IR keymaps"
	default y
	help
	Changhong tv keymaps
config IR_KEYMAP_HISENSE
	bool "Hisense IR keymaps"
	default y
	help
	Hisense tv keymaps
config IR_KEYMAP_HAIER
	bool "Haier IR keymaps"
	default y
	help
	Haier tv keymaps
config IR_KEYMAP_KONKA
	bool "Konka IR keymaps"
	default y
	help
	Konka tv keymaps
config IR_KEYMAP_SKYWORTH
	bool "Skyworth IR keymaps"
	default y
	help
	Skyworth tv keymaps
config IR_KEYMAP_PANASONIC_7051
	bool "Pnasonic 7051 IR keymaps"
	default y
	help
	panasonic tv keymaps
config IR_KEYMAP_KATHREIN
	bool "Kathrein RC6 MODE_6A IR keymaps"
	default y
	help
	Kathrein tv keymaps
config IR_KEYMAP_RC5
	bool "RC5 IR keymaps"
	default y
	help
	RC5 tv keymaps
config IR_KEYMAP_METZ
	bool "metz IR keymaps"
	default y
	help
	metz tv keymaps
config IR_KEYMAP_PANASONIC
	bool "Panasonic IR keymaps"
	default y
	help
	Panasonic tv keymaps	

endmenu

==> 显然这里就是要我们配置要注册哪些遥控器了   
这里我们以我们公司现在的映射文件keymap-mstar-tv.c为例简单跟读 
#if(CONFIG_IR_KEYMAP_MSTAR_NEC)
	init_key_map_mstar_tv();
#endif

这里init_key_map_mstar_tv函数就是keymap-mstar-tv.c文件中的加载函数  故这里就相当于加载了keymap-mstar-tv.c文件对应的映射驱动

******** ************************************这里开始分析keymap-mstar-tv.c文件 即映射文件: 扫描码映射成keycode,然后将映射表注册到ir_core中的存放所有映射表的链表中
int init_key_map_mstar_tv(void)
{
	return MIRC_Map_Register(&mstar_tv_map);		//将该文件配置的映射表添加到ir_core中统一存放映射表的链表keymap_list中, 目的是为了方便后面通过scancode 寻找keycode 即后面 有按键按下,我知道了它的扫描码,直接去这个链表中寻找它对应的keycode值即可
}

keymap-mstar-tv.c文件的按键映射表 mstar_tv_map
static struct key_map_list mstar_tv_map = {
	.map = {
		.scan     = mstar_tv,				//具体的映射关系表
		.size     = ARRAY_SIZE(mstar_tv),	//多少个按键映射对
		.name     = NAME_KEYMAP_MSTAR_TV,	//该按键映射表的名称   在ir_common.h中定义 #define NAME_KEYMAP_MSTAR_TV                  "ir-mstar-tv"  
		.headcode = NUM_KEYMAP_MSTAR_TV,	//头码  			   在ir_common.h中定义 #define    NUM_KEYMAP_MSTAR_TV                   0x4040
	}
};
具体的映射关系表的定义
static struct key_map_table mstar_tv[] = {		
#if(CUSTOMER_IR_SELECT == CUSTOMER_IR_SYKJWB)
	{ 0x0A, KEY_POWER }, //POWER
	{ 0x0F, KEY_MUTE }, //MUTE
	{ 0x40, KEY_MENU }, //MENU
	{ 0x18, KEY_BACK }, //RETURN
	{ 0x0B, KEY_UP }, //UP
	{ 0x0E, KEY_DOWN }, //DOWN
	{ 0x10, KEY_LEFT }, //LEFT
	{ 0x11, KEY_RIGHT }, //RIGHT
	{ 0x0D, KEY_ENTER }, //OK
	{ 0x15, KEY_VOLUMEUP }, //V+
	{ 0x1C, KEY_VOLUMEDOWN }, //V-
	{ 0x1B, KEY_HOME }, //HOME	no result
	{ 0x33, KEY_FN_F1 }, //OPS
	{ 0x37, KEY_FN_F2 }, //WB
	{ 0x41, KEY_KP1 }, //SOURCE
	{ 0x0C, KEY_FN_F6 }, //SCREENSHOT
	{ 0x00, KEY_F1},	//F1
	{ 0x00, KEY_F1},	//F1
#elif (CUSTOMER_IR_SELECT == CONFIG_CUSTOMER_PROWISE)    
	{ 0x52, KEY_POWER }, //POWER    
	{ 0x0D, KEY_MENU }, //MENU    
	{ 0x47, KEY_UP }, //UP    
	{ 0x4D, KEY_DOWN }, //DOWN    
	{ 0x49, KEY_LEFT }, //LEFT   
	{ 0x4B, KEY_RIGHT }, //RIGHT    
	{ 0x4A, KEY_ENTER }, //OK   
	{ 0x07, KEY_KP1 }, //SOURCE 
	{ 0x48, KEY_HOME }, //HOME  
	{ 0x03, KEY_VOLUMEUP }, //V+  
	{ 0x4E, KEY_F10}, //FREEZE   
	{ 0x0A, KEY_FN_F5 }, //SETTING  
	{ 0x41, KEY_VOLUMEDOWN }, //V-  
	{ 0x5C, KEY_KP8 }, //TOUCH 
	{ 0x40, KEY_BACK }, //RETURN   
	{ 0x53, KEY_MUTE }, //MUTE
... ...

}
==> 会进行客制化处理,不同的客户遥控器通过定义宏区分,最后通过宏CUSTOMER_IR_SELECT来表示选择哪个客户遥控器   **** 这些宏在ir_common.h中定义
分析映射对
{ 0x0A, KEY_POWER }, //POWER
0x0A: 按键的扫描码 ,在遥控器规格书中得到	
KEY_POWER: keycode按键值,即该按键代表的作用
当遥控器按下POWER键,触发中断,中断会上报 0x0A这个值到ir_core层,ir_core会把这个值发送给解码驱动ir-nec-decoder.c ,然后按键解码驱动会匹配keymap链表中的那些映射表,然后找到该扫描码对应的keycode值,
然后就会将keycode值上报给Android。


分析是如何将每一个遥控器的映射表注册到keymap_list链表中的?
MIRC_Map_Register(&mstar_tv_map);
	|
//key map functions     ******** 这个函数是定义在 ir_core.c中  所以keymap_list应该也是在这里定义的   *** static LIST_HEAD(keymap_list);   *************** ir_core.c中记录了所有映射表 **********
int MIRC_Map_Register(struct key_map_list *map)
{
	spin_lock(&key_map_lock);
	list_add_tail(&map->list, &keymap_list);		//把keymap-mstar-tv.c文件配置的映射表添加到keymap_list中
	spin_unlock(&key_map_lock);
	return 0;
}


********** 重新回到 mstar_ir.c 文件
mstar_ir_drv_init_module函数
1. 注册设备驱动  2. 注册遥控器映射表到ir_core层 

因为在mstar_ir.c中通过platform框架实现设备驱动,所以下面按照平台驱动分析代码

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)   //设备树匹配   在.config文件中有如下定义:  CONFIG_OF=y  ==> 说明该系统支持设备树
		.of_match_table = mstarir_of_device_ids,
#endif
		.name   = "Mstar-ir",
		.owner  = THIS_MODULE,
		.bus   = &platform_bus_type,
	}
};

设备树匹配表
static struct of_device_id mstarir_of_device_ids[] = {
{.compatible = "Mstar-ir"},
               {},
           };
		   
设备树配置文件 arch/arm/boot/dts/m7221_an.dts中有如下配置
ir {
	compatible = "mstar-ir";
};

************ 好像匹配是区分大小写的啊  这里大小写不一样。。?   ?????????????????  
猜测是非设备树匹配
848_pm_mboot_kernel/kernel$ grep -rn "Mstar-ir" ./
==>
./mstar2/hal/m7221/cpu/arm/chip_arch.c:161:     .name           = "Mstar-ir",

匹配成功调用probe函数
static int mstar_ir_drv_probe(struct platform_device *pdev)
{
	//判断是否匹配成功  !(pdev->name): 传统模式 ,strcmp(pdev->name,"Mstar-ir"):匹配name字段;pdev->id!=0:匹配设备树
	IRDBG_ERR("wjc_ir mstar_ir.c  mstar_ir_drv_probe \n");
	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);			//********* 这里就非常重要了  这个是input子系统操作的地方 这里实现了input子系统3步骤,
	if (ret < 0)
	{
		IRDBG_ERR("mstar_ir_register_device Failed! \n");
	}
	pdev->dev.platform_data=&IRDev;		//将IR设备驱动对应的设备信息全局变量保存到platform_device中

	mstar_ir_customer_config();			//加载遥控器配置  即把我们在ir_config.h中配置的信息加载进来

#ifdef CONFIG_MIRC_INPUT_DEVICE
	mstar_ir_init(0);					//中断操作   ********   
	IRDev.u32IRFlag |= (IRFLAG_IRENABLE|IRFLAG_HWINITED);
#endif
	return ret;
}

驱动基本框架_创建字符设备
static int mstar_ir_cdev_init(void)
{
	int ret;
	dev_t dev;
	IR_PRINT("##### Mstar IR Cdev Init #####\n");
	
	//注册设备号
	if (IRDev.s32IRMajor) {
		dev = MKDEV(IRDev.s32IRMajor, IRDev.s32IRMinor);
		ret = register_chrdev_region(dev, MOD_IR_DEVICE_COUNT, MDRV_NAME_IR);
	} else {
		ret = alloc_chrdev_region(&dev, IRDev.s32IRMinor, MOD_IR_DEVICE_COUNT, MDRV_NAME_IR);
		IRDev.s32IRMajor = MAJOR(dev);
	}
	
	if ( 0 > ret) {
		IRDBG_ERR("Unable to get major %d\n", IRDev.s32IRMajor);
		return ret;
	}
	
	//cdev操作 将fops和设备号建立联系
	cdev_init(&IRDev.cDevice, &IRDev.IRFop);
	if (0!= (ret= cdev_add(&IRDev.cDevice, dev, MOD_IR_DEVICE_COUNT))) {
		IRDBG_ERR("Unable add a character device\n");
		unregister_chrdev_region(dev, MOD_IR_DEVICE_COUNT);
		return ret;
	}
	return 0;
}

创建属性文件
static int mstar_ir_creat_sysfs_attr(struct platform_device *pdev)
{
	struct device *dev = &(pdev->dev);
	int ret = 0;
	IRDBG_INFO("Debug Mstar IR Creat Sysfs\n");
	if ((ret = device_create_file(dev, &dev_attr_IRProtocols)))		//系统采用什么协议
		goto err_out;
	if ((ret = device_create_file(dev, &dev_attr_IRDebug)))			//打印等级 默认error级别 等级1
		goto err_out;
	if ((ret = device_create_file(dev, &dev_attr_IRSpeed)))			//灵敏度,过滤多少个波形   默认0
		goto err_out;
	if ((ret = device_create_file(dev, &dev_attr_IREnable)))
		goto err_out;
	if ((ret = device_create_file(dev, &dev_attr_IREvent)))
		goto err_out;
#ifdef CONFIG_MIRC_INPUT_DEVICE
	if ((ret = device_create_file(dev, &dev_attr_IRTimeout)))
		goto err_out;
#endif
	return 0;
err_out:
	return ret;
}

测试现象:
IFP:/sys/devices/ir # ls
IRDebug   IRProtocols  driver           modalias  subsystem  
IREnable  IRSpeed      driver_override  of_node   uevent     
IREvent   IRTimeout    input            power  

dev_attr_IRProtocols ==>  IRProtocols文件    ==>猜测生成的文件名称就是dev_attr_IRProtocols后面的这个字符串
IFP:/sys/devices/ir # cat IRProtocols                                          
Eenable Protocols Name:NEC  


input子系统操作
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   ==> mstar_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);		//申请空间  dev->read_fifo: 猜测是用于存放按键中断中读取到的按键扫描码
	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();		//***************** input_dev层 步骤1: 申请一个input_dev对象
	if (!dev->input_dev)
	{
		ret = -ENOMEM;
		goto out_kfifo;
	}
	input_set_drvdata(dev->input_dev, dev);			// dev_set_drvdata(&dev->dev, data) ==> dev->driver_data = data ==>  dev->input_dev->dev->driver_data = dev  相当于在input_dev中保存它父类mstar_ir_dev的信息
	dev->input_name = MSTAR_IR_DEVICE_NAME;			//#define MSTAR_IR_DEVICE_NAME    "MStar Smart TV IR Receiver"
	dev->input_phys = "/dev/ir";
	dev->driver_name = MSTAR_IR_DRIVER_NAME;	
	dev->map_num = NUM_KEYMAP_MSTAR_TV; //default :mstar keymap
	//6. init&register  input device   ===> *************** input_dev层步骤2   初始化input_dev对象
	dev->input_dev->id.bustype = BUS_I2C;			//input_dev结构体成员分析: https://blog.csdn.net/ielife/article/details/7814108   
	dev->input_dev->id.vendor = INPUTID_VENDOR;		//#define INPUTID_VENDOR 0x3697UL;   这4个属性bustype,vendor,product,vendor是input_dev和input_handler匹配的条件  
	dev->input_dev->id.product = INPUTID_PRODUCT;	//#define INPUTID_PRODUCT 0x0001;	  也决定了我们android中对应的kl文件的命名   Vendor_3697_Product_0001.kl
	dev->input_dev->id.version = INPUTID_VERSION;	//#define INPUTID_VERSION 0x0001; 
	set_bit(EV_KEY, dev->input_dev->evbit);		//表示该input设备要上报的事件类型包括: EV_KEY(按键事件),EV_REP(重复事件),EV_MSC中的MSC_SCAN表示扫描按键  ==>表示可以向上上报一个scancode(scancode==遥控器规格书中的值)
	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;		//input_phys: 设备节点名称  *******   "/dev/ir"
	dev->input_dev->name = dev->input_name;		//输入设备的名称    "MStar Smart TV IR Receiver"
	for (i = 0; i<KEY_CNT; i++)					//注册所有按键
	{
		__set_bit(i, dev->input_dev->keybit);	//设置遥控器按键对应的按键值  input.h中定义的那个按键值
	}
	__clear_bit(BTN_TOUCH,dev->input_dev->keybit);// IR device without this case

	ret = input_register_device(dev->input_dev);		//***************** input_dev层 步骤3: 注册input_dev对象到input_core层中存放所有input_dev对象的链表中,并尝试去driver_list中匹配该device对应的driver,匹配成功执行connect函数,然后创建一个handled对象将device和driver建立联系
#endif
	//7. register IR Data ctrl
	ret = MIRC_Data_Ctrl_Init(dev);					//********** 非常关键  注册IR 数据kthread线程MIRC_Data_Ctrl_Thread从kfifo中获取原始的按键数据,并将数据发送给匹配的decoder文件去解析
	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;
}

struct mstar_ir_dev {
	struct mutex             lock;              //lock for handle mstar_ir_dev menber variables
	struct ir_raw_data_ctrl  *raw;              //shot count handle struct
	u64                      enabled_protocols; //surport decoders
	spinlock_t               keylock;           //spinlock
	void                     *priv;             //
	IR_SPEED_LEVEL_e         speed;             //ir speed level
	u8                       filter_flag;
	struct semaphore         sem;
	wait_queue_head_t        read_wait;
	struct kfifo_rec_ptr_1   read_fifo;         //for user space read     
#ifdef CONFIG_MIRC_INPUT_DEVICE
	struct input_dev         *input_dev;
	bool                     keypressed;
	u32                      last_keycode;
	u32                      last_scancode;
	const char               *input_name;
	const char               *input_phys;
	char                     *driver_name;
	u32                       map_num;
#endif
	IR_Mode_e                ir_mode;
	IR_Profile_t             support_ir[IR_SUPPORT_MAX];
	u8                       support_num;
};

/*
 * Used to (un)register raw event clients  用于(un)注册原始事件客户端   
 */
int MIRC_Data_Ctrl_Init(struct mstar_ir_dev *dev)
{
	int ret;
	if (!dev)
		return -EINVAL;

	dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL);   //申请raw内存空间 ,raw中存放原始按键信息
	if (!dev->raw)
		return -ENOMEM;

	dev->raw->dev = dev;
	dev->enabled_protocols = 0;				//支持的解码协议 
	ret= kfifo_alloc(&dev->raw->kfifo,			
        sizeof(struct ir_raw_data) * MAX_IR_DATA_SIZE,				
        GFP_KERNEL);
	if (ret < 0)
		goto out;

	spin_lock_init(&dev->raw->lock);		//初始化自旋锁 
	dev->raw->thread = kthread_run(MIRC_Data_Ctrl_Thread, dev->raw,"Mstar_ir"); //kthread_run是一个宏定义,功能是创建并启动内核线程 创建一个名为"Mstar_ir"的线程,将dev->raw作为参数传递给该线程对应的线程函数MIRC_Data_Ctrl_Thread

	if (IS_ERR(dev->raw->thread)) {
		ret = PTR_ERR(dev->raw->thread);
		goto out;
	}
	#ifdef CONFIG_MIRC_INPUT_DEVICE
	// init timer event up			初始化一个定时器
	dev->raw->keyup_jiffies = jiffies;//record timeout for event up
	init_timer(&(dev->raw->timer_keyup));
	dev->raw->timer_keyup.function = MIRC_Timer_Proc;		//超时处理函数
	dev->raw->timer_keyup.expires =jiffies+ msecs_to_jiffies(eventtimeout);		//设置的定时时间
	dev->raw->timer_keyup.data = (unsigned long)dev;		//传递给超时函数的参数
#endif
	return 0;
out:
	kfree(dev->raw);
	dev->raw = NULL;
	return ret;
}

raw成员: 保存着原始按键值
struct ir_raw_data_ctrl {
	struct task_struct      *thread;		//线程
	spinlock_t              lock;
	struct kfifo_rec_ptr_1  kfifo;           /* fifo for the pulse/space durations  脉冲/空间持续时间的fifo*/
	struct mstar_ir_dev     *dev;
	struct ir_scancode      prev_sc;		//前一个扫描码
	struct ir_scancode      this_sc;		//当前扫描码
	u8                      u8RepeatFlag;
#ifdef CONFIG_MIRC_INPUT_DEVICE
	unsigned long           keyup_jiffies;     //time record
	struct timer_list       timer_keyup;       //定时器  事件发生定时器			
#endif
};

"Mstar_ir"线程分析: 关键步骤总结分析   该函数定义在ir_core.c
static int MIRC_Data_Ctrl_Thread(void *data)
{
	//1. 从raw->kfifo中获取数据到ev中,获取的元素数量为sizeof(ev)   ==这个fifo中的数据就是按键的原始值
	retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev));
	
	//2. 将获取到的数据发送给对应的decoder匹配协议解析数据   
	mutex_lock(&ir_decoder_lock);		
	else //hw decoder    //对应IR_TYPE_FULLDECODE_MODE NEC full解码 支持两个头码的遥控器   在IR_MSTAR_DTV.h 中有如下定义:#define IR_MODE_SEL             IR_TYPE_FULLDECODE_MODE
    {
        raw->this_sc.scancode = ev.duration;
        raw->u8RepeatFlag = ev.pulse;
        get_scancode = 1;	//是否获取到扫描值的标志  1=获取扫描值,读后面就是对这个获取到的按键扫描值进行处理
        IRDBG_MSG("keycode =%x  repeatflag =%d \n",raw->this_sc.scancode,raw->u8RepeatFlag);
    }
	
	//3. 匹配映射表,获取映射后按键对应的keycode值,上报event事件
	MIRC_Keydown(raw->dev, raw->this_sc.scancode);
	MIRC_Keyup(raw->dev);
}

//设置遥控器配置    就是ir_config.h中的配置  配置遥控器的打印级别,速率,支持的遥控器的协议和头码
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    防止系统从待机状态唤醒时sw fifo中存在剩余值
   REG(REG_IR_CTRL) &= (0xFF00); //disable IR ctrl regs									失能IR控制寄存器
   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))
		{
		#ifdef E_FIQEXPL_IR_INT_RC
			ret = request_irq(E_FIQEXPL_IR_INT_RC, _MDrv_IR_RC_ISR, SA_INTERRUPT, "IR_RC", &IRDev);
			ir_irq_sel = 1;
		#else
			printk("E_FIQEXPL_IR_INT_RC IRQ not Found\n");
		#endif
		}
		else
		{	
			//申请中断 
			ret = request_irq(INT_NUM_IR_ALL, _MDrv_IR_ISR, SA_INTERRUPT, "IR", &IRDev);
			ir_irq_sel = 0;		//这次申请了说明该解码方式以及配置好了,防止后面再次配置
		}

		if (ret < 0)
		{
			IRDBG_ERR("IR IRQ registartion ERROR!\n");
		}

		else
		{
			ir_irq_enable = 1;
			IRDBG_INFO("IR IRQ registartion OK!\n");
		}
	}
	return ;
}

//做好硬解码的寄存器配置  头码 + NEC解码的时序    
static void mstar_ir_hw_fulldecode_config(void)
{
	
	//1. set customer code0
	REG(REG_IR_CCODE) = ((u32IRHeaderCode[0]&0xff)<<8)|((u32IRHeaderCode[0]>>8) &0xff);
	//2. set customer code1
	REG(REG_IR_CCODE1) =((u32IRHeaderCode[1]&0xff)<<8)|((u32IRHeaderCode[1]>>8) &0xff);

	if(ir_config_mode == IR_TYPE_FULLDECODE_MODE)
	{
		return ;
	}
	ir_config_mode = IR_TYPE_FULLDECODE_MODE;	//表示现在这个系统的解码配置为: 硬解码
	IR_PRINT("##### Mstar IR HW Full Decode Config #####\n");
	//3. set NEC timing & FIFO depth 16 bytes
	_MDrv_IR_Timing();
	REG(REG_IR_SEPR_BIT_FIFO_CTRL) = 0xF00UL;//[10:8]: FIFO depth, [11]:Enable FIFO full
	REG(REG_IR_CCODE1_CHK_EN) |= IR_CCODE1_CHK_EN;
	//4. Glitch Remove (for prevent Abnormal waves)  reg_ir_glhrm_num = 4拢卢reg_ir_glhrm_en = 1
	REG(REG_IR_GLHRM_NUM) = 0x804UL;
	//5.set full decode mode
	REG(REG_IR_GLHRM_NUM) |= (0x3UL <<12);
	//6.set Data bits ===>two byte customer code +IR DATA bits(32bits)+timeout clear+timeout value 4 high bits
	REG(REG_IR_TIMEOUT_CYC_H_CODE_BYTE) = IR_CCB_CB | 0x30UL | ((IR_RP_TIMEOUT >> 16) & 0x0FUL);
	//7.set IR clock DIV
	REG(REG_IR_CKDIV_NUM_KEY_DATA) = IR_CKDIV_NUM;   //set clock div --->IR clock =1MHZ
	//8.reg_ir_wkup_key_sel ---> out key value
	REG(REG_IR_FIFO_RD_PULSE) |= 0x0020UL; //wakeup key sel
	//9. set ctrl enable IR
	REG(REG_IR_CTRL) = IR_TIMEOUT_CHK_EN |
					   IR_INV            |
					   IR_RPCODE_EN      |
					   IR_LG01H_CHK_EN   |
					   IR_DCODE_PCHK_EN  |
					   IR_CCODE_CHK_EN   |
					   IR_LDCCHK_EN      |
					   IR_EN;
}

NEC红外编码的发送波形
//Time, upper bound, low bound
{9000,20,(-20)},// header code time					
{4500,20,(-20)},//off code time
{2500,20,(-20)},                    // off code repeat time
{560,35,(-30)},                     // logical 0/1 high time
{1120,20,(-20)},                    // logical 0 time
{2240,20,(-20)},                    // logical 1 time

0代表低电平,1=高电平
引导码: 0:9ms,1:4.5ms
引导重复码: 0:9ms,1:2.24ms
数据1: 0:0.56ms.1:(2.25-0.56)ms
数据0: 0:0.56ms.1:(1.12-0.56)ms

一个完整的数据波形
引导码/引导重复码  地址  地址取反    数据  数据取反

硬解码模式中配置中断: 申请一个中断号为INT_NUM_IR_ALL,中断名称为"IR",中断处理函数为_MDrv_IR_ISR的中断
ret = request_irq(INT_NUM_IR_ALL, _MDrv_IR_ISR, SA_INTERRUPT, "IR", &IRDev);
SA_INTERRUPT: 中断处理的属性,若设置SA_INTERRUPT,标明中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断   //将遥控器按键中断设置成快速中断,为了对按键进行快速响应

分析中断处理函数 **************************
irqreturn_t _MDrv_IR_ISR(int irq, void *dev_id)
{
	IRModHandle *mstar_dev = dev_id;		//获取申请中断时传递进来的参数  IRDev指针 IR设备驱动信息结构体
	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;
}
 
mstar_ir_isr_getdata_fulldecode(mstar_dev)   //获取触发中断的按键值,并将按键值写入到fifo中*******
	|
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;

	ev.duration = (u32IRHeaderCode[u8Ir_Index]<<8) | u8Keycode;			//ev中保存了该中断触发导致的按键的原始按键值(扫描值)
	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);			//********** 非常关键  将触发中断的按键值写入fifo中
	if (ret < 0)
	{
		IRDBG_ERR("Store IR data Error!\n");
	}
	mstar_ir_nec_clearfifo();
	return ret;
}

//ir_core.c文件  *********** 这里就失ir_core层中保存了按键中断触发分按键值了   前面在mstar_ir.c中的驱动入口函数中将解码映射表也注册到了ir_core中  *****  所以在ir_core中万事俱备(有原始值,有映射表),开始解码
int MIRC_Data_Store(struct mstar_ir_dev *dev, struct ir_raw_data *ev)
{
	if (!dev->raw)
		return -EINVAL;
	if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))   //kfifo_in函数就是将数据写入到fifo中   / kfifo_in函数就是读取fifo中的数据
		return -ENOMEM;

	return 0;
}

MIRC_Data_Wakeup(mstar_dev->pIRDev);   //唤醒"mstar_ir"线程来读取fifo中的按键值,然后解析获取keycode,然后input_event上报数据到eventX文件
		|
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);			//唤醒执行dev->raw->thread线程  在 mstar_ir_register_device()-> MIRC_Data_Ctrl_Init(dev) --> dev->raw->thread = kthread_run(MIRC_Data_Ctrl_Thread, dev->raw,"Mstar_ir ; ===>所以这里就会执行Mstar_ir线程对应的MIRC_Data_Ctrl_Thread函数
	spin_unlock_irqrestore(&dev->raw->lock, flags);
}

//再次具体分析 读取fifo中按键原始值,匹配映射表,解析数据,input系统上报数据的实现 ****************
static int MIRC_Data_Ctrl_Thread(void *data)
{
	//1. 读取fifo中按键原始值
	retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev));  //kfifo_out函数就是读取fifo中的数据,并将读取到的数据保存在ev中
	
	//2. 获取原始值之后就需要解析原始值    解析按键按下时的原始值
	MIRC_Keydown(raw->dev, raw->this_sc.scancode);
		
}

//解析按键按下时的原始值
void MIRC_Keydown(struct mstar_ir_dev *dev, int scancode)
{
	unsigned long flags;
	u32 keycode = MIRC_Keycode_From_Map(dev->map_num, scancode);			//非常重要 这里就是匹配映射表,获取该原始扫描按键扫描值对应的keycode值
	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);								//获取keycode之后上报按键按下的数据
	spin_unlock_irqrestore(&dev->keylock, flags);
}

u32 keycode = MIRC_Keycode_From_Map(dev->map_num, scancode);	
		|
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)		//获取原始值映射后的keycode值
	{
		for (i = 0; i<map->map.size; i++)	//map.size:映射表中的映射对数量
		{
			if (((map->map.scan[i].scancode&0xff) == (scancode&0xff)) && ((scancode>>8) == map->map.headcode))  //选这里 (map->map.scan[i].scancode&0xff) == (scancode&0xff)) 在映射表中找到匹配的scancode
			{
				IRDBG_INFO("[Match 8bit Scancode] Scancode =%x -----> Keycode= %x\n",scancode,map->map.scan[i].keycode);	//,map->map.scan[i].keycode: 就是该scancode对应的keycode值
				keycode = map->map.scan[i].keycode;
				break;//match scancode, and return keycode
			}
			if ( ((map->map.scan[i].scancode&0xffff) == (scancode&0xffff)) && (keymapnum == map->map.headcode))
			{
				IRDBG_INFO("[Match 16bit Scancode] Scancode =%x -----> Keycode= %x\n",scancode,map->map.scan[i].keycode);
				keycode = map->map.scan[i].keycode;
				break;//match scancode, and return keycode
			}
		}
	}
	spin_unlock(&key_map_lock);
	return keycode;
}	

keymapnum的值?
mstar_ir_register_device() 中dev->map_num = NUM_KEYMAP_MSTAR_TV; //default :mstar keymap   这里就一直调即可
所以keymapnum == NUM_KEYMAP_MSTAR_TV     //#define    NUM_KEYMAP_MSTAR_TV                   0x4040   这个值就是我们在ir_common.h中定义的不同客户的头码值,与ir_config.h中定义的遥控器头码值相同 {IR_TYPE_NEC, NUM_KEYMAP_MSTAR_TV, 0},

在驱动入口函数中有如下步骤 加载解码驱动,在该解码驱动中有如下操作,将映射包添加到ir_core层的key_map_list链表中
int MIRC_Map_Register(struct key_map_list *map)
{
	spin_lock(&key_map_lock);
	list_add_tail(&map->list, &keymap_list);		//把keymap-mstar-tv.c文件配置的映射表map添加到keymap_list中  在ir_core层中创建了keymap_list链表:static LIST_HEAD(keymap_list); 
	spin_unlock(&key_map_lock);
	return 0;
}


匹配映射表
list_for_each_entry(map, &keymap_list, list)  //遍历映射表
{
	if (((scancode>>8) == map->map.headcode) || (keymapnum == map->map.headcode))	//匹配头码  keymapnum == map->map.headcode 
	{
		IRDBG_INFO("[Match] Keymap Name: %s\n",map->map.name);
		match_flag = true;		//匹配成功标志位置ture
		break;//find IR map
	}
}

==> 例如:nec解码驱动  我们注册的映射表:mstar_tv_map  故: map->map.headcode == NUM_KEYMAP_MSTAR_TV ************* 这不就匹配上了吗?   
static struct key_map_list mstar_tv_map = {
	.map = {
		.scan     = mstar_tv,				//具体的映射关系表
		.size     = ARRAY_SIZE(mstar_tv),	//多少个按键映射对
		.name     = NAME_KEYMAP_MSTAR_TV,	//该按键映射表的名称   在ir_common.h中定义 #define NAME_KEYMAP_MSTAR_TV                  "ir-mstar-tv"  
		.headcode = NUM_KEYMAP_MSTAR_TV,	//头码  			   在ir_common.h中定义 #define    NUM_KEYMAP_MSTAR_TV                   0x4040
	}
};

匹配成功开始解码,获取keycode,这个看前面的代码注释

获取keycode值之后,就需要把keycode值上报
MIRC_Do_Keydown(dev, scancode, keycode);
	|
static void MIRC_Do_Keydown(struct mstar_ir_dev *dev, int scancode,u32 keycode)
{
	bool new_event = !dev->keypressed ||
		dev->last_scancode != scancode;		//new_event表示该按键是否为新按键 (是否和上一个按键不同)

	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);				//这个就是当是新按键被按下,需要重新上报一下新的keycode值     1:代表按键按下   
	}

	input_sync(dev->input_dev);			//上报同步事件 即将上报信息立刻方法出去 
}


后面的流程就是input子系统的流程了: 大概流程为
上报的数据,分发给订阅了该input_dev的input_handle,然后input_handle在此将数据分发给与它相关的input_handle,最后在input_handle中的event方法中将数据分发给所有打开该设备文件的缓冲区中  

所以现在 你可以通过  getevent -l /dev/input/event0来查看上报信息   input子系统的设备文件就是eventX类型,主设备号13,这些都是在input_hander层就写死的


总结: 遥控器上报数据的流程   ***************
加载遥控器驱动 Mstar_ir.c,加载解码驱动将映射表注册到ir_core层中的keymap_list链表中
遥控器按键按下;进入中断处理函数,获取按键scancode值,并将值保存在fifo缓冲区中,好像"MSTAR_IR"线程; "MSTAR_IR"线程读取fifo中的数据,然后开始解析数据,先获取该遥控器驱动匹配的映射表,然后根据scancode值找到相应的keycode值,最后input上报按键值

调试方法: mstar_遥控器文档  :设置printk和IRDEUG的打印等级


查看打印信息
IFP:/ # [  310.833687] [IR ERR ]: _MDrv_IR_ISR[629]: [  310.838228] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  _MDrv_IR_ISR enter request_irq 
[  310.847193] [  310.848861] [IR ERR ]: _MDrv_IR_ISR[635]: 
[  310.853571] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  _MDrv_IR_ISR mstar_dev->pIRDev->ir_mode = 5   
*********** WTF  ir_mode不是IR_TYPE_FULLDECODE_MODE,而是IR_TYPE_SWDECODE_MODE,  
typedef enum{
	IR_TYPE_FULLDECODE_MODE = 0,   /* NEC full deocoder mode */ nec full解码,支持两个头码遥控器  他只会解NEC编码的遥控器
	IR_TYPE_RAWDATA_MODE,          /* NEC raw decoder mode*/
	IR_TYPE_HWRC5_MODE,            /* RC5 decoder mode*/
	IR_TYPE_HWRC5X_MODE,           /* RC5_ext decoder mode*/
	IR_TYPE_HWRC6_MODE,            /* RC6_mode0 decoder mode*/
	IR_TYPE_SWDECODE_MODE,         /* SW decoder mode*/		软解码,支持多种不同协议
	IR_TYPE_MAX_MODE
}IR_Mode_e;

在ir_config.h中 我们定义了两种编码的遥控器   ==> 所以应该采用IR_TYPE_SWDECODE_MODE 解码方式 
#define IR_SUPPORT_NUM 2
static IR_Profile_t ir_config[IR_SUPPORT_NUM]=
{
	// {IR_TYPE_NEC,NUM_KEYMAP_MSTAR_TV,0},         // Mstar 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_NEC, NUM_KEYMAP_MSTAR_TV, 0},
	//{IR_TYPE_RC6,NUM_KEYMAP_KATHREIN_TV,0},       // Kathrein RC6 customer code
	//{IR_TYPE_KONKA,NUM_KEYMAP_KONKA_TV,2},
	{IR_TYPE_PANASONIC,NUM_KEYMAP_PANASONIC_TV,2},
};

//Description  of IR
typedef struct IR_Profile_s {
	IR_Type_e eIRType;
	u32 u32HeadCode;
	u32 u32IRSpeed;
}IR_Profile_t;

代码具体实现流程如下 即_MDrv_IR_ISR mstar_dev->pIRDev->ir_mode = 5 这个的来源
在遥控器驱动 Mstar_ir.c中
驱动入口函数  	ret = platform_driver_register(&Mstar_ir_driver);
probe函数     	mstar_ir_customer_config(); 
					|
				MIRC_IRCustomer_Config(ir_config,IR_SUPPORT_NUM);
					|
				MIRC_IRCustomer_Init();

int MIRC_IRCustomer_Init(void)
{
	struct mstar_ir_dev *dev = IRDev.pIRDev;
	IR_Type_e IrType = IR_TYPE_MAX;
	u8 i = 0;
	bool bIsDiffType = false;
	if (NULL == dev)
		return -EINVAL;
	for(i = 0; i<dev->support_num; i++)   	//#define IR_SUPPORT_NUM 2   
	{
		if(dev->support_ir[i].eIRType == dev->support_ir[i+1].eIRType)   
		{
			IrType = dev->support_ir[i].eIRType;
			bIsDiffType = false;
		}
		else			//会执行这里的代码 因为IR_TYPE_PANASONIC !=  IR_TYPE_NEC
		{
			dev->ir_mode = IR_TYPE_SWDECODE_MODE;  //这里就是ir_mode的来来源
			bIsDiffType = true;
			break;
		}
	}
	if(bIsDiffType == false)	//不走这里
	{
		if(IrType == IR_TYPE_NEC)
		{
			if(dev->support_num <=2)
			{
				//set customer code0
				u32IRHeaderCode[0] = dev->support_ir[0].u32HeadCode;
				u32IRHeaderCode[1] = dev->support_ir[1].u32HeadCode;
				dev->ir_mode = IR_TYPE_FULLDECODE_MODE;
			}
			else
			{
				dev->ir_mode = IR_TYPE_RAWDATA_MODE;
			}
		}
		else if(IrType == IR_TYPE_RC5)
		{
			dev->ir_mode = IR_TYPE_HWRC5_MODE;
		}
		else if(IrType == IR_TYPE_RC5X)
		{
			dev->ir_mode = IR_TYPE_HWRC5X_MODE;
		}
		else if(IrType == IR_TYPE_RC6_MODE0)
		{
			dev->ir_mode = IR_TYPE_HWRC6_MODE;
		}
		else
		{
			dev->ir_mode = IR_TYPE_SWDECODE_MODE;
		}
	}
	if(IR_TYPE_SWDECODE_MODE == dev->ir_mode)		//这里要走路
	{
		for(i = 0;i<(dev->support_num);i++)
		{
			switch(dev->support_ir[i].eIRType)
			{
				case IR_TYPE_NEC :
					nec_decode_init();		//这个解码驱动有加载  我们中性的是nec编码,等等如何解码后面在分析  这个解码 == 根据接收到的遥控器发送的波形的时序,如何根据NEC协议解码 *******
					break;
				case IR_TYPE_RCA:
					rca_decode_init();
					break;
				case IR_TYPE_P7051:
					p7051_decode_init();
					break;
				case IR_TYPE_RC5:
				case IR_TYPE_RC5X:
					rc5_decode_init();
					break;
				case IR_TYPE_RC6_MODE0:
				case IR_TYPE_RC6:
					rc6_decode_init();
					break;
				case IR_TYPE_TOSHIBA:
					toshiba_decode_init();
					break;
				case IR_TYPE_RCMM:
					rcmm_decode_init();
					break;
				case IR_TYPE_KONKA:
					konka_decode_init();
					break;
				case IR_TYPE_PANASONIC:
					panasonic_decode_init();	//这个解码驱动要加载
					break;
				default :
					IRDBG_ERR("IR TYPE not define,please check!!!\n");
					break;
			}
		}
	}
	return 0;
}


故前面的代码跟读就有误了 ******************** WTF  


先按下source按键,在按下menu按键后,menu按键的log分析,******我们这里只是跟踪了按键按下时的流程 **** ****** wjc_ir是我们添加的打印   第一次尝试  没有进入到按键按下处理的函数的log
IFP:/ # [  281.707665] [IR ERR ]: _MDrv_IR_ISR[630]: 
[  281.712385] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  _MDrv_IR_ISR enter request_irq 
[  281.721347] [  281.723015] [IR ERR ]: _MDrv_IR_ISR[636]: 
[  281.727724] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  _MDrv_IR_ISR mstar_dev->pIRDev->ir_mode = 5				//软解码
[  281.737728] [  281.739398] [IR ERR ]: mstar_ir_isr_getdata_swdecode[597]: 													
[  281.745582] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  mstar_ir_isr_getdata_swdecode  							//获取按下menu键,遥控器发送的波形 duration/pulse值 
[  281.754544] [  281.756214] [IR ERR ]: MIRC_Data_Store[247]: 
[  281.761184] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  MIRC_Data_Store add scancode 								//将获取到的波形数据存放在fifo中     循环处理9次
[  281.769971] [  281.771644] [IR ERR ]: mstar_ir_isr_getdata_swdecode[597]: 
[  281.777829] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  mstar_ir_isr_getdata_swdecode  
[  281.786791] [  281.788462] [IR ERR ]: MIRC_Data_Store[247]: 
[  281.793430] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  MIRC_Data_Store add scancode 
[  281.802217] [  281.803890] [IR ERR ]: mstar_ir_isr_getdata_swdecode[597]: 
[  281.810075] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  mstar_ir_isr_getdata_swdecode  
[  281.819036] [  281.820707] [IR ERR ]: MIRC_Data_Store[247]: 
[  281.825676] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  MIRC_Data_Store add scancode 
[  281.834462] [  281.836132] [IR ERR ]: mstar_ir_isr_getdata_swdecode[597]: 
[  281.842317] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  mstar_ir_isr_getdata_swdecode  
[  281.851280] [  281.852951] [IR ERR ]: MIRC_Data_Store[247]: 
[  281.857920] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  MIRC_Data_Store add scancode 
[  281.866707] [  281.868377] [IR ERR ]: mstar_ir_isr_getdata_swdecode[597]: 
[  281.874561] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  mstar_ir_isr_getdata_swdecode  
[  281.883523] [  281.885192] [IR ERR ]: MIRC_Data_Store[247]: 
[  281.890162] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  MIRC_Data_Store add scancode 
[  281.898951] [  281.900621] [IR ERR ]: mstar_ir_isr_getdata_swdecode[597]: 
[  281.906806] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  mstar_ir_isr_getdata_swdecode  
[  281.915772] [  281.917442] [IR ERR ]: MIRC_Data_Store[247]: 
[  281.922411] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  MIRC_Data_Store add scancode 
[  281.931199] [  281.932869] [IR ERR ]: mstar_ir_isr_getdata_swdecode[597]: 
[  281.939055] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  mstar_ir_isr_getdata_swdecode  
[  281.948017] [  281.949685] [IR ERR ]: MIRC_Data_Store[247]: 
[  281.954654] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  MIRC_Data_Store add scancode 
[  281.963443] [  281.965113] [IR ERR ]: mstar_ir_isr_getdata_swdecode[597]: 
[  281.971298] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  mstar_ir_isr_getdata_swdecode  
[  281.980261] [  281.981930] [IR ERR ]: MIRC_Data_Store[247]: 
[  281.986899] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  MIRC_Data_Store add scancode 
[  281.995687] [  281.997357] [IR ERR ]: mstar_ir_isr_getdata_swdecode[597]: 
[  282.003542] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  mstar_ir_isr_getdata_swdecode  
[  282.012504] [  282.014174] [IR ERR ]: MIRC_Data_Store[247]: 
[  282.019142] ************* ^_^ ************* [wjc_ir] [mstar_ir.c]  MIRC_Data_Store add scancode 
[  282.027929] [  282.029602] [IR ERR ]: MIRC_Data_Wakeup[264]: 
[  282.034657] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Wakeup Wakeup thread 							//将数据都存放在fifo之后,唤醒线程去处理数据	
[  282.043532] [  282.045232] [IR ERR ]: MIRC_Data_Ctrl_Thread[147]: 
[  282.050900] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread thread_get_scancode = 15 			//这里就是将前面存放在fifo中的数据取出来	这个数据不是scancode 而是duration,实际上应该会有pulse值
[  282.061299] [  282.062997] [IR ERR ]: MIRC_Data_Ctrl_Thread[147]: 
[  282.068523] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread thread_get_scancode = 575 
[  282.078899] [  282.080583] [IR ERR ]: MIRC_Data_Ctrl_Thread[147]: 
[  282.086094] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread thread_get_scancode = 495 
[  282.096466] [  282.098134] [IR ERR ]: MIRC_Data_Ctrl_Thread[147]: 
[  282.103635] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread thread_get_scancode = 1615 
[  282.114081] [  282.115747] [IR ERR ]: MIRC_Data_Ctrl_Thread[147]: 
[  282.121260] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread thread_get_scancode = 495 
[  282.131862] [  282.133541] [IR ERR ]: MIRC_Data_Ctrl_Thread[147]: 
[  282.139047] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread thread_get_scancode = 16383 
[  282.149822] [  282.151491] [IR ERR ]: MIRC_Data_Ctrl_Thread[147]: 
[  282.156996] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread thread_get_scancode = 8319 
[  282.170418] [  282.172151] [IR ERR ]: MIRC_Data_Ctrl_Thread[147]: 
[  282.177860] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread thread_get_scancode = 2175 
[  282.188571] [  282.190242] [IR ERR ]: MIRC_Data_Ctrl_Thread[147]: 
[  282.195766] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread thread_get_scancode = 495 


加get_scancode的打印
[  253.961074] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread ev.duration = 495 , ev.pulse = 1 ,get_scancode = 0 

所以前面的解析,上报的代码跟踪就不对了,前面的那种是nec full解码方式的数据解析和上报,  队员软解码的解析应该为下面代码的操作
static int MIRC_Data_Ctrl_Thread(void *data)
{
	... 
	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;
            }
        }
		IRDBG_ERR("************* ^_^ ************* [wjc_ir] [ir_core.c]  %s ev.duration = %d , ev.pulse = %d ,get_scancode = %d \n",__FUNCTION__,ev.duration,ev.pulse,get_scancode);
    }
	... 
}

调用NEC遥控器编码对应的解码驱动  
if(handler->decode(raw->dev, ev) > 0)

先分析在Mstar_ir.c中probe函数执行的加载nec解码驱动 //调用关系 和前面分析ir_mode来源一致
nec_decode_init();
	|
int nec_decode_init(void)    //ir-nec0decoder.c文件
{
	if(u8InitFlag_nec == FALSE)		//还没有初始化就执行这里 
	{
		scancode = 0;
		mapnum = 0;
		KeyTime = 0;
		memset(&nec,0,sizeof(IR_NEC_Spec_t));
		MIRC_Decoder_Register(&nec_handler);
		IR_PRINT("[IR Log] NEC Spec Protocol Init\n");
		u8InitFlag_nec = TRUE;
	}
	else
	{
		IR_PRINT("[IR Log] NEC Spec Protocol Has been Initialized\n");
	}
	return 0;
}

MIRC_Decoder_Register(&nec_handler);
	|
/*
 * Extension interface - used to register the IR decoders    扩展接口-用于注册红外解码器
 */
int MIRC_Decoder_Register(struct ir_decoder_handler *handler)	//ir_core.c文件
{
	mutex_lock(&ir_decoder_lock);
	list_add_tail(&handler->list, &ir_decoder_list);		//将nec红外解码器注册到ir_decoder_list链表中 ,  static LIST_HEAD(ir_decoder_list); 在ir_core.c中创建了该链表
	protocols |= handler->protocols;
	MIRC_Set_Protocols(protocols);							
	mutex_unlock(&ir_decoder_lock);

	return 0;
}

MIRC_Set_Protocols(protocols);	
		|
void MIRC_Set_Protocols(u64 data)		//设置IRDev.pIRDev->enabled_protocols 成员变量的值
{
	protocols = data;
	IRDev.pIRDev->enabled_protocols = protocols;
}

static struct ir_decoder_handler nec_handler = {		//这就是nec解码器的信息  
	.protocols	= (1<<IR_TYPE_NEC),
	.decode		= ir_nec_decode,
};

IRDev.pIRDev->enabled_protocols = protocols;  ==>   IRDev.pIRDev->enabled_protocols =  1<<IR_TYPE_NEC == 1<<0 == 1   //这个就成员代表的是当前遥控器可以用那些解码器来解码,一个位代表一种解码器

分析解码*********** ************
list_for_each_entry(handler, &ir_decoder_list, list){		//遍历ir_decoder_list链表,该链表中存放了nec_handler这个解码器,
            if(handler->decode(raw->dev, ev) > 0){
                get_scancode = 1;
                break;
            }
        }
handler->decode(raw->dev, ev) 
		|
static int ir_nec_decode(struct mstar_ir_dev *dev, struct ir_raw_data ev)	//NEC协议详解: https://www.cnblogs.com/lifexy/p/9783694.html
{
	IRDBG_ERR("************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  %s  \n",__FUNCTION__);
	IR_NEC_Spec_t *data = &nec;
	struct ir_scancode *sc = &dev->raw->this_sc;
	struct ir_scancode *prevsc = &dev->raw->prev_sc;
	u8 i = 0;
	u8 u8Addr = 0;					//地址
	u8 u8AddrInv =0;				//地址取反
	u8 u8Cmd =0;					//数据
	u8 u8CmdInv =0;					//数据取反        NEC协议中一个完整的数据波形为: 引导码 地址 地址取反 数据 数据取反 
	
	if (!(dev->enabled_protocols & (1<<IR_TYPE_NEC)))		//判断是否为NEC编码  
		return -EINVAL;
	switch (data->eStatus)
	{
	case STATE_INACTIVE:		//判断是否为9ms,是则进入下一个判断,判断是引导码还是重复码
		if (!ev.pulse)
			break;
		if (eq_margin(ev.duration,NEC_HEADER_PULSE_LWB,NEC_HEADER_PULSE_UPB))  //NEC_HEADER_PULSE_LWB = NEC_HEADER_PULSE_UPB = 9ms 
		{
			IRDBG_ERR("************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  %s ev.duration = %d 1. [case STATE_INACTIVE] jx_ydm:9ms\n",__FUNCTION__,ev.duration);
			data->u8BitCount = 0;
			data->eStatus = STATE_HEADER_SPACE;
			//IRDBG_INFO("NEC_HEADER_PULSE\n");
			return 0;
		}
		else
			break;
	case STATE_HEADER_SPACE:	//判断是引导码,还是重复码
		if (ev.pulse)
			break;
		if (eq_margin(ev.duration,NEC_HEADER_SPACE_LWB,NEC_HEADER_SPACE_UPB))	//NEC_HEADER_SPACE_LWB =  NEC_HEADER_SPACE_UPB = 4.5ms   判断是否为4.5ms,是则为引导码,是引导码接下来就去判断数据的值
		{
			IRDBG_ERR("************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  %s ev.duration = %d  2.1 HEADER  [case STATE_HEADER_SPACE] if HEADER(4.5ms)/REPORT(2.25ms) \n",__FUNCTION__,ev.duration);
			data->eStatus = STATE_BIT_PULSE;
			return 0;
		}
		else if (eq_margin(ev.duration,NEC_REPEAT_SPACE_LWB,NEC_REPEAT_SPACE_UPB))	//重复码  这里就将u8RepeatFlag值置为1   *********** 连续按键时的情况
		{//repeat
			//IRDBG_INFO("[NEC] TIME =%ld\n",(MIRC_Get_System_Time()-KeyTime));
			IRDBG_ERR("************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  %s ev.duration = %d  2.2 REPEAT  [case STATE_HEADER_SPACE] if HEADER(4.5ms)/REPORT(2.25ms) \n",__FUNCTION__,ev.duration);
			if (prevsc->scancode_protocol == (1<<IR_TYPE_NEC) && ((u32)(MIRC_Get_System_Time()- KeyTime) <= NEC_REPEAT_TIMEOUT))
			{
				IRDBG_ERR("************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c] 111111111111 \n");
				KeyTime = MIRC_Get_System_Time();
				if (((speed != 0)&&( data->u8RepeatTimes >= (speed - 1)))
						|| ((speed == 0)&&(data->u8RepeatTimes >= dev->speed)))
				{
#ifdef CONFIG_MIRC_INPUT_DEVICE
				IRDBG_ERR("************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c] 2222222 \n");
                sc->scancode = scancode;
                sc->scancode_protocol = (1<<IR_TYPE_NEC);
                dev->map_num = mapnum;
                dev->raw->u8RepeatFlag = 1;
#else
                sc->scancode_protocol = (1<<IR_TYPE_NEC);
                sc->scancode = scancode|0x01;//repeat
#endif
                memset(data,0,sizeof(IR_NEC_Spec_t));
                return 1;

				}
				data->u8RepeatTimes ++;

				//IRDBG_INFO("[NEC] repeattimes =%d \n",data->u8RepeatTimes);
			}
			else
			{
				IRDBG_ERR("************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c] 333333333 \n");
				scancode = 0;
				mapnum = NUM_KEYMAP_MAX;
			}
			data->eStatus = STATE_INACTIVE;
			return 0;
		}
		break;
	case STATE_BIT_PULSE:	//判断是否为0.56ms,如果是在判断是数据1还是0
		if (!ev.pulse)
			break;
		IRDBG_ERR("************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  %s ev.duration = %d  3. [case STATE_BIT_PULSE] if data_duration(0.56ms) \n",__FUNCTION__,ev.duration);
		if (!eq_margin(ev.duration,NEC_BIT_PULSE_LWB,NEC_BIT_PULSE_UPB))
			break;

		data->eStatus = STATE_BIT_SPACE;
		return 0;
	case STATE_BIT_SPACE:	//判断是数据1还是0
		if (ev.pulse)
			break;
		IRDBG_ERR("************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  %s ev.pulse = %d  4. [case STATE_BIT_SPACE] if data_space(1=2.25-0.56,0=1.12-0.56) \n",__FUNCTION__,ev.pulse);
		//printk("************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c] text_printk \n");
		data->u32DataBits <<= 1;

		if (eq_margin(ev.duration,NEC_BIT_1_SPACE_LWB,NEC_BIT_1_SPACE_UPB))			//如果为2.25-0.56ms,就是数据1
			data->u32DataBits |= 1;													//配合前面的移位操作实现对最终上报数据的拼接获取工作
		else if (!eq_margin(ev.duration,NEC_BIT_0_SPACE_LWB,NEC_BIT_0_SPACE_UPB))	//如果为1.12-0.56ms就是数据0 
			break;
		data->u8BitCount++;
		
		if (data->u8BitCount == NEC_NBITS)		//NEC_NBITS =32,=32表示数据接收完成了
		{
			IRDBG_ERR("************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  %s decode_data_finish   5. [case STATE_BIT_SPACE]  \n",__FUNCTION__);
			u8Addr    = bitrev8((data->u32DataBits >> 24) & 0xff);
			u8AddrInv = bitrev8((data->u32DataBits >> 16) & 0xff);
			u8Cmd	  = bitrev8((data->u32DataBits >>  8) & 0xff);
			u8CmdInv  = bitrev8((data->u32DataBits >>  0) & 0xff);
			
			IRDBG_INFO("[NEC] u8Addr = %x u8AddrInv = %x u8Cmd = %x u8CmdInv = %x\n",u8Addr,u8AddrInv,u8Cmd,u8CmdInv);  
			IRDBG_ERR("[wjc_ir] [ir-nec-decoder.c] u8Addr = %x u8AddrInv = %x u8Cmd = %x u8CmdInv = %x\n",u8Addr,u8AddrInv,u8Cmd,u8CmdInv); 
			for (i= 0;i<dev->support_num;i++)
			{
				if(dev->support_ir[i].eIRType == IR_TYPE_NEC)
				{
					if((((u8Addr<<8) | u8AddrInv) == dev->support_ir[i].u32HeadCode))
					{
						IRDBG_ERR("[wjc_ir] [ir-nec-decoder.c] match_headcode_ok headcode = %x \n",dev->support_ir[i].u32HeadCode); 
						if (u8Cmd == (u8)~u8CmdInv) 
						{
#ifdef CONFIG_MIRC_INPUT_DEVICE		//执行这里 ************
							sc->scancode = (u8Addr<<16) | (u8AddrInv<<8) | u8Cmd;  	//u8Cmd 就是声明值,遥控器开发文档中的值
							sc->scancode_protocol = (1<<IR_TYPE_NEC);
							scancode = sc->scancode;					
							speed = dev->support_ir[i].u32IRSpeed;
							dev->map_num = dev->support_ir[i].u32HeadCode;
							mapnum = dev->map_num;        
							dev->raw->u8RepeatFlag = 0;			//非重复码即非相同按键
							IRDBG_ERR("[wjc_ir] [ir-nec-decoder.c] jiaoyan_data_ok  sc->scancode = %d \n",scancode);
#else
							sc->scancode = (u8Cmd<<8) |0x00;
							sc->scancode |= (0x01UL << 28);
							sc->scancode_protocol = (1<<IR_TYPE_NEC);
							scancode = sc->scancode;
							speed = dev->support_ir[i].u32IRSpeed;
#endif 	
							KeyTime = MIRC_Get_System_Time();
							memset(data,0,sizeof(IR_NEC_Spec_t));
							return 1;			/*********** 非常关键,返回值大于0,实现get_scancode=1,下面的代码就是前面分析的根据scancode的值匹配映射表,获取keycode,然后上报数据
						}
					}
				}
			}

		}
		else
			data->eStatus = STATE_BIT_PULSE;

		return 0;
	default:
		break;
	
	}	
	data->eStatus = STATE_INACTIVE;
		return -EINVAL;		
}
		
		
		
		
		
		
		
		

******************** 重中之重:不能在中断函数:_MDrv_IR_ISR中添加打印,会导致程序出现问题  **************************


打印分析: 因为中断中不能添加打印所以,从唤醒线程,即从线程中开始分析打印  *********** 最终版    按下音量+ 按键     
duration:持续时间
pulse: 高低电平  ev.pulse = 1表示低电平,ev.pulse = 0表示高电平    *******非常重要
[  164.202167] [  164.203854] [IR ERR ]: MIRC_Data_Ctrl_Thread[148]: 
[  164.209349] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread [sw_decoder] ev.duration = 16383 , ev.pulse = 0 ,get_scancode = 0   //???????????? 还不知道16383代表什么意思 。。
[  164.223195] [  164.224862] [IR ERR ]: ir_nec_decode[36]: 
[  164.229575] ************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  ir_nec_decode  
[  164.237682] [  164.239355] [IR ERR ]: ir_nec_decode[56]: 
[  164.244081] ************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  ir_nec_decode ev.duration = 8319 1. [case STATE_INACTIVE] jx_ydm:9ms				//9ms
[  164.256800] [  164.258467] [IR ERR ]: MIRC_Data_Ctrl_Thread[148]: 
[  164.263976] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread [sw_decoder] ev.duration = 8319 , ev.pulse = 1 ,get_scancode = 0 
[  164.278842] [  164.280524] [IR ERR ]: ir_nec_decode[36]: 
[  164.285236] ************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  ir_nec_decode  
[  164.293346] [  164.295011] [IR ERR ]: ir_nec_decode[70]: 
[  164.299723] ************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  ir_nec_decode ev.duration = 4223  2.1 HEADER  [case STATE_HEADER_SPACE] if HEADER(4.5ms)/REPORT(2.25ms) 	//4.5ms ,9ms+4.5ms表示是引导码 下面开始判断数据是1还是0
[  164.315568] [  164.317234] [IR ERR ]: MIRC_Data_Ctrl_Thread[148]: 
[  164.322728] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread [sw_decoder] ev.duration = 4223 , ev.pulse = 0 ,get_scancode = 0 
[  164.336480] [  164.338146] [IR ERR ]: ir_nec_decode[36]: 
[  164.342862] ************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  ir_nec_decode  
[  164.350975] [  164.352646] [IR ERR ]: ir_nec_decode[117]: 
[  164.357444] ************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  ir_nec_decode ev.duration = 527  3. [case STATE_BIT_PULSE] if data_duration(0.56ms) 					//0.56ms 数据波形前缀正确
[  164.371546] [  164.373211] [IR ERR ]: MIRC_Data_Ctrl_Thread[148]: 
[  164.378707] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread [sw_decoder] ev.duration = 527 , ev.pulse = 1 ,get_scancode = 0 
[  164.392378] [  164.394044] [IR ERR ]: ir_nec_decode[36]: 
[  164.398756] ************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  ir_nec_decode  
[  164.406863] [  164.408532] [IR ERR ]: ir_nec_decode[127]: 
[  164.413329] ************* ^_^ ************* [wjc_ir] [ir-nec-decoder.c]  ir_nec_decode ev.duration = 559  4. [case STATE_BIT_SPACE] if data_space(1=2.25-0.56,0=1.12-0.56) 
[  164.428644] [  164.430310] *** ^_^ *** [wjc_ir] [ir-nec-decoder.c] bit0 = 0																										//0.56ms 数据0
[  164.435979] [IR ERR ]: MIRC_Data_Ctrl_Thread[148]: [  164.441313] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread [sw_decoder] ev.duration = 559 , ev.pulse = 0 ,get_scancode = 0 
... .... 下面就开始一直解析数据  即解析32个数据波形中分别代码的值
bit0 = 0			bit8 = 0			bit16 = 1			bit24 = 0
bit1 = 0			bit9 = 0			bit17 = 0			bit25 = 1
bit2 = 0			bit10 = 0			bit18 = 1			bit26 = 0
bit3 = 0			bit11 = 0			bit19 = 0			bit27 = 1
bit4 = 0			bit12 = 0			bit20 = 1			bit28 = 0
bit5 = 0			bit13 = 0			bit21 = 0			bit29 = 1
bit6 = 1			bit14 = 1			bit22 = 0			bit30 = 1
bit7 = 0			bit15 = 0			bit23 = 0			bit31 = 1
==>					==>					==>					==>
0x40				0x40				0x15				0xea

[  168.217732] [wjc_ir] [ir-nec-decoder.c] u8Addr = 40 u8AddrInv = 40 u8Cmd = 15 u8CmdInv = ea  		//刚刚好就是前面得到的4个值   *******xixi ^_^
[  168.226152] [  168.227828] [IR ERR ]: ir_nec_decode[161]: 
[  168.232631] [wjc_ir] [ir-nec-decoder.c] match_headcode_ok headcode = 4040 							//这个就是u8Addr<<8 | u8AddrInv的值 ,这不就是头码吗?  *******
[  168.239531] [  168.241249] [IR ERR ]: ir_nec_decode[173]: 
[  168.246051] [wjc_ir] [ir-nec-decoder.c] jiaoyan_data_ok  sc->scancode = 4210709 						//这个是校验数据ok的打印   ****************  4210709 >> 8 ==0x4040  头码,  sc->scancode = (u8Addr<<16) | (u8AddrInv<<8) | u8Cmd;
[  168.253459] [  168.255190] [IR ERR ]: MIRC_Data_Ctrl_Thread[148]: 
[  168.260686] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Data_Ctrl_Thread [sw_decoder] ev.duration = 1615 , ev.pulse = 0 ,get_scancode = 1  //32bit数据全部解析完 get_scancode置1 然后开始通过scancode值获取keycode值然后input上报
[  168.274448] [  168.276175] [IR ERR ]: MIRC_Data_Ctrl_Thread[160]: 
[  168.281672] ***** ^_^ ******* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread raw->u8RepeatFlag = 0 
[  168.290389] [  168.292111] [IR ERR ]: MIRC_Data_Ctrl_Thread[173]: 
[  168.297611] ***** ^_^ ******* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread  raw->dev->filter_flag == 0 
[  168.306848] [  168.308566] [IR ERR ]: MIRC_Data_Ctrl_Thread[184]: 
[  168.314064] ***** ^_^ ******* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread  diff protocol 	//第一次按按键是不同的协议 后面按应该就是相同的协议了
[  168.322180] [  168.323910] [IR ERR ]: MIRC_Keydown[642]: 
[  168.328623] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Keydown  process_key_press		//进入MIRC_Keydown函数
[  168.337500] [  168.339220] [IR ERR ]: MIRC_Keycode_From_Map[594]: 
[  168.344720] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Keycode_From_Map  match_keymap_ok keycode= 115  //MIRC_Keycode_From_Map函数中 按键的扫描值 = c->scancode中的低8位即可   代码实现: if (((map->map.scan[i].scancode&0xff) == (scancode&0xff)) && ((scancode>>8) == map->map.headcode))
[   49.100590] ************* ^_^ ************* [wjc_ir] [ir_core.c]  MIRC_Do_Keydown input data input_keycode = 115 ,keyvalue = 1  			//这就是 最终input上报的数据



如果是开机之后按键按了好几次 ==> 相同协议条件达成
+
按同一个按键的打印   开机之后,间隔的按下v+
前面32bit打印就不展示了 都是一样的 *********  
[   85.654837] [IR ERR ]: ir_nec_decode[154]: 

[ 85.654838] [wjc_ir] [ir-nec-decoder.c] u8Addr = 40 u8AddrInv = 40 u8Cmd = 15 u8CmdInv = ea
[ 85.654840]
[ 85.654841] [IR ERR ]: ir_nec_decode[161]:
[ 85.654841] [wjc_ir] [ir-nec-decoder.c] match_headcode_ok headcode = 4040
[ 85.654843]
[ 85.654844] [IR ERR ]: ir_nec_decode[173]:
[ 85.654844] [wjc_ir] [ir-nec-decoder.c] jiaoyan_data_ok sc->scancode = 4210709
[ 85.654846]
[ 85.654848] [IR ERR ]: MIRC_Data_Ctrl_Thread[148]:
[ 85.654848] ************* _ ************* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread [sw_decoder] ev.duration = 1615 , ev.pulse = 0 ,get_scancode = 1
[ 85.654850]
[ 85.654851] [IR ERR ]: MIRC_Data_Ctrl_Thread[160]:
[ 85.654851] ***** _ ******* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread raw->u8RepeatFlag = 0
[ 85.654853]
[ 85.654854] [IR ERR ]: MIRC_Data_Ctrl_Thread[173]:
[ 85.654854] ***** _ ******* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread raw->dev->filter_flag == 0
[ 85.654856]
[ 85.654858] [IR ERR ]: MIRC_Data_Ctrl_Thread[192]:
[ 85.654858] ************* _ ************* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread same protocol diff key press = 1615
[ 85.654860]
[ 85.654861] [IR ERR ]: MIRC_Data_Ctrl_Thread[199]:
[ 85.654861] ***** _ ******* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread same protocol + diff key press //这个是按键按下
[ 85.654863]
[ 85.654864] [IR ERR ]: MIRC_Keydown[642]:
[ 85.654865] ************* _ ************* [wjc_ir] [ir_core.c] MIRC_Keydown process_key_press
[ 85.654867]
[ 85.654868] [IR ERR ]: MIRC_Keycode_From_Map[594]:
[ 85.654869] ************* _ ************* [wjc_ir] [ir_core.c] MIRC_Keycode_From_Map match_keymap_ok keycode= 115
[ 85.654905]
[ 85.654918] [IR ERR ]: MIRC_Do_Keydown[637]:
[ 85.654918] ************* _ ************* [wjc_ir] [ir_core.c] MIRC_Do_Keydown input data input_keycode = 115 ,keyvalue = 1
[ 85.655012]
[ 85.655014] [IR ERR ]: ir_nec_decode[36]:
[ 85.655014] ************* _ ************* [wjc_ir] [ir-nec-decoder.c] ir_nec_decode
[ 85.655017]
[ 85.655019] [IR ERR ]: MIRC_Data_Ctrl_Thread[148]:
[ 85.655019] ************* _ ************* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread [sw_decoder] ev.duration = 495 , ev.pulse = 1 ,get_scancode = 0
[ 85.655021]
[ 85.655022] [IR ERR ]: ir_nec_decode[36]:
[ 85.655023] ************* _ ************* [wjc_ir] [ir-nec-decoder.c] ir_nec_decode
[ 85.655024]
[ 85.655026] [IR ERR ]: MIRC_Data_Ctrl_Thread[148]:
[ 85.655027] ************* _ ************* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread [sw_decoder] ev.duration = 16383 , ev.pulse = 0 ,get_scancode = 0
[ 85.655029]
[ 85.655030] [IR ERR ]: ir_nec_decode[36]:
[ 85.655030] ************* _ ************* [wjc_ir] [ir-nec-decoder.c] ir_nec_decode
[ 85.655032]
[ 85.655033] [IR ERR ]: ir_nec_decode[56]:
[ 85.655033] ************* _ ************* [wjc_ir] [ir-nec-decoder.c] ir_nec_decode ev.duration = 8319 1. [case STATE_INACTIVE] jx_ydm:9ms //这里就会在一次判断,最终发现是相同协议,相同按键按下
[ 85.655035]
[ 85.655037] [IR ERR ]: MIRC_Data_Ctrl_Thread[148]:
[ 85.655037] ************* _ ************* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread [sw_decoder] ev.duration = 8319 , ev.pulse = 1 ,get_scancode = 0
[ 85.655039]
[ 85.655040] [IR ERR ]: ir_nec_decode[36]:
[ 85.655040] ************* _ ************* [wjc_ir] [ir-nec-decoder.c] ir_nec_decode
[ 85.655042]
[ 85.655044] [IR ERR ]: ir_nec_decode[77]:
[ 85.655044] ************* _ ************* [wjc_ir] [ir-nec-decoder.c] ir_nec_decode ev.duration = 2175 2.2 REPEAT [case STATE_HEADER_SPACE] if HEADER(4.5ms)/REPORT(2.25ms)
[ 85.655046]
[ 85.655047] [IR ERR ]: ir_nec_decode[80]:
[ 85.655047] ************* _ ************* [wjc_ir] [ir-nec-decoder.c] 111111111111
[ 85.655048]
[ 85.655049] [IR ERR ]: ir_nec_decode[86]:
[ 85.655050] ************* _ ************* [wjc_ir] [ir-nec-decoder.c] 2222222
[ 85.655051]
[ 85.655053] [IR ERR ]: MIRC_Data_Ctrl_Thread[148]:
[ 85.655053] ************* _ ************* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread [sw_decoder] ev.duration = 2175 , ev.pulse = 0 ,get_scancode = 1
[ 85.655055]
[ 85.655056] [IR ERR ]: MIRC_Data_Ctrl_Thread[160]:
[ 85.655056] ***** _ ******* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread raw->u8RepeatFlag = 1
[ 85.655058]
[ 85.655059] [IR ERR ]: MIRC_Data_Ctrl_Thread[173]:
[ 85.655060] ***** _ ******* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread raw->dev->filter_flag == 0
[ 85.655061]
[ 85.655063] [IR ERR ]: MIRC_Data_Ctrl_Thread[204]:
[ 85.655063] ************* _ ************* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread same protocol Repeat key press = 2175 //*********** 相同协议 相同按键
[ 85.655066]
[ 85.655067] [IR ERR ]: ir_nec_decode[36]:
[ 85.655067] ************* _ ************* [wjc_ir] [ir-nec-decoder.c] ir_nec_decode
[ 85.655069]
[ 85.655071] [IR ERR ]: MIRC_Data_Ctrl_Thread[148]:
[ 85.655071] ************* _ ************* [wjc_ir] [ir_core.c] MIRC_Data_Ctrl_Thread [sw_decoder] ev.duration = 495 , ev.pulse = 1 ,get_scancode = 0

************** 没了 说明前面一开始的分析是ok 的。。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值