1. 程式人生 > >46.Linux-分析rc紅外遙控平臺驅動框架,修改核心的NEC解碼函式BUG(1)

46.Linux-分析rc紅外遙控平臺驅動框架,修改核心的NEC解碼函式BUG(1)

static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
         struct nec_dec *data = &dev->raw->nec;
         u32 scancode;
         u8 address, not_address, command, not_command;
         bool send_32bits = false;

         if (!(dev->enabled_protocols & RC_BIT_NEC))              //
判斷協議是否支援 return 0; //… … switch (data->state) { case STATE_INACTIVE: if (!ev.pulse) break; if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT * 2)) { //判斷ev.duration 是否等於9ms頭引導碼
data->is_nec_x = false; //標記當前格式不是NECX編碼格式 data->necx_repeat = false; } else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2)) //另一種不常見的NECX引導碼 data->is_nec_x = true; //
標記是NECX編碼格式 else break; data->count = 0; data->state = STATE_HEADER_SPACE; //進入判斷引導碼間隔值,是4.5ms還是2.25ms ? return 0; case STATE_HEADER_SPACE: if (ev.pulse) break; if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT)) { //如果ev.duration=4.5ms 間隔引導碼 data->state = STATE_BIT_PULSE; //進入解析32bit模式 return 0; } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) { //如果ev.duration=2.5ms ,表示重複引導碼 if (!dev->keypressed) { //dev->keypressed是鬆開的,則放棄(這裡有BUG,後面會分析到) IR_dprintk(1, "Discarding last key repeat: event after key up\n"); } else { rc_repeat(dev); //dev->keypressed是未鬆開,則上報事件 IR_dprintk(1, "Repeat last key\n"); data->state = STATE_TRAILER_PULSE; } return 0; } break; case STATE_BIT_PULSE: //接收資料位的脈衝數據 if (!ev.pulse) break; if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2)) //不等於0.56ms,則忽略掉 break; data->state = STATE_BIT_SPACE; //等於0.56ms,接下來進入STATE_BIT_SPACE,開始解析資料bit return 0; case STATE_BIT_SPACE: if (ev.pulse) break; if (data->necx_repeat && data->count == NECX_REPEAT_BITS && geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) { //解析NECX編碼格式 IR_dprintk(1, "Repeat last key\n"); rc_repeat(dev); data->state = STATE_INACTIVE; return 0; } else if (data->count > NECX_REPEAT_BITS) data->necx_repeat = false; data->bits <<= 1; if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2)) // 1.68ms 資料1 data->bits |= 1; else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2)) // 既不等於1.68ms,也不等於0.56ms,則是無效資料 break; data->count++; if (data->count == NEC_NBITS) //data->count == 32,則表示資料接收完成 data->state = STATE_TRAILER_PULSE; else data->state = STATE_BIT_PULSE; return 0; case STATE_TRAILER_PULSE: if (!ev.pulse) break; if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2)) break; data->state = STATE_TRAILER_SPACE; return 0; case STATE_TRAILER_SPACE: if (ev.pulse) break; if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) break; address = bitrev8((data->bits >> 24) & 0xff); not_address = bitrev8((data->bits >> 16) & 0xff); command = bitrev8((data->bits >> 8) & 0xff); not_command = bitrev8((data->bits >> 0) & 0xff); if ((command ^ not_command) != 0xff) { //解析資料 IR_dprintk(1, "NEC checksum error: received 0x%08x\n", data->bits); send_32bits = true; } if (send_32bits) { /* NEC transport, but modified protocol, used by at * least Apple and TiVo remotes */ scancode = data->bits; IR_dprintk(1, "NEC (modified) scancode 0x%08x\n", scancode); } else if ((address ^ not_address) != 0xff) { /* Extended NEC */ scancode = address << 16 | not_address << 8 | command; IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode); } else { /* Normal NEC */ scancode = address << 8 | command; IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); } if (data->is_nec_x) data->necx_repeat = true; rc_keydown(dev, scancode, 0); //通過scancode編碼來上報按鍵事件 data->state = STATE_INACTIVE; return 0; } //… … }