]>
Commit | Line | Data |
---|---|---|
dd3f616d | 1 | /* ir-keytable.c - handle IR scancode->keycode tables |
ef53a115 MCC |
2 | * |
3 | * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com> | |
446e4a64 MCC |
4 | * |
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. | |
ef53a115 MCC |
13 | */ |
14 | ||
ef53a115 | 15 | |
882ead32 | 16 | #include <linux/input.h> |
5a0e3ad6 | 17 | #include <linux/slab.h> |
3f113e36 | 18 | #include "ir-core-priv.h" |
ef53a115 | 19 | |
b3074c0a DH |
20 | /* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */ |
21 | #define IR_TAB_MIN_SIZE 256 | |
22 | #define IR_TAB_MAX_SIZE 8192 | |
f6fc5049 | 23 | |
a374fef4 DH |
24 | /* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */ |
25 | #define IR_KEYPRESS_TIMEOUT 250 | |
26 | ||
9f470095 DT |
27 | /** |
28 | * ir_create_table() - initializes a scancode table | |
29 | * @rc_tab: the ir_scancode_table to initialize | |
30 | * @name: name to assign to the table | |
31 | * @ir_type: ir type to assign to the new table | |
32 | * @size: initial size of the table | |
33 | * @return: zero on success or a negative error code | |
34 | * | |
35 | * This routine will initialize the ir_scancode_table and will allocate | |
36 | * memory to hold at least the specified number elements. | |
37 | */ | |
38 | static int ir_create_table(struct ir_scancode_table *rc_tab, | |
39 | const char *name, u64 ir_type, size_t size) | |
40 | { | |
41 | rc_tab->name = name; | |
42 | rc_tab->ir_type = ir_type; | |
43 | rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode)); | |
44 | rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); | |
45 | rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL); | |
46 | if (!rc_tab->scan) | |
47 | return -ENOMEM; | |
48 | ||
49 | IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", | |
50 | rc_tab->size, rc_tab->alloc); | |
51 | return 0; | |
52 | } | |
53 | ||
54 | /** | |
55 | * ir_free_table() - frees memory allocated by a scancode table | |
56 | * @rc_tab: the table whose mappings need to be freed | |
57 | * | |
58 | * This routine will free memory alloctaed for key mappings used by given | |
59 | * scancode table. | |
60 | */ | |
61 | static void ir_free_table(struct ir_scancode_table *rc_tab) | |
62 | { | |
63 | rc_tab->size = 0; | |
64 | kfree(rc_tab->scan); | |
65 | rc_tab->scan = NULL; | |
66 | } | |
67 | ||
7fee03e4 | 68 | /** |
b3074c0a DH |
69 | * ir_resize_table() - resizes a scancode table if necessary |
70 | * @rc_tab: the ir_scancode_table to resize | |
9f470095 | 71 | * @gfp_flags: gfp flags to use when allocating memory |
b3074c0a | 72 | * @return: zero on success or a negative error code |
7fee03e4 | 73 | * |
b3074c0a DH |
74 | * This routine will shrink the ir_scancode_table if it has lots of |
75 | * unused entries and grow it if it is full. | |
7fee03e4 | 76 | */ |
9f470095 | 77 | static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags) |
7fee03e4 | 78 | { |
b3074c0a DH |
79 | unsigned int oldalloc = rc_tab->alloc; |
80 | unsigned int newalloc = oldalloc; | |
81 | struct ir_scancode *oldscan = rc_tab->scan; | |
82 | struct ir_scancode *newscan; | |
83 | ||
84 | if (rc_tab->size == rc_tab->len) { | |
85 | /* All entries in use -> grow keytable */ | |
86 | if (rc_tab->alloc >= IR_TAB_MAX_SIZE) | |
87 | return -ENOMEM; | |
7fee03e4 | 88 | |
b3074c0a DH |
89 | newalloc *= 2; |
90 | IR_dprintk(1, "Growing table to %u bytes\n", newalloc); | |
91 | } | |
7fee03e4 | 92 | |
b3074c0a DH |
93 | if ((rc_tab->len * 3 < rc_tab->size) && (oldalloc > IR_TAB_MIN_SIZE)) { |
94 | /* Less than 1/3 of entries in use -> shrink keytable */ | |
95 | newalloc /= 2; | |
96 | IR_dprintk(1, "Shrinking table to %u bytes\n", newalloc); | |
97 | } | |
7fee03e4 | 98 | |
b3074c0a DH |
99 | if (newalloc == oldalloc) |
100 | return 0; | |
7fee03e4 | 101 | |
9f470095 | 102 | newscan = kmalloc(newalloc, gfp_flags); |
b3074c0a DH |
103 | if (!newscan) { |
104 | IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc); | |
105 | return -ENOMEM; | |
106 | } | |
7fee03e4 | 107 | |
b3074c0a DH |
108 | memcpy(newscan, rc_tab->scan, rc_tab->len * sizeof(struct ir_scancode)); |
109 | rc_tab->scan = newscan; | |
110 | rc_tab->alloc = newalloc; | |
111 | rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); | |
112 | kfree(oldscan); | |
113 | return 0; | |
7fee03e4 MCC |
114 | } |
115 | ||
f6fc5049 | 116 | /** |
9f470095 | 117 | * ir_update_mapping() - set a keycode in the scancode->keycode table |
b3074c0a | 118 | * @dev: the struct input_dev device descriptor |
9f470095 DT |
119 | * @rc_tab: scancode table to be adjusted |
120 | * @index: index of the mapping that needs to be updated | |
121 | * @keycode: the desired keycode | |
122 | * @return: previous keycode assigned to the mapping | |
123 | * | |
124 | * This routine is used to update scancode->keycopde mapping at given | |
125 | * position. | |
126 | */ | |
127 | static unsigned int ir_update_mapping(struct input_dev *dev, | |
128 | struct ir_scancode_table *rc_tab, | |
129 | unsigned int index, | |
130 | unsigned int new_keycode) | |
131 | { | |
132 | int old_keycode = rc_tab->scan[index].keycode; | |
133 | int i; | |
134 | ||
135 | /* Did the user wish to remove the mapping? */ | |
136 | if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) { | |
137 | IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", | |
138 | index, rc_tab->scan[index].scancode); | |
139 | rc_tab->len--; | |
140 | memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1], | |
141 | (rc_tab->len - index) * sizeof(struct ir_scancode)); | |
142 | } else { | |
143 | IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n", | |
144 | index, | |
145 | old_keycode == KEY_RESERVED ? "New" : "Replacing", | |
146 | rc_tab->scan[index].scancode, new_keycode); | |
147 | rc_tab->scan[index].keycode = new_keycode; | |
148 | __set_bit(new_keycode, dev->keybit); | |
149 | } | |
150 | ||
151 | if (old_keycode != KEY_RESERVED) { | |
152 | /* A previous mapping was updated... */ | |
153 | __clear_bit(old_keycode, dev->keybit); | |
154 | /* ... but another scancode might use the same keycode */ | |
155 | for (i = 0; i < rc_tab->len; i++) { | |
156 | if (rc_tab->scan[i].keycode == old_keycode) { | |
157 | __set_bit(old_keycode, dev->keybit); | |
158 | break; | |
159 | } | |
160 | } | |
161 | ||
162 | /* Possibly shrink the keytable, failure is not a problem */ | |
163 | ir_resize_table(rc_tab, GFP_ATOMIC); | |
164 | } | |
165 | ||
166 | return old_keycode; | |
167 | } | |
168 | ||
169 | /** | |
170 | * ir_locate_scancode() - set a keycode in the scancode->keycode table | |
171 | * @ir_dev: the struct ir_input_dev device descriptor | |
172 | * @rc_tab: scancode table to be searched | |
173 | * @scancode: the desired scancode | |
174 | * @resize: controls whether we allowed to resize the table to | |
175 | * accomodate not yet present scancodes | |
176 | * @return: index of the mapping containing scancode in question | |
177 | * or -1U in case of failure. | |
f6fc5049 | 178 | * |
9f470095 DT |
179 | * This routine is used to locate given scancode in ir_scancode_table. |
180 | * If scancode is not yet present the routine will allocate a new slot | |
181 | * for it. | |
f6fc5049 | 182 | */ |
9f470095 DT |
183 | static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev, |
184 | struct ir_scancode_table *rc_tab, | |
185 | unsigned int scancode, | |
186 | bool resize) | |
f6fc5049 | 187 | { |
b3074c0a | 188 | unsigned int i; |
9dfe4e83 MCC |
189 | |
190 | /* | |
191 | * Unfortunately, some hardware-based IR decoders don't provide | |
192 | * all bits for the complete IR code. In general, they provide only | |
193 | * the command part of the IR code. Yet, as it is possible to replace | |
194 | * the provided IR with another one, it is needed to allow loading | |
195 | * IR tables from other remotes. So, | |
196 | */ | |
9f470095 | 197 | if (ir_dev->props && ir_dev->props->scanmask) |
9dfe4e83 | 198 | scancode &= ir_dev->props->scanmask; |
b3074c0a DH |
199 | |
200 | /* First check if we already have a mapping for this ir command */ | |
201 | for (i = 0; i < rc_tab->len; i++) { | |
9f470095 DT |
202 | if (rc_tab->scan[i].scancode == scancode) |
203 | return i; | |
204 | ||
b3074c0a | 205 | /* Keytable is sorted from lowest to highest scancode */ |
9f470095 | 206 | if (rc_tab->scan[i].scancode >= scancode) |
b3074c0a | 207 | break; |
b3074c0a | 208 | } |
f6fc5049 | 209 | |
9f470095 DT |
210 | /* No previous mapping found, we might need to grow the table */ |
211 | if (rc_tab->size == rc_tab->len) { | |
212 | if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC)) | |
213 | return -1U; | |
214 | } | |
35438946 | 215 | |
9f470095 DT |
216 | /* i is the proper index to insert our new keycode */ |
217 | if (i < rc_tab->len) | |
b3074c0a DH |
218 | memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i], |
219 | (rc_tab->len - i) * sizeof(struct ir_scancode)); | |
9f470095 DT |
220 | rc_tab->scan[i].scancode = scancode; |
221 | rc_tab->scan[i].keycode = KEY_RESERVED; | |
222 | rc_tab->len++; | |
f6fc5049 | 223 | |
9f470095 | 224 | return i; |
f6fc5049 MCC |
225 | } |
226 | ||
ef53a115 | 227 | /** |
b3074c0a | 228 | * ir_setkeycode() - set a keycode in the scancode->keycode table |
ef53a115 MCC |
229 | * @dev: the struct input_dev device descriptor |
230 | * @scancode: the desired scancode | |
b3074c0a DH |
231 | * @keycode: result |
232 | * @return: -EINVAL if the keycode could not be inserted, otherwise zero. | |
ef53a115 | 233 | * |
b3074c0a | 234 | * This routine is used to handle evdev EVIOCSKEY ioctl. |
ef53a115 | 235 | */ |
b3074c0a | 236 | static int ir_setkeycode(struct input_dev *dev, |
9f470095 DT |
237 | const struct input_keymap_entry *ke, |
238 | unsigned int *old_keycode) | |
ef53a115 | 239 | { |
75543cce MCC |
240 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); |
241 | struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; | |
9f470095 DT |
242 | unsigned int index; |
243 | unsigned int scancode; | |
244 | int retval; | |
245 | unsigned long flags; | |
ef53a115 | 246 | |
b3074c0a | 247 | spin_lock_irqsave(&rc_tab->lock, flags); |
9f470095 DT |
248 | |
249 | if (ke->flags & INPUT_KEYMAP_BY_INDEX) { | |
250 | index = ke->index; | |
251 | if (index >= rc_tab->len) { | |
252 | retval = -EINVAL; | |
253 | goto out; | |
254 | } | |
255 | } else { | |
256 | retval = input_scancode_to_scalar(ke, &scancode); | |
257 | if (retval) | |
258 | goto out; | |
259 | ||
260 | index = ir_establish_scancode(ir_dev, rc_tab, scancode, true); | |
261 | if (index >= rc_tab->len) { | |
262 | retval = -ENOMEM; | |
263 | goto out; | |
264 | } | |
265 | } | |
266 | ||
267 | *old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode); | |
268 | ||
269 | out: | |
b3074c0a | 270 | spin_unlock_irqrestore(&rc_tab->lock, flags); |
9f470095 | 271 | return retval; |
e97f4677 MCC |
272 | } |
273 | ||
274 | /** | |
b3074c0a DH |
275 | * ir_setkeytable() - sets several entries in the scancode->keycode table |
276 | * @dev: the struct input_dev device descriptor | |
277 | * @to: the struct ir_scancode_table to copy entries to | |
278 | * @from: the struct ir_scancode_table to copy entries from | |
9f470095 | 279 | * @return: -ENOMEM if all keycodes could not be inserted, otherwise zero. |
e97f4677 | 280 | * |
b3074c0a | 281 | * This routine is used to handle table initialization. |
e97f4677 | 282 | */ |
9f470095 | 283 | static int ir_setkeytable(struct ir_input_dev *ir_dev, |
b3074c0a | 284 | const struct ir_scancode_table *from) |
e97f4677 | 285 | { |
b3074c0a | 286 | struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; |
9f470095 DT |
287 | unsigned int i, index; |
288 | int rc; | |
289 | ||
290 | rc = ir_create_table(&ir_dev->rc_tab, | |
291 | from->name, from->ir_type, from->size); | |
292 | if (rc) | |
293 | return rc; | |
294 | ||
295 | IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", | |
296 | rc_tab->size, rc_tab->alloc); | |
e97f4677 | 297 | |
b3074c0a | 298 | for (i = 0; i < from->size; i++) { |
9f470095 DT |
299 | index = ir_establish_scancode(ir_dev, rc_tab, |
300 | from->scan[i].scancode, false); | |
301 | if (index >= rc_tab->len) { | |
302 | rc = -ENOMEM; | |
b3074c0a | 303 | break; |
9f470095 DT |
304 | } |
305 | ||
306 | ir_update_mapping(ir_dev->input_dev, rc_tab, index, | |
307 | from->scan[i].keycode); | |
e97f4677 | 308 | } |
9f470095 DT |
309 | |
310 | if (rc) | |
311 | ir_free_table(rc_tab); | |
312 | ||
b3074c0a | 313 | return rc; |
ef53a115 MCC |
314 | } |
315 | ||
9f470095 DT |
316 | /** |
317 | * ir_lookup_by_scancode() - locate mapping by scancode | |
318 | * @rc_tab: the &struct ir_scancode_table to search | |
319 | * @scancode: scancode to look for in the table | |
320 | * @return: index in the table, -1U if not found | |
321 | * | |
322 | * This routine performs binary search in RC keykeymap table for | |
323 | * given scancode. | |
324 | */ | |
325 | static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab, | |
326 | unsigned int scancode) | |
327 | { | |
0d07025e DH |
328 | int start = 0; |
329 | int end = rc_tab->len - 1; | |
330 | int mid; | |
9f470095 DT |
331 | |
332 | while (start <= end) { | |
333 | mid = (start + end) / 2; | |
334 | if (rc_tab->scan[mid].scancode < scancode) | |
335 | start = mid + 1; | |
336 | else if (rc_tab->scan[mid].scancode > scancode) | |
337 | end = mid - 1; | |
338 | else | |
339 | return mid; | |
340 | } | |
341 | ||
342 | return -1U; | |
343 | } | |
344 | ||
ef53a115 | 345 | /** |
b3074c0a | 346 | * ir_getkeycode() - get a keycode from the scancode->keycode table |
ef53a115 MCC |
347 | * @dev: the struct input_dev device descriptor |
348 | * @scancode: the desired scancode | |
b3074c0a DH |
349 | * @keycode: used to return the keycode, if found, or KEY_RESERVED |
350 | * @return: always returns zero. | |
ef53a115 | 351 | * |
b3074c0a | 352 | * This routine is used to handle evdev EVIOCGKEY ioctl. |
ef53a115 | 353 | */ |
b3074c0a | 354 | static int ir_getkeycode(struct input_dev *dev, |
9f470095 | 355 | struct input_keymap_entry *ke) |
ef53a115 | 356 | { |
75543cce MCC |
357 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); |
358 | struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; | |
9f470095 DT |
359 | struct ir_scancode *entry; |
360 | unsigned long flags; | |
361 | unsigned int index; | |
362 | unsigned int scancode; | |
363 | int retval; | |
ef53a115 | 364 | |
b3074c0a | 365 | spin_lock_irqsave(&rc_tab->lock, flags); |
9f470095 DT |
366 | |
367 | if (ke->flags & INPUT_KEYMAP_BY_INDEX) { | |
368 | index = ke->index; | |
369 | } else { | |
370 | retval = input_scancode_to_scalar(ke, &scancode); | |
371 | if (retval) | |
372 | goto out; | |
373 | ||
374 | index = ir_lookup_by_scancode(rc_tab, scancode); | |
375 | } | |
376 | ||
377 | if (index >= rc_tab->len) { | |
378 | if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) | |
379 | IR_dprintk(1, "unknown key for scancode 0x%04x\n", | |
380 | scancode); | |
381 | retval = -EINVAL; | |
382 | goto out; | |
e97f4677 MCC |
383 | } |
384 | ||
9f470095 | 385 | entry = &rc_tab->scan[index]; |
35438946 | 386 | |
9f470095 DT |
387 | ke->index = index; |
388 | ke->keycode = entry->keycode; | |
389 | ke->len = sizeof(entry->scancode); | |
390 | memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode)); | |
391 | ||
392 | out: | |
393 | spin_unlock_irqrestore(&rc_tab->lock, flags); | |
394 | return retval; | |
ef53a115 MCC |
395 | } |
396 | ||
397 | /** | |
398 | * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode | |
7fee03e4 | 399 | * @input_dev: the struct input_dev descriptor of the device |
ef53a115 MCC |
400 | * @scancode: the scancode that we're seeking |
401 | * | |
402 | * This routine is used by the input routines when a key is pressed at the | |
403 | * IR. The scancode is received and needs to be converted into a keycode. | |
6660de56 | 404 | * If the key is not found, it returns KEY_RESERVED. Otherwise, returns the |
ef53a115 MCC |
405 | * corresponding keycode from the table. |
406 | */ | |
407 | u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) | |
408 | { | |
9f470095 DT |
409 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); |
410 | struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; | |
411 | unsigned int keycode; | |
412 | unsigned int index; | |
413 | unsigned long flags; | |
414 | ||
415 | spin_lock_irqsave(&rc_tab->lock, flags); | |
416 | ||
417 | index = ir_lookup_by_scancode(rc_tab, scancode); | |
418 | keycode = index < rc_tab->len ? | |
419 | rc_tab->scan[index].keycode : KEY_RESERVED; | |
420 | ||
421 | spin_unlock_irqrestore(&rc_tab->lock, flags); | |
ef53a115 | 422 | |
35438946 MCC |
423 | if (keycode != KEY_RESERVED) |
424 | IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", | |
425 | dev->name, scancode, keycode); | |
9f470095 | 426 | |
b3074c0a | 427 | return keycode; |
ef53a115 | 428 | } |
446e4a64 | 429 | EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); |
ef53a115 | 430 | |
6660de56 MCC |
431 | /** |
432 | * ir_keyup() - generates input event to cleanup a key press | |
a374fef4 | 433 | * @ir: the struct ir_input_dev descriptor of the device |
6660de56 | 434 | * |
a374fef4 DH |
435 | * This routine is used to signal that a key has been released on the |
436 | * remote control. It reports a keyup input event via input_report_key(). | |
437 | */ | |
ee089405 | 438 | void ir_keyup(struct ir_input_dev *ir) |
a374fef4 DH |
439 | { |
440 | if (!ir->keypressed) | |
441 | return; | |
442 | ||
443 | IR_dprintk(1, "keyup key 0x%04x\n", ir->last_keycode); | |
444 | input_report_key(ir->input_dev, ir->last_keycode, 0); | |
445 | input_sync(ir->input_dev); | |
446 | ir->keypressed = false; | |
447 | } | |
ee089405 | 448 | EXPORT_SYMBOL_GPL(ir_keyup); |
a374fef4 DH |
449 | |
450 | /** | |
451 | * ir_timer_keyup() - generates a keyup event after a timeout | |
452 | * @cookie: a pointer to struct ir_input_dev passed to setup_timer() | |
453 | * | |
454 | * This routine will generate a keyup event some time after a keydown event | |
455 | * is generated when no further activity has been detected. | |
6660de56 | 456 | */ |
a374fef4 | 457 | static void ir_timer_keyup(unsigned long cookie) |
6660de56 | 458 | { |
a374fef4 DH |
459 | struct ir_input_dev *ir = (struct ir_input_dev *)cookie; |
460 | unsigned long flags; | |
461 | ||
462 | /* | |
463 | * ir->keyup_jiffies is used to prevent a race condition if a | |
464 | * hardware interrupt occurs at this point and the keyup timer | |
465 | * event is moved further into the future as a result. | |
466 | * | |
467 | * The timer will then be reactivated and this function called | |
468 | * again in the future. We need to exit gracefully in that case | |
469 | * to allow the input subsystem to do its auto-repeat magic or | |
470 | * a keyup event might follow immediately after the keydown. | |
471 | */ | |
472 | spin_lock_irqsave(&ir->keylock, flags); | |
e0172fd3 | 473 | if (time_is_before_eq_jiffies(ir->keyup_jiffies)) |
a374fef4 DH |
474 | ir_keyup(ir); |
475 | spin_unlock_irqrestore(&ir->keylock, flags); | |
476 | } | |
477 | ||
478 | /** | |
479 | * ir_repeat() - notifies the IR core that a key is still pressed | |
480 | * @dev: the struct input_dev descriptor of the device | |
481 | * | |
482 | * This routine is used by IR decoders when a repeat message which does | |
483 | * not include the necessary bits to reproduce the scancode has been | |
484 | * received. | |
485 | */ | |
486 | void ir_repeat(struct input_dev *dev) | |
487 | { | |
488 | unsigned long flags; | |
6660de56 MCC |
489 | struct ir_input_dev *ir = input_get_drvdata(dev); |
490 | ||
a374fef4 DH |
491 | spin_lock_irqsave(&ir->keylock, flags); |
492 | ||
ed4d3876 ML |
493 | input_event(dev, EV_MSC, MSC_SCAN, ir->last_scancode); |
494 | ||
6660de56 | 495 | if (!ir->keypressed) |
a374fef4 | 496 | goto out; |
6660de56 | 497 | |
a374fef4 DH |
498 | ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); |
499 | mod_timer(&ir->timer_keyup, ir->keyup_jiffies); | |
500 | ||
501 | out: | |
502 | spin_unlock_irqrestore(&ir->keylock, flags); | |
6660de56 | 503 | } |
a374fef4 | 504 | EXPORT_SYMBOL_GPL(ir_repeat); |
6660de56 MCC |
505 | |
506 | /** | |
507 | * ir_keydown() - generates input event for a key press | |
a374fef4 DH |
508 | * @dev: the struct input_dev descriptor of the device |
509 | * @scancode: the scancode that we're seeking | |
510 | * @toggle: the toggle value (protocol dependent, if the protocol doesn't | |
511 | * support toggle values, this should be set to zero) | |
6660de56 MCC |
512 | * |
513 | * This routine is used by the input routines when a key is pressed at the | |
514 | * IR. It gets the keycode for a scancode and reports an input event via | |
515 | * input_report_key(). | |
516 | */ | |
a374fef4 | 517 | void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) |
6660de56 | 518 | { |
a374fef4 | 519 | unsigned long flags; |
6660de56 MCC |
520 | struct ir_input_dev *ir = input_get_drvdata(dev); |
521 | ||
522 | u32 keycode = ir_g_keycode_from_table(dev, scancode); | |
523 | ||
a374fef4 | 524 | spin_lock_irqsave(&ir->keylock, flags); |
6660de56 | 525 | |
ed4d3876 ML |
526 | input_event(dev, EV_MSC, MSC_SCAN, scancode); |
527 | ||
a374fef4 DH |
528 | /* Repeat event? */ |
529 | if (ir->keypressed && | |
530 | ir->last_scancode == scancode && | |
531 | ir->last_toggle == toggle) | |
532 | goto set_timer; | |
6660de56 | 533 | |
a374fef4 DH |
534 | /* Release old keypress */ |
535 | ir_keyup(ir); | |
6660de56 | 536 | |
a374fef4 DH |
537 | ir->last_scancode = scancode; |
538 | ir->last_toggle = toggle; | |
539 | ir->last_keycode = keycode; | |
540 | ||
ed4d3876 | 541 | |
a374fef4 DH |
542 | if (keycode == KEY_RESERVED) |
543 | goto out; | |
6660de56 | 544 | |
ed4d3876 | 545 | |
a374fef4 DH |
546 | /* Register a keypress */ |
547 | ir->keypressed = true; | |
548 | IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", | |
549 | dev->name, keycode, scancode); | |
550 | input_report_key(dev, ir->last_keycode, 1); | |
6660de56 MCC |
551 | input_sync(dev); |
552 | ||
a374fef4 DH |
553 | set_timer: |
554 | ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); | |
555 | mod_timer(&ir->timer_keyup, ir->keyup_jiffies); | |
556 | out: | |
557 | spin_unlock_irqrestore(&ir->keylock, flags); | |
6660de56 MCC |
558 | } |
559 | EXPORT_SYMBOL_GPL(ir_keydown); | |
560 | ||
716aab44 MCC |
561 | static int ir_open(struct input_dev *input_dev) |
562 | { | |
563 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | |
564 | ||
565 | return ir_dev->props->open(ir_dev->props->priv); | |
566 | } | |
567 | ||
568 | static void ir_close(struct input_dev *input_dev) | |
569 | { | |
570 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | |
571 | ||
572 | ir_dev->props->close(ir_dev->props->priv); | |
573 | } | |
6660de56 | 574 | |
ef53a115 | 575 | /** |
b2245ba1 | 576 | * __ir_input_register() - sets the IR keycode table and add the handlers |
ef53a115 MCC |
577 | * for keymap table get/set |
578 | * @input_dev: the struct input_dev descriptor of the device | |
579 | * @rc_tab: the struct ir_scancode_table table of scancode/keymap | |
580 | * | |
d4b778d3 MCC |
581 | * This routine is used to initialize the input infrastructure |
582 | * to work with an IR. | |
583 | * It will register the input/evdev interface for the device and | |
584 | * register the syfs code for IR class | |
ef53a115 | 585 | */ |
b2245ba1 | 586 | int __ir_input_register(struct input_dev *input_dev, |
e93854da | 587 | const struct ir_scancode_table *rc_tab, |
4a702ebf | 588 | struct ir_dev_props *props, |
727e625c | 589 | const char *driver_name) |
ef53a115 | 590 | { |
75543cce | 591 | struct ir_input_dev *ir_dev; |
b3074c0a | 592 | int rc; |
ef53a115 MCC |
593 | |
594 | if (rc_tab->scan == NULL || !rc_tab->size) | |
595 | return -EINVAL; | |
596 | ||
75543cce MCC |
597 | ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL); |
598 | if (!ir_dev) | |
599 | return -ENOMEM; | |
600 | ||
b3074c0a DH |
601 | ir_dev->driver_name = kasprintf(GFP_KERNEL, "%s", driver_name); |
602 | if (!ir_dev->driver_name) { | |
603 | rc = -ENOMEM; | |
604 | goto out_dev; | |
605 | } | |
75543cce | 606 | |
9f470095 DT |
607 | input_dev->getkeycode_new = ir_getkeycode; |
608 | input_dev->setkeycode_new = ir_setkeycode; | |
b3074c0a | 609 | input_set_drvdata(input_dev, ir_dev); |
a374fef4 | 610 | ir_dev->input_dev = input_dev; |
b3074c0a DH |
611 | |
612 | spin_lock_init(&ir_dev->rc_tab.lock); | |
a374fef4 DH |
613 | spin_lock_init(&ir_dev->keylock); |
614 | setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev); | |
615 | ||
9dfe4e83 MCC |
616 | if (props) { |
617 | ir_dev->props = props; | |
618 | if (props->open) | |
619 | input_dev->open = ir_open; | |
620 | if (props->close) | |
621 | input_dev->close = ir_close; | |
622 | } | |
b3074c0a | 623 | |
b3074c0a | 624 | set_bit(EV_KEY, input_dev->evbit); |
a374fef4 | 625 | set_bit(EV_REP, input_dev->evbit); |
ed4d3876 ML |
626 | set_bit(EV_MSC, input_dev->evbit); |
627 | set_bit(MSC_SCAN, input_dev->mscbit); | |
a374fef4 | 628 | |
9f470095 DT |
629 | rc = ir_setkeytable(ir_dev, rc_tab); |
630 | if (rc) | |
631 | goto out_name; | |
75543cce | 632 | |
4714eda8 | 633 | rc = ir_register_class(input_dev); |
945cdfa2 | 634 | if (rc < 0) |
b3074c0a | 635 | goto out_table; |
579e7d60 | 636 | |
84b14f18 IL |
637 | if (ir_dev->props) |
638 | if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) { | |
639 | rc = ir_raw_event_register(input_dev); | |
640 | if (rc < 0) | |
641 | goto out_event; | |
642 | } | |
626cf697 | 643 | |
58b3dd44 | 644 | rc = ir_register_input(input_dev); |
991369e3 MCC |
645 | if (rc < 0) |
646 | goto out_event; | |
58b3dd44 | 647 | |
844a9e93 MCC |
648 | IR_dprintk(1, "Registered input device on %s for %s remote%s.\n", |
649 | driver_name, rc_tab->name, | |
ede67a30 DC |
650 | (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ? |
651 | " in raw mode" : ""); | |
35438946 | 652 | |
04cab131 MCC |
653 | /* |
654 | * Default delay of 250ms is too short for some protocols, expecially | |
655 | * since the timeout is currently set to 250ms. Increase it to 500ms, | |
656 | * to avoid wrong repetition of the keycodes. | |
657 | */ | |
658 | input_dev->rep[REP_DELAY] = 500; | |
659 | ||
4714eda8 MCC |
660 | return 0; |
661 | ||
626cf697 MCC |
662 | out_event: |
663 | ir_unregister_class(input_dev); | |
b3074c0a | 664 | out_table: |
9f470095 | 665 | ir_free_table(&ir_dev->rc_tab); |
b3074c0a DH |
666 | out_name: |
667 | kfree(ir_dev->driver_name); | |
668 | out_dev: | |
4714eda8 | 669 | kfree(ir_dev); |
579e7d60 | 670 | return rc; |
ef53a115 | 671 | } |
b2245ba1 | 672 | EXPORT_SYMBOL_GPL(__ir_input_register); |
f6fc5049 | 673 | |
d4b778d3 MCC |
674 | /** |
675 | * ir_input_unregister() - unregisters IR and frees resources | |
676 | * @input_dev: the struct input_dev descriptor of the device | |
677 | ||
678 | * This routine is used to free memory and de-register interfaces. | |
679 | */ | |
626cf697 | 680 | void ir_input_unregister(struct input_dev *input_dev) |
f6fc5049 | 681 | { |
626cf697 | 682 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); |
f6fc5049 | 683 | |
579e7d60 | 684 | if (!ir_dev) |
05395a3d MCC |
685 | return; |
686 | ||
f6fc5049 | 687 | IR_dprintk(1, "Freed keycode table\n"); |
626cf697 | 688 | |
a374fef4 | 689 | del_timer_sync(&ir_dev->timer_keyup); |
84b14f18 IL |
690 | if (ir_dev->props) |
691 | if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) | |
692 | ir_raw_event_unregister(input_dev); | |
693 | ||
9f470095 | 694 | ir_free_table(&ir_dev->rc_tab); |
75543cce | 695 | |
626cf697 | 696 | ir_unregister_class(input_dev); |
4714eda8 | 697 | |
b3074c0a | 698 | kfree(ir_dev->driver_name); |
75543cce | 699 | kfree(ir_dev); |
f6fc5049 | 700 | } |
38ef6aa8 | 701 | EXPORT_SYMBOL_GPL(ir_input_unregister); |
f6fc5049 | 702 | |
446e4a64 MCC |
703 | int ir_core_debug; /* ir_debug level (0,1,2) */ |
704 | EXPORT_SYMBOL_GPL(ir_core_debug); | |
705 | module_param_named(debug, ir_core_debug, int, 0644); | |
706 | ||
707 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | |
708 | MODULE_LICENSE("GPL"); |