aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/media/IR/ir-keytable.c125
-rw-r--r--drivers/media/IR/ir-nec-decoder.c7
-rw-r--r--drivers/media/IR/ir-raw-event.c14
-rw-r--r--include/media/ir-core.h15
4 files changed, 113 insertions, 48 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);
diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c
index 83a9912722f4..0b50060ffbaf 100644
--- a/drivers/media/IR/ir-nec-decoder.c
+++ b/drivers/media/IR/ir-nec-decoder.c
@@ -180,8 +180,7 @@ static int __ir_nec_decode(struct input_dev *input_dev,
180 if (is_repeat(evs, len, *pos)) { 180 if (is_repeat(evs, len, *pos)) {
181 *pos += 2; 181 *pos += 2;
182 if (ir->keypressed) { 182 if (ir->keypressed) {
183 mod_timer(&ir->raw->timer_keyup, 183 ir_repeat(input_dev);
184 jiffies + msecs_to_jiffies(REPEAT_TIME));
185 IR_dprintk(1, "NEC repeat event\n"); 184 IR_dprintk(1, "NEC repeat event\n");
186 return 1; 185 return 1;
187 } else { 186 } else {
@@ -238,9 +237,7 @@ static int __ir_nec_decode(struct input_dev *input_dev,
238 } 237 }
239 238
240 IR_dprintk(1, "NEC scancode 0x%04x\n", ircode); 239 IR_dprintk(1, "NEC scancode 0x%04x\n", ircode);
241 ir_keydown(input_dev, ircode); 240 ir_keydown(input_dev, ircode, 0);
242 mod_timer(&ir->raw->timer_keyup,
243 jiffies + msecs_to_jiffies(REPEAT_TIME));
244 241
245 return 1; 242 return 1;
246err: 243err:
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
index 371d88e5a586..59f20541b03e 100644
--- a/drivers/media/IR/ir-raw-event.c
+++ b/drivers/media/IR/ir-raw-event.c
@@ -53,13 +53,6 @@ static spinlock_t ir_raw_handler_lock;
53/* Used to load the decoders */ 53/* Used to load the decoders */
54static struct work_struct wq_load; 54static struct work_struct wq_load;
55 55
56static void ir_keyup_timer(unsigned long data)
57{
58 struct input_dev *input_dev = (struct input_dev *)data;
59
60 ir_keyup(input_dev);
61}
62
63int ir_raw_event_register(struct input_dev *input_dev) 56int ir_raw_event_register(struct input_dev *input_dev)
64{ 57{
65 struct ir_input_dev *ir = input_get_drvdata(input_dev); 58 struct ir_input_dev *ir = input_get_drvdata(input_dev);
@@ -72,11 +65,6 @@ int ir_raw_event_register(struct input_dev *input_dev)
72 size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2; 65 size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2;
73 size = roundup_pow_of_two(size); 66 size = roundup_pow_of_two(size);
74 67
75 init_timer(&ir->raw->timer_keyup);
76 ir->raw->timer_keyup.function = ir_keyup_timer;
77 ir->raw->timer_keyup.data = (unsigned long)input_dev;
78 set_bit(EV_REP, input_dev->evbit);
79
80 rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL); 68 rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL);
81 if (rc < 0) { 69 if (rc < 0) {
82 kfree(ir->raw); 70 kfree(ir->raw);
@@ -103,8 +91,6 @@ void ir_raw_event_unregister(struct input_dev *input_dev)
103 if (!ir->raw) 91 if (!ir->raw)
104 return; 92 return;
105 93
106 del_timer_sync(&ir->raw->timer_keyup);
107
108 RUN_DECODER(raw_unregister, input_dev); 94 RUN_DECODER(raw_unregister, input_dev);
109 95
110 kfifo_free(&ir->raw->kfifo); 96 kfifo_free(&ir->raw->kfifo);
diff --git a/include/media/ir-core.h b/include/media/ir-core.h
index 7a0be8d4999d..b452a478c12c 100644
--- a/include/media/ir-core.h
+++ b/include/media/ir-core.h
@@ -76,7 +76,6 @@ struct ir_raw_event {
76struct ir_raw_event_ctrl { 76struct ir_raw_event_ctrl {
77 struct kfifo kfifo; /* fifo for the pulse/space events */ 77 struct kfifo kfifo; /* fifo for the pulse/space events */
78 struct timespec last_event; /* when last event occurred */ 78 struct timespec last_event; /* when last event occurred */
79 struct timer_list timer_keyup; /* timer for key release */
80}; 79};
81 80
82struct ir_input_dev { 81struct ir_input_dev {
@@ -86,10 +85,16 @@ struct ir_input_dev {
86 unsigned long devno; /* device number */ 85 unsigned long devno; /* device number */
87 const struct ir_dev_props *props; /* Device properties */ 86 const struct ir_dev_props *props; /* Device properties */
88 struct ir_raw_event_ctrl *raw; /* for raw pulse/space events */ 87 struct ir_raw_event_ctrl *raw; /* for raw pulse/space events */
88 struct input_dev *input_dev; /* the input device associated with this device */
89 89
90 /* key info - needed by IR keycode handlers */ 90 /* key info - needed by IR keycode handlers */
91 u32 keycode; /* linux key code */ 91 spinlock_t keylock; /* protects the below members */
92 int keypressed; /* current state */ 92 bool keypressed; /* current state */
93 unsigned long keyup_jiffies; /* when should the current keypress be released? */
94 struct timer_list timer_keyup; /* timer for releasing a keypress */
95 u32 last_keycode; /* keycode of last command */
96 u32 last_scancode; /* scancode of last command */
97 u8 last_toggle; /* toggle of last command */
93}; 98};
94 99
95struct ir_raw_handler { 100struct ir_raw_handler {
@@ -115,8 +120,8 @@ void rc_map_init(void);
115 120
116u32 ir_g_keycode_from_table(struct input_dev *input_dev, 121u32 ir_g_keycode_from_table(struct input_dev *input_dev,
117 u32 scancode); 122 u32 scancode);
118void ir_keyup(struct input_dev *dev); 123void ir_repeat(struct input_dev *dev);
119void ir_keydown(struct input_dev *dev, int scancode); 124void ir_keydown(struct input_dev *dev, int scancode, u8 toggle);
120int __ir_input_register(struct input_dev *dev, 125int __ir_input_register(struct input_dev *dev,
121 const struct ir_scancode_table *ir_codes, 126 const struct ir_scancode_table *ir_codes,
122 const struct ir_dev_props *props, 127 const struct ir_dev_props *props,