Hi3716C Android IR Remote control driver分析

http://blog.sina.com.cn/s/blog_602f877001019wtx.html

 

Hi3716C Android IR Remote control driver分析

(2012-12-15 12:54:54)
标签:

ir

remote

hi3716

分类: Android
作者:Sam (甄峰) sam_code@hotmail.com
 
Sam之前一直认为Android各芯片厂商是利用UInput将红外遥控器(IR Remote Control)模拟为Input Device(Keyboard)的。 但今天在察看Hi3716C Android下driver信息时,突然发现ir_keyboad这样一个driver. 于是怀疑海思其实还是使用driver来模拟Input Device的。于是在其代码树内察看。在/froyo/device/hisi/Hi3716C/driver/sdk/msp/android_driver/hi_keypad中找到这个driver源码。
 
现分析如下:
 
1. driver入口:
module_init(IR_Keypad_Init);
insmod 时则调用IR_Keypad_Init.
 
 
2. 注册platform driver.
retval = platform_device_register(&ir_keypad_dev);
retval = platform_driver_register(&irevent_driver);
 
关键程序在irevent_driver中的probo中。
 
2.1:
分配device 资源。
 
2.2:指出此device会发送什么类型的信息
set_bit(EV_KEY, edev->input->evbit);  //键盘。
set_bit(EV_REL, edev->input->evbit);  //相对光标,鼠标
//Sam: 指出此Device支持键盘和鼠标设备消息。
 
// 允许Key为:1--0x1ff
//ESC-- 0x1ff的键和Button都支持。
for (i=1; i<= 0x1ff; i++) {
        set_bit(i, edev->input->keybit);
}
//Sam:注意,此处和UInput的set_bit类似。都是指明我们会发送什么Key或者Button。
 
set_bit(EV_SYN, edev->input->relbit);
set_bit(EV_KEY, edev->input->relbit);
//Sam: 设置支持什么相对Event。但这里写的有点问题,虽然不影响结果。但容易误导自己。正确的写法应该是:
set_bit(REL_X, edev->input->relbit);
set_bit(REL_Y, edev->input->relbit);
 
 
 
2.3:注册input device
将edev->input 设置。之后再注册到input 子系统中
input_register_device(edev->input);
 
 
2.4: 注册中断处理程序:
 request_irq(edev->irq, IR_Keypad_IntIsr, IRQF_SHARED, "irkeypad_events", edev)
当发生edev->irq中断时,调用IR_Keypak_IntIsr中断服务程序。
 
 
2.5:IR硬件初始化:
写一些寄存器。选定IR NEC具体方案等。
 
 
 
中断处理程序:
static irqreturn_t IR_Keypad_IntIsr(int irq, void *dev_id)
当有键按下是,中断处理程序被调用。此时,通过读取register中某些特定值得到按键值。翻译成为KeyCode并发送给Input子系统。
 
细节:
通过读取Register(#define  IR_INTS          (IR_REG_BASE + 0x2c))中内容, 判断遥控器是按下,抬起还是状态错误。如果是按下,且value值和上一次一致,则判断是保持。
然后将读出的Register_key与下表比较,如果有匹配,则发送具体的KeyEvent。
const hikeycode Key_Code[] = 
{
{IR_KEY_UP            ,KEY_UP          },// 0x35caff00
{IR_KEY_DOWN          ,KEY_DOWN        },// 0x2dd2ff00
{IR_KEY_RIGHT         ,KEY_LEFT        },// 0x6699ff00
{IR_KEY_LEFT          ,KEY_RIGHT       },// 0x3ec1ff00
{IR_KEY_OK            ,KEY_ENTER       },// 0x31ceff00
{IR_KEY_BACK          ,KEY_BACK        },// 0x6f90ff00
{IR_KEY_MENU          ,KEY_MENU        },// 0x629dff00
{IR_KEY_POWER         ,KEY_POWER       },// 0x639cff00
{IR_KEY_HOME          ,KEY_HOME        },// 0x34cbff00
{IR_KEY_VOLADD        ,KEY_VOLUMEUP    },// 0x7f80ff00
{IR_KEY_VOLSUB        ,KEY_VOLUMEDOWN  },// 0x7e81ff00
{IR_KEY_MUTE          ,KEY_MUTE        },// 0x22ddff00
{IR_KEY_1             ,KEY_1           },// 0x6d92ff00
{IR_KEY_2             ,KEY_2           },// 0x6c93ff00
{IR_KEY_3             ,KEY_3           },// 0x33ccff00
{IR_KEY_4             ,KEY_4           },// 0x718eff00
{IR_KEY_5             ,KEY_5           },// 0x708fff00
{IR_KEY_6             ,KEY_6           },// 0x37c8ff00
{IR_KEY_7             ,KEY_7           },// 0x758aff00
{IR_KEY_8             ,KEY_8           },// 0x748bff00
{IR_KEY_9             ,KEY_9           },// 0x3bc4ff00
{IR_KEY_0             ,KEY_0           },// 0x7887ff00
{IR_KEY_F1            ,KEY_F1          },// 0x7b84ff00
{IR_KEY_F2            ,KEY_F2          },// 0x7689ff00
{IR_KEY_F3            ,KEY_F3          },// 0x26d9ff00
{IR_KEY_F4            ,KEY_F4          },// 0x6996ff00
{IR_KEY_SEARCH        ,KEY_SEARCH      },// 0x6897ff00
{IR_KEY_REWIND        ,KEY_REWIND      },// 0x25daff00
{IR_KEY_FORWARD       ,KEY_FORWARD     },// 0x29d6ff00
{IR_KEY_STOP          ,KEY_STOP        },// 0x2fd0ff00
{IR_KEY_SETUP         ,KEY_SETUP       },// 0x6a95ff00
{IR_KEY_INFO          ,KEY_INFO        },// 0x38c7ff00
{IR_KEY_AUDIO         ,KEY_AUDIO       },// 0x2ed1ff00
{IR_KEY_SUBTITLE      ,KEY_SUBTITLE    },// 0x738cff00
{IR_KEY_BACKSPACE     ,KEY_BACKSPACE   },// 0x7788ff00
{IR_KEY_PLAYPAUSE     ,KEY_PLAYPAUSE   },// 0x3cc3ff00
{IR_KEY_FAVORITES     ,KEY_FAVORITES   },// 0x6b94ff00
{IR_KEY_CHANNELUP     ,KEY_CHANNELUP   },// 0x7a85ff00  
{IR_KEY_CHANNELDOWN   ,KEY_CHANNELDOWN },// 0x7986ff00
{IR_KEY_PAGEDOWN      ,KEY_PAGEDOWN    },// 0x6798ff00
{IR_KEY_PAGEUP        ,KEY_PAGEUP      },// 0x30cfff00
{IR_KEY_IME           ,KEY_FN_1        },// 0x609fff00   
{IR_KEY_MORE          ,KEY_FN_2        },// 0x39c6ff00   
{IR_KEY_BTV           ,KEY_FN_D        },// 0x649bff00   
{IR_KEY_VOD           ,KEY_FN_E        },// 0x659aff00   
{IR_KEY_NVOD          ,KEY_FN_F        },// 0x3fc0ff00   
{IR_KEY_NPVR          ,KEY_FN_S        },// 0x3dc2ff00   
{IR_KEY_SEEK          ,KEY_FN_B        },// 0x7d82ff00 
};
 
 
 
 
 
注1:
关于Platform driver的注册:
要用注册一个platform驱动的步骤:
1,注册设备platform_device_register
2,注册驱动platform_driver_register
注册时候的两个名字必须一样,才能匹配。
 platform_driver_register(&xx_driver) 会向系统注册xx_driver这个驱动程序,这个函数会以 xx_driver中的.name内容,搜索系统注册的device中有没有这个platform_device,如果有,就会执行 platform_driver(也就是xx_driver的类型)中的.probe函数。


注2:
input_dev 中内容讲解:
它用来描述一个Input Device. 
 
const char *name;    //Device的名字
const char *phys;    //physical path to the device in the system hierarchy
const char *uniq;    //唯一识别号。(如果设备存在)
struct input_id id;  // id of the device (struct input_id)
 
 
unsigned long evbit[BITS_TO_LONGS(EV_CNT)];  //指出这个device都支持哪种类型的event. 例如:EV_KEY,EV_REL (详见注3)
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];  //这个device可以支持的Key和Button(如果evbit支持EV_KEY)
unsigned long relbit[BITS_TO_LONGS(REL_CNT)];  //这个device可以支持的轴相对信息。(鼠标是相对)
unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];  // 这个device可以支持的轴绝对信息。(Touch是绝对)
unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
 
 
 
 
 
注3:不同类型的Input Event:
#define EV_SYN          0x00    表示设备支持所有的事件
#define EV_KEY          0x01    键盘或者按键,表示一个键码  
#define EV_REL          0x02    鼠标设备,表示一个相对的光标位置结果
#define EV_ABS          0x03    手写板产生的值,其是一个绝对整数值 
#define EV_MSC          0x04    其他类型 
#define EV_LED          0x11    LED灯设备
#define EV_SND          0x12    蜂鸣器,输入声音 
#define EV_REP          0x14    允许重复按键类型 
#define EV_PWR          0x16    电源管理事件 
#define EV_FF_STATUS 0x17
#define EV_MAX 0x1f
#define EV_CNT (EV_MAX+1)
posted @ 2015-01-26 20:06  alxe_yu  阅读(852)  评论(0)    收藏  举报