diff options
Diffstat (limited to 'drivers/media/IR/ir-keytable.c')
-rw-r--r-- | drivers/media/IR/ir-keytable.c | 61 |
1 files changed, 40 insertions, 21 deletions
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index b521ed9d6e2e..0903f539bf68 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c | |||
@@ -65,7 +65,7 @@ exit: | |||
65 | * In order to reduce the quantity of table resizes, it has a minimum | 65 | * In order to reduce the quantity of table resizes, it has a minimum |
66 | * table size of IR_TAB_MIN_SIZE. | 66 | * table size of IR_TAB_MIN_SIZE. |
67 | */ | 67 | */ |
68 | int ir_roundup_tablesize(int n_elems) | 68 | static int ir_roundup_tablesize(int n_elems) |
69 | { | 69 | { |
70 | size_t size; | 70 | size_t size; |
71 | 71 | ||
@@ -81,7 +81,6 @@ int ir_roundup_tablesize(int n_elems) | |||
81 | 81 | ||
82 | return n_elems; | 82 | return n_elems; |
83 | } | 83 | } |
84 | EXPORT_SYMBOL_GPL(ir_roundup_tablesize); | ||
85 | 84 | ||
86 | /** | 85 | /** |
87 | * ir_copy_table() - copies a keytable, discarding the unused entries | 86 | * ir_copy_table() - copies a keytable, discarding the unused entries |
@@ -89,9 +88,11 @@ EXPORT_SYMBOL_GPL(ir_roundup_tablesize); | |||
89 | * @origin: origin table | 88 | * @origin: origin table |
90 | * | 89 | * |
91 | * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED | 90 | * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED |
91 | * Also copies table size and table protocol. | ||
92 | * NOTE: It shouldn't copy the lock field | ||
92 | */ | 93 | */ |
93 | 94 | ||
94 | int ir_copy_table(struct ir_scancode_table *destin, | 95 | static int ir_copy_table(struct ir_scancode_table *destin, |
95 | const struct ir_scancode_table *origin) | 96 | const struct ir_scancode_table *origin) |
96 | { | 97 | { |
97 | int i, j = 0; | 98 | int i, j = 0; |
@@ -105,12 +106,12 @@ int ir_copy_table(struct ir_scancode_table *destin, | |||
105 | j++; | 106 | j++; |
106 | } | 107 | } |
107 | destin->size = j; | 108 | destin->size = j; |
109 | destin->ir_type = origin->ir_type; | ||
108 | 110 | ||
109 | IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size); | 111 | IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size); |
110 | 112 | ||
111 | return 0; | 113 | return 0; |
112 | } | 114 | } |
113 | EXPORT_SYMBOL_GPL(ir_copy_table); | ||
114 | 115 | ||
115 | /** | 116 | /** |
116 | * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table | 117 | * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table |
@@ -184,18 +185,14 @@ static void ir_delete_key(struct ir_scancode_table *rc_tab, int elem) | |||
184 | int newsize = rc_tab->size - 1; | 185 | int newsize = rc_tab->size - 1; |
185 | int resize = ir_is_resize_needed(rc_tab, newsize); | 186 | int resize = ir_is_resize_needed(rc_tab, newsize); |
186 | struct ir_scancode *oldkeymap = rc_tab->scan; | 187 | struct ir_scancode *oldkeymap = rc_tab->scan; |
187 | struct ir_scancode *newkeymap; | 188 | struct ir_scancode *newkeymap = NULL; |
188 | 189 | ||
189 | if (resize) { | 190 | if (resize) |
190 | newkeymap = kzalloc(ir_roundup_tablesize(newsize) * | 191 | newkeymap = kzalloc(ir_roundup_tablesize(newsize) * |
191 | sizeof(*newkeymap), GFP_ATOMIC); | 192 | sizeof(*newkeymap), GFP_ATOMIC); |
192 | 193 | ||
193 | /* There's no memory for resize. Keep the old table */ | 194 | /* There's no memory for resize. Keep the old table */ |
194 | if (!newkeymap) | 195 | if (!resize || !newkeymap) { |
195 | resize = 0; | ||
196 | } | ||
197 | |||
198 | if (!resize) { | ||
199 | newkeymap = oldkeymap; | 196 | newkeymap = oldkeymap; |
200 | 197 | ||
201 | /* We'll modify the live table. Lock it */ | 198 | /* We'll modify the live table. Lock it */ |
@@ -399,12 +396,14 @@ EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); | |||
399 | * @input_dev: the struct input_dev descriptor of the device | 396 | * @input_dev: the struct input_dev descriptor of the device |
400 | * @rc_tab: the struct ir_scancode_table table of scancode/keymap | 397 | * @rc_tab: the struct ir_scancode_table table of scancode/keymap |
401 | * | 398 | * |
402 | * This routine is used to initialize the input infrastructure to work with | 399 | * This routine is used to initialize the input infrastructure |
403 | * an IR. | 400 | * to work with an IR. |
404 | * It should be called before registering the IR device. | 401 | * It will register the input/evdev interface for the device and |
402 | * register the syfs code for IR class | ||
405 | */ | 403 | */ |
406 | int ir_input_register(struct input_dev *input_dev, | 404 | int ir_input_register(struct input_dev *input_dev, |
407 | struct ir_scancode_table *rc_tab) | 405 | const struct ir_scancode_table *rc_tab, |
406 | const struct ir_dev_props *props) | ||
408 | { | 407 | { |
409 | struct ir_input_dev *ir_dev; | 408 | struct ir_input_dev *ir_dev; |
410 | struct ir_scancode *keymap = rc_tab->scan; | 409 | struct ir_scancode *keymap = rc_tab->scan; |
@@ -417,19 +416,22 @@ int ir_input_register(struct input_dev *input_dev, | |||
417 | if (!ir_dev) | 416 | if (!ir_dev) |
418 | return -ENOMEM; | 417 | return -ENOMEM; |
419 | 418 | ||
420 | spin_lock_init(&rc_tab->lock); | 419 | spin_lock_init(&ir_dev->rc_tab.lock); |
421 | 420 | ||
422 | ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size); | 421 | ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size); |
423 | ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size * | 422 | ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size * |
424 | sizeof(struct ir_scancode), GFP_KERNEL); | 423 | sizeof(struct ir_scancode), GFP_KERNEL); |
425 | if (!ir_dev->rc_tab.scan) | 424 | if (!ir_dev->rc_tab.scan) { |
425 | kfree(ir_dev); | ||
426 | return -ENOMEM; | 426 | return -ENOMEM; |
427 | } | ||
427 | 428 | ||
428 | IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", | 429 | IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", |
429 | ir_dev->rc_tab.size, | 430 | ir_dev->rc_tab.size, |
430 | ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan)); | 431 | ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan)); |
431 | 432 | ||
432 | ir_copy_table(&ir_dev->rc_tab, rc_tab); | 433 | ir_copy_table(&ir_dev->rc_tab, rc_tab); |
434 | ir_dev->props = props; | ||
433 | 435 | ||
434 | /* set the bits for the keys */ | 436 | /* set the bits for the keys */ |
435 | IR_dprintk(1, "key map size: %d\n", rc_tab->size); | 437 | IR_dprintk(1, "key map size: %d\n", rc_tab->size); |
@@ -447,16 +449,31 @@ int ir_input_register(struct input_dev *input_dev, | |||
447 | input_set_drvdata(input_dev, ir_dev); | 449 | input_set_drvdata(input_dev, ir_dev); |
448 | 450 | ||
449 | rc = input_register_device(input_dev); | 451 | rc = input_register_device(input_dev); |
452 | if (rc < 0) | ||
453 | goto err; | ||
454 | |||
455 | rc = ir_register_class(input_dev); | ||
450 | if (rc < 0) { | 456 | if (rc < 0) { |
451 | kfree(rc_tab->scan); | 457 | input_unregister_device(input_dev); |
452 | kfree(ir_dev); | 458 | goto err; |
453 | input_set_drvdata(input_dev, NULL); | ||
454 | } | 459 | } |
455 | 460 | ||
461 | return 0; | ||
462 | |||
463 | err: | ||
464 | kfree(rc_tab->scan); | ||
465 | kfree(ir_dev); | ||
466 | input_set_drvdata(input_dev, NULL); | ||
456 | return rc; | 467 | return rc; |
457 | } | 468 | } |
458 | EXPORT_SYMBOL_GPL(ir_input_register); | 469 | EXPORT_SYMBOL_GPL(ir_input_register); |
459 | 470 | ||
471 | /** | ||
472 | * ir_input_unregister() - unregisters IR and frees resources | ||
473 | * @input_dev: the struct input_dev descriptor of the device | ||
474 | |||
475 | * This routine is used to free memory and de-register interfaces. | ||
476 | */ | ||
460 | void ir_input_unregister(struct input_dev *dev) | 477 | void ir_input_unregister(struct input_dev *dev) |
461 | { | 478 | { |
462 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); | 479 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); |
@@ -472,6 +489,8 @@ void ir_input_unregister(struct input_dev *dev) | |||
472 | kfree(rc_tab->scan); | 489 | kfree(rc_tab->scan); |
473 | rc_tab->scan = NULL; | 490 | rc_tab->scan = NULL; |
474 | 491 | ||
492 | ir_unregister_class(dev); | ||
493 | |||
475 | kfree(ir_dev); | 494 | kfree(ir_dev); |
476 | input_unregister_device(dev); | 495 | input_unregister_device(dev); |
477 | } | 496 | } |