diff -ur linux-old/drivers/media/dvb/ttpci/budget-ci.c linux/drivers/media/dvb/ttpci/budget-ci.c --- linux-old/drivers/media/dvb/ttpci/budget-ci.c 2006-09-26 17:12:41.000000000 +0200 +++ linux/drivers/media/dvb/ttpci/budget-ci.c 2006-09-28 00:13:13.000000000 +0200 @@ -65,6 +65,17 @@ #define SLOTSTATUS_READY 8 #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) +#define IR_RECV_NONE 0 +#define IR_RECV_DEVICE 1 +#define IR_RECV_CMD1 2 +#define IR_RECV_CMD2 4 +#define IR_RECV_ALL (IR_RECV_DEVICE|IR_RECV_CMD1|IR_RECV_CMD2) + +static int ir_device = -1; +module_param(ir_device, int, 0644); +MODULE_PARM_DESC(ir_device, + "Listen to IR commands from given device (0 - 31, default: all)."); + struct budget_ci { struct budget budget; struct input_dev *input_dev; @@ -150,36 +161,91 @@ { struct budget_ci *budget_ci = (struct budget_ci *) data; struct input_dev *dev = budget_ci->input_dev; - unsigned int code = - ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; + static unsigned int code1; + static unsigned int code2; + static unsigned int device; + static int status = IR_RECV_NONE; + unsigned int command = + ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0); + command = ((command >> 8) & 0xff); + + /* + * Theory of operation + * =================== + * (from http://home.tiscali.nl/m.majoor/DVBSHardware.pdf) + * + * The msp430 generates three different sequences for IR data, each one byte: + * 0x00 <= data < 0x40 = device and toggle information + * 0x40 <= data < 0x80 = command 1 + * 0x80 <= data < 0xc0 = invalid + * 0xc0 <= data < 0xff = command 2 + * + * The device and toggle information byte has the following bit structure: + * 00TDDDDD, T is the RC5 toggle bit, D are the device code bits (0 - 31) + * + * The command bytes have the following bit structure: + * X1CCCCCC, X signifies command 1 or 2, C are the command code bits (0 - 63) + * + * The order of the sequences can vary, but a command is only sucessfully + * received once all three have appeared at least once, and when the command 1 + * and command 2 commands match. + */ + + if (command < 0x40) { + /* Device and toggle information */ + device = command & 0x1f; + status |= IR_RECV_DEVICE; + dprintk(4, "budget_ci: IR data (device code) - %02x\n", device); + } else if (command < 0x80) { + /* Command 1 */ + code1 = command - 0x40; + dprintk(4, "budget_ci: IR data (command 1) - %02x\n", code1); + status |= IR_RECV_CMD1; + } else if (command >= 0xc0) { + /* Command 2 */ + code2 = command - 0xc0; + dprintk(4, "budget_ci: IR data (command 2) - %02x\n", code2); + status |= IR_RECV_CMD2; + } else { + /* Invalid */ + dprintk(4, "budget_ci: IR data (invalid) - %02x\n", command); + return; + } - if (code & 0x40) { - code &= 0x3f; + if (status != IR_RECV_ALL || code1 != code2) + return; - if (timer_pending(&dev->timer)) { - if (code == dev->repeat_key) { - ++dev->rep[0]; - return; - } - del_timer(&dev->timer); - input_report_key(dev, INPUT_KEYCODE(dev, dev->repeat_key), 0); - } + dprintk(2, "budget_ci: IR key (dev %02x) - %02x\n", device, code1); + status = IR_RECV_NONE; + + if (ir_device >= 0 && ir_device != device) { + dprintk(4, "budget_ci: IR key ignored\n"); + return; + } - if (!INPUT_KEYCODE(dev, code)) { - printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code); + if (timer_pending(&dev->timer)) { + if (code1 == dev->repeat_key) { + ++dev->rep[0]; return; } + del_timer(&dev->timer); + input_report_key(dev, INPUT_KEYCODE(dev, dev->repeat_key), 0); + } - /* initialize debounce and repeat */ - dev->repeat_key = code; - /* Zenith remote _always_ sends 2 sequences */ - dev->rep[0] = ~0; - /* 350 milliseconds */ - dev->timer.expires = jiffies + HZ * 350 / 1000; - /* MAKE */ - input_report_key(dev, INPUT_KEYCODE(dev, dev->repeat_key), !0); - add_timer(&dev->timer); + if (!INPUT_KEYCODE(dev, code1)) { + printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code1); + return; } + + /* initialize debounce and repeat */ + dev->repeat_key = code1; + /* Zenith remote _always_ sends 2 sequences */ + dev->rep[0] = ~0; + /* 350 milliseconds */ + dev->timer.expires = jiffies + HZ * 350 / 1000; + /* MAKE */ + input_report_key(dev, INPUT_KEYCODE(dev, dev->repeat_key), !0); + add_timer(&dev->timer); } static int msp430_ir_init(struct budget_ci *budget_ci)