RK 3066リモコンデバッグプロセス
RK 3066リモコンフロー
1.まず構成されたドライバを見てみましょう
3.分析ソースプログラム
#vi kernel/drivers/input/remotectl/rkxx_remotectl.c
デバッグ中に発生した問題:
1.リモコンは操作されていないが、駆動表示に割り込みが発生している
与えられたusercodeコードとキー値の対応関係を押して、そのマッピングと関連するlogを増やした後、コンパイル-録画して、正常にキーに応答できないことを発見して、logを見てUSERCODEに入っていないことを知って、観察して、意外にもリモコンを操作していないで、中断しても報告します.これは基本的にハードウェアの原因であると判断できる.プレートを交換してください.
2.コードから読み出されたデータとリモコンメーカーから提供された値は、ちょうど逆シーケンスです
リモコンメーカーはこれが正常だと言っています.私たちが提供したコード値のため、彼らのソフトウェアは逆シーケンスで発行されます.修正したいなら、逆シーケンスのコード値を直接提供すればいいです.リモコンの報告値に基づいて駆動で対応すればいいです.
1.まず構成されたドライバを見てみましょう
#vi kernel/.config
CONFIG_RECKCHIP_REMOTECTL=y
CONFIG_RK_REMOTECTL=y
2.上記のオプションが構成されているプロファイルを検索すると、ドライバのソースがわかります. #vi kernel/drivers/input/remotectl/Kconfig
menuconfig ROCKCHIP_REMOTECTL
bool "rkxx remotectl"
default y
help
...
if ROCKCHIP_REMOTECTL
config RK_REMOTECTL
bool "rkxx remotectl"
default y
...
endif
#vi kernel/drivers/input/remotectl/Makefile
obj-$(CONFIG_RK_REMOTECTL) += rkxx_remotectl.o
RK_が構成されている場合はREMOTECTLがyであればrkxx_remotectl.oカーネルを入れて、このrkxx_remotectl.oはrkxx_に対応するremotectl.cファイル3.分析ソースプログラム
#vi kernel/drivers/input/remotectl/rkxx_remotectl.c
static int __devinit remotectl_probe(struc platform_device *pdev)
{
struct RKxx_remotectl_platform_data *pdata; //
pdata = pdev->dev.platform_data;
struc rkxx_remotectl_drvdata *ddata; // , , ,
...
ddata = kzalloc(sizeof(struct rkxx_remotectl_drvdata),GFP_KERNEL); //
memset(ddata, 0, sizeof(struct rkxx_remotectl_drvdata)); // , “ ”
ddata->state = RMC_PRELAOD; // , typedef enum _RMC_STATE{RMC_IDLE,RMC_PRELOAD,RMC_USERCODE,RMC_GETDATA,RMC_SEQUENCE}eRMC_STATE
input = input_allocate_device(); // 。 input_free_device,
platform_set_drvdata(pdev,ddata); // ,
//
input->name = pdev->name;
input->phys = "gpio-keys/input0";
input->dev.parent = &pdev->dev;
input->id.bustype = BUS_HOST;
input->id.vendor = 0x0001;
input->id.product = 0x0001;
input->id.version = 0x0100;
if(pdata->rep) //
__set_bit(EV_REP, input->evbit); // Linux (Enable auto repeat feature of Linux input subsystem)
ddata->input = input; // input input
wake_lock_init(&ddata->remotectl_wake_lock, WAKE_LOCK_SUSPEND,"rk29_remote"); // , , 。
...
error = gpio_request(pdata->gpio, "remotectl"); // gpio , GPIO(These"optonal" allocation calls help prevent drivers from stomping on each other, and help provide better diagnostics debugfs. They're called even less than the "set direction" call)
...error ,goto fail1;
error = gpio_direction_input(pdata->gpio); //(Drivers Must set GPIO directoin before making get/set calls. In some cases this is done in early boot, befor IRQs are enabled.)
...error ,goto fail1;
irq = gpio_to_irq(pdata->gpio); //(return the IRQ corresponding to a GPIO,@gpio whose IRQ will be return{already requested})
...error ,goto fail1;
error = request_irq(irq, remotectl_isr,IRQF_TRIGGER_FALLING,"remotectl",ddata); //
...error ,goto fail1;
setup_timer(&ddata->timer, remotectl_timer, (unsigned long)ddata; // , remotectl_timer
tasklet_init(&ddata->remote_tasklet, remotectl_do_something, (unsigned long)ddata); // tasklet, remotectl_do_something
/*
struct input_event ,
struct input_event {
structtimeval time; //
__u16type; //
__u16code; //
__s32value; //
};
, linux/input.h
#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 //
,
EV_KEY KEY_1,KEY_2,KEY_3…
EV_REL REL_X,REL_Y, REL_Z…
EV_ABS ABS_X,ABS_Y, ABS_Z…
, , GPIO ( ), 0, 1
*/
for(j = 0; j < sizeof(remotectl_button)/sizeof(struct rkxx_remotectl_button); j++){
for(i = 0; i < remotectl_button[j].nbuttons; i++){
unsigned int type = EV_KEY;
input_set_capability(input, type, remotectl_button[j].key_table[i].keyCode); // : , keyCode
//input_set_capability :
/*
// ( )
set_bit(EV_KEY, input->evbit);
// ( 1 set_bit(KEY_1, input->keybit);)
set_bit(remotectl_button[j].key_table[i].keyCode, input->keybit);
*/
}
}
error = input_register_device(input); // , input
//error
input_set_capability(input, EV_KEY, KEY_WAKEUP); // :
device_init_wakeup(&pdev->dev, 1);
return 0;
fail*:
//
}
static struct platform_driver remotectl_device_driver = {
.probe = remotectl_probe, // ,
.remove = __devexit_p(remotectl_remove),
.driver = {
.name = "rkxx-remotectl",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &remotectl_pm_ops, //
#endif
}
}
static int remotectl_init(void) //
{
return platform_driver_register(&remotectl_device_driver);
}
static int remotectl_exit(void) //
{
return platform_driver_unregister(&remotectl_device_driver);
}
module_init(remotectl_init);
module_exit(remotectl_exit);
MODULE_DESCRIPTION("Keyboard driver for CUP GPIOs"); // GPIO
, , , input_report_key, , :
void input_report_key(struct input_dev *dev, unsigned int code, int value)
void input_report_rel(struct input_dev *dev, unsigned int code, int value)
void input_report_abs(struct input_dev *dev, unsigned int code, int value)
,
void input_sync(struct input_dev *dev)
Input_event
void input_event(struct input_dev *dev,unsigned int type, unsigned int code, intvalue)
input_report_key :
static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev,EV_KEY, code, !!value); //!!value value 0 1,
}
, , , 。
static irqreturn_t remotectl_isr(int irq, void *dev_id)
{
...
ddata->period = ddata->cur_time - ddata->pre_time; //
// &ddata->remote_tasklet, tasklet remotectl_do_something
tasklet_hi_schedule(&ddata->remote_tasklet); //tasklet_schedule() tasklet_hi_schedule() CPU TASKLET_SOFTIRQ HI_SOFTIRQ, tasklet CPU tasklet 。tasklet_hi_schedule()
if((ddata->state == RMC_PRELOAD) || (ddata->state == RMC_SEQUENCE))
mod_timer(&ddata->timer, jiffies + msecs_to_jiffies(130)); // 130
}
static void remotectl_do_something(unsigned long data)
{
/*
RMC_PRELOAD -> RMC_USERCODE -> RMC_GETDATA ( -> RMC_SEQUENCE , )
*/
struct rkxx_remotectl_drvdata *ddata = (struct rkxx_remotectl_drvdata *)data;
switch(ddata->state)
{
case RMC_IDLE:
break;
case RMC_PRELOAD:
//#define TIME_PRE_MIN 13000
//#define TIME_PRE_MAX 14000
if((TIME_PRE_MIN < ddata->period) && (ddata->period < TIME_PRE_MAX)){ // period , , RMC_USERCODE
ddata->scanData = 0;
ddata->count = 0;
ddata->state = RMC_USERCODE;
}else{
ddata-> state = RMC_PRELOAD;
}
ddata->pre_time = ddata->cur_time;
break;
case RMC_USERCODE:
ddata->scanData <<= 1; // scanData, , spec ,
ddata->count++; // usercode 16bit , count , 0x10 usercode
if((TIME_BIT1_MIN < ddata->preiod) && (ddata->preiod < TIME_BIT1_MAN)){
ddata->scanData |= 0x01; // spec scanData
}
if(ddata->count == 0x10){ 16bit usercode
if(remotectl_keybdNum_lookup(ddata){ // usercode
ddata->state = RMC_GETDATA;
ddata->scanData = 0;
ddata->count = 0;
}else{
ddata->state = RMC_PRELOAD;
}
}
break;
case RMC_GETDATA:
ddata->count++;
ddata->scanData <<=1;
if((TIME_BIT1_MIN < ddata->period) && (ddata->period < TIME_BIT1_MAX)){
ddata->scanData |= 0x01;
}
if(ddata->count == 0x10){
if((ddata->scanData&0x0ff) == ((!ddata->scanData >> 8)&0x0ff)){ //&0x0ff 8
if(remotectl_keycode_lookup(ddata)){
ddata->press = 1;
if(get_suspend_state() == 0){ // ,
input_event(ddata->input, EV_KEY, ddata->keycode, 1);
input_sync(ddata->input);
}else if((get_suspend_state()) && (ddata->keycode==KEY_POWER)){ // , KEY_POWER, KEY_WAKEUP ( )
input_event(ddata->input, EV_KEY, KEY_WAKEUP, 1);
input_sync(ddata->input);
}
ddata-> state = RMC_SEQUENCE;
}else{
ddata->state = RMC_PRELOAD;
}
}
}
break;
case RMC_SEQUENCE:
if((TIME_RPT_MIN < ddata->period) && (ddata->period < TIME_RPT_MAX)){
;
}else if((TIME_SEQ_MIN < ddata->period) && (ddata->period < TIME_SEQ_MAX)){
if(ddata->press == 1){
ddata->press = 3;
}else if(ddata->press & 0x2){
ddata->press = 2;
}
}
default:
}
}
, , , ,
, 130
static void remotectl_timer(unsigned long data)
{
struct rkxx_remotectl_drvdata *ddata = (struct rkxx_remotectl_drvdata*)__data;
if(ddata->press != ddata->pre_press){
ddata->pre_press = ddata->press = 0;
if(get_suspend_state() == 0){
input_event(ddata->input, EV_KEY, ddata->keycode, 0);
input_sync(ddata->input);
}else if((get_suspend_state()) && (ddata->keycode == KEY_POWER)){
input_event(ddata->input, EV_KEY, KEY_WAKEUP, 0);
input_sync(ddata->input);
}
}
}
注意:logを見ると、リモコンがbitを1つ報告するたびに割り込みが発生し、報告順序やルールについてはNECプロトコルの原理を参照することができます.(1つお勧め:http://download.csdn.net/detail/lijinwei_123/5698249)デバッグ中に発生した問題:
1.リモコンは操作されていないが、駆動表示に割り込みが発生している
与えられたusercodeコードとキー値の対応関係を押して、そのマッピングと関連するlogを増やした後、コンパイル-録画して、正常にキーに応答できないことを発見して、logを見てUSERCODEに入っていないことを知って、観察して、意外にもリモコンを操作していないで、中断しても報告します.これは基本的にハードウェアの原因であると判断できる.プレートを交換してください.
2.コードから読み出されたデータとリモコンメーカーから提供された値は、ちょうど逆シーケンスです
リモコンメーカーはこれが正常だと言っています.私たちが提供したコード値のため、彼らのソフトウェアは逆シーケンスで発行されます.修正したいなら、逆シーケンスのコード値を直接提供すればいいです.リモコンの報告値に基づいて駆動で対応すればいいです.