aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/IR/ir-keytable.c
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2010-04-02 14:58:29 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-19 11:56:54 -0400
commita374fef4437abd0a1ee27afe0cca7a55425c1c3c (patch)
tree652e36573ac29d360d7f59cfb64a160c08390a54 /drivers/media/IR/ir-keytable.c
parent354389467b6b2a3b36666b6e933d78bbd9e23577 (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.c125
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 */
274static 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 */
271void ir_keyup(struct input_dev *dev) 292static 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 */
321void 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; 334out:
335 spin_unlock_irqrestore(&ir->keylock, flags);
282} 336}
283EXPORT_SYMBOL_GPL(ir_keyup); 337EXPORT_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 */
294void ir_keydown(struct input_dev *dev, int scancode) 350void 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
382set_timer:
383 ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT);
384 mod_timer(&ir->timer_keyup, ir->keyup_jiffies);
385out:
386 spin_unlock_irqrestore(&ir->keylock, flags);
316} 387}
317EXPORT_SYMBOL_GPL(ir_keydown); 388EXPORT_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);