Merge branch 'tip/tracing/core' of git://git.kernel.org/pub/scm/linux/kernel/git...
[deliverable/linux.git] / drivers / media / common / ir-keytable.c
CommitLineData
ef53a115
MCC
1/* ir-register.c - handle IR scancode->keycode tables
2 *
3 * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 */
5
6#include <linux/usb/input.h>
7
8#include <media/ir-common.h>
9
f6fc5049 10#define IR_TAB_MIN_SIZE 32
e97f4677 11#define IR_TAB_MAX_SIZE 1024
f6fc5049 12
7fee03e4
MCC
13/**
14 * ir_seek_table() - returns the element order on the table
15 * @rc_tab: the ir_scancode_table with the keymap to be used
16 * @scancode: the scancode that we're seeking
17 *
18 * This routine is used by the input routines when a key is pressed at the
19 * IR. The scancode is received and needs to be converted into a keycode.
20 * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the
21 * corresponding keycode from the table.
22 */
23static int ir_seek_table(struct ir_scancode_table *rc_tab, u32 scancode)
24{
25 int rc;
26 unsigned long flags;
27 struct ir_scancode *keymap = rc_tab->scan;
28
29 spin_lock_irqsave(&rc_tab->lock, flags);
30
31 /* FIXME: replace it by a binary search */
32
33 for (rc = 0; rc < rc_tab->size; rc++)
34 if (keymap[rc].scancode == scancode)
35 goto exit;
36
37 /* Not found */
38 rc = -EINVAL;
39
40exit:
41 spin_unlock_irqrestore(&rc_tab->lock, flags);
42 return rc;
43}
44
f6fc5049
MCC
45/**
46 * ir_roundup_tablesize() - gets an optimum value for the table size
47 * @n_elems: minimum number of entries to store keycodes
48 *
49 * This routine is used to choose the keycode table size.
50 *
51 * In order to have some empty space for new keycodes,
52 * and knowing in advance that kmalloc allocates only power of two
53 * segments, it optimizes the allocated space to have some spare space
54 * for those new keycodes by using the maximum number of entries that
55 * will be effectively be allocated by kmalloc.
56 * In order to reduce the quantity of table resizes, it has a minimum
57 * table size of IR_TAB_MIN_SIZE.
58 */
59int ir_roundup_tablesize(int n_elems)
60{
61 size_t size;
62
63 if (n_elems < IR_TAB_MIN_SIZE)
64 n_elems = IR_TAB_MIN_SIZE;
65
66 /*
67 * As kmalloc only allocates sizes of power of two, get as
68 * much entries as possible for the allocated memory segment
69 */
70 size = roundup_pow_of_two(n_elems * sizeof(struct ir_scancode));
71 n_elems = size / sizeof(struct ir_scancode);
72
73 return n_elems;
74}
75
76/**
77 * ir_copy_table() - copies a keytable, discarding the unused entries
78 * @destin: destin table
79 * @origin: origin table
80 *
81 * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED
82 */
83
84int ir_copy_table(struct ir_scancode_table *destin,
85 const struct ir_scancode_table *origin)
86{
87 int i, j = 0;
88
89 for (i = 0; i < origin->size; i++) {
7fee03e4
MCC
90 if (origin->scan[i].keycode == KEY_UNKNOWN ||
91 origin->scan[i].keycode == KEY_RESERVED)
92 continue;
93
94 memcpy(&destin->scan[j], &origin->scan[i], sizeof(struct ir_scancode));
95 j++;
f6fc5049
MCC
96 }
97 destin->size = j;
98
7fee03e4 99 IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size);
f6fc5049
MCC
100
101 return 0;
102}
103
ef53a115
MCC
104/**
105 * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table
106 * @dev: the struct input_dev device descriptor
107 * @scancode: the desired scancode
108 * @keycode: the keycode to be retorned.
109 *
110 * This routine is used to handle evdev EVIOCGKEY ioctl.
111 * If the key is not found, returns -EINVAL, otherwise, returns 0.
112 */
113static int ir_getkeycode(struct input_dev *dev,
114 int scancode, int *keycode)
115{
7fee03e4 116 int elem;
ef53a115 117 struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
ef53a115 118
7fee03e4
MCC
119 elem = ir_seek_table(rc_tab, scancode);
120 if (elem >= 0) {
121 *keycode = rc_tab->scan[elem].keycode;
122 return 0;
123 }
ef53a115 124
e97f4677
MCC
125 /*
126 * Scancode not found and table can't be expanded
127 */
128 if (elem < 0 && rc_tab->size == IR_TAB_MAX_SIZE)
129 return -EINVAL;
130
131 /*
132 * If is there extra space, returns KEY_RESERVED,
133 * otherwise, input core won't let ir_setkeycode to work
134 */
135 *keycode = KEY_RESERVED;
136 return 0;
137}
138
139
140/**
141 * ir_is_resize_needed() - Check if the table needs rezise
142 * @table: keycode table that may need to resize
143 * @n_elems: minimum number of entries to store keycodes
144 *
145 * Considering that kmalloc uses power of two storage areas, this
146 * routine detects if the real alloced size will change. If not, it
147 * just returns without doing nothing. Otherwise, it will extend or
148 * reduce the table size to meet the new needs.
149 *
150 * It returns 0 if no resize is needed, 1 otherwise.
151 */
152static int ir_is_resize_needed(struct ir_scancode_table *table, int n_elems)
153{
154 int cur_size = ir_roundup_tablesize(table->size);
155 int new_size = ir_roundup_tablesize(n_elems);
156
157 if (cur_size == new_size)
158 return 0;
159
160 /* Resize is needed */
161 return 1;
162}
163
164/**
165 * ir_delete_key() - remove a keycode from the table
166 * @rc_tab: keycode table
167 * @elem: element to be removed
168 *
169 */
170static void ir_delete_key(struct ir_scancode_table *rc_tab, int elem)
171{
172 unsigned long flags = 0;
173 int newsize = rc_tab->size - 1;
174 int resize = ir_is_resize_needed(rc_tab, newsize);
175 struct ir_scancode *oldkeymap = rc_tab->scan;
176 struct ir_scancode *newkeymap;
177
178 if (resize) {
179 newkeymap = kzalloc(ir_roundup_tablesize(newsize) *
180 sizeof(*newkeymap), GFP_ATOMIC);
181
182 /* There's no memory for resize. Keep the old table */
183 if (!newkeymap)
184 resize = 0;
185 }
186
187 if (!resize) {
188 newkeymap = oldkeymap;
189
190 /* We'll modify the live table. Lock it */
191 spin_lock_irqsave(&rc_tab->lock, flags);
192 }
193
194 /*
195 * Copy the elements before the one that will be deleted
196 * if (!resize), both oldkeymap and newkeymap points
197 * to the same place, so, there's no need to copy
198 */
199 if (resize && elem > 0)
200 memcpy(newkeymap, oldkeymap,
201 elem * sizeof(*newkeymap));
202
203 /*
204 * Copy the other elements overwriting the element to be removed
205 * This operation applies to both resize and non-resize case
206 */
207 if (elem < newsize)
208 memcpy(&newkeymap[elem], &oldkeymap[elem + 1],
209 (newsize - elem) * sizeof(*newkeymap));
210
211 if (resize) {
212 /*
213 * As the copy happened to a temporary table, only here
214 * it needs to lock while replacing the table pointers
215 * to use the new table
216 */
217 spin_lock_irqsave(&rc_tab->lock, flags);
218 rc_tab->size = newsize;
219 rc_tab->scan = newkeymap;
220 spin_unlock_irqrestore(&rc_tab->lock, flags);
221
222 /* Frees the old keytable */
223 kfree(oldkeymap);
224 } else {
225 rc_tab->size = newsize;
226 spin_unlock_irqrestore(&rc_tab->lock, flags);
227 }
228}
229
230/**
231 * ir_insert_key() - insert a keycode at the table
232 * @rc_tab: keycode table
233 * @scancode: the desired scancode
234 * @keycode: the keycode to be retorned.
235 *
236 */
237static int ir_insert_key(struct ir_scancode_table *rc_tab,
238 int scancode, int keycode)
239{
240 unsigned long flags;
241 int elem = rc_tab->size;
242 int newsize = rc_tab->size + 1;
243 int resize = ir_is_resize_needed(rc_tab, newsize);
244 struct ir_scancode *oldkeymap = rc_tab->scan;
245 struct ir_scancode *newkeymap;
246
247 if (resize) {
248 newkeymap = kzalloc(ir_roundup_tablesize(newsize) *
249 sizeof(*newkeymap), GFP_ATOMIC);
250 if (!newkeymap)
251 return -ENOMEM;
252
253 memcpy(newkeymap, oldkeymap,
254 rc_tab->size * sizeof(*newkeymap));
255 } else
256 newkeymap = oldkeymap;
257
258 /* Stores the new code at the table */
259 IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n",
260 rc_tab->size, scancode, keycode);
261
262 spin_lock_irqsave(&rc_tab->lock, flags);
263 rc_tab->size = newsize;
264 if (resize) {
265 rc_tab->scan = newkeymap;
266 kfree(oldkeymap);
267 }
268 newkeymap[elem].scancode = scancode;
269 newkeymap[elem].keycode = keycode;
270 spin_unlock_irqrestore(&rc_tab->lock, flags);
271
272 return 0;
ef53a115
MCC
273}
274
275/**
276 * ir_setkeycode() - set a keycode at the evdev scancode ->keycode table
277 * @dev: the struct input_dev device descriptor
278 * @scancode: the desired scancode
279 * @keycode: the keycode to be retorned.
280 *
281 * This routine is used to handle evdev EVIOCSKEY ioctl.
282 * There's one caveat here: how can we increase the size of the table?
283 * If the key is not found, returns -EINVAL, otherwise, returns 0.
284 */
285static int ir_setkeycode(struct input_dev *dev,
286 int scancode, int keycode)
287{
7fee03e4 288 int rc = 0;
ef53a115
MCC
289 struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
290 struct ir_scancode *keymap = rc_tab->scan;
7fee03e4 291 unsigned long flags;
ef53a115 292
e97f4677
MCC
293 /*
294 * Handle keycode table deletions
295 *
296 * If userspace is adding a KEY_UNKNOWN or KEY_RESERVED,
297 * deal as a trial to remove an existing scancode attribution
298 * if table become too big, reduce it to save space
299 */
300 if (keycode == KEY_UNKNOWN || keycode == KEY_RESERVED) {
301 rc = ir_seek_table(rc_tab, scancode);
302 if (rc < 0)
303 return 0;
304
305 IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", rc, scancode);
306 clear_bit(keymap[rc].keycode, dev->keybit);
307 ir_delete_key(rc_tab, rc);
308
309 return 0;
310 }
311
312 /*
313 * Handle keycode replacements
314 *
315 * If the scancode exists, just replace by the new value
316 */
7fee03e4 317 rc = ir_seek_table(rc_tab, scancode);
e97f4677
MCC
318 if (rc >= 0) {
319 IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n",
320 rc, scancode, keycode);
ef53a115 321
e97f4677 322 clear_bit(keymap[rc].keycode, dev->keybit);
ef53a115 323
e97f4677
MCC
324 spin_lock_irqsave(&rc_tab->lock, flags);
325 keymap[rc].keycode = keycode;
326 spin_unlock_irqrestore(&rc_tab->lock, flags);
7fee03e4 327
e97f4677 328 set_bit(keycode, dev->keybit);
7fee03e4 329
e97f4677
MCC
330 return 0;
331 }
332
333 /*
334 * Handle new scancode inserts
335 *
336 * reallocate table if needed and insert a new keycode
337 */
338
339 /* Avoid growing the table indefinitely */
340 if (rc_tab->size + 1 > IR_TAB_MAX_SIZE)
341 return -EINVAL;
342
343 rc = ir_insert_key(rc_tab, scancode, keycode);
344 if (rc < 0)
345 return rc;
7fee03e4
MCC
346 set_bit(keycode, dev->keybit);
347
348 return 0;
ef53a115
MCC
349}
350
351/**
352 * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode
7fee03e4 353 * @input_dev: the struct input_dev descriptor of the device
ef53a115
MCC
354 * @scancode: the scancode that we're seeking
355 *
356 * This routine is used by the input routines when a key is pressed at the
357 * IR. The scancode is received and needs to be converted into a keycode.
358 * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the
359 * corresponding keycode from the table.
360 */
361u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
362{
ef53a115
MCC
363 struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
364 struct ir_scancode *keymap = rc_tab->scan;
7fee03e4 365 int elem;
ef53a115 366
7fee03e4
MCC
367 elem = ir_seek_table(rc_tab, scancode);
368 if (elem >= 0) {
369 IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
370 dev->name, scancode, keymap[elem].keycode);
ef53a115 371
7fee03e4
MCC
372 return rc_tab->scan[elem].keycode;
373 }
ef53a115
MCC
374
375 printk(KERN_INFO "%s: unknown key for scancode 0x%04x\n",
376 dev->name, scancode);
377
7fee03e4
MCC
378 /* Reports userspace that an unknown keycode were got */
379 return KEY_RESERVED;
ef53a115 380}
ef53a115
MCC
381
382/**
383 * ir_set_keycode_table() - sets the IR keycode table and add the handlers
384 * for keymap table get/set
385 * @input_dev: the struct input_dev descriptor of the device
386 * @rc_tab: the struct ir_scancode_table table of scancode/keymap
387 *
388 * This routine is used to initialize the input infrastructure to work with
7fee03e4
MCC
389 * an IR.
390 * It should be called before registering the IR device.
ef53a115
MCC
391 */
392int ir_set_keycode_table(struct input_dev *input_dev,
393 struct ir_scancode_table *rc_tab)
394{
395 struct ir_scancode *keymap = rc_tab->scan;
396 int i;
397
7fee03e4
MCC
398 spin_lock_init(&rc_tab->lock);
399
ef53a115
MCC
400 if (rc_tab->scan == NULL || !rc_tab->size)
401 return -EINVAL;
402
403 /* set the bits for the keys */
404 IR_dprintk(1, "key map size: %d\n", rc_tab->size);
405 for (i = 0; i < rc_tab->size; i++) {
406 IR_dprintk(1, "#%d: setting bit for keycode 0x%04x\n",
407 i, keymap[i].keycode);
408 set_bit(keymap[i].keycode, input_dev->keybit);
409 }
410
411 input_dev->getkeycode = ir_getkeycode;
412 input_dev->setkeycode = ir_setkeycode;
413 input_set_drvdata(input_dev, rc_tab);
414
415 return 0;
416}
f6fc5049
MCC
417
418void ir_input_free(struct input_dev *dev)
419{
420 struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
421
422 IR_dprintk(1, "Freed keycode table\n");
423
424 rc_tab->size = 0;
425 kfree(rc_tab->scan);
426 rc_tab->scan = NULL;
427}
428EXPORT_SYMBOL_GPL(ir_input_free);
429
This page took 0.065208 seconds and 5 git commands to generate.