aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMarvin Raaijmakers <marvin_raaijmakers@linux-box.nl>2007-03-14 22:50:42 -0400
committerDmitry Torokhov <dtor@insightbb.com>2007-03-14 22:50:42 -0400
commitc8e4c77277ca5db0c4ddbfb4bc628b8abad585b0 (patch)
tree07bebb34767c8c3bd0902d6c2be3f4819b30a7bf /drivers
parent55e3d9224b60df0fd2dc36bff9b538ce40fd9586 (diff)
Input: add getkeycode and setkeycode methods
Allow drivers to implement their own get and set keycode methods. This will allow drivers to change their keymaps without allocating huge tables covering entire range of possible scancodes. Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/keyboard.c71
-rw-r--r--drivers/input/evdev.c29
-rw-r--r--drivers/input/input.c87
3 files changed, 119 insertions, 68 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index cb8d691576da..3d211e8553f7 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -159,65 +159,41 @@ static int sysrq_alt_use;
159static int sysrq_alt; 159static int sysrq_alt;
160 160
161/* 161/*
162 * Translation of scancodes to keycodes. We set them on only the first attached 162 * Translation of scancodes to keycodes. We set them on only the first
163 * keyboard - for per-keyboard setting, /dev/input/event is more useful. 163 * keyboard in the list that accepts the scancode and keycode.
164 * Explanation for not choosing the first attached keyboard anymore:
165 * USB keyboards for example have two event devices: one for all "normal"
166 * keys and one for extra function keys (like "volume up", "make coffee",
167 * etc.). So this means that scancodes for the extra function keys won't
168 * be valid for the first event device, but will be for the second.
164 */ 169 */
165int getkeycode(unsigned int scancode) 170int getkeycode(unsigned int scancode)
166{ 171{
167 struct list_head *node; 172 struct input_handle *handle;
168 struct input_dev *dev = NULL; 173 int keycode;
174 int error = -ENODEV;
169 175
170 list_for_each(node, &kbd_handler.h_list) { 176 list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
171 struct input_handle *handle = to_handle_h(node); 177 error = handle->dev->getkeycode(handle->dev, scancode, &keycode);
172 if (handle->dev->keycodesize) { 178 if (!error)
173 dev = handle->dev; 179 return keycode;
174 break;
175 }
176 } 180 }
177 181
178 if (!dev) 182 return error;
179 return -ENODEV;
180
181 if (scancode >= dev->keycodemax)
182 return -EINVAL;
183
184 return INPUT_KEYCODE(dev, scancode);
185} 183}
186 184
187int setkeycode(unsigned int scancode, unsigned int keycode) 185int setkeycode(unsigned int scancode, unsigned int keycode)
188{ 186{
189 struct list_head *node; 187 struct input_handle *handle;
190 struct input_dev *dev = NULL; 188 int error = -ENODEV;
191 unsigned int i, oldkey;
192 189
193 list_for_each(node, &kbd_handler.h_list) { 190 list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
194 struct input_handle *handle = to_handle_h(node); 191 error = handle->dev->setkeycode(handle->dev, scancode, keycode);
195 if (handle->dev->keycodesize) { 192 if (!error)
196 dev = handle->dev;
197 break; 193 break;
198 }
199 } 194 }
200 195
201 if (!dev) 196 return error;
202 return -ENODEV;
203
204 if (scancode >= dev->keycodemax)
205 return -EINVAL;
206 if (keycode < 0 || keycode > KEY_MAX)
207 return -EINVAL;
208 if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
209 return -EINVAL;
210
211 oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode);
212
213 clear_bit(oldkey, dev->keybit);
214 set_bit(keycode, dev->keybit);
215
216 for (i = 0; i < dev->keycodemax; i++)
217 if (INPUT_KEYCODE(dev,i) == oldkey)
218 set_bit(oldkey, dev->keybit);
219
220 return 0;
221} 197}
222 198
223/* 199/*
@@ -225,10 +201,9 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
225 */ 201 */
226static void kd_nosound(unsigned long ignored) 202static void kd_nosound(unsigned long ignored)
227{ 203{
228 struct list_head *node; 204 struct input_handle *handle;
229 205
230 list_for_each(node, &kbd_handler.h_list) { 206 list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
231 struct input_handle *handle = to_handle_h(node);
232 if (test_bit(EV_SND, handle->dev->evbit)) { 207 if (test_bit(EV_SND, handle->dev->evbit)) {
233 if (test_bit(SND_TONE, handle->dev->sndbit)) 208 if (test_bit(SND_TONE, handle->dev->sndbit))
234 input_inject_event(handle, EV_SND, SND_TONE, 0); 209 input_inject_event(handle, EV_SND, SND_TONE, 0);
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 6439f378f6cc..64b47de052bb 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -434,32 +434,21 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
434 case EVIOCGKEYCODE: 434 case EVIOCGKEYCODE:
435 if (get_user(t, ip)) 435 if (get_user(t, ip))
436 return -EFAULT; 436 return -EFAULT;
437 if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) 437
438 return -EINVAL; 438 error = dev->getkeycode(dev, t, &v);
439 if (put_user(INPUT_KEYCODE(dev, t), ip + 1)) 439 if (error)
440 return error;
441
442 if (put_user(v, ip + 1))
440 return -EFAULT; 443 return -EFAULT;
444
441 return 0; 445 return 0;
442 446
443 case EVIOCSKEYCODE: 447 case EVIOCSKEYCODE:
444 if (get_user(t, ip)) 448 if (get_user(t, ip) || get_user(v, ip + 1))
445 return -EFAULT;
446 if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
447 return -EINVAL;
448 if (get_user(v, ip + 1))
449 return -EFAULT; 449 return -EFAULT;
450 if (v < 0 || v > KEY_MAX)
451 return -EINVAL;
452 if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8)))
453 return -EINVAL;
454
455 u = SET_INPUT_KEYCODE(dev, t, v);
456 clear_bit(u, dev->keybit);
457 set_bit(v, dev->keybit);
458 for (i = 0; i < dev->keycodemax; i++)
459 if (INPUT_KEYCODE(dev, i) == u)
460 set_bit(u, dev->keybit);
461 450
462 return 0; 451 return dev->setkeycode(dev, t, v);
463 452
464 case EVIOCSFF: 453 case EVIOCSFF:
465 if (copy_from_user(&effect, p, sizeof(effect))) 454 if (copy_from_user(&effect, p, sizeof(effect)))
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 4486402fbf5d..26393a606e6f 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -299,6 +299,87 @@ void input_close_device(struct input_handle *handle)
299} 299}
300EXPORT_SYMBOL(input_close_device); 300EXPORT_SYMBOL(input_close_device);
301 301
302static int input_fetch_keycode(struct input_dev *dev, int scancode)
303{
304 switch (dev->keycodesize) {
305 case 1:
306 return ((u8 *)dev->keycode)[scancode];
307
308 case 2:
309 return ((u16 *)dev->keycode)[scancode];
310
311 default:
312 return ((u32 *)dev->keycode)[scancode];
313 }
314}
315
316static int input_default_getkeycode(struct input_dev *dev,
317 int scancode, int *keycode)
318{
319 if (!dev->keycodesize)
320 return -EINVAL;
321
322 if (scancode < 0 || scancode >= dev->keycodemax)
323 return -EINVAL;
324
325 *keycode = input_fetch_keycode(dev, scancode);
326
327 return 0;
328}
329
330static int input_default_setkeycode(struct input_dev *dev,
331 int scancode, int keycode)
332{
333 int old_keycode;
334 int i;
335
336 if (scancode < 0 || scancode >= dev->keycodemax)
337 return -EINVAL;
338
339 if (keycode < 0 || keycode > KEY_MAX)
340 return -EINVAL;
341
342 if (!dev->keycodesize)
343 return -EINVAL;
344
345 if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
346 return -EINVAL;
347
348 switch (dev->keycodesize) {
349 case 1: {
350 u8 *k = (u8 *)dev->keycode;
351 old_keycode = k[scancode];
352 k[scancode] = keycode;
353 break;
354 }
355 case 2: {
356 u16 *k = (u16 *)dev->keycode;
357 old_keycode = k[scancode];
358 k[scancode] = keycode;
359 break;
360 }
361 default: {
362 u32 *k = (u32 *)dev->keycode;
363 old_keycode = k[scancode];
364 k[scancode] = keycode;
365 break;
366 }
367 }
368
369 clear_bit(old_keycode, dev->keybit);
370 set_bit(keycode, dev->keybit);
371
372 for (i = 0; i < dev->keycodemax; i++) {
373 if (input_fetch_keycode(dev, i) == old_keycode) {
374 set_bit(old_keycode, dev->keybit);
375 break; /* Setting the bit twice is useless, so break */
376 }
377 }
378
379 return 0;
380}
381
382
302static void input_link_handle(struct input_handle *handle) 383static void input_link_handle(struct input_handle *handle)
303{ 384{
304 list_add_tail(&handle->d_node, &handle->dev->h_list); 385 list_add_tail(&handle->d_node, &handle->dev->h_list);
@@ -978,6 +1059,12 @@ int input_register_device(struct input_dev *dev)
978 dev->rep[REP_PERIOD] = 33; 1059 dev->rep[REP_PERIOD] = 33;
979 } 1060 }
980 1061
1062 if (!dev->getkeycode)
1063 dev->getkeycode = input_default_getkeycode;
1064
1065 if (!dev->setkeycode)
1066 dev->setkeycode = input_default_setkeycode;
1067
981 list_add_tail(&dev->node, &input_dev_list); 1068 list_add_tail(&dev->node, &input_dev_list);
982 1069
983 snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id), 1070 snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),