blob: bfca26d51827823fdb42c15778843bb2f5889c51 [file] [log] [blame]
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -03001/* ir-register.c - handle IR scancode->keycode tables
2 *
3 * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com>
Mauro Carvalho Chehab446e4a62009-12-11 08:34:07 -03004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -030013 */
14
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -030015
Mauro Carvalho Chehab882ead32009-12-29 10:37:38 -030016#include <linux/input.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090017#include <linux/slab.h>
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -030018#include <media/ir-common.h>
19
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -030020#define IR_TAB_MIN_SIZE 32
Mauro Carvalho Chehabe97f4672009-12-04 17:17:47 -030021#define IR_TAB_MAX_SIZE 1024
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -030022
23/**
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -030024 * ir_seek_table() - returns the element order on the table
25 * @rc_tab: the ir_scancode_table with the keymap to be used
26 * @scancode: the scancode that we're seeking
27 *
28 * This routine is used by the input routines when a key is pressed at the
29 * IR. The scancode is received and needs to be converted into a keycode.
30 * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the
31 * corresponding keycode from the table.
32 */
33static int ir_seek_table(struct ir_scancode_table *rc_tab, u32 scancode)
34{
35 int rc;
36 unsigned long flags;
37 struct ir_scancode *keymap = rc_tab->scan;
38
39 spin_lock_irqsave(&rc_tab->lock, flags);
40
41 /* FIXME: replace it by a binary search */
42
43 for (rc = 0; rc < rc_tab->size; rc++)
44 if (keymap[rc].scancode == scancode)
45 goto exit;
46
47 /* Not found */
48 rc = -EINVAL;
49
50exit:
51 spin_unlock_irqrestore(&rc_tab->lock, flags);
52 return rc;
53}
54
55/**
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -030056 * ir_roundup_tablesize() - gets an optimum value for the table size
57 * @n_elems: minimum number of entries to store keycodes
58 *
59 * This routine is used to choose the keycode table size.
60 *
61 * In order to have some empty space for new keycodes,
62 * and knowing in advance that kmalloc allocates only power of two
63 * segments, it optimizes the allocated space to have some spare space
64 * for those new keycodes by using the maximum number of entries that
65 * will be effectively be allocated by kmalloc.
66 * In order to reduce the quantity of table resizes, it has a minimum
67 * table size of IR_TAB_MIN_SIZE.
68 */
Mauro Carvalho Chehab8719cfd2009-12-17 09:24:37 -030069static int ir_roundup_tablesize(int n_elems)
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -030070{
71 size_t size;
72
73 if (n_elems < IR_TAB_MIN_SIZE)
74 n_elems = IR_TAB_MIN_SIZE;
75
76 /*
77 * As kmalloc only allocates sizes of power of two, get as
78 * much entries as possible for the allocated memory segment
79 */
80 size = roundup_pow_of_two(n_elems * sizeof(struct ir_scancode));
81 n_elems = size / sizeof(struct ir_scancode);
82
83 return n_elems;
84}
85
86/**
87 * ir_copy_table() - copies a keytable, discarding the unused entries
88 * @destin: destin table
89 * @origin: origin table
90 *
91 * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED
Mauro Carvalho Chehabe93854d2009-12-14 00:16:55 -030092 * Also copies table size and table protocol.
93 * NOTE: It shouldn't copy the lock field
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -030094 */
95
Mauro Carvalho Chehab8719cfd2009-12-17 09:24:37 -030096static int ir_copy_table(struct ir_scancode_table *destin,
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -030097 const struct ir_scancode_table *origin)
98{
99 int i, j = 0;
100
101 for (i = 0; i < origin->size; i++) {
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300102 if (origin->scan[i].keycode == KEY_UNKNOWN ||
103 origin->scan[i].keycode == KEY_RESERVED)
104 continue;
105
106 memcpy(&destin->scan[j], &origin->scan[i], sizeof(struct ir_scancode));
107 j++;
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -0300108 }
109 destin->size = j;
Mauro Carvalho Chehabe93854d2009-12-14 00:16:55 -0300110 destin->ir_type = origin->ir_type;
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -0300111
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300112 IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size);
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -0300113
114 return 0;
115}
116
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300117/**
118 * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table
119 * @dev: the struct input_dev device descriptor
120 * @scancode: the desired scancode
121 * @keycode: the keycode to be retorned.
122 *
123 * This routine is used to handle evdev EVIOCGKEY ioctl.
124 * If the key is not found, returns -EINVAL, otherwise, returns 0.
125 */
126static int ir_getkeycode(struct input_dev *dev,
Dmitry Torokhov58b93992010-03-08 22:37:10 -0800127 unsigned int scancode, unsigned int *keycode)
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300128{
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300129 int elem;
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300130 struct ir_input_dev *ir_dev = input_get_drvdata(dev);
131 struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300132
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300133 elem = ir_seek_table(rc_tab, scancode);
134 if (elem >= 0) {
135 *keycode = rc_tab->scan[elem].keycode;
136 return 0;
137 }
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300138
Mauro Carvalho Chehabe97f4672009-12-04 17:17:47 -0300139 /*
140 * Scancode not found and table can't be expanded
141 */
142 if (elem < 0 && rc_tab->size == IR_TAB_MAX_SIZE)
143 return -EINVAL;
144
145 /*
146 * If is there extra space, returns KEY_RESERVED,
147 * otherwise, input core won't let ir_setkeycode to work
148 */
149 *keycode = KEY_RESERVED;
150 return 0;
151}
152
Mauro Carvalho Chehabe97f4672009-12-04 17:17:47 -0300153/**
154 * ir_is_resize_needed() - Check if the table needs rezise
155 * @table: keycode table that may need to resize
156 * @n_elems: minimum number of entries to store keycodes
157 *
158 * Considering that kmalloc uses power of two storage areas, this
159 * routine detects if the real alloced size will change. If not, it
160 * just returns without doing nothing. Otherwise, it will extend or
161 * reduce the table size to meet the new needs.
162 *
163 * It returns 0 if no resize is needed, 1 otherwise.
164 */
165static int ir_is_resize_needed(struct ir_scancode_table *table, int n_elems)
166{
167 int cur_size = ir_roundup_tablesize(table->size);
168 int new_size = ir_roundup_tablesize(n_elems);
169
170 if (cur_size == new_size)
171 return 0;
172
173 /* Resize is needed */
174 return 1;
175}
176
177/**
178 * ir_delete_key() - remove a keycode from the table
179 * @rc_tab: keycode table
180 * @elem: element to be removed
181 *
182 */
183static void ir_delete_key(struct ir_scancode_table *rc_tab, int elem)
184{
185 unsigned long flags = 0;
186 int newsize = rc_tab->size - 1;
187 int resize = ir_is_resize_needed(rc_tab, newsize);
188 struct ir_scancode *oldkeymap = rc_tab->scan;
Mauro Carvalho Chehab3205e4f2009-12-29 08:25:13 -0300189 struct ir_scancode *newkeymap = NULL;
Mauro Carvalho Chehabe97f4672009-12-04 17:17:47 -0300190
Mauro Carvalho Chehab3205e4f2009-12-29 08:25:13 -0300191 if (resize)
Mauro Carvalho Chehabe97f4672009-12-04 17:17:47 -0300192 newkeymap = kzalloc(ir_roundup_tablesize(newsize) *
193 sizeof(*newkeymap), GFP_ATOMIC);
194
Mauro Carvalho Chehab3205e4f2009-12-29 08:25:13 -0300195 /* There's no memory for resize. Keep the old table */
196 if (!resize || !newkeymap) {
Mauro Carvalho Chehabe97f4672009-12-04 17:17:47 -0300197 newkeymap = oldkeymap;
198
199 /* We'll modify the live table. Lock it */
200 spin_lock_irqsave(&rc_tab->lock, flags);
201 }
202
203 /*
204 * Copy the elements before the one that will be deleted
205 * if (!resize), both oldkeymap and newkeymap points
206 * to the same place, so, there's no need to copy
207 */
208 if (resize && elem > 0)
209 memcpy(newkeymap, oldkeymap,
210 elem * sizeof(*newkeymap));
211
212 /*
213 * Copy the other elements overwriting the element to be removed
214 * This operation applies to both resize and non-resize case
215 */
216 if (elem < newsize)
217 memcpy(&newkeymap[elem], &oldkeymap[elem + 1],
218 (newsize - elem) * sizeof(*newkeymap));
219
220 if (resize) {
221 /*
222 * As the copy happened to a temporary table, only here
223 * it needs to lock while replacing the table pointers
224 * to use the new table
225 */
226 spin_lock_irqsave(&rc_tab->lock, flags);
227 rc_tab->size = newsize;
228 rc_tab->scan = newkeymap;
229 spin_unlock_irqrestore(&rc_tab->lock, flags);
230
231 /* Frees the old keytable */
232 kfree(oldkeymap);
233 } else {
234 rc_tab->size = newsize;
235 spin_unlock_irqrestore(&rc_tab->lock, flags);
236 }
237}
238
239/**
240 * ir_insert_key() - insert a keycode at the table
241 * @rc_tab: keycode table
242 * @scancode: the desired scancode
243 * @keycode: the keycode to be retorned.
244 *
245 */
246static int ir_insert_key(struct ir_scancode_table *rc_tab,
247 int scancode, int keycode)
248{
249 unsigned long flags;
250 int elem = rc_tab->size;
251 int newsize = rc_tab->size + 1;
252 int resize = ir_is_resize_needed(rc_tab, newsize);
253 struct ir_scancode *oldkeymap = rc_tab->scan;
254 struct ir_scancode *newkeymap;
255
256 if (resize) {
257 newkeymap = kzalloc(ir_roundup_tablesize(newsize) *
258 sizeof(*newkeymap), GFP_ATOMIC);
259 if (!newkeymap)
260 return -ENOMEM;
261
262 memcpy(newkeymap, oldkeymap,
263 rc_tab->size * sizeof(*newkeymap));
264 } else
265 newkeymap = oldkeymap;
266
267 /* Stores the new code at the table */
268 IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n",
269 rc_tab->size, scancode, keycode);
270
271 spin_lock_irqsave(&rc_tab->lock, flags);
272 rc_tab->size = newsize;
273 if (resize) {
274 rc_tab->scan = newkeymap;
275 kfree(oldkeymap);
276 }
277 newkeymap[elem].scancode = scancode;
278 newkeymap[elem].keycode = keycode;
279 spin_unlock_irqrestore(&rc_tab->lock, flags);
280
281 return 0;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300282}
283
284/**
285 * ir_setkeycode() - set a keycode at the evdev scancode ->keycode table
286 * @dev: the struct input_dev device descriptor
287 * @scancode: the desired scancode
288 * @keycode: the keycode to be retorned.
289 *
290 * This routine is used to handle evdev EVIOCSKEY ioctl.
291 * There's one caveat here: how can we increase the size of the table?
292 * If the key is not found, returns -EINVAL, otherwise, returns 0.
293 */
294static int ir_setkeycode(struct input_dev *dev,
Dmitry Torokhov58b93992010-03-08 22:37:10 -0800295 unsigned int scancode, unsigned int keycode)
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300296{
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300297 int rc = 0;
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300298 struct ir_input_dev *ir_dev = input_get_drvdata(dev);
299 struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300300 struct ir_scancode *keymap = rc_tab->scan;
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300301 unsigned long flags;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300302
Mauro Carvalho Chehabe97f4672009-12-04 17:17:47 -0300303 /*
304 * Handle keycode table deletions
305 *
306 * If userspace is adding a KEY_UNKNOWN or KEY_RESERVED,
307 * deal as a trial to remove an existing scancode attribution
308 * if table become too big, reduce it to save space
309 */
310 if (keycode == KEY_UNKNOWN || keycode == KEY_RESERVED) {
311 rc = ir_seek_table(rc_tab, scancode);
312 if (rc < 0)
313 return 0;
314
315 IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", rc, scancode);
316 clear_bit(keymap[rc].keycode, dev->keybit);
317 ir_delete_key(rc_tab, rc);
318
319 return 0;
320 }
321
322 /*
323 * Handle keycode replacements
324 *
325 * If the scancode exists, just replace by the new value
326 */
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300327 rc = ir_seek_table(rc_tab, scancode);
Mauro Carvalho Chehabe97f4672009-12-04 17:17:47 -0300328 if (rc >= 0) {
329 IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n",
330 rc, scancode, keycode);
331
332 clear_bit(keymap[rc].keycode, dev->keybit);
333
334 spin_lock_irqsave(&rc_tab->lock, flags);
335 keymap[rc].keycode = keycode;
336 spin_unlock_irqrestore(&rc_tab->lock, flags);
337
338 set_bit(keycode, dev->keybit);
339
340 return 0;
341 }
342
343 /*
344 * Handle new scancode inserts
345 *
346 * reallocate table if needed and insert a new keycode
347 */
348
349 /* Avoid growing the table indefinitely */
350 if (rc_tab->size + 1 > IR_TAB_MAX_SIZE)
351 return -EINVAL;
352
353 rc = ir_insert_key(rc_tab, scancode, keycode);
354 if (rc < 0)
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300355 return rc;
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300356 set_bit(keycode, dev->keybit);
357
358 return 0;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300359}
360
361/**
362 * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300363 * @input_dev: the struct input_dev descriptor of the device
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300364 * @scancode: the scancode that we're seeking
365 *
366 * This routine is used by the input routines when a key is pressed at the
367 * IR. The scancode is received and needs to be converted into a keycode.
368 * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the
369 * corresponding keycode from the table.
370 */
371u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
372{
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300373 struct ir_input_dev *ir_dev = input_get_drvdata(dev);
374 struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300375 struct ir_scancode *keymap = rc_tab->scan;
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300376 int elem;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300377
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300378 elem = ir_seek_table(rc_tab, scancode);
379 if (elem >= 0) {
380 IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
381 dev->name, scancode, keymap[elem].keycode);
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300382
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300383 return rc_tab->scan[elem].keycode;
384 }
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300385
386 printk(KERN_INFO "%s: unknown key for scancode 0x%04x\n",
387 dev->name, scancode);
388
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300389 /* Reports userspace that an unknown keycode were got */
390 return KEY_RESERVED;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300391}
Mauro Carvalho Chehab446e4a62009-12-11 08:34:07 -0300392EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300393
394/**
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300395 * ir_input_register() - sets the IR keycode table and add the handlers
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300396 * for keymap table get/set
397 * @input_dev: the struct input_dev descriptor of the device
398 * @rc_tab: the struct ir_scancode_table table of scancode/keymap
399 *
Mauro Carvalho Chehabd4b778d2009-12-14 02:55:03 -0300400 * This routine is used to initialize the input infrastructure
401 * to work with an IR.
402 * It will register the input/evdev interface for the device and
403 * register the syfs code for IR class
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300404 */
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300405int ir_input_register(struct input_dev *input_dev,
Mauro Carvalho Chehabe93854d2009-12-14 00:16:55 -0300406 const struct ir_scancode_table *rc_tab,
407 const struct ir_dev_props *props)
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300408{
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300409 struct ir_input_dev *ir_dev;
410 struct ir_scancode *keymap = rc_tab->scan;
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300411 int i, rc;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300412
413 if (rc_tab->scan == NULL || !rc_tab->size)
414 return -EINVAL;
415
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300416 ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL);
417 if (!ir_dev)
418 return -ENOMEM;
419
Mauro Carvalho Chehabe93854d2009-12-14 00:16:55 -0300420 spin_lock_init(&ir_dev->rc_tab.lock);
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300421
422 ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size);
423 ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size *
424 sizeof(struct ir_scancode), GFP_KERNEL);
Alexander Beregalov82311522010-01-09 13:51:14 -0300425 if (!ir_dev->rc_tab.scan) {
426 kfree(ir_dev);
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300427 return -ENOMEM;
Alexander Beregalov82311522010-01-09 13:51:14 -0300428 }
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300429
430 IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n",
431 ir_dev->rc_tab.size,
432 ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan));
433
434 ir_copy_table(&ir_dev->rc_tab, rc_tab);
Mauro Carvalho Chehabe93854d2009-12-14 00:16:55 -0300435 ir_dev->props = props;
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300436
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300437 /* set the bits for the keys */
438 IR_dprintk(1, "key map size: %d\n", rc_tab->size);
439 for (i = 0; i < rc_tab->size; i++) {
440 IR_dprintk(1, "#%d: setting bit for keycode 0x%04x\n",
441 i, keymap[i].keycode);
442 set_bit(keymap[i].keycode, input_dev->keybit);
443 }
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300444 clear_bit(0, input_dev->keybit);
445
446 set_bit(EV_KEY, input_dev->evbit);
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300447
448 input_dev->getkeycode = ir_getkeycode;
449 input_dev->setkeycode = ir_setkeycode;
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300450 input_set_drvdata(input_dev, ir_dev);
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300451
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300452 rc = input_register_device(input_dev);
Mauro Carvalho Chehab4714eda2009-12-13 16:00:08 -0300453 if (rc < 0)
454 goto err;
455
456 rc = ir_register_class(input_dev);
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300457 if (rc < 0) {
Mauro Carvalho Chehab4714eda2009-12-13 16:00:08 -0300458 input_unregister_device(input_dev);
459 goto err;
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300460 }
461
Mauro Carvalho Chehab4714eda2009-12-13 16:00:08 -0300462 return 0;
463
464err:
465 kfree(rc_tab->scan);
466 kfree(ir_dev);
467 input_set_drvdata(input_dev, NULL);
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300468 return rc;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300469}
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300470EXPORT_SYMBOL_GPL(ir_input_register);
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -0300471
Mauro Carvalho Chehabd4b778d2009-12-14 02:55:03 -0300472/**
473 * ir_input_unregister() - unregisters IR and frees resources
474 * @input_dev: the struct input_dev descriptor of the device
475
476 * This routine is used to free memory and de-register interfaces.
477 */
Mauro Carvalho Chehab38ef6aa2009-12-11 09:47:42 -0300478void ir_input_unregister(struct input_dev *dev)
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -0300479{
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300480 struct ir_input_dev *ir_dev = input_get_drvdata(dev);
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300481 struct ir_scancode_table *rc_tab;
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -0300482
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300483 if (!ir_dev)
Mauro Carvalho Chehab05395a32009-12-06 08:32:49 -0300484 return;
485
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -0300486 IR_dprintk(1, "Freed keycode table\n");
487
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300488 rc_tab = &ir_dev->rc_tab;
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -0300489 rc_tab->size = 0;
490 kfree(rc_tab->scan);
491 rc_tab->scan = NULL;
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300492
Mauro Carvalho Chehab4714eda2009-12-13 16:00:08 -0300493 ir_unregister_class(dev);
494
Mauro Carvalho Chehab75543cc2009-12-11 09:44:23 -0300495 kfree(ir_dev);
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300496 input_unregister_device(dev);
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -0300497}
Mauro Carvalho Chehab38ef6aa2009-12-11 09:47:42 -0300498EXPORT_SYMBOL_GPL(ir_input_unregister);
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -0300499
Mauro Carvalho Chehab446e4a62009-12-11 08:34:07 -0300500int ir_core_debug; /* ir_debug level (0,1,2) */
501EXPORT_SYMBOL_GPL(ir_core_debug);
502module_param_named(debug, ir_core_debug, int, 0644);
503
504MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
505MODULE_LICENSE("GPL");