Em Fri, 14 Dec 2012 17:39:50 -0200 Mauro Carvalho Chehab <mchehab@xxxxxxxxxx> escreveu: > > Anyway, first we have to GET the bytes from the hardware. That's our > > current problem ! > > And the hardware seems to need a different setup for reg 0x50 for the > > different NEC sub protocols. > > Which means that the we need to know the sub protocol BEFORE we get any > > bytes from the device. > > No. All em28xx needs is to make sure that the NEC protocol will return > the full 32 bits scancode. It seems a way easier/quicker to just add the proper support there at the driver than keep answering to this thread ;) Tested here with a Terratec HTC stick, and using two different IR's: - a Terratec IR (address code 0x14 - standard NEC); - a Pixelview IR (address code 0x866b - 24 bits NEC). All tests were done with the very latest version of ir-keytable, found at v4l-utils.git tree (http://git.linuxtv.org/v4l-utils.git). See the results, with the Terratec table loaded (default when the driver is loaded): # ir-keytable -t Testing events. Please, press CTRL-C to abort. # Terratec IR 1355529698.198046: event type EV_MSC(0x04): scancode = 0x1402 1355529698.198046: event type EV_KEY(0x01) key_down: KEY_1(0x0001) 1355529698.198046: event type EV_SYN(0x00). 11355529698.298170: event type EV_MSC(0x04): scancode = 0x1402 1355529698.298170: event type EV_SYN(0x00). 1355529698.547998: event type EV_KEY(0x01) key_up: KEY_1(0x0001) 1355529698.547998: event type EV_SYN(0x00). # Pixelview IR 1355530261.416415: event type EV_MSC(0x04): scancode = 0x866b01 1355530261.416415: event type EV_SYN(0x00). 1355530262.216301: event type EV_MSC(0x04): scancode = 0x866b0b 1355530262.216301: event type EV_SYN(0x00). Replacing the keytable to the Pixelview's one: # ir-keytable -w /etc/rc_keymaps/pixelview_002t -c Read pixelview_002t table Old keytable cleared Wrote 26 keycode(s) to driver Protocols changed to NEC # ir-keytable -t Testing events. Please, press CTRL-C to abort. 1355530569.420398: event type EV_MSC(0x04): scancode = 0x1402 1355530569.420398: event type EV_SYN(0x00). 1355530588.120409: event type EV_MSC(0x04): scancode = 0x866b01 1355530588.120409: event type EV_KEY(0x01) key_down: KEY_1(0x0001) 1355530591.670077: event type EV_SYN(0x00). And, finally, keeping both keytables active at the same time: # ir-keytable -c -w /etc/rc_keymaps/pixelview_002t -w /etc/rc_keymaps/nec_terratec_cinergy_xs Read pixelview_002t table Read nec_terratec_cinergy_xs table Old keytable cleared Wrote 74 keycode(s) to driver Protocols changed to NEC # sudo ir-keytable -t Testing events. Please, press CTRL-C to abort. 1355530856.325201: event type EV_MSC(0x04): scancode = 0x866b01 1355530856.325201: event type EV_KEY(0x01) key_down: KEY_1(0x0001) 1355530856.325201: event type EV_SYN(0x00). 11355530856.575070: event type EV_KEY(0x01) key_up: KEY_1(0x0001) 1355530856.575070: event type EV_SYN(0x00). 1355530869.125226: event type EV_MSC(0x04): scancode = 0x1402 1355530869.125226: event type EV_KEY(0x01) key_down: KEY_1(0x0001) 1355530869.125226: event type EV_SYN(0x00). 11355530869.225216: event type EV_MSC(0x04): scancode = 0x1402 1355530869.225216: event type EV_SYN(0x00). 1355530869.475075: event type EV_KEY(0x01) key_up: KEY_1(0x0001) 1355530869.475075: event type EV_SYN(0x00). - em28xx: add support for 24bits/32 bits NEC variants on em2874 and upper By disabling the NEC parity check, it is possible to handle all 3 NEC protocol variants (32, 24 or 16 bits). Change the driver in order to handle all of them. Signed-off-by: Mauro Carvalho Chehab <mchehab@xxxxxxxxxx> diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 97d36b4..c84e4c8 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -57,8 +57,8 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); struct em28xx_ir_poll_result { unsigned int toggle_bit:1; unsigned int read_count:7; - u8 rc_address; - u8 rc_data[4]; /* 1 byte on em2860/2880, 4 on em2874 */ + + u32 scancode; }; struct em28xx_IR { @@ -72,6 +72,7 @@ struct em28xx_IR { struct delayed_work work; unsigned int full_code:1; unsigned int last_readcount; + u64 rc_type; int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); }; @@ -236,11 +237,8 @@ static int default_polling_getkey(struct em28xx_IR *ir, /* Infrared read count (Reg 0x45[6:0] */ poll_result->read_count = (msg[0] & 0x7f); - /* Remote Control Address (Reg 0x46) */ - poll_result->rc_address = msg[1]; - - /* Remote Control Data (Reg 0x47) */ - poll_result->rc_data[0] = msg[2]; + /* Remote Control Address/Data (Regs 0x46/0x47) */ + poll_result->scancode = msg[1] << 8 | msg[2]; return 0; } @@ -266,13 +264,30 @@ static int em2874_polling_getkey(struct em28xx_IR *ir, /* Infrared read count (Reg 0x51[6:0] */ poll_result->read_count = (msg[0] & 0x7f); - /* Remote Control Address (Reg 0x52) */ - poll_result->rc_address = msg[1]; - - /* Remote Control Data (Reg 0x53-55) */ - poll_result->rc_data[0] = msg[2]; - poll_result->rc_data[1] = msg[3]; - poll_result->rc_data[2] = msg[4]; + /* Remote Control Address (Reg 0x52) */ + /* Remote Control Data (Reg 0x53-0x55) */ + switch (ir->rc_type) { + case RC_TYPE_RC5: + poll_result->scancode = msg[1] << 8 | msg[2]; + break; + case RC_TYPE_NEC: + if ((msg[3] ^ msg[4]) != 0xff) /* 32 bits NEC */ + poll_result->scancode = (msg[1] << 24) | + (msg[2] << 16) | + (msg[3] << 8) | + msg[4]; + else if ((msg[1] ^ msg[2]) != 0xff) /* 24 bits NEC */ + poll_result->scancode = (msg[1] << 16) | + (msg[3] << 8) | + msg[4]; + else /* Normal NEC */ + poll_result->scancode = msg[1] << 8 | msg[3]; + break; + default: + poll_result->scancode = (msg[1] << 24) | (msg[2] << 16) | + (msg[3] << 8) | msg[4]; + break; + } return 0; } @@ -294,17 +309,16 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) } if (unlikely(poll_result.read_count != ir->last_readcount)) { - dprintk("%s: toggle: %d, count: %d, key 0x%02x%02x\n", __func__, + dprintk("%s: toggle: %d, count: %d, key 0x%04x\n", __func__, poll_result.toggle_bit, poll_result.read_count, - poll_result.rc_address, poll_result.rc_data[0]); + poll_result.scancode); if (ir->full_code) rc_keydown(ir->rc, - poll_result.rc_address << 8 | - poll_result.rc_data[0], + poll_result.scancode, poll_result.toggle_bit); else rc_keydown(ir->rc, - poll_result.rc_data[0], + poll_result.scancode & 0xff, poll_result.toggle_bit); if (ir->dev->chip_id == CHIP_ID_EM2874 || @@ -359,11 +373,13 @@ static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type) ir->full_code = 1; } else if (rc_type == RC_TYPE_NEC) { dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; - ir_config = EM2874_IR_NEC; + ir_config = EM2874_IR_NEC | EM2874_IR_NEC_NO_PARITY; ir->full_code = 1; } else if (rc_type != RC_TYPE_UNKNOWN) rc = -EINVAL; + ir->rc_type = rc_type; + em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, EM28XX_XCLK_IR_RC5_MODE); diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h index 6ff3682..2ad3573 100644 --- a/drivers/media/usb/em28xx/em28xx-reg.h +++ b/drivers/media/usb/em28xx/em28xx-reg.h @@ -177,6 +177,7 @@ /* em2874 IR config register (0x50) */ #define EM2874_IR_NEC 0x00 +#define EM2874_IR_NEC_NO_PARITY 0x01 #define EM2874_IR_RC5 0x04 #define EM2874_IR_RC6_MODE_0 0x08 #define EM2874_IR_RC6_MODE_6A 0x0b -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html