Commit | Line | Data |
---|---|---|
bc2a6c57 | 1 | /* rc-core.c - handle IR scancode->keycode tables |
ef53a115 | 2 | * |
bc2a6c57 | 3 | * Copyright (C) 2009-2010 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 | ||
6bda9644 | 15 | #include <media/rc-core.h> |
631493ec MCC |
16 | #include <linux/spinlock.h> |
17 | #include <linux/delay.h> | |
882ead32 | 18 | #include <linux/input.h> |
5a0e3ad6 | 19 | #include <linux/slab.h> |
bc2a6c57 | 20 | #include <linux/device.h> |
f62de675 | 21 | #include "rc-core-priv.h" |
ef53a115 | 22 | |
b3074c0a DH |
23 | /* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */ |
24 | #define IR_TAB_MIN_SIZE 256 | |
25 | #define IR_TAB_MAX_SIZE 8192 | |
f6fc5049 | 26 | |
a374fef4 DH |
27 | /* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */ |
28 | #define IR_KEYPRESS_TIMEOUT 250 | |
29 | ||
4c7b355d | 30 | /* Used to keep track of known keymaps */ |
631493ec MCC |
31 | static LIST_HEAD(rc_map_list); |
32 | static DEFINE_SPINLOCK(rc_map_lock); | |
33 | ||
d100e659 | 34 | static struct rc_map_list *seek_rc_map(const char *name) |
631493ec | 35 | { |
d100e659 | 36 | struct rc_map_list *map = NULL; |
631493ec MCC |
37 | |
38 | spin_lock(&rc_map_lock); | |
39 | list_for_each_entry(map, &rc_map_list, list) { | |
40 | if (!strcmp(name, map->map.name)) { | |
41 | spin_unlock(&rc_map_lock); | |
42 | return map; | |
43 | } | |
44 | } | |
45 | spin_unlock(&rc_map_lock); | |
46 | ||
47 | return NULL; | |
48 | } | |
49 | ||
d100e659 | 50 | struct rc_map *rc_map_get(const char *name) |
631493ec MCC |
51 | { |
52 | ||
d100e659 | 53 | struct rc_map_list *map; |
631493ec MCC |
54 | |
55 | map = seek_rc_map(name); | |
56 | #ifdef MODULE | |
57 | if (!map) { | |
58 | int rc = request_module(name); | |
59 | if (rc < 0) { | |
60 | printk(KERN_ERR "Couldn't load IR keymap %s\n", name); | |
61 | return NULL; | |
62 | } | |
63 | msleep(20); /* Give some time for IR to register */ | |
64 | ||
65 | map = seek_rc_map(name); | |
66 | } | |
67 | #endif | |
68 | if (!map) { | |
69 | printk(KERN_ERR "IR keymap %s not found\n", name); | |
70 | return NULL; | |
71 | } | |
72 | ||
73 | printk(KERN_INFO "Registered IR keymap %s\n", map->map.name); | |
74 | ||
75 | return &map->map; | |
76 | } | |
d100e659 | 77 | EXPORT_SYMBOL_GPL(rc_map_get); |
631493ec | 78 | |
d100e659 | 79 | int rc_map_register(struct rc_map_list *map) |
631493ec MCC |
80 | { |
81 | spin_lock(&rc_map_lock); | |
82 | list_add_tail(&map->list, &rc_map_list); | |
83 | spin_unlock(&rc_map_lock); | |
84 | return 0; | |
85 | } | |
d100e659 | 86 | EXPORT_SYMBOL_GPL(rc_map_register); |
631493ec | 87 | |
d100e659 | 88 | void rc_map_unregister(struct rc_map_list *map) |
631493ec MCC |
89 | { |
90 | spin_lock(&rc_map_lock); | |
91 | list_del(&map->list); | |
92 | spin_unlock(&rc_map_lock); | |
93 | } | |
d100e659 | 94 | EXPORT_SYMBOL_GPL(rc_map_unregister); |
631493ec MCC |
95 | |
96 | ||
2f4f58d6 | 97 | static struct rc_map_table empty[] = { |
631493ec MCC |
98 | { 0x2a, KEY_COFFEE }, |
99 | }; | |
100 | ||
d100e659 | 101 | static struct rc_map_list empty_map = { |
631493ec MCC |
102 | .map = { |
103 | .scan = empty, | |
104 | .size = ARRAY_SIZE(empty), | |
52b66144 | 105 | .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ |
631493ec MCC |
106 | .name = RC_MAP_EMPTY, |
107 | } | |
108 | }; | |
109 | ||
9f470095 DT |
110 | /** |
111 | * ir_create_table() - initializes a scancode table | |
b088ba65 | 112 | * @rc_map: the rc_map to initialize |
9f470095 | 113 | * @name: name to assign to the table |
52b66144 | 114 | * @rc_type: ir type to assign to the new table |
9f470095 DT |
115 | * @size: initial size of the table |
116 | * @return: zero on success or a negative error code | |
117 | * | |
b088ba65 | 118 | * This routine will initialize the rc_map and will allocate |
d8b4b582 | 119 | * memory to hold at least the specified number of elements. |
9f470095 | 120 | */ |
b088ba65 | 121 | static int ir_create_table(struct rc_map *rc_map, |
52b66144 | 122 | const char *name, u64 rc_type, size_t size) |
9f470095 | 123 | { |
b088ba65 MCC |
124 | rc_map->name = name; |
125 | rc_map->rc_type = rc_type; | |
2f4f58d6 MCC |
126 | rc_map->alloc = roundup_pow_of_two(size * sizeof(struct rc_map_table)); |
127 | rc_map->size = rc_map->alloc / sizeof(struct rc_map_table); | |
b088ba65 MCC |
128 | rc_map->scan = kmalloc(rc_map->alloc, GFP_KERNEL); |
129 | if (!rc_map->scan) | |
9f470095 DT |
130 | return -ENOMEM; |
131 | ||
132 | IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", | |
b088ba65 | 133 | rc_map->size, rc_map->alloc); |
9f470095 DT |
134 | return 0; |
135 | } | |
136 | ||
137 | /** | |
138 | * ir_free_table() - frees memory allocated by a scancode table | |
b088ba65 | 139 | * @rc_map: the table whose mappings need to be freed |
9f470095 DT |
140 | * |
141 | * This routine will free memory alloctaed for key mappings used by given | |
142 | * scancode table. | |
143 | */ | |
b088ba65 | 144 | static void ir_free_table(struct rc_map *rc_map) |
9f470095 | 145 | { |
b088ba65 MCC |
146 | rc_map->size = 0; |
147 | kfree(rc_map->scan); | |
148 | rc_map->scan = NULL; | |
9f470095 DT |
149 | } |
150 | ||
7fee03e4 | 151 | /** |
b3074c0a | 152 | * ir_resize_table() - resizes a scancode table if necessary |
b088ba65 | 153 | * @rc_map: the rc_map to resize |
9f470095 | 154 | * @gfp_flags: gfp flags to use when allocating memory |
b3074c0a | 155 | * @return: zero on success or a negative error code |
7fee03e4 | 156 | * |
b088ba65 | 157 | * This routine will shrink the rc_map if it has lots of |
b3074c0a | 158 | * unused entries and grow it if it is full. |
7fee03e4 | 159 | */ |
b088ba65 | 160 | static int ir_resize_table(struct rc_map *rc_map, gfp_t gfp_flags) |
7fee03e4 | 161 | { |
b088ba65 | 162 | unsigned int oldalloc = rc_map->alloc; |
b3074c0a | 163 | unsigned int newalloc = oldalloc; |
2f4f58d6 MCC |
164 | struct rc_map_table *oldscan = rc_map->scan; |
165 | struct rc_map_table *newscan; | |
b3074c0a | 166 | |
b088ba65 | 167 | if (rc_map->size == rc_map->len) { |
b3074c0a | 168 | /* All entries in use -> grow keytable */ |
b088ba65 | 169 | if (rc_map->alloc >= IR_TAB_MAX_SIZE) |
b3074c0a | 170 | return -ENOMEM; |
7fee03e4 | 171 | |
b3074c0a DH |
172 | newalloc *= 2; |
173 | IR_dprintk(1, "Growing table to %u bytes\n", newalloc); | |
174 | } | |
7fee03e4 | 175 | |
b088ba65 | 176 | if ((rc_map->len * 3 < rc_map->size) && (oldalloc > IR_TAB_MIN_SIZE)) { |
b3074c0a DH |
177 | /* Less than 1/3 of entries in use -> shrink keytable */ |
178 | newalloc /= 2; | |
179 | IR_dprintk(1, "Shrinking table to %u bytes\n", newalloc); | |
180 | } | |
7fee03e4 | 181 | |
b3074c0a DH |
182 | if (newalloc == oldalloc) |
183 | return 0; | |
7fee03e4 | 184 | |
9f470095 | 185 | newscan = kmalloc(newalloc, gfp_flags); |
b3074c0a DH |
186 | if (!newscan) { |
187 | IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc); | |
188 | return -ENOMEM; | |
189 | } | |
7fee03e4 | 190 | |
2f4f58d6 | 191 | memcpy(newscan, rc_map->scan, rc_map->len * sizeof(struct rc_map_table)); |
b088ba65 MCC |
192 | rc_map->scan = newscan; |
193 | rc_map->alloc = newalloc; | |
2f4f58d6 | 194 | rc_map->size = rc_map->alloc / sizeof(struct rc_map_table); |
b3074c0a DH |
195 | kfree(oldscan); |
196 | return 0; | |
7fee03e4 MCC |
197 | } |
198 | ||
f6fc5049 | 199 | /** |
9f470095 | 200 | * ir_update_mapping() - set a keycode in the scancode->keycode table |
d8b4b582 | 201 | * @dev: the struct rc_dev device descriptor |
b088ba65 | 202 | * @rc_map: scancode table to be adjusted |
9f470095 DT |
203 | * @index: index of the mapping that needs to be updated |
204 | * @keycode: the desired keycode | |
205 | * @return: previous keycode assigned to the mapping | |
206 | * | |
d8b4b582 | 207 | * This routine is used to update scancode->keycode mapping at given |
9f470095 DT |
208 | * position. |
209 | */ | |
d8b4b582 | 210 | static unsigned int ir_update_mapping(struct rc_dev *dev, |
b088ba65 | 211 | struct rc_map *rc_map, |
9f470095 DT |
212 | unsigned int index, |
213 | unsigned int new_keycode) | |
214 | { | |
b088ba65 | 215 | int old_keycode = rc_map->scan[index].keycode; |
9f470095 DT |
216 | int i; |
217 | ||
218 | /* Did the user wish to remove the mapping? */ | |
219 | if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) { | |
220 | IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", | |
b088ba65 MCC |
221 | index, rc_map->scan[index].scancode); |
222 | rc_map->len--; | |
223 | memmove(&rc_map->scan[index], &rc_map->scan[index+ 1], | |
2f4f58d6 | 224 | (rc_map->len - index) * sizeof(struct rc_map_table)); |
9f470095 DT |
225 | } else { |
226 | IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n", | |
227 | index, | |
228 | old_keycode == KEY_RESERVED ? "New" : "Replacing", | |
b088ba65 MCC |
229 | rc_map->scan[index].scancode, new_keycode); |
230 | rc_map->scan[index].keycode = new_keycode; | |
d8b4b582 | 231 | __set_bit(new_keycode, dev->input_dev->keybit); |
9f470095 DT |
232 | } |
233 | ||
234 | if (old_keycode != KEY_RESERVED) { | |
235 | /* A previous mapping was updated... */ | |
d8b4b582 | 236 | __clear_bit(old_keycode, dev->input_dev->keybit); |
9f470095 | 237 | /* ... but another scancode might use the same keycode */ |
b088ba65 MCC |
238 | for (i = 0; i < rc_map->len; i++) { |
239 | if (rc_map->scan[i].keycode == old_keycode) { | |
d8b4b582 | 240 | __set_bit(old_keycode, dev->input_dev->keybit); |
9f470095 DT |
241 | break; |
242 | } | |
243 | } | |
244 | ||
245 | /* Possibly shrink the keytable, failure is not a problem */ | |
b088ba65 | 246 | ir_resize_table(rc_map, GFP_ATOMIC); |
9f470095 DT |
247 | } |
248 | ||
249 | return old_keycode; | |
250 | } | |
251 | ||
252 | /** | |
4c7b355d | 253 | * ir_establish_scancode() - set a keycode in the scancode->keycode table |
d8b4b582 | 254 | * @dev: the struct rc_dev device descriptor |
b088ba65 | 255 | * @rc_map: scancode table to be searched |
9f470095 DT |
256 | * @scancode: the desired scancode |
257 | * @resize: controls whether we allowed to resize the table to | |
258 | * accomodate not yet present scancodes | |
259 | * @return: index of the mapping containing scancode in question | |
260 | * or -1U in case of failure. | |
f6fc5049 | 261 | * |
b088ba65 | 262 | * This routine is used to locate given scancode in rc_map. |
9f470095 DT |
263 | * If scancode is not yet present the routine will allocate a new slot |
264 | * for it. | |
f6fc5049 | 265 | */ |
d8b4b582 | 266 | static unsigned int ir_establish_scancode(struct rc_dev *dev, |
b088ba65 | 267 | struct rc_map *rc_map, |
9f470095 DT |
268 | unsigned int scancode, |
269 | bool resize) | |
f6fc5049 | 270 | { |
b3074c0a | 271 | unsigned int i; |
9dfe4e83 MCC |
272 | |
273 | /* | |
274 | * Unfortunately, some hardware-based IR decoders don't provide | |
275 | * all bits for the complete IR code. In general, they provide only | |
276 | * the command part of the IR code. Yet, as it is possible to replace | |
277 | * the provided IR with another one, it is needed to allow loading | |
d8b4b582 DH |
278 | * IR tables from other remotes. So, we support specifying a mask to |
279 | * indicate the valid bits of the scancodes. | |
9dfe4e83 | 280 | */ |
d8b4b582 DH |
281 | if (dev->scanmask) |
282 | scancode &= dev->scanmask; | |
b3074c0a DH |
283 | |
284 | /* First check if we already have a mapping for this ir command */ | |
b088ba65 MCC |
285 | for (i = 0; i < rc_map->len; i++) { |
286 | if (rc_map->scan[i].scancode == scancode) | |
9f470095 DT |
287 | return i; |
288 | ||
b3074c0a | 289 | /* Keytable is sorted from lowest to highest scancode */ |
b088ba65 | 290 | if (rc_map->scan[i].scancode >= scancode) |
b3074c0a | 291 | break; |
b3074c0a | 292 | } |
f6fc5049 | 293 | |
9f470095 | 294 | /* No previous mapping found, we might need to grow the table */ |
b088ba65 MCC |
295 | if (rc_map->size == rc_map->len) { |
296 | if (!resize || ir_resize_table(rc_map, GFP_ATOMIC)) | |
9f470095 DT |
297 | return -1U; |
298 | } | |
35438946 | 299 | |
9f470095 | 300 | /* i is the proper index to insert our new keycode */ |
b088ba65 MCC |
301 | if (i < rc_map->len) |
302 | memmove(&rc_map->scan[i + 1], &rc_map->scan[i], | |
2f4f58d6 | 303 | (rc_map->len - i) * sizeof(struct rc_map_table)); |
b088ba65 MCC |
304 | rc_map->scan[i].scancode = scancode; |
305 | rc_map->scan[i].keycode = KEY_RESERVED; | |
306 | rc_map->len++; | |
f6fc5049 | 307 | |
9f470095 | 308 | return i; |
f6fc5049 MCC |
309 | } |
310 | ||
ef53a115 | 311 | /** |
b3074c0a | 312 | * ir_setkeycode() - set a keycode in the scancode->keycode table |
d8b4b582 | 313 | * @idev: the struct input_dev device descriptor |
ef53a115 | 314 | * @scancode: the desired scancode |
b3074c0a DH |
315 | * @keycode: result |
316 | * @return: -EINVAL if the keycode could not be inserted, otherwise zero. | |
ef53a115 | 317 | * |
b3074c0a | 318 | * This routine is used to handle evdev EVIOCSKEY ioctl. |
ef53a115 | 319 | */ |
d8b4b582 | 320 | static int ir_setkeycode(struct input_dev *idev, |
9f470095 DT |
321 | const struct input_keymap_entry *ke, |
322 | unsigned int *old_keycode) | |
ef53a115 | 323 | { |
d8b4b582 | 324 | struct rc_dev *rdev = input_get_drvdata(idev); |
b088ba65 | 325 | struct rc_map *rc_map = &rdev->rc_map; |
9f470095 DT |
326 | unsigned int index; |
327 | unsigned int scancode; | |
328 | int retval; | |
329 | unsigned long flags; | |
ef53a115 | 330 | |
b088ba65 | 331 | spin_lock_irqsave(&rc_map->lock, flags); |
9f470095 DT |
332 | |
333 | if (ke->flags & INPUT_KEYMAP_BY_INDEX) { | |
334 | index = ke->index; | |
b088ba65 | 335 | if (index >= rc_map->len) { |
9f470095 DT |
336 | retval = -EINVAL; |
337 | goto out; | |
338 | } | |
339 | } else { | |
340 | retval = input_scancode_to_scalar(ke, &scancode); | |
341 | if (retval) | |
342 | goto out; | |
343 | ||
b088ba65 MCC |
344 | index = ir_establish_scancode(rdev, rc_map, scancode, true); |
345 | if (index >= rc_map->len) { | |
9f470095 DT |
346 | retval = -ENOMEM; |
347 | goto out; | |
348 | } | |
349 | } | |
350 | ||
b088ba65 | 351 | *old_keycode = ir_update_mapping(rdev, rc_map, index, ke->keycode); |
9f470095 DT |
352 | |
353 | out: | |
b088ba65 | 354 | spin_unlock_irqrestore(&rc_map->lock, flags); |
9f470095 | 355 | return retval; |
e97f4677 MCC |
356 | } |
357 | ||
358 | /** | |
b3074c0a | 359 | * ir_setkeytable() - sets several entries in the scancode->keycode table |
d8b4b582 | 360 | * @dev: the struct rc_dev device descriptor |
b088ba65 MCC |
361 | * @to: the struct rc_map to copy entries to |
362 | * @from: the struct rc_map to copy entries from | |
9f470095 | 363 | * @return: -ENOMEM if all keycodes could not be inserted, otherwise zero. |
e97f4677 | 364 | * |
b3074c0a | 365 | * This routine is used to handle table initialization. |
e97f4677 | 366 | */ |
d8b4b582 | 367 | static int ir_setkeytable(struct rc_dev *dev, |
b088ba65 | 368 | const struct rc_map *from) |
e97f4677 | 369 | { |
b088ba65 | 370 | struct rc_map *rc_map = &dev->rc_map; |
9f470095 DT |
371 | unsigned int i, index; |
372 | int rc; | |
373 | ||
b088ba65 | 374 | rc = ir_create_table(rc_map, from->name, |
52b66144 | 375 | from->rc_type, from->size); |
9f470095 DT |
376 | if (rc) |
377 | return rc; | |
378 | ||
379 | IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", | |
b088ba65 | 380 | rc_map->size, rc_map->alloc); |
e97f4677 | 381 | |
b3074c0a | 382 | for (i = 0; i < from->size; i++) { |
b088ba65 | 383 | index = ir_establish_scancode(dev, rc_map, |
9f470095 | 384 | from->scan[i].scancode, false); |
b088ba65 | 385 | if (index >= rc_map->len) { |
9f470095 | 386 | rc = -ENOMEM; |
b3074c0a | 387 | break; |
9f470095 DT |
388 | } |
389 | ||
b088ba65 | 390 | ir_update_mapping(dev, rc_map, index, |
9f470095 | 391 | from->scan[i].keycode); |
e97f4677 | 392 | } |
9f470095 DT |
393 | |
394 | if (rc) | |
b088ba65 | 395 | ir_free_table(rc_map); |
9f470095 | 396 | |
b3074c0a | 397 | return rc; |
ef53a115 MCC |
398 | } |
399 | ||
9f470095 DT |
400 | /** |
401 | * ir_lookup_by_scancode() - locate mapping by scancode | |
b088ba65 | 402 | * @rc_map: the struct rc_map to search |
9f470095 DT |
403 | * @scancode: scancode to look for in the table |
404 | * @return: index in the table, -1U if not found | |
405 | * | |
406 | * This routine performs binary search in RC keykeymap table for | |
407 | * given scancode. | |
408 | */ | |
b088ba65 | 409 | static unsigned int ir_lookup_by_scancode(const struct rc_map *rc_map, |
9f470095 DT |
410 | unsigned int scancode) |
411 | { | |
0d07025e | 412 | int start = 0; |
b088ba65 | 413 | int end = rc_map->len - 1; |
0d07025e | 414 | int mid; |
9f470095 DT |
415 | |
416 | while (start <= end) { | |
417 | mid = (start + end) / 2; | |
b088ba65 | 418 | if (rc_map->scan[mid].scancode < scancode) |
9f470095 | 419 | start = mid + 1; |
b088ba65 | 420 | else if (rc_map->scan[mid].scancode > scancode) |
9f470095 DT |
421 | end = mid - 1; |
422 | else | |
423 | return mid; | |
424 | } | |
425 | ||
426 | return -1U; | |
427 | } | |
428 | ||
ef53a115 | 429 | /** |
b3074c0a | 430 | * ir_getkeycode() - get a keycode from the scancode->keycode table |
d8b4b582 | 431 | * @idev: the struct input_dev device descriptor |
ef53a115 | 432 | * @scancode: the desired scancode |
b3074c0a DH |
433 | * @keycode: used to return the keycode, if found, or KEY_RESERVED |
434 | * @return: always returns zero. | |
ef53a115 | 435 | * |
b3074c0a | 436 | * This routine is used to handle evdev EVIOCGKEY ioctl. |
ef53a115 | 437 | */ |
d8b4b582 | 438 | static int ir_getkeycode(struct input_dev *idev, |
9f470095 | 439 | struct input_keymap_entry *ke) |
ef53a115 | 440 | { |
d8b4b582 | 441 | struct rc_dev *rdev = input_get_drvdata(idev); |
b088ba65 | 442 | struct rc_map *rc_map = &rdev->rc_map; |
2f4f58d6 | 443 | struct rc_map_table *entry; |
9f470095 DT |
444 | unsigned long flags; |
445 | unsigned int index; | |
446 | unsigned int scancode; | |
447 | int retval; | |
ef53a115 | 448 | |
b088ba65 | 449 | spin_lock_irqsave(&rc_map->lock, flags); |
9f470095 DT |
450 | |
451 | if (ke->flags & INPUT_KEYMAP_BY_INDEX) { | |
452 | index = ke->index; | |
453 | } else { | |
454 | retval = input_scancode_to_scalar(ke, &scancode); | |
455 | if (retval) | |
456 | goto out; | |
457 | ||
b088ba65 | 458 | index = ir_lookup_by_scancode(rc_map, scancode); |
9f470095 DT |
459 | } |
460 | ||
b088ba65 | 461 | if (index >= rc_map->len) { |
9f470095 DT |
462 | if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) |
463 | IR_dprintk(1, "unknown key for scancode 0x%04x\n", | |
464 | scancode); | |
465 | retval = -EINVAL; | |
466 | goto out; | |
e97f4677 MCC |
467 | } |
468 | ||
b088ba65 | 469 | entry = &rc_map->scan[index]; |
35438946 | 470 | |
9f470095 DT |
471 | ke->index = index; |
472 | ke->keycode = entry->keycode; | |
473 | ke->len = sizeof(entry->scancode); | |
474 | memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode)); | |
475 | ||
47c5ba53 DT |
476 | retval = 0; |
477 | ||
9f470095 | 478 | out: |
b088ba65 | 479 | spin_unlock_irqrestore(&rc_map->lock, flags); |
9f470095 | 480 | return retval; |
ef53a115 MCC |
481 | } |
482 | ||
483 | /** | |
ca86674b | 484 | * rc_g_keycode_from_table() - gets the keycode that corresponds to a scancode |
d8b4b582 DH |
485 | * @dev: the struct rc_dev descriptor of the device |
486 | * @scancode: the scancode to look for | |
487 | * @return: the corresponding keycode, or KEY_RESERVED | |
ef53a115 | 488 | * |
d8b4b582 DH |
489 | * This routine is used by drivers which need to convert a scancode to a |
490 | * keycode. Normally it should not be used since drivers should have no | |
491 | * interest in keycodes. | |
ef53a115 | 492 | */ |
ca86674b | 493 | u32 rc_g_keycode_from_table(struct rc_dev *dev, u32 scancode) |
ef53a115 | 494 | { |
b088ba65 | 495 | struct rc_map *rc_map = &dev->rc_map; |
9f470095 DT |
496 | unsigned int keycode; |
497 | unsigned int index; | |
498 | unsigned long flags; | |
499 | ||
b088ba65 | 500 | spin_lock_irqsave(&rc_map->lock, flags); |
9f470095 | 501 | |
b088ba65 MCC |
502 | index = ir_lookup_by_scancode(rc_map, scancode); |
503 | keycode = index < rc_map->len ? | |
504 | rc_map->scan[index].keycode : KEY_RESERVED; | |
9f470095 | 505 | |
b088ba65 | 506 | spin_unlock_irqrestore(&rc_map->lock, flags); |
ef53a115 | 507 | |
35438946 MCC |
508 | if (keycode != KEY_RESERVED) |
509 | IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", | |
d8b4b582 | 510 | dev->input_name, scancode, keycode); |
9f470095 | 511 | |
b3074c0a | 512 | return keycode; |
ef53a115 | 513 | } |
ca86674b | 514 | EXPORT_SYMBOL_GPL(rc_g_keycode_from_table); |
ef53a115 | 515 | |
6660de56 | 516 | /** |
62c65031 | 517 | * ir_do_keyup() - internal function to signal the release of a keypress |
d8b4b582 | 518 | * @dev: the struct rc_dev descriptor of the device |
6660de56 | 519 | * |
62c65031 DH |
520 | * This function is used internally to release a keypress, it must be |
521 | * called with keylock held. | |
a374fef4 | 522 | */ |
d8b4b582 | 523 | static void ir_do_keyup(struct rc_dev *dev) |
a374fef4 | 524 | { |
d8b4b582 | 525 | if (!dev->keypressed) |
a374fef4 DH |
526 | return; |
527 | ||
d8b4b582 DH |
528 | IR_dprintk(1, "keyup key 0x%04x\n", dev->last_keycode); |
529 | input_report_key(dev->input_dev, dev->last_keycode, 0); | |
530 | input_sync(dev->input_dev); | |
531 | dev->keypressed = false; | |
a374fef4 | 532 | } |
62c65031 DH |
533 | |
534 | /** | |
ca86674b | 535 | * rc_keyup() - signals the release of a keypress |
d8b4b582 | 536 | * @dev: the struct rc_dev descriptor of the device |
62c65031 DH |
537 | * |
538 | * This routine is used to signal that a key has been released on the | |
539 | * remote control. | |
540 | */ | |
ca86674b | 541 | void rc_keyup(struct rc_dev *dev) |
62c65031 DH |
542 | { |
543 | unsigned long flags; | |
62c65031 | 544 | |
d8b4b582 DH |
545 | spin_lock_irqsave(&dev->keylock, flags); |
546 | ir_do_keyup(dev); | |
547 | spin_unlock_irqrestore(&dev->keylock, flags); | |
62c65031 | 548 | } |
ca86674b | 549 | EXPORT_SYMBOL_GPL(rc_keyup); |
a374fef4 DH |
550 | |
551 | /** | |
552 | * ir_timer_keyup() - generates a keyup event after a timeout | |
d8b4b582 | 553 | * @cookie: a pointer to the struct rc_dev for the device |
a374fef4 DH |
554 | * |
555 | * This routine will generate a keyup event some time after a keydown event | |
556 | * is generated when no further activity has been detected. | |
6660de56 | 557 | */ |
a374fef4 | 558 | static void ir_timer_keyup(unsigned long cookie) |
6660de56 | 559 | { |
d8b4b582 | 560 | struct rc_dev *dev = (struct rc_dev *)cookie; |
a374fef4 DH |
561 | unsigned long flags; |
562 | ||
563 | /* | |
564 | * ir->keyup_jiffies is used to prevent a race condition if a | |
565 | * hardware interrupt occurs at this point and the keyup timer | |
566 | * event is moved further into the future as a result. | |
567 | * | |
568 | * The timer will then be reactivated and this function called | |
569 | * again in the future. We need to exit gracefully in that case | |
570 | * to allow the input subsystem to do its auto-repeat magic or | |
571 | * a keyup event might follow immediately after the keydown. | |
572 | */ | |
d8b4b582 DH |
573 | spin_lock_irqsave(&dev->keylock, flags); |
574 | if (time_is_before_eq_jiffies(dev->keyup_jiffies)) | |
575 | ir_do_keyup(dev); | |
576 | spin_unlock_irqrestore(&dev->keylock, flags); | |
a374fef4 DH |
577 | } |
578 | ||
579 | /** | |
ca86674b | 580 | * rc_repeat() - signals that a key is still pressed |
d8b4b582 | 581 | * @dev: the struct rc_dev descriptor of the device |
a374fef4 DH |
582 | * |
583 | * This routine is used by IR decoders when a repeat message which does | |
584 | * not include the necessary bits to reproduce the scancode has been | |
585 | * received. | |
586 | */ | |
ca86674b | 587 | void rc_repeat(struct rc_dev *dev) |
a374fef4 DH |
588 | { |
589 | unsigned long flags; | |
6660de56 | 590 | |
d8b4b582 | 591 | spin_lock_irqsave(&dev->keylock, flags); |
a374fef4 | 592 | |
d8b4b582 | 593 | input_event(dev->input_dev, EV_MSC, MSC_SCAN, dev->last_scancode); |
ed4d3876 | 594 | |
d8b4b582 | 595 | if (!dev->keypressed) |
a374fef4 | 596 | goto out; |
6660de56 | 597 | |
d8b4b582 DH |
598 | dev->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); |
599 | mod_timer(&dev->timer_keyup, dev->keyup_jiffies); | |
a374fef4 DH |
600 | |
601 | out: | |
d8b4b582 | 602 | spin_unlock_irqrestore(&dev->keylock, flags); |
6660de56 | 603 | } |
ca86674b | 604 | EXPORT_SYMBOL_GPL(rc_repeat); |
6660de56 MCC |
605 | |
606 | /** | |
62c65031 | 607 | * ir_do_keydown() - internal function to process a keypress |
d8b4b582 | 608 | * @dev: the struct rc_dev descriptor of the device |
62c65031 DH |
609 | * @scancode: the scancode of the keypress |
610 | * @keycode: the keycode of the keypress | |
611 | * @toggle: the toggle value of the keypress | |
6660de56 | 612 | * |
62c65031 DH |
613 | * This function is used internally to register a keypress, it must be |
614 | * called with keylock held. | |
6660de56 | 615 | */ |
d8b4b582 | 616 | static void ir_do_keydown(struct rc_dev *dev, int scancode, |
62c65031 | 617 | u32 keycode, u8 toggle) |
6660de56 | 618 | { |
d8b4b582 | 619 | input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode); |
ed4d3876 | 620 | |
a374fef4 | 621 | /* Repeat event? */ |
d8b4b582 DH |
622 | if (dev->keypressed && |
623 | dev->last_scancode == scancode && | |
624 | dev->last_toggle == toggle) | |
62c65031 | 625 | return; |
6660de56 | 626 | |
a374fef4 | 627 | /* Release old keypress */ |
d8b4b582 | 628 | ir_do_keyup(dev); |
6660de56 | 629 | |
d8b4b582 DH |
630 | dev->last_scancode = scancode; |
631 | dev->last_toggle = toggle; | |
632 | dev->last_keycode = keycode; | |
a374fef4 DH |
633 | |
634 | if (keycode == KEY_RESERVED) | |
62c65031 | 635 | return; |
ed4d3876 | 636 | |
a374fef4 | 637 | /* Register a keypress */ |
d8b4b582 | 638 | dev->keypressed = true; |
a374fef4 | 639 | IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", |
d8b4b582 DH |
640 | dev->input_name, keycode, scancode); |
641 | input_report_key(dev->input_dev, dev->last_keycode, 1); | |
642 | input_sync(dev->input_dev); | |
62c65031 | 643 | } |
6660de56 | 644 | |
62c65031 | 645 | /** |
ca86674b | 646 | * rc_keydown() - generates input event for a key press |
d8b4b582 | 647 | * @dev: the struct rc_dev descriptor of the device |
62c65031 DH |
648 | * @scancode: the scancode that we're seeking |
649 | * @toggle: the toggle value (protocol dependent, if the protocol doesn't | |
650 | * support toggle values, this should be set to zero) | |
651 | * | |
d8b4b582 DH |
652 | * This routine is used to signal that a key has been pressed on the |
653 | * remote control. | |
62c65031 | 654 | */ |
ca86674b | 655 | void rc_keydown(struct rc_dev *dev, int scancode, u8 toggle) |
62c65031 DH |
656 | { |
657 | unsigned long flags; | |
ca86674b | 658 | u32 keycode = rc_g_keycode_from_table(dev, scancode); |
62c65031 | 659 | |
d8b4b582 | 660 | spin_lock_irqsave(&dev->keylock, flags); |
62c65031 DH |
661 | ir_do_keydown(dev, scancode, keycode, toggle); |
662 | ||
d8b4b582 DH |
663 | if (dev->keypressed) { |
664 | dev->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); | |
665 | mod_timer(&dev->timer_keyup, dev->keyup_jiffies); | |
62c65031 | 666 | } |
d8b4b582 | 667 | spin_unlock_irqrestore(&dev->keylock, flags); |
6660de56 | 668 | } |
ca86674b | 669 | EXPORT_SYMBOL_GPL(rc_keydown); |
6660de56 | 670 | |
62c65031 | 671 | /** |
ca86674b | 672 | * rc_keydown_notimeout() - generates input event for a key press without |
62c65031 | 673 | * an automatic keyup event at a later time |
d8b4b582 | 674 | * @dev: the struct rc_dev descriptor of the device |
62c65031 DH |
675 | * @scancode: the scancode that we're seeking |
676 | * @toggle: the toggle value (protocol dependent, if the protocol doesn't | |
677 | * support toggle values, this should be set to zero) | |
678 | * | |
d8b4b582 | 679 | * This routine is used to signal that a key has been pressed on the |
ca86674b | 680 | * remote control. The driver must manually call rc_keyup() at a later stage. |
62c65031 | 681 | */ |
ca86674b | 682 | void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle) |
62c65031 DH |
683 | { |
684 | unsigned long flags; | |
ca86674b | 685 | u32 keycode = rc_g_keycode_from_table(dev, scancode); |
62c65031 | 686 | |
d8b4b582 | 687 | spin_lock_irqsave(&dev->keylock, flags); |
62c65031 | 688 | ir_do_keydown(dev, scancode, keycode, toggle); |
d8b4b582 | 689 | spin_unlock_irqrestore(&dev->keylock, flags); |
62c65031 | 690 | } |
ca86674b | 691 | EXPORT_SYMBOL_GPL(rc_keydown_notimeout); |
62c65031 | 692 | |
d8b4b582 | 693 | static int ir_open(struct input_dev *idev) |
ef53a115 | 694 | { |
d8b4b582 | 695 | struct rc_dev *rdev = input_get_drvdata(idev); |
75543cce | 696 | |
d8b4b582 | 697 | return rdev->open(rdev); |
ef53a115 | 698 | } |
d4b778d3 | 699 | |
d8b4b582 | 700 | static void ir_close(struct input_dev *idev) |
f6fc5049 | 701 | { |
d8b4b582 | 702 | struct rc_dev *rdev = input_get_drvdata(idev); |
626cf697 | 703 | |
d8b4b582 | 704 | rdev->close(rdev); |
f6fc5049 | 705 | } |
f6fc5049 | 706 | |
bc2a6c57 MCC |
707 | /* class for /sys/class/rc */ |
708 | static char *ir_devnode(struct device *dev, mode_t *mode) | |
709 | { | |
710 | return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev)); | |
711 | } | |
712 | ||
713 | static struct class ir_input_class = { | |
714 | .name = "rc", | |
715 | .devnode = ir_devnode, | |
716 | }; | |
717 | ||
718 | static struct { | |
719 | u64 type; | |
720 | char *name; | |
721 | } proto_names[] = { | |
52b66144 MCC |
722 | { RC_TYPE_UNKNOWN, "unknown" }, |
723 | { RC_TYPE_RC5, "rc-5" }, | |
724 | { RC_TYPE_NEC, "nec" }, | |
725 | { RC_TYPE_RC6, "rc-6" }, | |
726 | { RC_TYPE_JVC, "jvc" }, | |
727 | { RC_TYPE_SONY, "sony" }, | |
728 | { RC_TYPE_RC5_SZ, "rc-5-sz" }, | |
729 | { RC_TYPE_LIRC, "lirc" }, | |
bc2a6c57 MCC |
730 | }; |
731 | ||
732 | #define PROTO_NONE "none" | |
733 | ||
734 | /** | |
735 | * show_protocols() - shows the current IR protocol(s) | |
d8b4b582 | 736 | * @device: the device descriptor |
bc2a6c57 MCC |
737 | * @mattr: the device attribute struct (unused) |
738 | * @buf: a pointer to the output buffer | |
739 | * | |
740 | * This routine is a callback routine for input read the IR protocol type(s). | |
741 | * it is trigged by reading /sys/class/rc/rc?/protocols. | |
742 | * It returns the protocol names of supported protocols. | |
743 | * Enabled protocols are printed in brackets. | |
744 | */ | |
d8b4b582 | 745 | static ssize_t show_protocols(struct device *device, |
bc2a6c57 MCC |
746 | struct device_attribute *mattr, char *buf) |
747 | { | |
d8b4b582 | 748 | struct rc_dev *dev = to_rc_dev(device); |
bc2a6c57 MCC |
749 | u64 allowed, enabled; |
750 | char *tmp = buf; | |
751 | int i; | |
752 | ||
753 | /* Device is being removed */ | |
d8b4b582 | 754 | if (!dev) |
bc2a6c57 MCC |
755 | return -EINVAL; |
756 | ||
d8b4b582 | 757 | if (dev->driver_type == RC_DRIVER_SCANCODE) { |
b088ba65 | 758 | enabled = dev->rc_map.rc_type; |
d8b4b582 DH |
759 | allowed = dev->allowed_protos; |
760 | } else { | |
761 | enabled = dev->raw->enabled_protocols; | |
bc2a6c57 | 762 | allowed = ir_raw_get_allowed_protocols(); |
d8b4b582 | 763 | } |
bc2a6c57 MCC |
764 | |
765 | IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", | |
766 | (long long)allowed, | |
767 | (long long)enabled); | |
768 | ||
769 | for (i = 0; i < ARRAY_SIZE(proto_names); i++) { | |
770 | if (allowed & enabled & proto_names[i].type) | |
771 | tmp += sprintf(tmp, "[%s] ", proto_names[i].name); | |
772 | else if (allowed & proto_names[i].type) | |
773 | tmp += sprintf(tmp, "%s ", proto_names[i].name); | |
774 | } | |
775 | ||
776 | if (tmp != buf) | |
777 | tmp--; | |
778 | *tmp = '\n'; | |
779 | return tmp + 1 - buf; | |
780 | } | |
781 | ||
782 | /** | |
783 | * store_protocols() - changes the current IR protocol(s) | |
d8b4b582 | 784 | * @device: the device descriptor |
bc2a6c57 MCC |
785 | * @mattr: the device attribute struct (unused) |
786 | * @buf: a pointer to the input buffer | |
787 | * @len: length of the input buffer | |
788 | * | |
d8b4b582 | 789 | * This routine is for changing the IR protocol type. |
bc2a6c57 MCC |
790 | * It is trigged by writing to /sys/class/rc/rc?/protocols. |
791 | * Writing "+proto" will add a protocol to the list of enabled protocols. | |
792 | * Writing "-proto" will remove a protocol from the list of enabled protocols. | |
793 | * Writing "proto" will enable only "proto". | |
794 | * Writing "none" will disable all protocols. | |
795 | * Returns -EINVAL if an invalid protocol combination or unknown protocol name | |
796 | * is used, otherwise @len. | |
797 | */ | |
d8b4b582 | 798 | static ssize_t store_protocols(struct device *device, |
bc2a6c57 MCC |
799 | struct device_attribute *mattr, |
800 | const char *data, | |
801 | size_t len) | |
802 | { | |
d8b4b582 | 803 | struct rc_dev *dev = to_rc_dev(device); |
bc2a6c57 MCC |
804 | bool enable, disable; |
805 | const char *tmp; | |
806 | u64 type; | |
807 | u64 mask; | |
808 | int rc, i, count = 0; | |
809 | unsigned long flags; | |
810 | ||
811 | /* Device is being removed */ | |
d8b4b582 | 812 | if (!dev) |
bc2a6c57 MCC |
813 | return -EINVAL; |
814 | ||
d8b4b582 | 815 | if (dev->driver_type == RC_DRIVER_SCANCODE) |
b088ba65 | 816 | type = dev->rc_map.rc_type; |
d8b4b582 DH |
817 | else if (dev->raw) |
818 | type = dev->raw->enabled_protocols; | |
bc2a6c57 MCC |
819 | else { |
820 | IR_dprintk(1, "Protocol switching not supported\n"); | |
821 | return -EINVAL; | |
822 | } | |
823 | ||
824 | while ((tmp = strsep((char **) &data, " \n")) != NULL) { | |
825 | if (!*tmp) | |
826 | break; | |
827 | ||
828 | if (*tmp == '+') { | |
829 | enable = true; | |
830 | disable = false; | |
831 | tmp++; | |
832 | } else if (*tmp == '-') { | |
833 | enable = false; | |
834 | disable = true; | |
835 | tmp++; | |
836 | } else { | |
837 | enable = false; | |
838 | disable = false; | |
839 | } | |
840 | ||
841 | if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) { | |
842 | tmp += sizeof(PROTO_NONE); | |
843 | mask = 0; | |
844 | count++; | |
845 | } else { | |
846 | for (i = 0; i < ARRAY_SIZE(proto_names); i++) { | |
847 | if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) { | |
848 | tmp += strlen(proto_names[i].name); | |
849 | mask = proto_names[i].type; | |
850 | break; | |
851 | } | |
852 | } | |
853 | if (i == ARRAY_SIZE(proto_names)) { | |
854 | IR_dprintk(1, "Unknown protocol: '%s'\n", tmp); | |
855 | return -EINVAL; | |
856 | } | |
857 | count++; | |
858 | } | |
859 | ||
860 | if (enable) | |
861 | type |= mask; | |
862 | else if (disable) | |
863 | type &= ~mask; | |
864 | else | |
865 | type = mask; | |
866 | } | |
867 | ||
868 | if (!count) { | |
869 | IR_dprintk(1, "Protocol not specified\n"); | |
870 | return -EINVAL; | |
871 | } | |
872 | ||
d8b4b582 DH |
873 | if (dev->change_protocol) { |
874 | rc = dev->change_protocol(dev, type); | |
bc2a6c57 MCC |
875 | if (rc < 0) { |
876 | IR_dprintk(1, "Error setting protocols to 0x%llx\n", | |
877 | (long long)type); | |
878 | return -EINVAL; | |
879 | } | |
880 | } | |
881 | ||
d8b4b582 | 882 | if (dev->driver_type == RC_DRIVER_SCANCODE) { |
b088ba65 MCC |
883 | spin_lock_irqsave(&dev->rc_map.lock, flags); |
884 | dev->rc_map.rc_type = type; | |
885 | spin_unlock_irqrestore(&dev->rc_map.lock, flags); | |
bc2a6c57 | 886 | } else { |
d8b4b582 | 887 | dev->raw->enabled_protocols = type; |
bc2a6c57 MCC |
888 | } |
889 | ||
890 | IR_dprintk(1, "Current protocol(s): 0x%llx\n", | |
891 | (long long)type); | |
892 | ||
893 | return len; | |
894 | } | |
895 | ||
d8b4b582 DH |
896 | static void rc_dev_release(struct device *device) |
897 | { | |
898 | struct rc_dev *dev = to_rc_dev(device); | |
899 | ||
900 | kfree(dev); | |
901 | module_put(THIS_MODULE); | |
902 | } | |
903 | ||
bc2a6c57 MCC |
904 | #define ADD_HOTPLUG_VAR(fmt, val...) \ |
905 | do { \ | |
906 | int err = add_uevent_var(env, fmt, val); \ | |
907 | if (err) \ | |
908 | return err; \ | |
909 | } while (0) | |
910 | ||
911 | static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) | |
912 | { | |
d8b4b582 | 913 | struct rc_dev *dev = to_rc_dev(device); |
bc2a6c57 | 914 | |
b088ba65 MCC |
915 | if (dev->rc_map.name) |
916 | ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name); | |
d8b4b582 DH |
917 | if (dev->driver_name) |
918 | ADD_HOTPLUG_VAR("DRV_NAME=%s", dev->driver_name); | |
bc2a6c57 MCC |
919 | |
920 | return 0; | |
921 | } | |
922 | ||
923 | /* | |
924 | * Static device attribute struct with the sysfs attributes for IR's | |
925 | */ | |
926 | static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR, | |
927 | show_protocols, store_protocols); | |
928 | ||
929 | static struct attribute *rc_dev_attrs[] = { | |
930 | &dev_attr_protocols.attr, | |
931 | NULL, | |
932 | }; | |
933 | ||
934 | static struct attribute_group rc_dev_attr_grp = { | |
935 | .attrs = rc_dev_attrs, | |
936 | }; | |
937 | ||
938 | static const struct attribute_group *rc_dev_attr_groups[] = { | |
939 | &rc_dev_attr_grp, | |
940 | NULL | |
941 | }; | |
942 | ||
943 | static struct device_type rc_dev_type = { | |
944 | .groups = rc_dev_attr_groups, | |
d8b4b582 | 945 | .release = rc_dev_release, |
bc2a6c57 MCC |
946 | .uevent = rc_dev_uevent, |
947 | }; | |
948 | ||
d8b4b582 | 949 | struct rc_dev *rc_allocate_device(void) |
bc2a6c57 | 950 | { |
d8b4b582 | 951 | struct rc_dev *dev; |
bc2a6c57 | 952 | |
d8b4b582 DH |
953 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
954 | if (!dev) | |
955 | return NULL; | |
956 | ||
957 | dev->input_dev = input_allocate_device(); | |
958 | if (!dev->input_dev) { | |
959 | kfree(dev); | |
960 | return NULL; | |
961 | } | |
962 | ||
963 | dev->input_dev->getkeycode_new = ir_getkeycode; | |
964 | dev->input_dev->setkeycode_new = ir_setkeycode; | |
965 | input_set_drvdata(dev->input_dev, dev); | |
966 | ||
b088ba65 | 967 | spin_lock_init(&dev->rc_map.lock); |
d8b4b582 DH |
968 | spin_lock_init(&dev->keylock); |
969 | setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev); | |
bc2a6c57 | 970 | |
d8b4b582 DH |
971 | dev->dev.type = &rc_dev_type; |
972 | dev->dev.class = &ir_input_class; | |
973 | device_initialize(&dev->dev); | |
974 | ||
975 | __module_get(THIS_MODULE); | |
976 | return dev; | |
977 | } | |
978 | EXPORT_SYMBOL_GPL(rc_allocate_device); | |
979 | ||
980 | void rc_free_device(struct rc_dev *dev) | |
bc2a6c57 | 981 | { |
d8b4b582 DH |
982 | if (dev) { |
983 | input_free_device(dev->input_dev); | |
984 | put_device(&dev->dev); | |
985 | } | |
986 | } | |
987 | EXPORT_SYMBOL_GPL(rc_free_device); | |
988 | ||
989 | int rc_register_device(struct rc_dev *dev) | |
990 | { | |
991 | static atomic_t devno = ATOMIC_INIT(0); | |
b088ba65 | 992 | struct rc_map *rc_map; |
bc2a6c57 | 993 | const char *path; |
d8b4b582 | 994 | int rc; |
bc2a6c57 | 995 | |
d8b4b582 DH |
996 | if (!dev || !dev->map_name) |
997 | return -EINVAL; | |
bc2a6c57 | 998 | |
d100e659 | 999 | rc_map = rc_map_get(dev->map_name); |
b088ba65 | 1000 | if (!rc_map) |
d100e659 | 1001 | rc_map = rc_map_get(RC_MAP_EMPTY); |
b088ba65 | 1002 | if (!rc_map || !rc_map->scan || rc_map->size == 0) |
d8b4b582 DH |
1003 | return -EINVAL; |
1004 | ||
1005 | set_bit(EV_KEY, dev->input_dev->evbit); | |
1006 | set_bit(EV_REP, dev->input_dev->evbit); | |
1007 | set_bit(EV_MSC, dev->input_dev->evbit); | |
1008 | set_bit(MSC_SCAN, dev->input_dev->mscbit); | |
1009 | if (dev->open) | |
1010 | dev->input_dev->open = ir_open; | |
1011 | if (dev->close) | |
1012 | dev->input_dev->close = ir_close; | |
1013 | ||
1014 | dev->devno = (unsigned long)(atomic_inc_return(&devno) - 1); | |
1015 | dev_set_name(&dev->dev, "rc%ld", dev->devno); | |
1016 | dev_set_drvdata(&dev->dev, dev); | |
1017 | rc = device_add(&dev->dev); | |
1018 | if (rc) | |
bc2a6c57 | 1019 | return rc; |
bc2a6c57 | 1020 | |
b088ba65 | 1021 | rc = ir_setkeytable(dev, rc_map); |
d8b4b582 DH |
1022 | if (rc) |
1023 | goto out_dev; | |
1024 | ||
1025 | dev->input_dev->dev.parent = &dev->dev; | |
1026 | memcpy(&dev->input_dev->id, &dev->input_id, sizeof(dev->input_id)); | |
1027 | dev->input_dev->phys = dev->input_phys; | |
1028 | dev->input_dev->name = dev->input_name; | |
1029 | rc = input_register_device(dev->input_dev); | |
1030 | if (rc) | |
1031 | goto out_table; | |
bc2a6c57 | 1032 | |
d8b4b582 DH |
1033 | /* |
1034 | * Default delay of 250ms is too short for some protocols, expecially | |
1035 | * since the timeout is currently set to 250ms. Increase it to 500ms, | |
1036 | * to avoid wrong repetition of the keycodes. Note that this must be | |
1037 | * set after the call to input_register_device(). | |
1038 | */ | |
1039 | dev->input_dev->rep[REP_DELAY] = 500; | |
1040 | ||
1041 | path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); | |
bc2a6c57 | 1042 | printk(KERN_INFO "%s: %s as %s\n", |
d8b4b582 DH |
1043 | dev_name(&dev->dev), |
1044 | dev->input_name ? dev->input_name : "Unspecified device", | |
bc2a6c57 MCC |
1045 | path ? path : "N/A"); |
1046 | kfree(path); | |
1047 | ||
d8b4b582 DH |
1048 | if (dev->driver_type == RC_DRIVER_IR_RAW) { |
1049 | rc = ir_raw_event_register(dev); | |
1050 | if (rc < 0) | |
1051 | goto out_input; | |
1052 | } | |
1053 | ||
1054 | if (dev->change_protocol) { | |
b088ba65 | 1055 | rc = dev->change_protocol(dev, rc_map->rc_type); |
d8b4b582 DH |
1056 | if (rc < 0) |
1057 | goto out_raw; | |
1058 | } | |
1059 | ||
1060 | IR_dprintk(1, "Registered rc%ld (driver: %s, remote: %s, mode %s)\n", | |
1061 | dev->devno, | |
1062 | dev->driver_name ? dev->driver_name : "unknown", | |
b088ba65 | 1063 | rc_map->name ? rc_map->name : "unknown", |
d8b4b582 DH |
1064 | dev->driver_type == RC_DRIVER_IR_RAW ? "raw" : "cooked"); |
1065 | ||
bc2a6c57 | 1066 | return 0; |
d8b4b582 DH |
1067 | |
1068 | out_raw: | |
1069 | if (dev->driver_type == RC_DRIVER_IR_RAW) | |
1070 | ir_raw_event_unregister(dev); | |
1071 | out_input: | |
1072 | input_unregister_device(dev->input_dev); | |
1073 | dev->input_dev = NULL; | |
1074 | out_table: | |
b088ba65 | 1075 | ir_free_table(&dev->rc_map); |
d8b4b582 DH |
1076 | out_dev: |
1077 | device_del(&dev->dev); | |
1078 | return rc; | |
bc2a6c57 | 1079 | } |
d8b4b582 | 1080 | EXPORT_SYMBOL_GPL(rc_register_device); |
bc2a6c57 | 1081 | |
d8b4b582 | 1082 | void rc_unregister_device(struct rc_dev *dev) |
bc2a6c57 | 1083 | { |
d8b4b582 DH |
1084 | if (!dev) |
1085 | return; | |
bc2a6c57 | 1086 | |
d8b4b582 | 1087 | del_timer_sync(&dev->timer_keyup); |
bc2a6c57 | 1088 | |
d8b4b582 DH |
1089 | if (dev->driver_type == RC_DRIVER_IR_RAW) |
1090 | ir_raw_event_unregister(dev); | |
1091 | ||
1092 | input_unregister_device(dev->input_dev); | |
1093 | dev->input_dev = NULL; | |
1094 | ||
b088ba65 | 1095 | ir_free_table(&dev->rc_map); |
d8b4b582 DH |
1096 | IR_dprintk(1, "Freed keycode table\n"); |
1097 | ||
1098 | device_unregister(&dev->dev); | |
bc2a6c57 | 1099 | } |
d8b4b582 | 1100 | EXPORT_SYMBOL_GPL(rc_unregister_device); |
bc2a6c57 MCC |
1101 | |
1102 | /* | |
1103 | * Init/exit code for the module. Basically, creates/removes /sys/class/rc | |
1104 | */ | |
1105 | ||
6bda9644 | 1106 | static int __init rc_core_init(void) |
bc2a6c57 MCC |
1107 | { |
1108 | int rc = class_register(&ir_input_class); | |
1109 | if (rc) { | |
6bda9644 | 1110 | printk(KERN_ERR "rc_core: unable to register rc class\n"); |
bc2a6c57 MCC |
1111 | return rc; |
1112 | } | |
1113 | ||
1114 | /* Initialize/load the decoders/keymap code that will be used */ | |
1115 | ir_raw_init(); | |
d100e659 | 1116 | rc_map_register(&empty_map); |
bc2a6c57 MCC |
1117 | |
1118 | return 0; | |
1119 | } | |
1120 | ||
6bda9644 | 1121 | static void __exit rc_core_exit(void) |
bc2a6c57 MCC |
1122 | { |
1123 | class_unregister(&ir_input_class); | |
d100e659 | 1124 | rc_map_unregister(&empty_map); |
bc2a6c57 MCC |
1125 | } |
1126 | ||
6bda9644 MCC |
1127 | module_init(rc_core_init); |
1128 | module_exit(rc_core_exit); | |
bc2a6c57 | 1129 | |
6bda9644 MCC |
1130 | int rc_core_debug; /* ir_debug level (0,1,2) */ |
1131 | EXPORT_SYMBOL_GPL(rc_core_debug); | |
1132 | module_param_named(debug, rc_core_debug, int, 0644); | |
446e4a64 MCC |
1133 | |
1134 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | |
1135 | MODULE_LICENSE("GPL"); |