|
@@ -73,21 +73,15 @@
|
|
#define SLOTSTATUS_READY 8
|
|
#define SLOTSTATUS_READY 8
|
|
#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
|
|
#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
|
|
|
|
|
|
-/* Milliseconds during which key presses are regarded as key repeat and during
|
|
|
|
- * which the debounce logic is active
|
|
|
|
|
|
+/*
|
|
|
|
+ * Milliseconds during which a key is regarded as pressed.
|
|
|
|
+ * If an identical command arrives within this time, the timer will start over.
|
|
*/
|
|
*/
|
|
-#define IR_REPEAT_TIMEOUT 350
|
|
|
|
|
|
+#define IR_KEYPRESS_TIMEOUT 250
|
|
|
|
|
|
/* RC5 device wildcard */
|
|
/* RC5 device wildcard */
|
|
#define IR_DEVICE_ANY 255
|
|
#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
|
|
|
|
- */
|
|
|
|
-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;
|
|
static int rc5_device = -1;
|
|
module_param(rc5_device, int, 0644);
|
|
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)");
|
|
MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
|
|
@@ -99,10 +93,14 @@ MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
|
|
struct budget_ci_ir {
|
|
struct budget_ci_ir {
|
|
struct input_dev *dev;
|
|
struct input_dev *dev;
|
|
struct tasklet_struct msp430_irq_tasklet;
|
|
struct tasklet_struct msp430_irq_tasklet;
|
|
|
|
+ struct timer_list timer_keyup;
|
|
char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
|
|
char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
|
|
char phys[32];
|
|
char phys[32];
|
|
struct ir_input_state state;
|
|
struct ir_input_state state;
|
|
int rc5_device;
|
|
int rc5_device;
|
|
|
|
+ u32 last_raw;
|
|
|
|
+ u32 ir_key;
|
|
|
|
+ bool have_command;
|
|
};
|
|
};
|
|
|
|
|
|
struct budget_ci {
|
|
struct budget_ci {
|
|
@@ -125,13 +123,8 @@ static void msp430_ir_interrupt(unsigned long data)
|
|
{
|
|
{
|
|
struct budget_ci *budget_ci = (struct budget_ci *) data;
|
|
struct budget_ci *budget_ci = (struct budget_ci *) data;
|
|
struct input_dev *dev = budget_ci->ir.dev;
|
|
struct input_dev *dev = budget_ci->ir.dev;
|
|
- static int bounces = 0;
|
|
|
|
- int device;
|
|
|
|
- int toggle;
|
|
|
|
- static int prev_toggle = -1;
|
|
|
|
- static u32 ir_key;
|
|
|
|
- static int state = 0;
|
|
|
|
u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
|
|
u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
|
|
|
|
+ u32 raw;
|
|
|
|
|
|
/*
|
|
/*
|
|
* The msp430 chip can generate two different bytes, command and device
|
|
* The msp430 chip can generate two different bytes, command and device
|
|
@@ -143,7 +136,7 @@ static void msp430_ir_interrupt(unsigned long data)
|
|
* bytes and one or more device bytes. For the repeated bytes, the
|
|
* bytes and one or more device bytes. For the repeated bytes, the
|
|
* highest bit (X) is set. The first command byte is always generated
|
|
* highest bit (X) is set. The first command byte is always generated
|
|
* before the first device byte. Other than that, no specific order
|
|
* before the first device byte. Other than that, no specific order
|
|
- * seems to apply.
|
|
|
|
|
|
+ * seems to apply. To make life interesting, bytes can also be lost.
|
|
*
|
|
*
|
|
* Only when we have a command and device byte, a keypress is
|
|
* Only when we have a command and device byte, a keypress is
|
|
* generated.
|
|
* generated.
|
|
@@ -152,53 +145,35 @@ static void msp430_ir_interrupt(unsigned long data)
|
|
if (ir_debug)
|
|
if (ir_debug)
|
|
printk("budget_ci: received byte 0x%02x\n", command);
|
|
printk("budget_ci: received byte 0x%02x\n", command);
|
|
|
|
|
|
- /* Is this a repeated byte? */
|
|
|
|
- if (command & 0x80)
|
|
|
|
- return;
|
|
|
|
|
|
+ /* Remove repeat bit, we use every command */
|
|
|
|
+ command = command & 0x7f;
|
|
|
|
|
|
/* Is this a RC5 command byte? */
|
|
/* Is this a RC5 command byte? */
|
|
if (command & 0x40) {
|
|
if (command & 0x40) {
|
|
- state = 1;
|
|
|
|
- ir_key = command & 0x3f;
|
|
|
|
|
|
+ budget_ci->ir.have_command = true;
|
|
|
|
+ budget_ci->ir.ir_key = command & 0x3f;
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/* It's a RC5 device byte */
|
|
/* It's a RC5 device byte */
|
|
- if (!state)
|
|
|
|
|
|
+ if (!budget_ci->ir.have_command)
|
|
return;
|
|
return;
|
|
- state = 0;
|
|
|
|
- device = command & 0x1f;
|
|
|
|
- toggle = command & 0x20;
|
|
|
|
|
|
+ budget_ci->ir.have_command = false;
|
|
|
|
|
|
- if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device)
|
|
|
|
|
|
+ if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
|
|
|
|
+ budget_ci->ir.rc5_device != (command & 0x1f))
|
|
return;
|
|
return;
|
|
|
|
|
|
- /* Ignore repeated key sequences if requested */
|
|
|
|
- if (toggle == prev_toggle && ir_key == dev->repeat_key &&
|
|
|
|
- bounces > 0 && timer_pending(&dev->timer)) {
|
|
|
|
- if (ir_debug)
|
|
|
|
- printk("budget_ci: debounce logic ignored IR command\n");
|
|
|
|
- bounces--;
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- prev_toggle = toggle;
|
|
|
|
-
|
|
|
|
- /* Are we still waiting for a keyup event? */
|
|
|
|
- if (del_timer(&dev->timer))
|
|
|
|
- ir_input_nokey(dev, &budget_ci->ir.state);
|
|
|
|
-
|
|
|
|
- /* Generate keypress */
|
|
|
|
- if (ir_debug)
|
|
|
|
- printk("budget_ci: generating keypress 0x%02x\n", ir_key);
|
|
|
|
- ir_input_keydown(dev, &budget_ci->ir.state, ir_key, (ir_key & (command << 8)));
|
|
|
|
-
|
|
|
|
- /* Do we want to delay the keyup event? */
|
|
|
|
- if (debounce) {
|
|
|
|
- bounces = debounce;
|
|
|
|
- mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT));
|
|
|
|
- } else {
|
|
|
|
|
|
+ /* Is this a repeated key sequence? (same device, command, toggle) */
|
|
|
|
+ raw = budget_ci->ir.ir_key | (command << 8);
|
|
|
|
+ if (budget_ci->ir.last_raw != raw || !timer_pending(&budget_ci->ir.timer_keyup)) {
|
|
ir_input_nokey(dev, &budget_ci->ir.state);
|
|
ir_input_nokey(dev, &budget_ci->ir.state);
|
|
|
|
+ ir_input_keydown(dev, &budget_ci->ir.state,
|
|
|
|
+ budget_ci->ir.ir_key, raw);
|
|
|
|
+ budget_ci->ir.last_raw = raw;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ mod_timer(&budget_ci->ir.timer_keyup, jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT));
|
|
}
|
|
}
|
|
|
|
|
|
static int msp430_ir_init(struct budget_ci *budget_ci)
|
|
static int msp430_ir_init(struct budget_ci *budget_ci)
|
|
@@ -271,16 +246,21 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
- /* initialise the key-up debounce timeout handler */
|
|
|
|
- input_dev->timer.function = msp430_ir_keyup;
|
|
|
|
- input_dev->timer.data = (unsigned long) &budget_ci->ir;
|
|
|
|
-
|
|
|
|
|
|
+ /* initialise the key-up timeout handler */
|
|
|
|
+ init_timer(&budget_ci->ir.timer_keyup);
|
|
|
|
+ budget_ci->ir.timer_keyup.function = msp430_ir_keyup;
|
|
|
|
+ budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir;
|
|
|
|
+ budget_ci->ir.last_raw = 0xffff; /* An impossible value */
|
|
error = input_register_device(input_dev);
|
|
error = input_register_device(input_dev);
|
|
if (error) {
|
|
if (error) {
|
|
printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
|
|
printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
|
|
goto out2;
|
|
goto out2;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* note: these must be after input_register_device */
|
|
|
|
+ input_dev->rep[REP_DELAY] = 400;
|
|
|
|
+ input_dev->rep[REP_PERIOD] = 250;
|
|
|
|
+
|
|
tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
|
|
tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
|
|
(unsigned long) budget_ci);
|
|
(unsigned long) budget_ci);
|
|
|
|
|
|
@@ -304,10 +284,8 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci)
|
|
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
|
|
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
|
|
tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
|
|
tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
|
|
|
|
|
|
- if (del_timer(&dev->timer)) {
|
|
|
|
- ir_input_nokey(dev, &budget_ci->ir.state);
|
|
|
|
- input_sync(dev);
|
|
|
|
- }
|
|
|
|
|
|
+ del_timer_sync(&dev->timer);
|
|
|
|
+ ir_input_nokey(dev, &budget_ci->ir.state);
|
|
|
|
|
|
input_unregister_device(dev);
|
|
input_unregister_device(dev);
|
|
}
|
|
}
|