aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c76
1 files changed, 59 insertions, 17 deletions
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index d1b5402cd6f..76d3b6694bc 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -78,6 +78,9 @@
*/
#define IR_REPEAT_TIMEOUT 350
+/* RC5 device wildcard */
+#define IR_DEVICE_ANY 255
+
/* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two),
* this setting allows the superflous sequences to be ignored
*/
@@ -85,12 +88,17 @@ static int debounce = 0;
module_param(debounce, int, 0644);
MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)");
+static int rc5_device = -1;
+module_param(rc5_device, int, 0644);
+MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
+
struct budget_ci_ir {
struct input_dev *dev;
struct tasklet_struct msp430_irq_tasklet;
char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
char phys[32];
struct ir_input_state state;
+ int rc5_device;
};
struct budget_ci {
@@ -114,32 +122,56 @@ static void msp430_ir_interrupt(unsigned long data)
struct budget_ci *budget_ci = (struct budget_ci *) data;
struct input_dev *dev = budget_ci->ir.dev;
static int bounces = 0;
- u32 ir_key;
+ int device;
+ int toggle;
+ static int prev_toggle = -1;
+ static u32 ir_key;
u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
+ /*
+ * The msp430 chip can generate two different bytes, command and device
+ *
+ * type1: X1CCCCCC, C = command bits (0 - 63)
+ * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
+ *
+ * More than one command byte may be generated before the device byte
+ * Only when we have both, a correct keypress is generated
+ */
+
+ /* Is this a RC5 command byte? */
if (command & 0x40) {
ir_key = command & 0x3f;
+ return;
+ }
- if (ir_key != dev->repeat_key && del_timer(&dev->timer))
- /* We were still waiting for a keyup event but this is a new key */
- ir_input_nokey(dev, &budget_ci->ir.state);
+ /* It's a RC5 device byte */
+ device = command & 0x1f;
+ toggle = command & 0x20;
- if (ir_key == dev->repeat_key && bounces > 0 && timer_pending(&dev->timer)) {
- /* Ignore repeated key sequences if requested */
- bounces--;
- return;
- }
+ if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device)
+ return;
- if (!timer_pending(&dev->timer))
- /* New keypress */
- bounces = debounce;
+ /* Are we still waiting for a keyup event while this is a new key? */
+ if ((ir_key != dev->repeat_key || toggle != prev_toggle) && del_timer(&dev->timer))
+ ir_input_nokey(dev, &budget_ci->ir.state);
- /* Prepare a keyup event sometime in the future */
- mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT));
+ prev_toggle = toggle;
- /* Generate a new or repeated keypress */
- ir_input_keydown(dev, &budget_ci->ir.state, ir_key, command);
+ /* Ignore repeated key sequences if requested */
+ if (ir_key == dev->repeat_key && bounces > 0 && timer_pending(&dev->timer)) {
+ bounces--;
+ return;
}
+
+ /* New keypress? */
+ if (!timer_pending(&dev->timer))
+ bounces = debounce;
+
+ /* Prepare a keyup event sometime in the future */
+ mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT));
+
+ /* Generate a new or repeated keypress */
+ ir_input_keydown(dev, &budget_ci->ir.state, ir_key, ((device << 8) | command));
}
static void msp430_ir_debounce(unsigned long data)
@@ -228,7 +260,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
input_dev->dev = &saa->pci->dev;
# endif
- /* Select keymap */
+ /* Select keymap and address */
switch (budget_ci->budget.dev->pci->subsystem_device) {
case 0x100c:
case 0x100f:
@@ -239,11 +271,21 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
/* The hauppauge keymap is a superset of these remotes */
ir_input_init(input_dev, &budget_ci->ir.state,
IR_TYPE_RC5, ir_codes_hauppauge_new);
+
+ if (rc5_device < 0)
+ budget_ci->ir.rc5_device = 0x1f;
+ else
+ budget_ci->ir.rc5_device = rc5_device;
break;
default:
/* unknown remote */
ir_input_init(input_dev, &budget_ci->ir.state,
IR_TYPE_RC5, ir_codes_budget_ci_old);
+
+ if (rc5_device < 0)
+ budget_ci->ir.rc5_device = IR_DEVICE_ANY;
+ else
+ budget_ci->ir.rc5_device = rc5_device;
break;
}