Commit | Line | Data |
---|---|---|
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 | */ | |
23 | static 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 | ||
40 | exit: | |
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 | */ | |
59 | int 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 | ||
84 | int 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 | */ | |
113 | static 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 | */ | |
152 | static 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 | */ | |
170 | static 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 | */ | |
237 | static 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 | */ | |
285 | static 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 | */ | |
361 | u32 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 | */ |
392 | int 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 | |
418 | void 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 | } | |
428 | EXPORT_SYMBOL_GPL(ir_input_free); | |
429 |