diff options
author | David Härdeman <david@hardeman.nu> | 2010-04-02 14:58:29 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-19 11:56:54 -0400 |
commit | a374fef4437abd0a1ee27afe0cca7a55425c1c3c (patch) | |
tree | 652e36573ac29d360d7f59cfb64a160c08390a54 /drivers/media/IR/ir-keytable.c | |
parent | 354389467b6b2a3b36666b6e933d78bbd9e23577 (diff) |
V4L/DVB: ir-core: improve keyup/keydown logic
Rewrites the keyup/keydown logic in drivers/media/IR/ir-keytable.c.
All knowledge of keystates etc is now internal to ir-keytable.c
and not scattered around ir-raw-event.c and ir-nec-decoder.c (where
it doesn't belong).
In addition, I've changed the API slightly so that ir_input_dev is
passed as the first argument rather than input_dev. If we're ever
going to support multiple keytables we need to move towards making
ir_input_dev the main interface from a driver POV and obscure away
the input_dev as an implementational detail in ir-core.
Signed-off-by: David Härdeman <david@hardeman.nu>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/IR/ir-keytable.c')
-rw-r--r-- | drivers/media/IR/ir-keytable.c | 125 |
1 files changed, 101 insertions, 24 deletions
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index a0aa5c1b6b41..a89456932f7c 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c | |||
@@ -21,6 +21,9 @@ | |||
21 | #define IR_TAB_MIN_SIZE 256 | 21 | #define IR_TAB_MIN_SIZE 256 |
22 | #define IR_TAB_MAX_SIZE 8192 | 22 | #define IR_TAB_MAX_SIZE 8192 |
23 | 23 | ||
24 | /* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */ | ||
25 | #define IR_KEYPRESS_TIMEOUT 250 | ||
26 | |||
24 | /** | 27 | /** |
25 | * ir_resize_table() - resizes a scancode table if necessary | 28 | * ir_resize_table() - resizes a scancode table if necessary |
26 | * @rc_tab: the ir_scancode_table to resize | 29 | * @rc_tab: the ir_scancode_table to resize |
@@ -263,56 +266,124 @@ EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); | |||
263 | 266 | ||
264 | /** | 267 | /** |
265 | * ir_keyup() - generates input event to cleanup a key press | 268 | * ir_keyup() - generates input event to cleanup a key press |
266 | * @input_dev: the struct input_dev descriptor of the device | 269 | * @ir: the struct ir_input_dev descriptor of the device |
267 | * | 270 | * |
268 | * This routine is used by the input routines when a key is pressed at the | 271 | * This routine is used to signal that a key has been released on the |
269 | * IR. It reports a keyup input event via input_report_key(). | 272 | * remote control. It reports a keyup input event via input_report_key(). |
273 | */ | ||
274 | static void ir_keyup(struct ir_input_dev *ir) | ||
275 | { | ||
276 | if (!ir->keypressed) | ||
277 | return; | ||
278 | |||
279 | IR_dprintk(1, "keyup key 0x%04x\n", ir->last_keycode); | ||
280 | input_report_key(ir->input_dev, ir->last_keycode, 0); | ||
281 | input_sync(ir->input_dev); | ||
282 | ir->keypressed = false; | ||
283 | } | ||
284 | |||
285 | /** | ||
286 | * ir_timer_keyup() - generates a keyup event after a timeout | ||
287 | * @cookie: a pointer to struct ir_input_dev passed to setup_timer() | ||
288 | * | ||
289 | * This routine will generate a keyup event some time after a keydown event | ||
290 | * is generated when no further activity has been detected. | ||
270 | */ | 291 | */ |
271 | void ir_keyup(struct input_dev *dev) | 292 | static void ir_timer_keyup(unsigned long cookie) |
272 | { | 293 | { |
294 | struct ir_input_dev *ir = (struct ir_input_dev *)cookie; | ||
295 | unsigned long flags; | ||
296 | |||
297 | /* | ||
298 | * ir->keyup_jiffies is used to prevent a race condition if a | ||
299 | * hardware interrupt occurs at this point and the keyup timer | ||
300 | * event is moved further into the future as a result. | ||
301 | * | ||
302 | * The timer will then be reactivated and this function called | ||
303 | * again in the future. We need to exit gracefully in that case | ||
304 | * to allow the input subsystem to do its auto-repeat magic or | ||
305 | * a keyup event might follow immediately after the keydown. | ||
306 | */ | ||
307 | spin_lock_irqsave(&ir->keylock, flags); | ||
308 | if (time_is_after_eq_jiffies(ir->keyup_jiffies)) | ||
309 | ir_keyup(ir); | ||
310 | spin_unlock_irqrestore(&ir->keylock, flags); | ||
311 | } | ||
312 | |||
313 | /** | ||
314 | * ir_repeat() - notifies the IR core that a key is still pressed | ||
315 | * @dev: the struct input_dev descriptor of the device | ||
316 | * | ||
317 | * This routine is used by IR decoders when a repeat message which does | ||
318 | * not include the necessary bits to reproduce the scancode has been | ||
319 | * received. | ||
320 | */ | ||
321 | void ir_repeat(struct input_dev *dev) | ||
322 | { | ||
323 | unsigned long flags; | ||
273 | struct ir_input_dev *ir = input_get_drvdata(dev); | 324 | struct ir_input_dev *ir = input_get_drvdata(dev); |
274 | 325 | ||
326 | spin_lock_irqsave(&ir->keylock, flags); | ||
327 | |||
275 | if (!ir->keypressed) | 328 | if (!ir->keypressed) |
276 | return; | 329 | goto out; |
277 | 330 | ||
278 | IR_dprintk(1, "keyup key 0x%04x\n", ir->keycode); | 331 | ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); |
279 | input_report_key(dev, ir->keycode, 0); | 332 | mod_timer(&ir->timer_keyup, ir->keyup_jiffies); |
280 | input_sync(dev); | 333 | |
281 | ir->keypressed = 0; | 334 | out: |
335 | spin_unlock_irqrestore(&ir->keylock, flags); | ||
282 | } | 336 | } |
283 | EXPORT_SYMBOL_GPL(ir_keyup); | 337 | EXPORT_SYMBOL_GPL(ir_repeat); |
284 | 338 | ||
285 | /** | 339 | /** |
286 | * ir_keydown() - generates input event for a key press | 340 | * ir_keydown() - generates input event for a key press |
287 | * @input_dev: the struct input_dev descriptor of the device | 341 | * @dev: the struct input_dev descriptor of the device |
288 | * @scancode: the scancode that we're seeking | 342 | * @scancode: the scancode that we're seeking |
343 | * @toggle: the toggle value (protocol dependent, if the protocol doesn't | ||
344 | * support toggle values, this should be set to zero) | ||
289 | * | 345 | * |
290 | * This routine is used by the input routines when a key is pressed at the | 346 | * This routine is used by the input routines when a key is pressed at the |
291 | * IR. It gets the keycode for a scancode and reports an input event via | 347 | * IR. It gets the keycode for a scancode and reports an input event via |
292 | * input_report_key(). | 348 | * input_report_key(). |
293 | */ | 349 | */ |
294 | void ir_keydown(struct input_dev *dev, int scancode) | 350 | void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) |
295 | { | 351 | { |
352 | unsigned long flags; | ||
296 | struct ir_input_dev *ir = input_get_drvdata(dev); | 353 | struct ir_input_dev *ir = input_get_drvdata(dev); |
297 | 354 | ||
298 | u32 keycode = ir_g_keycode_from_table(dev, scancode); | 355 | u32 keycode = ir_g_keycode_from_table(dev, scancode); |
299 | 356 | ||
300 | /* If already sent a keydown, do a keyup */ | 357 | spin_lock_irqsave(&ir->keylock, flags); |
301 | if (ir->keypressed) | ||
302 | ir_keyup(dev); | ||
303 | 358 | ||
304 | if (KEY_RESERVED == keycode) | 359 | /* Repeat event? */ |
305 | return; | 360 | if (ir->keypressed && |
361 | ir->last_scancode == scancode && | ||
362 | ir->last_toggle == toggle) | ||
363 | goto set_timer; | ||
306 | 364 | ||
307 | ir->keycode = keycode; | 365 | /* Release old keypress */ |
308 | ir->keypressed = 1; | 366 | ir_keyup(ir); |
309 | 367 | ||
310 | IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", | 368 | ir->last_scancode = scancode; |
311 | dev->name, keycode, scancode); | 369 | ir->last_toggle = toggle; |
370 | ir->last_keycode = keycode; | ||
371 | |||
372 | if (keycode == KEY_RESERVED) | ||
373 | goto out; | ||
312 | 374 | ||
313 | input_report_key(dev, ir->keycode, 1); | 375 | /* Register a keypress */ |
376 | ir->keypressed = true; | ||
377 | IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", | ||
378 | dev->name, keycode, scancode); | ||
379 | input_report_key(dev, ir->last_keycode, 1); | ||
314 | input_sync(dev); | 380 | input_sync(dev); |
315 | 381 | ||
382 | set_timer: | ||
383 | ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); | ||
384 | mod_timer(&ir->timer_keyup, ir->keyup_jiffies); | ||
385 | out: | ||
386 | spin_unlock_irqrestore(&ir->keylock, flags); | ||
316 | } | 387 | } |
317 | EXPORT_SYMBOL_GPL(ir_keydown); | 388 | EXPORT_SYMBOL_GPL(ir_keydown); |
318 | 389 | ||
@@ -365,8 +436,12 @@ int __ir_input_register(struct input_dev *input_dev, | |||
365 | input_dev->getkeycode = ir_getkeycode; | 436 | input_dev->getkeycode = ir_getkeycode; |
366 | input_dev->setkeycode = ir_setkeycode; | 437 | input_dev->setkeycode = ir_setkeycode; |
367 | input_set_drvdata(input_dev, ir_dev); | 438 | input_set_drvdata(input_dev, ir_dev); |
439 | ir_dev->input_dev = input_dev; | ||
368 | 440 | ||
369 | spin_lock_init(&ir_dev->rc_tab.lock); | 441 | spin_lock_init(&ir_dev->rc_tab.lock); |
442 | spin_lock_init(&ir_dev->keylock); | ||
443 | setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev); | ||
444 | |||
370 | ir_dev->rc_tab.name = rc_tab->name; | 445 | ir_dev->rc_tab.name = rc_tab->name; |
371 | ir_dev->rc_tab.ir_type = rc_tab->ir_type; | 446 | ir_dev->rc_tab.ir_type = rc_tab->ir_type; |
372 | ir_dev->rc_tab.alloc = roundup_pow_of_two(rc_tab->size * | 447 | ir_dev->rc_tab.alloc = roundup_pow_of_two(rc_tab->size * |
@@ -383,6 +458,8 @@ int __ir_input_register(struct input_dev *input_dev, | |||
383 | ir_dev->rc_tab.size, ir_dev->rc_tab.alloc); | 458 | ir_dev->rc_tab.size, ir_dev->rc_tab.alloc); |
384 | 459 | ||
385 | set_bit(EV_KEY, input_dev->evbit); | 460 | set_bit(EV_KEY, input_dev->evbit); |
461 | set_bit(EV_REP, input_dev->evbit); | ||
462 | |||
386 | if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) { | 463 | if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) { |
387 | rc = -ENOMEM; | 464 | rc = -ENOMEM; |
388 | goto out_table; | 465 | goto out_table; |
@@ -428,7 +505,7 @@ void ir_input_unregister(struct input_dev *dev) | |||
428 | return; | 505 | return; |
429 | 506 | ||
430 | IR_dprintk(1, "Freed keycode table\n"); | 507 | IR_dprintk(1, "Freed keycode table\n"); |
431 | 508 | del_timer_sync(&ir_dev->timer_keyup); | |
432 | rc_tab = &ir_dev->rc_tab; | 509 | rc_tab = &ir_dev->rc_tab; |
433 | rc_tab->size = 0; | 510 | rc_tab->size = 0; |
434 | kfree(rc_tab->scan); | 511 | kfree(rc_tab->scan); |