diff options
Diffstat (limited to 'drivers/media/IR/ir-keytable.c')
-rw-r--r-- | drivers/media/IR/ir-keytable.c | 110 |
1 files changed, 83 insertions, 27 deletions
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index f60107c3b091..8039110350d3 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -431,13 +431,13 @@ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); /** - * ir_keyup() - generates input event to cleanup a key press + * ir_do_keyup() - internal function to signal the release of a keypress * @ir: the struct ir_input_dev descriptor of the device * - * This routine is used to signal that a key has been released on the - * remote control. It reports a keyup input event via input_report_key(). + * This function is used internally to release a keypress, it must be + * called with keylock held. */ -void ir_keyup(struct ir_input_dev *ir) +static void ir_do_keyup(struct ir_input_dev *ir) { if (!ir->keypressed) return; @@ -447,6 +447,23 @@ void ir_keyup(struct ir_input_dev *ir) input_sync(ir->input_dev); ir->keypressed = false; } + +/** + * ir_keyup() - generates input event to signal the release of a keypress + * @dev: the struct input_dev descriptor of the device + * + * This routine is used to signal that a key has been released on the + * remote control. + */ +void ir_keyup(struct input_dev *dev) +{ + unsigned long flags; + struct ir_input_dev *ir = input_get_drvdata(dev); + + spin_lock_irqsave(&ir->keylock, flags); + ir_do_keyup(ir); + spin_unlock_irqrestore(&ir->keylock, flags); +} EXPORT_SYMBOL_GPL(ir_keyup); /** @@ -473,7 +490,7 @@ static void ir_timer_keyup(unsigned long cookie) */ spin_lock_irqsave(&ir->keylock, flags); if (time_is_before_eq_jiffies(ir->keyup_jiffies)) - ir_keyup(ir); + ir_do_keyup(ir); spin_unlock_irqrestore(&ir->keylock, flags); } @@ -506,44 +523,37 @@ out: EXPORT_SYMBOL_GPL(ir_repeat); /** - * ir_keydown() - generates input event for a key press + * ir_do_keydown() - internal function to process a keypress * @dev: the struct input_dev descriptor of the device - * @scancode: the scancode that we're seeking - * @toggle: the toggle value (protocol dependent, if the protocol doesn't - * support toggle values, this should be set to zero) + * @scancode: the scancode of the keypress + * @keycode: the keycode of the keypress + * @toggle: the toggle value of the keypress * - * This routine is used by the input routines when a key is pressed at the - * IR. It gets the keycode for a scancode and reports an input event via - * input_report_key(). + * This function is used internally to register a keypress, it must be + * called with keylock held. */ -void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) +static void ir_do_keydown(struct input_dev *dev, int scancode, + u32 keycode, u8 toggle) { - unsigned long flags; struct ir_input_dev *ir = input_get_drvdata(dev); - u32 keycode = ir_g_keycode_from_table(dev, scancode); - - spin_lock_irqsave(&ir->keylock, flags); - input_event(dev, EV_MSC, MSC_SCAN, scancode); /* Repeat event? */ if (ir->keypressed && ir->last_scancode == scancode && ir->last_toggle == toggle) - goto set_timer; + return; /* Release old keypress */ - ir_keyup(ir); + ir_do_keyup(ir); ir->last_scancode = scancode; ir->last_toggle = toggle; ir->last_keycode = keycode; - if (keycode == KEY_RESERVED) - goto out; - + return; /* Register a keypress */ ir->keypressed = true; @@ -551,15 +561,61 @@ void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) dev->name, keycode, scancode); input_report_key(dev, ir->last_keycode, 1); input_sync(dev); +} -set_timer: - ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); - mod_timer(&ir->timer_keyup, ir->keyup_jiffies); -out: +/** + * ir_keydown() - generates input event for a key press + * @dev: the struct input_dev descriptor of the device + * @scancode: the scancode that we're seeking + * @toggle: the toggle value (protocol dependent, if the protocol doesn't + * support toggle values, this should be set to zero) + * + * This routine is used by the input routines when a key is pressed at the + * IR. It gets the keycode for a scancode and reports an input event via + * input_report_key(). + */ +void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) +{ + unsigned long flags; + struct ir_input_dev *ir = input_get_drvdata(dev); + u32 keycode = ir_g_keycode_from_table(dev, scancode); + + spin_lock_irqsave(&ir->keylock, flags); + ir_do_keydown(dev, scancode, keycode, toggle); + + if (ir->keypressed) { + ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); + mod_timer(&ir->timer_keyup, ir->keyup_jiffies); + } spin_unlock_irqrestore(&ir->keylock, flags); } EXPORT_SYMBOL_GPL(ir_keydown); +/** + * ir_keydown_notimeout() - generates input event for a key press without + * an automatic keyup event at a later time + * @dev: the struct input_dev descriptor of the device + * @scancode: the scancode that we're seeking + * @toggle: the toggle value (protocol dependent, if the protocol doesn't + * support toggle values, this should be set to zero) + * + * This routine is used by the input routines when a key is pressed at the + * IR. It gets the keycode for a scancode and reports an input event via + * input_report_key(). The driver must manually call ir_keyup() at a later + * stage. + */ +void ir_keydown_notimeout(struct input_dev *dev, int scancode, u8 toggle) +{ + unsigned long flags; + struct ir_input_dev *ir = input_get_drvdata(dev); + u32 keycode = ir_g_keycode_from_table(dev, scancode); + + spin_lock_irqsave(&ir->keylock, flags); + ir_do_keydown(dev, scancode, keycode, toggle); + spin_unlock_irqrestore(&ir->keylock, flags); +} +EXPORT_SYMBOL_GPL(ir_keydown_notimeout); + static int ir_open(struct input_dev *input_dev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); |