diff options
Diffstat (limited to 'drivers/input')
46 files changed, 2244 insertions, 536 deletions
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 078e4eed0894..2880eaae157a 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
@@ -231,6 +231,7 @@ static void gameport_find_driver(struct gameport *gameport) | |||
231 | enum gameport_event_type { | 231 | enum gameport_event_type { |
232 | GAMEPORT_REGISTER_PORT, | 232 | GAMEPORT_REGISTER_PORT, |
233 | GAMEPORT_REGISTER_DRIVER, | 233 | GAMEPORT_REGISTER_DRIVER, |
234 | GAMEPORT_ATTACH_DRIVER, | ||
234 | }; | 235 | }; |
235 | 236 | ||
236 | struct gameport_event { | 237 | struct gameport_event { |
@@ -245,11 +246,12 @@ static LIST_HEAD(gameport_event_list); | |||
245 | static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); | 246 | static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); |
246 | static struct task_struct *gameport_task; | 247 | static struct task_struct *gameport_task; |
247 | 248 | ||
248 | static void gameport_queue_event(void *object, struct module *owner, | 249 | static int gameport_queue_event(void *object, struct module *owner, |
249 | enum gameport_event_type event_type) | 250 | enum gameport_event_type event_type) |
250 | { | 251 | { |
251 | unsigned long flags; | 252 | unsigned long flags; |
252 | struct gameport_event *event; | 253 | struct gameport_event *event; |
254 | int retval = 0; | ||
253 | 255 | ||
254 | spin_lock_irqsave(&gameport_event_lock, flags); | 256 | spin_lock_irqsave(&gameport_event_lock, flags); |
255 | 257 | ||
@@ -268,24 +270,34 @@ static void gameport_queue_event(void *object, struct module *owner, | |||
268 | } | 270 | } |
269 | } | 271 | } |
270 | 272 | ||
271 | if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) { | 273 | event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC); |
272 | if (!try_module_get(owner)) { | 274 | if (!event) { |
273 | printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type); | 275 | printk(KERN_ERR |
274 | kfree(event); | 276 | "gameport: Not enough memory to queue event %d\n", |
275 | goto out; | 277 | event_type); |
276 | } | 278 | retval = -ENOMEM; |
277 | 279 | goto out; | |
278 | event->type = event_type; | 280 | } |
279 | event->object = object; | ||
280 | event->owner = owner; | ||
281 | 281 | ||
282 | list_add_tail(&event->node, &gameport_event_list); | 282 | if (!try_module_get(owner)) { |
283 | wake_up(&gameport_wait); | 283 | printk(KERN_WARNING |
284 | } else { | 284 | "gameport: Can't get module reference, dropping event %d\n", |
285 | printk(KERN_ERR "gameport: Not enough memory to queue event %d\n", event_type); | 285 | event_type); |
286 | kfree(event); | ||
287 | retval = -EINVAL; | ||
288 | goto out; | ||
286 | } | 289 | } |
290 | |||
291 | event->type = event_type; | ||
292 | event->object = object; | ||
293 | event->owner = owner; | ||
294 | |||
295 | list_add_tail(&event->node, &gameport_event_list); | ||
296 | wake_up(&gameport_wait); | ||
297 | |||
287 | out: | 298 | out: |
288 | spin_unlock_irqrestore(&gameport_event_lock, flags); | 299 | spin_unlock_irqrestore(&gameport_event_lock, flags); |
300 | return retval; | ||
289 | } | 301 | } |
290 | 302 | ||
291 | static void gameport_free_event(struct gameport_event *event) | 303 | static void gameport_free_event(struct gameport_event *event) |
@@ -378,9 +390,10 @@ static void gameport_handle_event(void) | |||
378 | } | 390 | } |
379 | 391 | ||
380 | /* | 392 | /* |
381 | * Remove all events that have been submitted for a given gameport port. | 393 | * Remove all events that have been submitted for a given object, |
394 | * be it a gameport port or a driver. | ||
382 | */ | 395 | */ |
383 | static void gameport_remove_pending_events(struct gameport *gameport) | 396 | static void gameport_remove_pending_events(void *object) |
384 | { | 397 | { |
385 | struct list_head *node, *next; | 398 | struct list_head *node, *next; |
386 | struct gameport_event *event; | 399 | struct gameport_event *event; |
@@ -390,7 +403,7 @@ static void gameport_remove_pending_events(struct gameport *gameport) | |||
390 | 403 | ||
391 | list_for_each_safe(node, next, &gameport_event_list) { | 404 | list_for_each_safe(node, next, &gameport_event_list) { |
392 | event = list_entry(node, struct gameport_event, node); | 405 | event = list_entry(node, struct gameport_event, node); |
393 | if (event->object == gameport) { | 406 | if (event->object == object) { |
394 | list_del_init(node); | 407 | list_del_init(node); |
395 | gameport_free_event(event); | 408 | gameport_free_event(event); |
396 | } | 409 | } |
@@ -705,10 +718,40 @@ static void gameport_add_driver(struct gameport_driver *drv) | |||
705 | drv->driver.name, error); | 718 | drv->driver.name, error); |
706 | } | 719 | } |
707 | 720 | ||
708 | void __gameport_register_driver(struct gameport_driver *drv, struct module *owner) | 721 | int __gameport_register_driver(struct gameport_driver *drv, struct module *owner, |
722 | const char *mod_name) | ||
709 | { | 723 | { |
724 | int error; | ||
725 | |||
710 | drv->driver.bus = &gameport_bus; | 726 | drv->driver.bus = &gameport_bus; |
711 | gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER); | 727 | drv->driver.owner = owner; |
728 | drv->driver.mod_name = mod_name; | ||
729 | |||
730 | /* | ||
731 | * Temporarily disable automatic binding because probing | ||
732 | * takes long time and we are better off doing it in kgameportd | ||
733 | */ | ||
734 | drv->ignore = 1; | ||
735 | |||
736 | error = driver_register(&drv->driver); | ||
737 | if (error) { | ||
738 | printk(KERN_ERR | ||
739 | "gameport: driver_register() failed for %s, error: %d\n", | ||
740 | drv->driver.name, error); | ||
741 | return error; | ||
742 | } | ||
743 | |||
744 | /* | ||
745 | * Reset ignore flag and let kgameportd bind the driver to free ports | ||
746 | */ | ||
747 | drv->ignore = 0; | ||
748 | error = gameport_queue_event(drv, NULL, GAMEPORT_ATTACH_DRIVER); | ||
749 | if (error) { | ||
750 | driver_unregister(&drv->driver); | ||
751 | return error; | ||
752 | } | ||
753 | |||
754 | return 0; | ||
712 | } | 755 | } |
713 | 756 | ||
714 | void gameport_unregister_driver(struct gameport_driver *drv) | 757 | void gameport_unregister_driver(struct gameport_driver *drv) |
@@ -716,7 +759,9 @@ void gameport_unregister_driver(struct gameport_driver *drv) | |||
716 | struct gameport *gameport; | 759 | struct gameport *gameport; |
717 | 760 | ||
718 | mutex_lock(&gameport_mutex); | 761 | mutex_lock(&gameport_mutex); |
762 | |||
719 | drv->ignore = 1; /* so gameport_find_driver ignores it */ | 763 | drv->ignore = 1; /* so gameport_find_driver ignores it */ |
764 | gameport_remove_pending_events(drv); | ||
720 | 765 | ||
721 | start_over: | 766 | start_over: |
722 | list_for_each_entry(gameport, &gameport_list, node) { | 767 | list_for_each_entry(gameport, &gameport_list, node) { |
@@ -729,6 +774,7 @@ start_over: | |||
729 | } | 774 | } |
730 | 775 | ||
731 | driver_unregister(&drv->driver); | 776 | driver_unregister(&drv->driver); |
777 | |||
732 | mutex_unlock(&gameport_mutex); | 778 | mutex_unlock(&gameport_mutex); |
733 | } | 779 | } |
734 | 780 | ||
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index 92498d470b1f..6489f4010c4f 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c | |||
@@ -414,8 +414,7 @@ static struct gameport_driver a3d_drv = { | |||
414 | 414 | ||
415 | static int __init a3d_init(void) | 415 | static int __init a3d_init(void) |
416 | { | 416 | { |
417 | gameport_register_driver(&a3d_drv); | 417 | return gameport_register_driver(&a3d_drv); |
418 | return 0; | ||
419 | } | 418 | } |
420 | 419 | ||
421 | static void __exit a3d_exit(void) | 420 | static void __exit a3d_exit(void) |
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index d1ca8a14950f..89c4c084d4ad 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c | |||
@@ -572,8 +572,7 @@ static struct gameport_driver adi_drv = { | |||
572 | 572 | ||
573 | static int __init adi_init(void) | 573 | static int __init adi_init(void) |
574 | { | 574 | { |
575 | gameport_register_driver(&adi_drv); | 575 | return gameport_register_driver(&adi_drv); |
576 | return 0; | ||
577 | } | 576 | } |
578 | 577 | ||
579 | static void __exit adi_exit(void) | 578 | static void __exit adi_exit(void) |
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 708c5ae13b24..356b3a25efa2 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
@@ -761,9 +761,7 @@ static struct gameport_driver analog_drv = { | |||
761 | static int __init analog_init(void) | 761 | static int __init analog_init(void) |
762 | { | 762 | { |
763 | analog_parse_options(); | 763 | analog_parse_options(); |
764 | gameport_register_driver(&analog_drv); | 764 | return gameport_register_driver(&analog_drv); |
765 | |||
766 | return 0; | ||
767 | } | 765 | } |
768 | 766 | ||
769 | static void __exit analog_exit(void) | 767 | static void __exit analog_exit(void) |
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c index 639b975a8ed7..3497b87c3d05 100644 --- a/drivers/input/joystick/cobra.c +++ b/drivers/input/joystick/cobra.c | |||
@@ -263,8 +263,7 @@ static struct gameport_driver cobra_drv = { | |||
263 | 263 | ||
264 | static int __init cobra_init(void) | 264 | static int __init cobra_init(void) |
265 | { | 265 | { |
266 | gameport_register_driver(&cobra_drv); | 266 | return gameport_register_driver(&cobra_drv); |
267 | return 0; | ||
268 | } | 267 | } |
269 | 268 | ||
270 | static void __exit cobra_exit(void) | 269 | static void __exit cobra_exit(void) |
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index cb6eef1f2d99..67c207f5b1a1 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c | |||
@@ -375,8 +375,7 @@ static struct gameport_driver gf2k_drv = { | |||
375 | 375 | ||
376 | static int __init gf2k_init(void) | 376 | static int __init gf2k_init(void) |
377 | { | 377 | { |
378 | gameport_register_driver(&gf2k_drv); | 378 | return gameport_register_driver(&gf2k_drv); |
379 | return 0; | ||
380 | } | 379 | } |
381 | 380 | ||
382 | static void __exit gf2k_exit(void) | 381 | static void __exit gf2k_exit(void) |
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c index 684e07cfccc8..fc55899ba6c5 100644 --- a/drivers/input/joystick/grip.c +++ b/drivers/input/joystick/grip.c | |||
@@ -426,8 +426,7 @@ static struct gameport_driver grip_drv = { | |||
426 | 426 | ||
427 | static int __init grip_init(void) | 427 | static int __init grip_init(void) |
428 | { | 428 | { |
429 | gameport_register_driver(&grip_drv); | 429 | return gameport_register_driver(&grip_drv); |
430 | return 0; | ||
431 | } | 430 | } |
432 | 431 | ||
433 | static void __exit grip_exit(void) | 432 | static void __exit grip_exit(void) |
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 8279481b16e7..2d47baf47769 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c | |||
@@ -689,8 +689,7 @@ static struct gameport_driver grip_drv = { | |||
689 | 689 | ||
690 | static int __init grip_init(void) | 690 | static int __init grip_init(void) |
691 | { | 691 | { |
692 | gameport_register_driver(&grip_drv); | 692 | return gameport_register_driver(&grip_drv); |
693 | return 0; | ||
694 | } | 693 | } |
695 | 694 | ||
696 | static void __exit grip_exit(void) | 695 | static void __exit grip_exit(void) |
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c index 25ec3fad9f27..4058d4b272fe 100644 --- a/drivers/input/joystick/guillemot.c +++ b/drivers/input/joystick/guillemot.c | |||
@@ -283,8 +283,7 @@ static struct gameport_driver guillemot_drv = { | |||
283 | 283 | ||
284 | static int __init guillemot_init(void) | 284 | static int __init guillemot_init(void) |
285 | { | 285 | { |
286 | gameport_register_driver(&guillemot_drv); | 286 | return gameport_register_driver(&guillemot_drv); |
287 | return 0; | ||
288 | } | 287 | } |
289 | 288 | ||
290 | static void __exit guillemot_exit(void) | 289 | static void __exit guillemot_exit(void) |
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c index 8c3290b68205..2478289aeeea 100644 --- a/drivers/input/joystick/interact.c +++ b/drivers/input/joystick/interact.c | |||
@@ -317,8 +317,7 @@ static struct gameport_driver interact_drv = { | |||
317 | 317 | ||
318 | static int __init interact_init(void) | 318 | static int __init interact_init(void) |
319 | { | 319 | { |
320 | gameport_register_driver(&interact_drv); | 320 | return gameport_register_driver(&interact_drv); |
321 | return 0; | ||
322 | } | 321 | } |
323 | 322 | ||
324 | static void __exit interact_exit(void) | 323 | static void __exit interact_exit(void) |
diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c index 2a1b82c8b31c..cd894a0564a2 100644 --- a/drivers/input/joystick/joydump.c +++ b/drivers/input/joystick/joydump.c | |||
@@ -161,8 +161,7 @@ static struct gameport_driver joydump_drv = { | |||
161 | 161 | ||
162 | static int __init joydump_init(void) | 162 | static int __init joydump_init(void) |
163 | { | 163 | { |
164 | gameport_register_driver(&joydump_drv); | 164 | return gameport_register_driver(&joydump_drv); |
165 | return 0; | ||
166 | } | 165 | } |
167 | 166 | ||
168 | static void __exit joydump_exit(void) | 167 | static void __exit joydump_exit(void) |
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index 7b4865fdee54..ca13a6bec33e 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c | |||
@@ -818,8 +818,7 @@ static struct gameport_driver sw_drv = { | |||
818 | 818 | ||
819 | static int __init sw_init(void) | 819 | static int __init sw_init(void) |
820 | { | 820 | { |
821 | gameport_register_driver(&sw_drv); | 821 | return gameport_register_driver(&sw_drv); |
822 | return 0; | ||
823 | } | 822 | } |
824 | 823 | ||
825 | static void __exit sw_exit(void) | 824 | static void __exit sw_exit(void) |
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index 60c37bcb938d..d6c609807115 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c | |||
@@ -438,8 +438,7 @@ static struct gameport_driver tmdc_drv = { | |||
438 | 438 | ||
439 | static int __init tmdc_init(void) | 439 | static int __init tmdc_init(void) |
440 | { | 440 | { |
441 | gameport_register_driver(&tmdc_drv); | 441 | return gameport_register_driver(&tmdc_drv); |
442 | return 0; | ||
443 | } | 442 | } |
444 | 443 | ||
445 | static void __exit tmdc_exit(void) | 444 | static void __exit tmdc_exit(void) |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 6791be81eb29..839d1c9622f6 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -455,10 +455,10 @@ static void xpad_bulk_out(struct urb *urb) | |||
455 | case -ENOENT: | 455 | case -ENOENT: |
456 | case -ESHUTDOWN: | 456 | case -ESHUTDOWN: |
457 | /* this urb is terminated, clean up */ | 457 | /* this urb is terminated, clean up */ |
458 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 458 | dbg("%s - urb shutting down with status: %d", __func__, urb->status); |
459 | break; | 459 | break; |
460 | default: | 460 | default: |
461 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 461 | dbg("%s - nonzero urb status received: %d", __func__, urb->status); |
462 | } | 462 | } |
463 | } | 463 | } |
464 | 464 | ||
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index b1ce10f50bcf..22016ca15351 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -834,10 +834,10 @@ static void atkbd_disconnect(struct serio *serio) | |||
834 | } | 834 | } |
835 | 835 | ||
836 | /* | 836 | /* |
837 | * Most special keys (Fn+F?) on Dell Latitudes do not generate release | 837 | * Most special keys (Fn+F?) on Dell laptops do not generate release |
838 | * events so we have to do it ourselves. | 838 | * events so we have to do it ourselves. |
839 | */ | 839 | */ |
840 | static void atkbd_latitude_keymap_fixup(struct atkbd *atkbd) | 840 | static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) |
841 | { | 841 | { |
842 | const unsigned int forced_release_keys[] = { | 842 | const unsigned int forced_release_keys[] = { |
843 | 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, | 843 | 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, |
@@ -1207,15 +1207,13 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun | |||
1207 | { | 1207 | { |
1208 | struct input_dev *old_dev, *new_dev; | 1208 | struct input_dev *old_dev, *new_dev; |
1209 | unsigned long value; | 1209 | unsigned long value; |
1210 | char *rest; | ||
1211 | int err; | 1210 | int err; |
1212 | unsigned char old_extra, old_set; | 1211 | unsigned char old_extra, old_set; |
1213 | 1212 | ||
1214 | if (!atkbd->write) | 1213 | if (!atkbd->write) |
1215 | return -EIO; | 1214 | return -EIO; |
1216 | 1215 | ||
1217 | value = simple_strtoul(buf, &rest, 10); | 1216 | if (strict_strtoul(buf, 10, &value) || value > 1) |
1218 | if (*rest || value > 1) | ||
1219 | return -EINVAL; | 1217 | return -EINVAL; |
1220 | 1218 | ||
1221 | if (atkbd->extra != value) { | 1219 | if (atkbd->extra != value) { |
@@ -1264,12 +1262,10 @@ static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t cou | |||
1264 | { | 1262 | { |
1265 | struct input_dev *old_dev, *new_dev; | 1263 | struct input_dev *old_dev, *new_dev; |
1266 | unsigned long value; | 1264 | unsigned long value; |
1267 | char *rest; | ||
1268 | int err; | 1265 | int err; |
1269 | unsigned char old_scroll; | 1266 | unsigned char old_scroll; |
1270 | 1267 | ||
1271 | value = simple_strtoul(buf, &rest, 10); | 1268 | if (strict_strtoul(buf, 10, &value) || value > 1) |
1272 | if (*rest || value > 1) | ||
1273 | return -EINVAL; | 1269 | return -EINVAL; |
1274 | 1270 | ||
1275 | if (atkbd->scroll != value) { | 1271 | if (atkbd->scroll != value) { |
@@ -1310,15 +1306,13 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count) | |||
1310 | { | 1306 | { |
1311 | struct input_dev *old_dev, *new_dev; | 1307 | struct input_dev *old_dev, *new_dev; |
1312 | unsigned long value; | 1308 | unsigned long value; |
1313 | char *rest; | ||
1314 | int err; | 1309 | int err; |
1315 | unsigned char old_set, old_extra; | 1310 | unsigned char old_set, old_extra; |
1316 | 1311 | ||
1317 | if (!atkbd->write) | 1312 | if (!atkbd->write) |
1318 | return -EIO; | 1313 | return -EIO; |
1319 | 1314 | ||
1320 | value = simple_strtoul(buf, &rest, 10); | 1315 | if (strict_strtoul(buf, 10, &value) || (value != 2 && value != 3)) |
1321 | if (*rest || (value != 2 && value != 3)) | ||
1322 | return -EINVAL; | 1316 | return -EINVAL; |
1323 | 1317 | ||
1324 | if (atkbd->set != value) { | 1318 | if (atkbd->set != value) { |
@@ -1361,15 +1355,13 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t | |||
1361 | { | 1355 | { |
1362 | struct input_dev *old_dev, *new_dev; | 1356 | struct input_dev *old_dev, *new_dev; |
1363 | unsigned long value; | 1357 | unsigned long value; |
1364 | char *rest; | ||
1365 | int err; | 1358 | int err; |
1366 | unsigned char old_softrepeat, old_softraw; | 1359 | unsigned char old_softrepeat, old_softraw; |
1367 | 1360 | ||
1368 | if (!atkbd->write) | 1361 | if (!atkbd->write) |
1369 | return -EIO; | 1362 | return -EIO; |
1370 | 1363 | ||
1371 | value = simple_strtoul(buf, &rest, 10); | 1364 | if (strict_strtoul(buf, 10, &value) || value > 1) |
1372 | if (*rest || value > 1) | ||
1373 | return -EINVAL; | 1365 | return -EINVAL; |
1374 | 1366 | ||
1375 | if (atkbd->softrepeat != value) { | 1367 | if (atkbd->softrepeat != value) { |
@@ -1413,12 +1405,10 @@ static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t co | |||
1413 | { | 1405 | { |
1414 | struct input_dev *old_dev, *new_dev; | 1406 | struct input_dev *old_dev, *new_dev; |
1415 | unsigned long value; | 1407 | unsigned long value; |
1416 | char *rest; | ||
1417 | int err; | 1408 | int err; |
1418 | unsigned char old_softraw; | 1409 | unsigned char old_softraw; |
1419 | 1410 | ||
1420 | value = simple_strtoul(buf, &rest, 10); | 1411 | if (strict_strtoul(buf, 10, &value) || value > 1) |
1421 | if (*rest || value > 1) | ||
1422 | return -EINVAL; | 1412 | return -EINVAL; |
1423 | 1413 | ||
1424 | if (atkbd->softraw != value) { | 1414 | if (atkbd->softraw != value) { |
@@ -1461,13 +1451,13 @@ static int __init atkbd_setup_fixup(const struct dmi_system_id *id) | |||
1461 | 1451 | ||
1462 | static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | 1452 | static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { |
1463 | { | 1453 | { |
1464 | .ident = "Dell Latitude series", | 1454 | .ident = "Dell Laptop", |
1465 | .matches = { | 1455 | .matches = { |
1466 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 1456 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
1467 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"), | 1457 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ |
1468 | }, | 1458 | }, |
1469 | .callback = atkbd_setup_fixup, | 1459 | .callback = atkbd_setup_fixup, |
1470 | .driver_data = atkbd_latitude_keymap_fixup, | 1460 | .driver_data = atkbd_dell_laptop_keymap_fixup, |
1471 | }, | 1461 | }, |
1472 | { | 1462 | { |
1473 | .ident = "HP 2133", | 1463 | .ident = "HP 2133", |
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index e348cfccc17a..19284016e0f4 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * | 8 | * |
9 | * | 9 | * |
10 | * Modified: | 10 | * Modified: |
11 | * Copyright 2007 Analog Devices Inc. | 11 | * Copyright 2007-2008 Analog Devices Inc. |
12 | * | 12 | * |
13 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 13 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ |
14 | * | 14 | * |
@@ -81,6 +81,9 @@ struct bf54x_kpad { | |||
81 | unsigned short *keycode; | 81 | unsigned short *keycode; |
82 | struct timer_list timer; | 82 | struct timer_list timer; |
83 | unsigned int keyup_test_jiffies; | 83 | unsigned int keyup_test_jiffies; |
84 | unsigned short kpad_msel; | ||
85 | unsigned short kpad_prescale; | ||
86 | unsigned short kpad_ctl; | ||
84 | }; | 87 | }; |
85 | 88 | ||
86 | static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad, | 89 | static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad, |
@@ -360,6 +363,10 @@ static int bfin_kpad_suspend(struct platform_device *pdev, pm_message_t state) | |||
360 | { | 363 | { |
361 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | 364 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); |
362 | 365 | ||
366 | bf54x_kpad->kpad_msel = bfin_read_KPAD_MSEL(); | ||
367 | bf54x_kpad->kpad_prescale = bfin_read_KPAD_PRESCALE(); | ||
368 | bf54x_kpad->kpad_ctl = bfin_read_KPAD_CTL(); | ||
369 | |||
363 | if (device_may_wakeup(&pdev->dev)) | 370 | if (device_may_wakeup(&pdev->dev)) |
364 | enable_irq_wake(bf54x_kpad->irq); | 371 | enable_irq_wake(bf54x_kpad->irq); |
365 | 372 | ||
@@ -370,6 +377,10 @@ static int bfin_kpad_resume(struct platform_device *pdev) | |||
370 | { | 377 | { |
371 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | 378 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); |
372 | 379 | ||
380 | bfin_write_KPAD_MSEL(bf54x_kpad->kpad_msel); | ||
381 | bfin_write_KPAD_PRESCALE(bf54x_kpad->kpad_prescale); | ||
382 | bfin_write_KPAD_CTL(bf54x_kpad->kpad_ctl); | ||
383 | |||
373 | if (device_may_wakeup(&pdev->dev)) | 384 | if (device_may_wakeup(&pdev->dev)) |
374 | disable_irq_wake(bf54x_kpad->irq); | 385 | disable_irq_wake(bf54x_kpad->irq); |
375 | 386 | ||
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index ec96b369dd7a..05f3f43582c2 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -36,9 +36,10 @@ struct gpio_keys_drvdata { | |||
36 | struct gpio_button_data data[0]; | 36 | struct gpio_button_data data[0]; |
37 | }; | 37 | }; |
38 | 38 | ||
39 | static void gpio_keys_report_event(struct gpio_keys_button *button, | 39 | static void gpio_keys_report_event(struct gpio_button_data *bdata) |
40 | struct input_dev *input) | ||
41 | { | 40 | { |
41 | struct gpio_keys_button *button = bdata->button; | ||
42 | struct input_dev *input = bdata->input; | ||
42 | unsigned int type = button->type ?: EV_KEY; | 43 | unsigned int type = button->type ?: EV_KEY; |
43 | int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low; | 44 | int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low; |
44 | 45 | ||
@@ -50,34 +51,23 @@ static void gpio_check_button(unsigned long _data) | |||
50 | { | 51 | { |
51 | struct gpio_button_data *data = (struct gpio_button_data *)_data; | 52 | struct gpio_button_data *data = (struct gpio_button_data *)_data; |
52 | 53 | ||
53 | gpio_keys_report_event(data->button, data->input); | 54 | gpio_keys_report_event(data); |
54 | } | 55 | } |
55 | 56 | ||
56 | static irqreturn_t gpio_keys_isr(int irq, void *dev_id) | 57 | static irqreturn_t gpio_keys_isr(int irq, void *dev_id) |
57 | { | 58 | { |
58 | struct platform_device *pdev = dev_id; | 59 | struct gpio_button_data *bdata = dev_id; |
59 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 60 | struct gpio_keys_button *button = bdata->button; |
60 | struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); | ||
61 | int i; | ||
62 | 61 | ||
63 | for (i = 0; i < pdata->nbuttons; i++) { | 62 | BUG_ON(irq != gpio_to_irq(button->gpio)); |
64 | struct gpio_keys_button *button = &pdata->buttons[i]; | ||
65 | 63 | ||
66 | if (irq == gpio_to_irq(button->gpio)) { | 64 | if (button->debounce_interval) |
67 | struct gpio_button_data *bdata = &ddata->data[i]; | 65 | mod_timer(&bdata->timer, |
68 | 66 | jiffies + msecs_to_jiffies(button->debounce_interval)); | |
69 | if (button->debounce_interval) | 67 | else |
70 | mod_timer(&bdata->timer, | 68 | gpio_keys_report_event(bdata); |
71 | jiffies + | ||
72 | msecs_to_jiffies(button->debounce_interval)); | ||
73 | else | ||
74 | gpio_keys_report_event(button, bdata->input); | ||
75 | |||
76 | return IRQ_HANDLED; | ||
77 | } | ||
78 | } | ||
79 | 69 | ||
80 | return IRQ_NONE; | 70 | return IRQ_HANDLED; |
81 | } | 71 | } |
82 | 72 | ||
83 | static int __devinit gpio_keys_probe(struct platform_device *pdev) | 73 | static int __devinit gpio_keys_probe(struct platform_device *pdev) |
@@ -151,7 +141,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
151 | IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING | | 141 | IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING | |
152 | IRQF_TRIGGER_FALLING, | 142 | IRQF_TRIGGER_FALLING, |
153 | button->desc ? button->desc : "gpio_keys", | 143 | button->desc ? button->desc : "gpio_keys", |
154 | pdev); | 144 | bdata); |
155 | if (error) { | 145 | if (error) { |
156 | pr_err("gpio-keys: Unable to claim irq %d; error %d\n", | 146 | pr_err("gpio-keys: Unable to claim irq %d; error %d\n", |
157 | irq, error); | 147 | irq, error); |
@@ -178,7 +168,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
178 | 168 | ||
179 | fail2: | 169 | fail2: |
180 | while (--i >= 0) { | 170 | while (--i >= 0) { |
181 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); | 171 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); |
182 | if (pdata->buttons[i].debounce_interval) | 172 | if (pdata->buttons[i].debounce_interval) |
183 | del_timer_sync(&ddata->data[i].timer); | 173 | del_timer_sync(&ddata->data[i].timer); |
184 | gpio_free(pdata->buttons[i].gpio); | 174 | gpio_free(pdata->buttons[i].gpio); |
@@ -203,7 +193,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
203 | 193 | ||
204 | for (i = 0; i < pdata->nbuttons; i++) { | 194 | for (i = 0; i < pdata->nbuttons; i++) { |
205 | int irq = gpio_to_irq(pdata->buttons[i].gpio); | 195 | int irq = gpio_to_irq(pdata->buttons[i].gpio); |
206 | free_irq(irq, pdev); | 196 | free_irq(irq, &ddata->data[i]); |
207 | if (pdata->buttons[i].debounce_interval) | 197 | if (pdata->buttons[i].debounce_interval) |
208 | del_timer_sync(&ddata->data[i].timer); | 198 | del_timer_sync(&ddata->data[i].timer); |
209 | gpio_free(pdata->buttons[i].gpio); | 199 | gpio_free(pdata->buttons[i].gpio); |
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index dcea87a0bc56..69e674ecf19a 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c | |||
@@ -62,7 +62,7 @@ struct omap_kp { | |||
62 | unsigned int debounce; | 62 | unsigned int debounce; |
63 | }; | 63 | }; |
64 | 64 | ||
65 | DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0); | 65 | static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0); |
66 | 66 | ||
67 | static int *keymap; | 67 | static int *keymap; |
68 | static unsigned int *row_gpios; | 68 | static unsigned int *row_gpios; |
@@ -72,12 +72,9 @@ static unsigned int *col_gpios; | |||
72 | static void set_col_gpio_val(struct omap_kp *omap_kp, u8 value) | 72 | static void set_col_gpio_val(struct omap_kp *omap_kp, u8 value) |
73 | { | 73 | { |
74 | int col; | 74 | int col; |
75 | for (col = 0; col < omap_kp->cols; col++) { | 75 | |
76 | if (value & (1 << col)) | 76 | for (col = 0; col < omap_kp->cols; col++) |
77 | omap_set_gpio_dataout(col_gpios[col], 1); | 77 | gpio_set_value(col_gpios[col], value & (1 << col)); |
78 | else | ||
79 | omap_set_gpio_dataout(col_gpios[col], 0); | ||
80 | } | ||
81 | } | 78 | } |
82 | 79 | ||
83 | static u8 get_row_gpio_val(struct omap_kp *omap_kp) | 80 | static u8 get_row_gpio_val(struct omap_kp *omap_kp) |
@@ -86,7 +83,7 @@ static u8 get_row_gpio_val(struct omap_kp *omap_kp) | |||
86 | u8 value = 0; | 83 | u8 value = 0; |
87 | 84 | ||
88 | for (row = 0; row < omap_kp->rows; row++) { | 85 | for (row = 0; row < omap_kp->rows; row++) { |
89 | if (omap_get_gpio_datain(row_gpios[row])) | 86 | if (gpio_get_value(row_gpios[row])) |
90 | value |= (1 << row); | 87 | value |= (1 << row); |
91 | } | 88 | } |
92 | return value; | 89 | return value; |
@@ -333,23 +330,23 @@ static int __init omap_kp_probe(struct platform_device *pdev) | |||
333 | if (cpu_is_omap24xx()) { | 330 | if (cpu_is_omap24xx()) { |
334 | /* Cols: outputs */ | 331 | /* Cols: outputs */ |
335 | for (col_idx = 0; col_idx < omap_kp->cols; col_idx++) { | 332 | for (col_idx = 0; col_idx < omap_kp->cols; col_idx++) { |
336 | if (omap_request_gpio(col_gpios[col_idx]) < 0) { | 333 | if (gpio_request(col_gpios[col_idx], "omap_kp_col") < 0) { |
337 | printk(KERN_ERR "Failed to request" | 334 | printk(KERN_ERR "Failed to request" |
338 | "GPIO%d for keypad\n", | 335 | "GPIO%d for keypad\n", |
339 | col_gpios[col_idx]); | 336 | col_gpios[col_idx]); |
340 | goto err1; | 337 | goto err1; |
341 | } | 338 | } |
342 | omap_set_gpio_direction(col_gpios[col_idx], 0); | 339 | gpio_direction_output(col_gpios[col_idx], 0); |
343 | } | 340 | } |
344 | /* Rows: inputs */ | 341 | /* Rows: inputs */ |
345 | for (row_idx = 0; row_idx < omap_kp->rows; row_idx++) { | 342 | for (row_idx = 0; row_idx < omap_kp->rows; row_idx++) { |
346 | if (omap_request_gpio(row_gpios[row_idx]) < 0) { | 343 | if (gpio_request(row_gpios[row_idx], "omap_kp_row") < 0) { |
347 | printk(KERN_ERR "Failed to request" | 344 | printk(KERN_ERR "Failed to request" |
348 | "GPIO%d for keypad\n", | 345 | "GPIO%d for keypad\n", |
349 | row_gpios[row_idx]); | 346 | row_gpios[row_idx]); |
350 | goto err2; | 347 | goto err2; |
351 | } | 348 | } |
352 | omap_set_gpio_direction(row_gpios[row_idx], 1); | 349 | gpio_direction_input(row_gpios[row_idx]); |
353 | } | 350 | } |
354 | } else { | 351 | } else { |
355 | col_idx = 0; | 352 | col_idx = 0; |
@@ -418,10 +415,10 @@ err3: | |||
418 | device_remove_file(&pdev->dev, &dev_attr_enable); | 415 | device_remove_file(&pdev->dev, &dev_attr_enable); |
419 | err2: | 416 | err2: |
420 | for (i = row_idx - 1; i >=0; i--) | 417 | for (i = row_idx - 1; i >=0; i--) |
421 | omap_free_gpio(row_gpios[i]); | 418 | gpio_free(row_gpios[i]); |
422 | err1: | 419 | err1: |
423 | for (i = col_idx - 1; i >=0; i--) | 420 | for (i = col_idx - 1; i >=0; i--) |
424 | omap_free_gpio(col_gpios[i]); | 421 | gpio_free(col_gpios[i]); |
425 | 422 | ||
426 | kfree(omap_kp); | 423 | kfree(omap_kp); |
427 | input_free_device(input_dev); | 424 | input_free_device(input_dev); |
@@ -438,9 +435,9 @@ static int omap_kp_remove(struct platform_device *pdev) | |||
438 | if (cpu_is_omap24xx()) { | 435 | if (cpu_is_omap24xx()) { |
439 | int i; | 436 | int i; |
440 | for (i = 0; i < omap_kp->cols; i++) | 437 | for (i = 0; i < omap_kp->cols; i++) |
441 | omap_free_gpio(col_gpios[i]); | 438 | gpio_free(col_gpios[i]); |
442 | for (i = 0; i < omap_kp->rows; i++) { | 439 | for (i = 0; i < omap_kp->rows; i++) { |
443 | omap_free_gpio(row_gpios[i]); | 440 | gpio_free(row_gpios[i]); |
444 | free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0); | 441 | free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0); |
445 | } | 442 | } |
446 | } else { | 443 | } else { |
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index e99b7882f382..199055db5082 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -180,6 +180,19 @@ config INPUT_YEALINK | |||
180 | To compile this driver as a module, choose M here: the module will be | 180 | To compile this driver as a module, choose M here: the module will be |
181 | called yealink. | 181 | called yealink. |
182 | 182 | ||
183 | config INPUT_CM109 | ||
184 | tristate "C-Media CM109 USB I/O Controller" | ||
185 | depends on EXPERIMENTAL | ||
186 | depends on USB_ARCH_HAS_HCD | ||
187 | select USB | ||
188 | help | ||
189 | Say Y here if you want to enable keyboard and buzzer functions of the | ||
190 | C-Media CM109 usb phones. The audio part is enabled by the generic | ||
191 | usb sound driver, so you might want to enable that as well. | ||
192 | |||
193 | To compile this driver as a module, choose M here: the module will be | ||
194 | called cm109. | ||
195 | |||
183 | config INPUT_UINPUT | 196 | config INPUT_UINPUT |
184 | tristate "User level driver support" | 197 | tristate "User level driver support" |
185 | help | 198 | help |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index f48009b52226..d7db2aeb8a98 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | |||
16 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o | 16 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o |
17 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o | 17 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o |
18 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o | 18 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o |
19 | obj-$(CONFIG_INPUT_CM109) += cm109.o | ||
19 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o | 20 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o |
20 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o | 21 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o |
21 | obj-$(CONFIG_INPUT_APANEL) += apanel.o | 22 | obj-$(CONFIG_INPUT_APANEL) += apanel.o |
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index a7fabafbd94c..3c9988dc0e9f 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * ati_remote2 - ATI/Philips USB RF remote driver | 2 | * ati_remote2 - ATI/Philips USB RF remote driver |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi> | 4 | * Copyright (C) 2005-2008 Ville Syrjala <syrjala@sci.fi> |
5 | * Copyright (C) 2007 Peter Stokes <linux@dadeos.freeserve.co.uk> | 5 | * Copyright (C) 2007-2008 Peter Stokes <linux@dadeos.co.uk> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 | 8 | * it under the terms of the GNU General Public License version 2 |
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/usb/input.h> | 12 | #include <linux/usb/input.h> |
13 | 13 | ||
14 | #define DRIVER_DESC "ATI/Philips USB RF remote driver" | 14 | #define DRIVER_DESC "ATI/Philips USB RF remote driver" |
15 | #define DRIVER_VERSION "0.2" | 15 | #define DRIVER_VERSION "0.3" |
16 | 16 | ||
17 | MODULE_DESCRIPTION(DRIVER_DESC); | 17 | MODULE_DESCRIPTION(DRIVER_DESC); |
18 | MODULE_VERSION(DRIVER_VERSION); | 18 | MODULE_VERSION(DRIVER_VERSION); |
@@ -27,7 +27,7 @@ MODULE_LICENSE("GPL"); | |||
27 | * A remote's "channel" may be altered by pressing and holding the "PC" button for | 27 | * A remote's "channel" may be altered by pressing and holding the "PC" button for |
28 | * approximately 3 seconds, after which the button will slowly flash the count of the | 28 | * approximately 3 seconds, after which the button will slowly flash the count of the |
29 | * currently configured "channel", using the numeric keypad enter a number between 1 and | 29 | * currently configured "channel", using the numeric keypad enter a number between 1 and |
30 | * 16 and then the "PC" button again, the button will slowly flash the count of the | 30 | * 16 and then press the "PC" button again, the button will slowly flash the count of the |
31 | * newly configured "channel". | 31 | * newly configured "channel". |
32 | */ | 32 | */ |
33 | 33 | ||
@@ -45,9 +45,25 @@ static struct usb_device_id ati_remote2_id_table[] = { | |||
45 | }; | 45 | }; |
46 | MODULE_DEVICE_TABLE(usb, ati_remote2_id_table); | 46 | MODULE_DEVICE_TABLE(usb, ati_remote2_id_table); |
47 | 47 | ||
48 | static struct { | 48 | static DEFINE_MUTEX(ati_remote2_mutex); |
49 | int hw_code; | 49 | |
50 | int key_code; | 50 | enum { |
51 | ATI_REMOTE2_OPENED = 0x1, | ||
52 | ATI_REMOTE2_SUSPENDED = 0x2, | ||
53 | }; | ||
54 | |||
55 | enum { | ||
56 | ATI_REMOTE2_AUX1, | ||
57 | ATI_REMOTE2_AUX2, | ||
58 | ATI_REMOTE2_AUX3, | ||
59 | ATI_REMOTE2_AUX4, | ||
60 | ATI_REMOTE2_PC, | ||
61 | ATI_REMOTE2_MODES, | ||
62 | }; | ||
63 | |||
64 | static const struct { | ||
65 | u8 hw_code; | ||
66 | u16 keycode; | ||
51 | } ati_remote2_key_table[] = { | 67 | } ati_remote2_key_table[] = { |
52 | { 0x00, KEY_0 }, | 68 | { 0x00, KEY_0 }, |
53 | { 0x01, KEY_1 }, | 69 | { 0x01, KEY_1 }, |
@@ -73,6 +89,7 @@ static struct { | |||
73 | { 0x37, KEY_RECORD }, | 89 | { 0x37, KEY_RECORD }, |
74 | { 0x38, KEY_DVD }, | 90 | { 0x38, KEY_DVD }, |
75 | { 0x39, KEY_TV }, | 91 | { 0x39, KEY_TV }, |
92 | { 0x3f, KEY_PROG1 }, /* AUX1-AUX4 and PC */ | ||
76 | { 0x54, KEY_MENU }, | 93 | { 0x54, KEY_MENU }, |
77 | { 0x58, KEY_UP }, | 94 | { 0x58, KEY_UP }, |
78 | { 0x59, KEY_DOWN }, | 95 | { 0x59, KEY_DOWN }, |
@@ -91,15 +108,9 @@ static struct { | |||
91 | { 0xa9, BTN_LEFT }, | 108 | { 0xa9, BTN_LEFT }, |
92 | { 0xaa, BTN_RIGHT }, | 109 | { 0xaa, BTN_RIGHT }, |
93 | { 0xbe, KEY_QUESTION }, | 110 | { 0xbe, KEY_QUESTION }, |
94 | { 0xd5, KEY_FRONT }, | ||
95 | { 0xd0, KEY_EDIT }, | 111 | { 0xd0, KEY_EDIT }, |
112 | { 0xd5, KEY_FRONT }, | ||
96 | { 0xf9, KEY_INFO }, | 113 | { 0xf9, KEY_INFO }, |
97 | { (0x00 << 8) | 0x3f, KEY_PROG1 }, | ||
98 | { (0x01 << 8) | 0x3f, KEY_PROG2 }, | ||
99 | { (0x02 << 8) | 0x3f, KEY_PROG3 }, | ||
100 | { (0x03 << 8) | 0x3f, KEY_PROG4 }, | ||
101 | { (0x04 << 8) | 0x3f, KEY_PC }, | ||
102 | { 0, KEY_RESERVED } | ||
103 | }; | 114 | }; |
104 | 115 | ||
105 | struct ati_remote2 { | 116 | struct ati_remote2 { |
@@ -117,46 +128,106 @@ struct ati_remote2 { | |||
117 | 128 | ||
118 | char name[64]; | 129 | char name[64]; |
119 | char phys[64]; | 130 | char phys[64]; |
131 | |||
132 | /* Each mode (AUX1-AUX4 and PC) can have an independent keymap. */ | ||
133 | u16 keycode[ATI_REMOTE2_MODES][ARRAY_SIZE(ati_remote2_key_table)]; | ||
134 | |||
135 | unsigned int flags; | ||
120 | }; | 136 | }; |
121 | 137 | ||
122 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); | 138 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); |
123 | static void ati_remote2_disconnect(struct usb_interface *interface); | 139 | static void ati_remote2_disconnect(struct usb_interface *interface); |
140 | static int ati_remote2_suspend(struct usb_interface *interface, pm_message_t message); | ||
141 | static int ati_remote2_resume(struct usb_interface *interface); | ||
124 | 142 | ||
125 | static struct usb_driver ati_remote2_driver = { | 143 | static struct usb_driver ati_remote2_driver = { |
126 | .name = "ati_remote2", | 144 | .name = "ati_remote2", |
127 | .probe = ati_remote2_probe, | 145 | .probe = ati_remote2_probe, |
128 | .disconnect = ati_remote2_disconnect, | 146 | .disconnect = ati_remote2_disconnect, |
129 | .id_table = ati_remote2_id_table, | 147 | .id_table = ati_remote2_id_table, |
148 | .suspend = ati_remote2_suspend, | ||
149 | .resume = ati_remote2_resume, | ||
150 | .supports_autosuspend = 1, | ||
130 | }; | 151 | }; |
131 | 152 | ||
132 | static int ati_remote2_open(struct input_dev *idev) | 153 | static int ati_remote2_submit_urbs(struct ati_remote2 *ar2) |
133 | { | 154 | { |
134 | struct ati_remote2 *ar2 = input_get_drvdata(idev); | ||
135 | int r; | 155 | int r; |
136 | 156 | ||
137 | r = usb_submit_urb(ar2->urb[0], GFP_KERNEL); | 157 | r = usb_submit_urb(ar2->urb[0], GFP_KERNEL); |
138 | if (r) { | 158 | if (r) { |
139 | dev_err(&ar2->intf[0]->dev, | 159 | dev_err(&ar2->intf[0]->dev, |
140 | "%s: usb_submit_urb() = %d\n", __func__, r); | 160 | "%s(): usb_submit_urb() = %d\n", __func__, r); |
141 | return r; | 161 | return r; |
142 | } | 162 | } |
143 | r = usb_submit_urb(ar2->urb[1], GFP_KERNEL); | 163 | r = usb_submit_urb(ar2->urb[1], GFP_KERNEL); |
144 | if (r) { | 164 | if (r) { |
145 | usb_kill_urb(ar2->urb[0]); | 165 | usb_kill_urb(ar2->urb[0]); |
146 | dev_err(&ar2->intf[1]->dev, | 166 | dev_err(&ar2->intf[1]->dev, |
147 | "%s: usb_submit_urb() = %d\n", __func__, r); | 167 | "%s(): usb_submit_urb() = %d\n", __func__, r); |
148 | return r; | 168 | return r; |
149 | } | 169 | } |
150 | 170 | ||
151 | return 0; | 171 | return 0; |
152 | } | 172 | } |
153 | 173 | ||
174 | static void ati_remote2_kill_urbs(struct ati_remote2 *ar2) | ||
175 | { | ||
176 | usb_kill_urb(ar2->urb[1]); | ||
177 | usb_kill_urb(ar2->urb[0]); | ||
178 | } | ||
179 | |||
180 | static int ati_remote2_open(struct input_dev *idev) | ||
181 | { | ||
182 | struct ati_remote2 *ar2 = input_get_drvdata(idev); | ||
183 | int r; | ||
184 | |||
185 | dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); | ||
186 | |||
187 | r = usb_autopm_get_interface(ar2->intf[0]); | ||
188 | if (r) { | ||
189 | dev_err(&ar2->intf[0]->dev, | ||
190 | "%s(): usb_autopm_get_interface() = %d\n", __func__, r); | ||
191 | goto fail1; | ||
192 | } | ||
193 | |||
194 | mutex_lock(&ati_remote2_mutex); | ||
195 | |||
196 | if (!(ar2->flags & ATI_REMOTE2_SUSPENDED)) { | ||
197 | r = ati_remote2_submit_urbs(ar2); | ||
198 | if (r) | ||
199 | goto fail2; | ||
200 | } | ||
201 | |||
202 | ar2->flags |= ATI_REMOTE2_OPENED; | ||
203 | |||
204 | mutex_unlock(&ati_remote2_mutex); | ||
205 | |||
206 | usb_autopm_put_interface(ar2->intf[0]); | ||
207 | |||
208 | return 0; | ||
209 | |||
210 | fail2: | ||
211 | mutex_unlock(&ati_remote2_mutex); | ||
212 | usb_autopm_put_interface(ar2->intf[0]); | ||
213 | fail1: | ||
214 | return r; | ||
215 | } | ||
216 | |||
154 | static void ati_remote2_close(struct input_dev *idev) | 217 | static void ati_remote2_close(struct input_dev *idev) |
155 | { | 218 | { |
156 | struct ati_remote2 *ar2 = input_get_drvdata(idev); | 219 | struct ati_remote2 *ar2 = input_get_drvdata(idev); |
157 | 220 | ||
158 | usb_kill_urb(ar2->urb[0]); | 221 | dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); |
159 | usb_kill_urb(ar2->urb[1]); | 222 | |
223 | mutex_lock(&ati_remote2_mutex); | ||
224 | |||
225 | if (!(ar2->flags & ATI_REMOTE2_SUSPENDED)) | ||
226 | ati_remote2_kill_urbs(ar2); | ||
227 | |||
228 | ar2->flags &= ~ATI_REMOTE2_OPENED; | ||
229 | |||
230 | mutex_unlock(&ati_remote2_mutex); | ||
160 | } | 231 | } |
161 | 232 | ||
162 | static void ati_remote2_input_mouse(struct ati_remote2 *ar2) | 233 | static void ati_remote2_input_mouse(struct ati_remote2 *ar2) |
@@ -172,7 +243,7 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2) | |||
172 | 243 | ||
173 | mode = data[0] & 0x0F; | 244 | mode = data[0] & 0x0F; |
174 | 245 | ||
175 | if (mode > 4) { | 246 | if (mode > ATI_REMOTE2_PC) { |
176 | dev_err(&ar2->intf[0]->dev, | 247 | dev_err(&ar2->intf[0]->dev, |
177 | "Unknown mode byte (%02x %02x %02x %02x)\n", | 248 | "Unknown mode byte (%02x %02x %02x %02x)\n", |
178 | data[3], data[2], data[1], data[0]); | 249 | data[3], data[2], data[1], data[0]); |
@@ -191,7 +262,7 @@ static int ati_remote2_lookup(unsigned int hw_code) | |||
191 | { | 262 | { |
192 | int i; | 263 | int i; |
193 | 264 | ||
194 | for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) | 265 | for (i = 0; i < ARRAY_SIZE(ati_remote2_key_table); i++) |
195 | if (ati_remote2_key_table[i].hw_code == hw_code) | 266 | if (ati_remote2_key_table[i].hw_code == hw_code) |
196 | return i; | 267 | return i; |
197 | 268 | ||
@@ -211,7 +282,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
211 | 282 | ||
212 | mode = data[0] & 0x0F; | 283 | mode = data[0] & 0x0F; |
213 | 284 | ||
214 | if (mode > 4) { | 285 | if (mode > ATI_REMOTE2_PC) { |
215 | dev_err(&ar2->intf[1]->dev, | 286 | dev_err(&ar2->intf[1]->dev, |
216 | "Unknown mode byte (%02x %02x %02x %02x)\n", | 287 | "Unknown mode byte (%02x %02x %02x %02x)\n", |
217 | data[3], data[2], data[1], data[0]); | 288 | data[3], data[2], data[1], data[0]); |
@@ -219,10 +290,6 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
219 | } | 290 | } |
220 | 291 | ||
221 | hw_code = data[2]; | 292 | hw_code = data[2]; |
222 | /* | ||
223 | * Mode keys (AUX1-AUX4, PC) all generate the same code byte. | ||
224 | * Use the mode byte to figure out which one was pressed. | ||
225 | */ | ||
226 | if (hw_code == 0x3f) { | 293 | if (hw_code == 0x3f) { |
227 | /* | 294 | /* |
228 | * For some incomprehensible reason the mouse pad generates | 295 | * For some incomprehensible reason the mouse pad generates |
@@ -236,8 +303,6 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
236 | 303 | ||
237 | if (data[1] == 0) | 304 | if (data[1] == 0) |
238 | ar2->mode = mode; | 305 | ar2->mode = mode; |
239 | |||
240 | hw_code |= mode << 8; | ||
241 | } | 306 | } |
242 | 307 | ||
243 | if (!((1 << mode) & mode_mask)) | 308 | if (!((1 << mode) & mode_mask)) |
@@ -260,8 +325,8 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
260 | case 2: /* repeat */ | 325 | case 2: /* repeat */ |
261 | 326 | ||
262 | /* No repeat for mouse buttons. */ | 327 | /* No repeat for mouse buttons. */ |
263 | if (ati_remote2_key_table[index].key_code == BTN_LEFT || | 328 | if (ar2->keycode[mode][index] == BTN_LEFT || |
264 | ati_remote2_key_table[index].key_code == BTN_RIGHT) | 329 | ar2->keycode[mode][index] == BTN_RIGHT) |
265 | return; | 330 | return; |
266 | 331 | ||
267 | if (!time_after_eq(jiffies, ar2->jiffies)) | 332 | if (!time_after_eq(jiffies, ar2->jiffies)) |
@@ -276,7 +341,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
276 | return; | 341 | return; |
277 | } | 342 | } |
278 | 343 | ||
279 | input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]); | 344 | input_event(idev, EV_KEY, ar2->keycode[mode][index], data[1]); |
280 | input_sync(idev); | 345 | input_sync(idev); |
281 | } | 346 | } |
282 | 347 | ||
@@ -287,6 +352,7 @@ static void ati_remote2_complete_mouse(struct urb *urb) | |||
287 | 352 | ||
288 | switch (urb->status) { | 353 | switch (urb->status) { |
289 | case 0: | 354 | case 0: |
355 | usb_mark_last_busy(ar2->udev); | ||
290 | ati_remote2_input_mouse(ar2); | 356 | ati_remote2_input_mouse(ar2); |
291 | break; | 357 | break; |
292 | case -ENOENT: | 358 | case -ENOENT: |
@@ -297,6 +363,7 @@ static void ati_remote2_complete_mouse(struct urb *urb) | |||
297 | "%s(): urb status = %d\n", __func__, urb->status); | 363 | "%s(): urb status = %d\n", __func__, urb->status); |
298 | return; | 364 | return; |
299 | default: | 365 | default: |
366 | usb_mark_last_busy(ar2->udev); | ||
300 | dev_err(&ar2->intf[0]->dev, | 367 | dev_err(&ar2->intf[0]->dev, |
301 | "%s(): urb status = %d\n", __func__, urb->status); | 368 | "%s(): urb status = %d\n", __func__, urb->status); |
302 | } | 369 | } |
@@ -314,6 +381,7 @@ static void ati_remote2_complete_key(struct urb *urb) | |||
314 | 381 | ||
315 | switch (urb->status) { | 382 | switch (urb->status) { |
316 | case 0: | 383 | case 0: |
384 | usb_mark_last_busy(ar2->udev); | ||
317 | ati_remote2_input_key(ar2); | 385 | ati_remote2_input_key(ar2); |
318 | break; | 386 | break; |
319 | case -ENOENT: | 387 | case -ENOENT: |
@@ -324,6 +392,7 @@ static void ati_remote2_complete_key(struct urb *urb) | |||
324 | "%s(): urb status = %d\n", __func__, urb->status); | 392 | "%s(): urb status = %d\n", __func__, urb->status); |
325 | return; | 393 | return; |
326 | default: | 394 | default: |
395 | usb_mark_last_busy(ar2->udev); | ||
327 | dev_err(&ar2->intf[1]->dev, | 396 | dev_err(&ar2->intf[1]->dev, |
328 | "%s(): urb status = %d\n", __func__, urb->status); | 397 | "%s(): urb status = %d\n", __func__, urb->status); |
329 | } | 398 | } |
@@ -334,10 +403,60 @@ static void ati_remote2_complete_key(struct urb *urb) | |||
334 | "%s(): usb_submit_urb() = %d\n", __func__, r); | 403 | "%s(): usb_submit_urb() = %d\n", __func__, r); |
335 | } | 404 | } |
336 | 405 | ||
406 | static int ati_remote2_getkeycode(struct input_dev *idev, | ||
407 | int scancode, int *keycode) | ||
408 | { | ||
409 | struct ati_remote2 *ar2 = input_get_drvdata(idev); | ||
410 | int index, mode; | ||
411 | |||
412 | mode = scancode >> 8; | ||
413 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask)) | ||
414 | return -EINVAL; | ||
415 | |||
416 | index = ati_remote2_lookup(scancode & 0xFF); | ||
417 | if (index < 0) | ||
418 | return -EINVAL; | ||
419 | |||
420 | *keycode = ar2->keycode[mode][index]; | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keycode) | ||
425 | { | ||
426 | struct ati_remote2 *ar2 = input_get_drvdata(idev); | ||
427 | int index, mode, old_keycode; | ||
428 | |||
429 | mode = scancode >> 8; | ||
430 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask)) | ||
431 | return -EINVAL; | ||
432 | |||
433 | index = ati_remote2_lookup(scancode & 0xFF); | ||
434 | if (index < 0) | ||
435 | return -EINVAL; | ||
436 | |||
437 | if (keycode < KEY_RESERVED || keycode > KEY_MAX) | ||
438 | return -EINVAL; | ||
439 | |||
440 | old_keycode = ar2->keycode[mode][index]; | ||
441 | ar2->keycode[mode][index] = keycode; | ||
442 | set_bit(keycode, idev->keybit); | ||
443 | |||
444 | for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) { | ||
445 | for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) { | ||
446 | if (ar2->keycode[mode][index] == old_keycode) | ||
447 | return 0; | ||
448 | } | ||
449 | } | ||
450 | |||
451 | clear_bit(old_keycode, idev->keybit); | ||
452 | |||
453 | return 0; | ||
454 | } | ||
455 | |||
337 | static int ati_remote2_input_init(struct ati_remote2 *ar2) | 456 | static int ati_remote2_input_init(struct ati_remote2 *ar2) |
338 | { | 457 | { |
339 | struct input_dev *idev; | 458 | struct input_dev *idev; |
340 | int i, retval; | 459 | int index, mode, retval; |
341 | 460 | ||
342 | idev = input_allocate_device(); | 461 | idev = input_allocate_device(); |
343 | if (!idev) | 462 | if (!idev) |
@@ -350,8 +469,26 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) | |||
350 | idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | | 469 | idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | |
351 | BIT_MASK(BTN_RIGHT); | 470 | BIT_MASK(BTN_RIGHT); |
352 | idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); | 471 | idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); |
353 | for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) | 472 | |
354 | set_bit(ati_remote2_key_table[i].key_code, idev->keybit); | 473 | for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) { |
474 | for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) { | ||
475 | ar2->keycode[mode][index] = ati_remote2_key_table[index].keycode; | ||
476 | set_bit(ar2->keycode[mode][index], idev->keybit); | ||
477 | } | ||
478 | } | ||
479 | |||
480 | /* AUX1-AUX4 and PC generate the same scancode. */ | ||
481 | index = ati_remote2_lookup(0x3f); | ||
482 | ar2->keycode[ATI_REMOTE2_AUX1][index] = KEY_PROG1; | ||
483 | ar2->keycode[ATI_REMOTE2_AUX2][index] = KEY_PROG2; | ||
484 | ar2->keycode[ATI_REMOTE2_AUX3][index] = KEY_PROG3; | ||
485 | ar2->keycode[ATI_REMOTE2_AUX4][index] = KEY_PROG4; | ||
486 | ar2->keycode[ATI_REMOTE2_PC][index] = KEY_PC; | ||
487 | set_bit(KEY_PROG1, idev->keybit); | ||
488 | set_bit(KEY_PROG2, idev->keybit); | ||
489 | set_bit(KEY_PROG3, idev->keybit); | ||
490 | set_bit(KEY_PROG4, idev->keybit); | ||
491 | set_bit(KEY_PC, idev->keybit); | ||
355 | 492 | ||
356 | idev->rep[REP_DELAY] = 250; | 493 | idev->rep[REP_DELAY] = 250; |
357 | idev->rep[REP_PERIOD] = 33; | 494 | idev->rep[REP_PERIOD] = 33; |
@@ -359,6 +496,9 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) | |||
359 | idev->open = ati_remote2_open; | 496 | idev->open = ati_remote2_open; |
360 | idev->close = ati_remote2_close; | 497 | idev->close = ati_remote2_close; |
361 | 498 | ||
499 | idev->getkeycode = ati_remote2_getkeycode; | ||
500 | idev->setkeycode = ati_remote2_setkeycode; | ||
501 | |||
362 | idev->name = ar2->name; | 502 | idev->name = ar2->name; |
363 | idev->phys = ar2->phys; | 503 | idev->phys = ar2->phys; |
364 | 504 | ||
@@ -490,6 +630,8 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d | |||
490 | 630 | ||
491 | usb_set_intfdata(interface, ar2); | 631 | usb_set_intfdata(interface, ar2); |
492 | 632 | ||
633 | interface->needs_remote_wakeup = 1; | ||
634 | |||
493 | return 0; | 635 | return 0; |
494 | 636 | ||
495 | fail2: | 637 | fail2: |
@@ -522,6 +664,57 @@ static void ati_remote2_disconnect(struct usb_interface *interface) | |||
522 | kfree(ar2); | 664 | kfree(ar2); |
523 | } | 665 | } |
524 | 666 | ||
667 | static int ati_remote2_suspend(struct usb_interface *interface, | ||
668 | pm_message_t message) | ||
669 | { | ||
670 | struct ati_remote2 *ar2; | ||
671 | struct usb_host_interface *alt = interface->cur_altsetting; | ||
672 | |||
673 | if (alt->desc.bInterfaceNumber) | ||
674 | return 0; | ||
675 | |||
676 | ar2 = usb_get_intfdata(interface); | ||
677 | |||
678 | dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); | ||
679 | |||
680 | mutex_lock(&ati_remote2_mutex); | ||
681 | |||
682 | if (ar2->flags & ATI_REMOTE2_OPENED) | ||
683 | ati_remote2_kill_urbs(ar2); | ||
684 | |||
685 | ar2->flags |= ATI_REMOTE2_SUSPENDED; | ||
686 | |||
687 | mutex_unlock(&ati_remote2_mutex); | ||
688 | |||
689 | return 0; | ||
690 | } | ||
691 | |||
692 | static int ati_remote2_resume(struct usb_interface *interface) | ||
693 | { | ||
694 | struct ati_remote2 *ar2; | ||
695 | struct usb_host_interface *alt = interface->cur_altsetting; | ||
696 | int r = 0; | ||
697 | |||
698 | if (alt->desc.bInterfaceNumber) | ||
699 | return 0; | ||
700 | |||
701 | ar2 = usb_get_intfdata(interface); | ||
702 | |||
703 | dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); | ||
704 | |||
705 | mutex_lock(&ati_remote2_mutex); | ||
706 | |||
707 | if (ar2->flags & ATI_REMOTE2_OPENED) | ||
708 | r = ati_remote2_submit_urbs(ar2); | ||
709 | |||
710 | if (!r) | ||
711 | ar2->flags &= ~ATI_REMOTE2_SUSPENDED; | ||
712 | |||
713 | mutex_unlock(&ati_remote2_mutex); | ||
714 | |||
715 | return r; | ||
716 | } | ||
717 | |||
525 | static int __init ati_remote2_init(void) | 718 | static int __init ati_remote2_init(void) |
526 | { | 719 | { |
527 | int r; | 720 | int r; |
diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c new file mode 100644 index 000000000000..bce160f4349b --- /dev/null +++ b/drivers/input/misc/cm109.c | |||
@@ -0,0 +1,882 @@ | |||
1 | /* | ||
2 | * Driver for the VoIP USB phones with CM109 chipsets. | ||
3 | * | ||
4 | * Copyright (C) 2007 - 2008 Alfred E. Heggestad <aeh@db.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * Tested devices: | ||
13 | * - Komunikate KIP1000 | ||
14 | * - Genius G-talk | ||
15 | * - Allied-Telesis Corega USBPH01 | ||
16 | * - ... | ||
17 | * | ||
18 | * This driver is based on the yealink.c driver | ||
19 | * | ||
20 | * Thanks to: | ||
21 | * - Authors of yealink.c | ||
22 | * - Thomas Reitmayr | ||
23 | * - Oliver Neukum for good review comments and code | ||
24 | * - Shaun Jackman <sjackman@gmail.com> for Genius G-talk keymap | ||
25 | * - Dmitry Torokhov for valuable input and review | ||
26 | * | ||
27 | * Todo: | ||
28 | * - Read/write EEPROM | ||
29 | */ | ||
30 | |||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/moduleparam.h> | ||
36 | #include <linux/rwsem.h> | ||
37 | #include <linux/usb/input.h> | ||
38 | |||
39 | #define DRIVER_VERSION "20080805" | ||
40 | #define DRIVER_AUTHOR "Alfred E. Heggestad" | ||
41 | #define DRIVER_DESC "CM109 phone driver" | ||
42 | |||
43 | static char *phone = "kip1000"; | ||
44 | module_param(phone, charp, S_IRUSR); | ||
45 | MODULE_PARM_DESC(phone, "Phone name {kip1000, gtalk, usbph01}"); | ||
46 | |||
47 | enum { | ||
48 | /* HID Registers */ | ||
49 | HID_IR0 = 0x00, /* Record/Playback-mute button, Volume up/down */ | ||
50 | HID_IR1 = 0x01, /* GPI, generic registers or EEPROM_DATA0 */ | ||
51 | HID_IR2 = 0x02, /* Generic registers or EEPROM_DATA1 */ | ||
52 | HID_IR3 = 0x03, /* Generic registers or EEPROM_CTRL */ | ||
53 | HID_OR0 = 0x00, /* Mapping control, buzzer, SPDIF (offset 0x04) */ | ||
54 | HID_OR1 = 0x01, /* GPO - General Purpose Output */ | ||
55 | HID_OR2 = 0x02, /* Set GPIO to input/output mode */ | ||
56 | HID_OR3 = 0x03, /* SPDIF status channel or EEPROM_CTRL */ | ||
57 | |||
58 | /* HID_IR0 */ | ||
59 | RECORD_MUTE = 1 << 3, | ||
60 | PLAYBACK_MUTE = 1 << 2, | ||
61 | VOLUME_DOWN = 1 << 1, | ||
62 | VOLUME_UP = 1 << 0, | ||
63 | |||
64 | /* HID_OR0 */ | ||
65 | /* bits 7-6 | ||
66 | 0: HID_OR1-2 are used for GPO; HID_OR0, 3 are used for buzzer | ||
67 | and SPDIF | ||
68 | 1: HID_OR0-3 are used as generic HID registers | ||
69 | 2: Values written to HID_OR0-3 are also mapped to MCU_CTRL, | ||
70 | EEPROM_DATA0-1, EEPROM_CTRL (see Note) | ||
71 | 3: Reserved | ||
72 | */ | ||
73 | HID_OR_GPO_BUZ_SPDIF = 0 << 6, | ||
74 | HID_OR_GENERIC_HID_REG = 1 << 6, | ||
75 | HID_OR_MAP_MCU_EEPROM = 2 << 6, | ||
76 | |||
77 | BUZZER_ON = 1 << 5, | ||
78 | |||
79 | /* up to 256 normal keys, up to 16 special keys */ | ||
80 | KEYMAP_SIZE = 256 + 16, | ||
81 | }; | ||
82 | |||
83 | /* CM109 protocol packet */ | ||
84 | struct cm109_ctl_packet { | ||
85 | u8 byte[4]; | ||
86 | } __attribute__ ((packed)); | ||
87 | |||
88 | enum { USB_PKT_LEN = sizeof(struct cm109_ctl_packet) }; | ||
89 | |||
90 | /* CM109 device structure */ | ||
91 | struct cm109_dev { | ||
92 | struct input_dev *idev; /* input device */ | ||
93 | struct usb_device *udev; /* usb device */ | ||
94 | struct usb_interface *intf; | ||
95 | |||
96 | /* irq input channel */ | ||
97 | struct cm109_ctl_packet *irq_data; | ||
98 | dma_addr_t irq_dma; | ||
99 | struct urb *urb_irq; | ||
100 | |||
101 | /* control output channel */ | ||
102 | struct cm109_ctl_packet *ctl_data; | ||
103 | dma_addr_t ctl_dma; | ||
104 | struct usb_ctrlrequest *ctl_req; | ||
105 | dma_addr_t ctl_req_dma; | ||
106 | struct urb *urb_ctl; | ||
107 | /* | ||
108 | * The 3 bitfields below are protected by ctl_submit_lock. | ||
109 | * They have to be separate since they are accessed from IRQ | ||
110 | * context. | ||
111 | */ | ||
112 | unsigned irq_urb_pending:1; /* irq_urb is in flight */ | ||
113 | unsigned ctl_urb_pending:1; /* ctl_urb is in flight */ | ||
114 | unsigned buzzer_pending:1; /* need to issue buzz command */ | ||
115 | spinlock_t ctl_submit_lock; | ||
116 | |||
117 | unsigned char buzzer_state; /* on/off */ | ||
118 | |||
119 | /* flags */ | ||
120 | unsigned open:1; | ||
121 | unsigned resetting:1; | ||
122 | unsigned shutdown:1; | ||
123 | |||
124 | /* This mutex protects writes to the above flags */ | ||
125 | struct mutex pm_mutex; | ||
126 | |||
127 | unsigned short keymap[KEYMAP_SIZE]; | ||
128 | |||
129 | char phys[64]; /* physical device path */ | ||
130 | int key_code; /* last reported key */ | ||
131 | int keybit; /* 0=new scan 1,2,4,8=scan columns */ | ||
132 | u8 gpi; /* Cached value of GPI (high nibble) */ | ||
133 | }; | ||
134 | |||
135 | /****************************************************************************** | ||
136 | * CM109 key interface | ||
137 | *****************************************************************************/ | ||
138 | |||
139 | static unsigned short special_keymap(int code) | ||
140 | { | ||
141 | if (code > 0xff) { | ||
142 | switch (code - 0xff) { | ||
143 | case RECORD_MUTE: return KEY_MUTE; | ||
144 | case PLAYBACK_MUTE: return KEY_MUTE; | ||
145 | case VOLUME_DOWN: return KEY_VOLUMEDOWN; | ||
146 | case VOLUME_UP: return KEY_VOLUMEUP; | ||
147 | } | ||
148 | } | ||
149 | return KEY_RESERVED; | ||
150 | } | ||
151 | |||
152 | /* Map device buttons to internal key events. | ||
153 | * | ||
154 | * The "up" and "down" keys, are symbolised by arrows on the button. | ||
155 | * The "pickup" and "hangup" keys are symbolised by a green and red phone | ||
156 | * on the button. | ||
157 | |||
158 | Komunikate KIP1000 Keyboard Matrix | ||
159 | |||
160 | -> -- 1 -- 2 -- 3 --> GPI pin 4 (0x10) | ||
161 | | | | | | ||
162 | <- -- 4 -- 5 -- 6 --> GPI pin 5 (0x20) | ||
163 | | | | | | ||
164 | END - 7 -- 8 -- 9 --> GPI pin 6 (0x40) | ||
165 | | | | | | ||
166 | OK -- * -- 0 -- # --> GPI pin 7 (0x80) | ||
167 | | | | | | ||
168 | |||
169 | /|\ /|\ /|\ /|\ | ||
170 | | | | | | ||
171 | GPO | ||
172 | pin: 3 2 1 0 | ||
173 | 0x8 0x4 0x2 0x1 | ||
174 | |||
175 | */ | ||
176 | static unsigned short keymap_kip1000(int scancode) | ||
177 | { | ||
178 | switch (scancode) { /* phone key: */ | ||
179 | case 0x82: return KEY_NUMERIC_0; /* 0 */ | ||
180 | case 0x14: return KEY_NUMERIC_1; /* 1 */ | ||
181 | case 0x12: return KEY_NUMERIC_2; /* 2 */ | ||
182 | case 0x11: return KEY_NUMERIC_3; /* 3 */ | ||
183 | case 0x24: return KEY_NUMERIC_4; /* 4 */ | ||
184 | case 0x22: return KEY_NUMERIC_5; /* 5 */ | ||
185 | case 0x21: return KEY_NUMERIC_6; /* 6 */ | ||
186 | case 0x44: return KEY_NUMERIC_7; /* 7 */ | ||
187 | case 0x42: return KEY_NUMERIC_8; /* 8 */ | ||
188 | case 0x41: return KEY_NUMERIC_9; /* 9 */ | ||
189 | case 0x81: return KEY_NUMERIC_POUND; /* # */ | ||
190 | case 0x84: return KEY_NUMERIC_STAR; /* * */ | ||
191 | case 0x88: return KEY_ENTER; /* pickup */ | ||
192 | case 0x48: return KEY_ESC; /* hangup */ | ||
193 | case 0x28: return KEY_LEFT; /* IN */ | ||
194 | case 0x18: return KEY_RIGHT; /* OUT */ | ||
195 | default: return special_keymap(scancode); | ||
196 | } | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | Contributed by Shaun Jackman <sjackman@gmail.com> | ||
201 | |||
202 | Genius G-Talk keyboard matrix | ||
203 | 0 1 2 3 | ||
204 | 4: 0 4 8 Talk | ||
205 | 5: 1 5 9 End | ||
206 | 6: 2 6 # Up | ||
207 | 7: 3 7 * Down | ||
208 | */ | ||
209 | static unsigned short keymap_gtalk(int scancode) | ||
210 | { | ||
211 | switch (scancode) { | ||
212 | case 0x11: return KEY_NUMERIC_0; | ||
213 | case 0x21: return KEY_NUMERIC_1; | ||
214 | case 0x41: return KEY_NUMERIC_2; | ||
215 | case 0x81: return KEY_NUMERIC_3; | ||
216 | case 0x12: return KEY_NUMERIC_4; | ||
217 | case 0x22: return KEY_NUMERIC_5; | ||
218 | case 0x42: return KEY_NUMERIC_6; | ||
219 | case 0x82: return KEY_NUMERIC_7; | ||
220 | case 0x14: return KEY_NUMERIC_8; | ||
221 | case 0x24: return KEY_NUMERIC_9; | ||
222 | case 0x44: return KEY_NUMERIC_POUND; /* # */ | ||
223 | case 0x84: return KEY_NUMERIC_STAR; /* * */ | ||
224 | case 0x18: return KEY_ENTER; /* Talk (green handset) */ | ||
225 | case 0x28: return KEY_ESC; /* End (red handset) */ | ||
226 | case 0x48: return KEY_UP; /* Menu up (rocker switch) */ | ||
227 | case 0x88: return KEY_DOWN; /* Menu down (rocker switch) */ | ||
228 | default: return special_keymap(scancode); | ||
229 | } | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | * Keymap for Allied-Telesis Corega USBPH01 | ||
234 | * http://www.alliedtelesis-corega.com/2/1344/1437/1360/chprd.html | ||
235 | * | ||
236 | * Contributed by july@nat.bg | ||
237 | */ | ||
238 | static unsigned short keymap_usbph01(int scancode) | ||
239 | { | ||
240 | switch (scancode) { | ||
241 | case 0x11: return KEY_NUMERIC_0; /* 0 */ | ||
242 | case 0x21: return KEY_NUMERIC_1; /* 1 */ | ||
243 | case 0x41: return KEY_NUMERIC_2; /* 2 */ | ||
244 | case 0x81: return KEY_NUMERIC_3; /* 3 */ | ||
245 | case 0x12: return KEY_NUMERIC_4; /* 4 */ | ||
246 | case 0x22: return KEY_NUMERIC_5; /* 5 */ | ||
247 | case 0x42: return KEY_NUMERIC_6; /* 6 */ | ||
248 | case 0x82: return KEY_NUMERIC_7; /* 7 */ | ||
249 | case 0x14: return KEY_NUMERIC_8; /* 8 */ | ||
250 | case 0x24: return KEY_NUMERIC_9; /* 9 */ | ||
251 | case 0x44: return KEY_NUMERIC_POUND; /* # */ | ||
252 | case 0x84: return KEY_NUMERIC_STAR; /* * */ | ||
253 | case 0x18: return KEY_ENTER; /* pickup */ | ||
254 | case 0x28: return KEY_ESC; /* hangup */ | ||
255 | case 0x48: return KEY_LEFT; /* IN */ | ||
256 | case 0x88: return KEY_RIGHT; /* OUT */ | ||
257 | default: return special_keymap(scancode); | ||
258 | } | ||
259 | } | ||
260 | |||
261 | static unsigned short (*keymap)(int) = keymap_kip1000; | ||
262 | |||
263 | /* | ||
264 | * Completes a request by converting the data into events for the | ||
265 | * input subsystem. | ||
266 | */ | ||
267 | static void report_key(struct cm109_dev *dev, int key) | ||
268 | { | ||
269 | struct input_dev *idev = dev->idev; | ||
270 | |||
271 | if (dev->key_code >= 0) { | ||
272 | /* old key up */ | ||
273 | input_report_key(idev, dev->key_code, 0); | ||
274 | } | ||
275 | |||
276 | dev->key_code = key; | ||
277 | if (key >= 0) { | ||
278 | /* new valid key */ | ||
279 | input_report_key(idev, key, 1); | ||
280 | } | ||
281 | |||
282 | input_sync(idev); | ||
283 | } | ||
284 | |||
285 | /****************************************************************************** | ||
286 | * CM109 usb communication interface | ||
287 | *****************************************************************************/ | ||
288 | |||
289 | static void cm109_submit_buzz_toggle(struct cm109_dev *dev) | ||
290 | { | ||
291 | int error; | ||
292 | |||
293 | if (dev->buzzer_state) | ||
294 | dev->ctl_data->byte[HID_OR0] |= BUZZER_ON; | ||
295 | else | ||
296 | dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON; | ||
297 | |||
298 | error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC); | ||
299 | if (error) | ||
300 | err("%s: usb_submit_urb (urb_ctl) failed %d", __func__, error); | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * IRQ handler | ||
305 | */ | ||
306 | static void cm109_urb_irq_callback(struct urb *urb) | ||
307 | { | ||
308 | struct cm109_dev *dev = urb->context; | ||
309 | const int status = urb->status; | ||
310 | int error; | ||
311 | |||
312 | dev_dbg(&urb->dev->dev, "### URB IRQ: [0x%02x 0x%02x 0x%02x 0x%02x] keybit=0x%02x\n", | ||
313 | dev->irq_data->byte[0], | ||
314 | dev->irq_data->byte[1], | ||
315 | dev->irq_data->byte[2], | ||
316 | dev->irq_data->byte[3], | ||
317 | dev->keybit); | ||
318 | |||
319 | if (status) { | ||
320 | if (status == -ESHUTDOWN) | ||
321 | return; | ||
322 | err("%s: urb status %d", __func__, status); | ||
323 | } | ||
324 | |||
325 | /* Special keys */ | ||
326 | if (dev->irq_data->byte[HID_IR0] & 0x0f) { | ||
327 | const int code = (dev->irq_data->byte[HID_IR0] & 0x0f); | ||
328 | report_key(dev, dev->keymap[0xff + code]); | ||
329 | } | ||
330 | |||
331 | /* Scan key column */ | ||
332 | if (dev->keybit == 0xf) { | ||
333 | |||
334 | /* Any changes ? */ | ||
335 | if ((dev->gpi & 0xf0) == (dev->irq_data->byte[HID_IR1] & 0xf0)) | ||
336 | goto out; | ||
337 | |||
338 | dev->gpi = dev->irq_data->byte[HID_IR1] & 0xf0; | ||
339 | dev->keybit = 0x1; | ||
340 | } else { | ||
341 | report_key(dev, dev->keymap[dev->irq_data->byte[HID_IR1]]); | ||
342 | |||
343 | dev->keybit <<= 1; | ||
344 | if (dev->keybit > 0x8) | ||
345 | dev->keybit = 0xf; | ||
346 | } | ||
347 | |||
348 | out: | ||
349 | |||
350 | spin_lock(&dev->ctl_submit_lock); | ||
351 | |||
352 | dev->irq_urb_pending = 0; | ||
353 | |||
354 | if (likely(!dev->shutdown)) { | ||
355 | |||
356 | if (dev->buzzer_state) | ||
357 | dev->ctl_data->byte[HID_OR0] |= BUZZER_ON; | ||
358 | else | ||
359 | dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON; | ||
360 | |||
361 | dev->ctl_data->byte[HID_OR1] = dev->keybit; | ||
362 | dev->ctl_data->byte[HID_OR2] = dev->keybit; | ||
363 | |||
364 | dev->buzzer_pending = 0; | ||
365 | dev->ctl_urb_pending = 1; | ||
366 | |||
367 | error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC); | ||
368 | if (error) | ||
369 | err("%s: usb_submit_urb (urb_ctl) failed %d", | ||
370 | __func__, error); | ||
371 | } | ||
372 | |||
373 | spin_unlock(&dev->ctl_submit_lock); | ||
374 | } | ||
375 | |||
376 | static void cm109_urb_ctl_callback(struct urb *urb) | ||
377 | { | ||
378 | struct cm109_dev *dev = urb->context; | ||
379 | const int status = urb->status; | ||
380 | int error; | ||
381 | |||
382 | dev_dbg(&urb->dev->dev, "### URB CTL: [0x%02x 0x%02x 0x%02x 0x%02x]\n", | ||
383 | dev->ctl_data->byte[0], | ||
384 | dev->ctl_data->byte[1], | ||
385 | dev->ctl_data->byte[2], | ||
386 | dev->ctl_data->byte[3]); | ||
387 | |||
388 | if (status) | ||
389 | err("%s: urb status %d", __func__, status); | ||
390 | |||
391 | spin_lock(&dev->ctl_submit_lock); | ||
392 | |||
393 | dev->ctl_urb_pending = 0; | ||
394 | |||
395 | if (likely(!dev->shutdown)) { | ||
396 | |||
397 | if (dev->buzzer_pending) { | ||
398 | dev->buzzer_pending = 0; | ||
399 | dev->ctl_urb_pending = 1; | ||
400 | cm109_submit_buzz_toggle(dev); | ||
401 | } else if (likely(!dev->irq_urb_pending)) { | ||
402 | /* ask for key data */ | ||
403 | dev->irq_urb_pending = 1; | ||
404 | error = usb_submit_urb(dev->urb_irq, GFP_ATOMIC); | ||
405 | if (error) | ||
406 | err("%s: usb_submit_urb (urb_irq) failed %d", | ||
407 | __func__, error); | ||
408 | } | ||
409 | } | ||
410 | |||
411 | spin_unlock(&dev->ctl_submit_lock); | ||
412 | } | ||
413 | |||
414 | static void cm109_toggle_buzzer_async(struct cm109_dev *dev) | ||
415 | { | ||
416 | unsigned long flags; | ||
417 | |||
418 | spin_lock_irqsave(&dev->ctl_submit_lock, flags); | ||
419 | |||
420 | if (dev->ctl_urb_pending) { | ||
421 | /* URB completion will resubmit */ | ||
422 | dev->buzzer_pending = 1; | ||
423 | } else { | ||
424 | dev->ctl_urb_pending = 1; | ||
425 | cm109_submit_buzz_toggle(dev); | ||
426 | } | ||
427 | |||
428 | spin_unlock_irqrestore(&dev->ctl_submit_lock, flags); | ||
429 | } | ||
430 | |||
431 | static void cm109_toggle_buzzer_sync(struct cm109_dev *dev, int on) | ||
432 | { | ||
433 | int error; | ||
434 | |||
435 | if (on) | ||
436 | dev->ctl_data->byte[HID_OR0] |= BUZZER_ON; | ||
437 | else | ||
438 | dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON; | ||
439 | |||
440 | error = usb_control_msg(dev->udev, | ||
441 | usb_sndctrlpipe(dev->udev, 0), | ||
442 | dev->ctl_req->bRequest, | ||
443 | dev->ctl_req->bRequestType, | ||
444 | le16_to_cpu(dev->ctl_req->wValue), | ||
445 | le16_to_cpu(dev->ctl_req->wIndex), | ||
446 | dev->ctl_data, | ||
447 | USB_PKT_LEN, USB_CTRL_SET_TIMEOUT); | ||
448 | if (error && error != EINTR) | ||
449 | err("%s: usb_control_msg() failed %d", __func__, error); | ||
450 | } | ||
451 | |||
452 | static void cm109_stop_traffic(struct cm109_dev *dev) | ||
453 | { | ||
454 | dev->shutdown = 1; | ||
455 | /* | ||
456 | * Make sure other CPUs see this | ||
457 | */ | ||
458 | smp_wmb(); | ||
459 | |||
460 | usb_kill_urb(dev->urb_ctl); | ||
461 | usb_kill_urb(dev->urb_irq); | ||
462 | |||
463 | cm109_toggle_buzzer_sync(dev, 0); | ||
464 | |||
465 | dev->shutdown = 0; | ||
466 | smp_wmb(); | ||
467 | } | ||
468 | |||
469 | static void cm109_restore_state(struct cm109_dev *dev) | ||
470 | { | ||
471 | if (dev->open) { | ||
472 | /* | ||
473 | * Restore buzzer state. | ||
474 | * This will also kick regular URB submission | ||
475 | */ | ||
476 | cm109_toggle_buzzer_async(dev); | ||
477 | } | ||
478 | } | ||
479 | |||
480 | /****************************************************************************** | ||
481 | * input event interface | ||
482 | *****************************************************************************/ | ||
483 | |||
484 | static int cm109_input_open(struct input_dev *idev) | ||
485 | { | ||
486 | struct cm109_dev *dev = input_get_drvdata(idev); | ||
487 | int error; | ||
488 | |||
489 | error = usb_autopm_get_interface(dev->intf); | ||
490 | if (error < 0) { | ||
491 | err("%s - cannot autoresume, result %d", | ||
492 | __func__, error); | ||
493 | return error; | ||
494 | } | ||
495 | |||
496 | mutex_lock(&dev->pm_mutex); | ||
497 | |||
498 | dev->buzzer_state = 0; | ||
499 | dev->key_code = -1; /* no keys pressed */ | ||
500 | dev->keybit = 0xf; | ||
501 | |||
502 | /* issue INIT */ | ||
503 | dev->ctl_data->byte[HID_OR0] = HID_OR_GPO_BUZ_SPDIF; | ||
504 | dev->ctl_data->byte[HID_OR1] = dev->keybit; | ||
505 | dev->ctl_data->byte[HID_OR2] = dev->keybit; | ||
506 | dev->ctl_data->byte[HID_OR3] = 0x00; | ||
507 | |||
508 | error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL); | ||
509 | if (error) | ||
510 | err("%s: usb_submit_urb (urb_ctl) failed %d", __func__, error); | ||
511 | else | ||
512 | dev->open = 1; | ||
513 | |||
514 | mutex_unlock(&dev->pm_mutex); | ||
515 | |||
516 | if (error) | ||
517 | usb_autopm_put_interface(dev->intf); | ||
518 | |||
519 | return error; | ||
520 | } | ||
521 | |||
522 | static void cm109_input_close(struct input_dev *idev) | ||
523 | { | ||
524 | struct cm109_dev *dev = input_get_drvdata(idev); | ||
525 | |||
526 | mutex_lock(&dev->pm_mutex); | ||
527 | |||
528 | /* | ||
529 | * Once we are here event delivery is stopped so we | ||
530 | * don't need to worry about someone starting buzzer | ||
531 | * again | ||
532 | */ | ||
533 | cm109_stop_traffic(dev); | ||
534 | dev->open = 0; | ||
535 | |||
536 | mutex_unlock(&dev->pm_mutex); | ||
537 | |||
538 | usb_autopm_put_interface(dev->intf); | ||
539 | } | ||
540 | |||
541 | static int cm109_input_ev(struct input_dev *idev, unsigned int type, | ||
542 | unsigned int code, int value) | ||
543 | { | ||
544 | struct cm109_dev *dev = input_get_drvdata(idev); | ||
545 | |||
546 | dev_dbg(&dev->udev->dev, | ||
547 | "input_ev: type=%u code=%u value=%d\n", type, code, value); | ||
548 | |||
549 | if (type != EV_SND) | ||
550 | return -EINVAL; | ||
551 | |||
552 | switch (code) { | ||
553 | case SND_TONE: | ||
554 | case SND_BELL: | ||
555 | dev->buzzer_state = !!value; | ||
556 | if (!dev->resetting) | ||
557 | cm109_toggle_buzzer_async(dev); | ||
558 | return 0; | ||
559 | |||
560 | default: | ||
561 | return -EINVAL; | ||
562 | } | ||
563 | } | ||
564 | |||
565 | |||
566 | /****************************************************************************** | ||
567 | * Linux interface and usb initialisation | ||
568 | *****************************************************************************/ | ||
569 | |||
570 | struct driver_info { | ||
571 | char *name; | ||
572 | }; | ||
573 | |||
574 | static const struct driver_info info_cm109 = { | ||
575 | .name = "CM109 USB driver", | ||
576 | }; | ||
577 | |||
578 | enum { | ||
579 | VENDOR_ID = 0x0d8c, /* C-Media Electronics */ | ||
580 | PRODUCT_ID_CM109 = 0x000e, /* CM109 defines range 0x0008 - 0x000f */ | ||
581 | }; | ||
582 | |||
583 | /* table of devices that work with this driver */ | ||
584 | static const struct usb_device_id cm109_usb_table[] = { | ||
585 | { | ||
586 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | | ||
587 | USB_DEVICE_ID_MATCH_INT_INFO, | ||
588 | .idVendor = VENDOR_ID, | ||
589 | .idProduct = PRODUCT_ID_CM109, | ||
590 | .bInterfaceClass = USB_CLASS_HID, | ||
591 | .bInterfaceSubClass = 0, | ||
592 | .bInterfaceProtocol = 0, | ||
593 | .driver_info = (kernel_ulong_t) &info_cm109 | ||
594 | }, | ||
595 | /* you can add more devices here with product ID 0x0008 - 0x000f */ | ||
596 | { } | ||
597 | }; | ||
598 | |||
599 | static void cm109_usb_cleanup(struct cm109_dev *dev) | ||
600 | { | ||
601 | if (dev->ctl_req) | ||
602 | usb_buffer_free(dev->udev, sizeof(*(dev->ctl_req)), | ||
603 | dev->ctl_req, dev->ctl_req_dma); | ||
604 | if (dev->ctl_data) | ||
605 | usb_buffer_free(dev->udev, USB_PKT_LEN, | ||
606 | dev->ctl_data, dev->ctl_dma); | ||
607 | if (dev->irq_data) | ||
608 | usb_buffer_free(dev->udev, USB_PKT_LEN, | ||
609 | dev->irq_data, dev->irq_dma); | ||
610 | |||
611 | usb_free_urb(dev->urb_irq); /* parameter validation in core/urb */ | ||
612 | usb_free_urb(dev->urb_ctl); /* parameter validation in core/urb */ | ||
613 | kfree(dev); | ||
614 | } | ||
615 | |||
616 | static void cm109_usb_disconnect(struct usb_interface *interface) | ||
617 | { | ||
618 | struct cm109_dev *dev = usb_get_intfdata(interface); | ||
619 | |||
620 | usb_set_intfdata(interface, NULL); | ||
621 | input_unregister_device(dev->idev); | ||
622 | cm109_usb_cleanup(dev); | ||
623 | } | ||
624 | |||
625 | static int cm109_usb_probe(struct usb_interface *intf, | ||
626 | const struct usb_device_id *id) | ||
627 | { | ||
628 | struct usb_device *udev = interface_to_usbdev(intf); | ||
629 | struct driver_info *nfo = (struct driver_info *)id->driver_info; | ||
630 | struct usb_host_interface *interface; | ||
631 | struct usb_endpoint_descriptor *endpoint; | ||
632 | struct cm109_dev *dev; | ||
633 | struct input_dev *input_dev = NULL; | ||
634 | int ret, pipe, i; | ||
635 | int error = -ENOMEM; | ||
636 | |||
637 | interface = intf->cur_altsetting; | ||
638 | endpoint = &interface->endpoint[0].desc; | ||
639 | |||
640 | if (!usb_endpoint_is_int_in(endpoint)) | ||
641 | return -ENODEV; | ||
642 | |||
643 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
644 | if (!dev) | ||
645 | return -ENOMEM; | ||
646 | |||
647 | spin_lock_init(&dev->ctl_submit_lock); | ||
648 | mutex_init(&dev->pm_mutex); | ||
649 | |||
650 | dev->udev = udev; | ||
651 | dev->intf = intf; | ||
652 | |||
653 | dev->idev = input_dev = input_allocate_device(); | ||
654 | if (!input_dev) | ||
655 | goto err_out; | ||
656 | |||
657 | /* allocate usb buffers */ | ||
658 | dev->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, | ||
659 | GFP_KERNEL, &dev->irq_dma); | ||
660 | if (!dev->irq_data) | ||
661 | goto err_out; | ||
662 | |||
663 | dev->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN, | ||
664 | GFP_KERNEL, &dev->ctl_dma); | ||
665 | if (!dev->ctl_data) | ||
666 | goto err_out; | ||
667 | |||
668 | dev->ctl_req = usb_buffer_alloc(udev, sizeof(*(dev->ctl_req)), | ||
669 | GFP_KERNEL, &dev->ctl_req_dma); | ||
670 | if (!dev->ctl_req) | ||
671 | goto err_out; | ||
672 | |||
673 | /* allocate urb structures */ | ||
674 | dev->urb_irq = usb_alloc_urb(0, GFP_KERNEL); | ||
675 | if (!dev->urb_irq) | ||
676 | goto err_out; | ||
677 | |||
678 | dev->urb_ctl = usb_alloc_urb(0, GFP_KERNEL); | ||
679 | if (!dev->urb_ctl) | ||
680 | goto err_out; | ||
681 | |||
682 | /* get a handle to the interrupt data pipe */ | ||
683 | pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); | ||
684 | ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
685 | if (ret != USB_PKT_LEN) | ||
686 | err("invalid payload size %d, expected %d", ret, USB_PKT_LEN); | ||
687 | |||
688 | /* initialise irq urb */ | ||
689 | usb_fill_int_urb(dev->urb_irq, udev, pipe, dev->irq_data, | ||
690 | USB_PKT_LEN, | ||
691 | cm109_urb_irq_callback, dev, endpoint->bInterval); | ||
692 | dev->urb_irq->transfer_dma = dev->irq_dma; | ||
693 | dev->urb_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
694 | dev->urb_irq->dev = udev; | ||
695 | |||
696 | /* initialise ctl urb */ | ||
697 | dev->ctl_req->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | | ||
698 | USB_DIR_OUT; | ||
699 | dev->ctl_req->bRequest = USB_REQ_SET_CONFIGURATION; | ||
700 | dev->ctl_req->wValue = cpu_to_le16(0x200); | ||
701 | dev->ctl_req->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); | ||
702 | dev->ctl_req->wLength = cpu_to_le16(USB_PKT_LEN); | ||
703 | |||
704 | usb_fill_control_urb(dev->urb_ctl, udev, usb_sndctrlpipe(udev, 0), | ||
705 | (void *)dev->ctl_req, dev->ctl_data, USB_PKT_LEN, | ||
706 | cm109_urb_ctl_callback, dev); | ||
707 | dev->urb_ctl->setup_dma = dev->ctl_req_dma; | ||
708 | dev->urb_ctl->transfer_dma = dev->ctl_dma; | ||
709 | dev->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP | | ||
710 | URB_NO_TRANSFER_DMA_MAP; | ||
711 | dev->urb_ctl->dev = udev; | ||
712 | |||
713 | /* find out the physical bus location */ | ||
714 | usb_make_path(udev, dev->phys, sizeof(dev->phys)); | ||
715 | strlcat(dev->phys, "/input0", sizeof(dev->phys)); | ||
716 | |||
717 | /* register settings for the input device */ | ||
718 | input_dev->name = nfo->name; | ||
719 | input_dev->phys = dev->phys; | ||
720 | usb_to_input_id(udev, &input_dev->id); | ||
721 | input_dev->dev.parent = &intf->dev; | ||
722 | |||
723 | input_set_drvdata(input_dev, dev); | ||
724 | input_dev->open = cm109_input_open; | ||
725 | input_dev->close = cm109_input_close; | ||
726 | input_dev->event = cm109_input_ev; | ||
727 | |||
728 | input_dev->keycode = dev->keymap; | ||
729 | input_dev->keycodesize = sizeof(unsigned char); | ||
730 | input_dev->keycodemax = ARRAY_SIZE(dev->keymap); | ||
731 | |||
732 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_SND); | ||
733 | input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); | ||
734 | |||
735 | /* register available key events */ | ||
736 | for (i = 0; i < KEYMAP_SIZE; i++) { | ||
737 | unsigned short k = keymap(i); | ||
738 | dev->keymap[i] = k; | ||
739 | __set_bit(k, input_dev->keybit); | ||
740 | } | ||
741 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
742 | |||
743 | error = input_register_device(dev->idev); | ||
744 | if (error) | ||
745 | goto err_out; | ||
746 | |||
747 | usb_set_intfdata(intf, dev); | ||
748 | |||
749 | return 0; | ||
750 | |||
751 | err_out: | ||
752 | input_free_device(input_dev); | ||
753 | cm109_usb_cleanup(dev); | ||
754 | return error; | ||
755 | } | ||
756 | |||
757 | static int cm109_usb_suspend(struct usb_interface *intf, pm_message_t message) | ||
758 | { | ||
759 | struct cm109_dev *dev = usb_get_intfdata(intf); | ||
760 | |||
761 | dev_info(&intf->dev, "cm109: usb_suspend (event=%d)\n", message.event); | ||
762 | |||
763 | mutex_lock(&dev->pm_mutex); | ||
764 | cm109_stop_traffic(dev); | ||
765 | mutex_unlock(&dev->pm_mutex); | ||
766 | |||
767 | return 0; | ||
768 | } | ||
769 | |||
770 | static int cm109_usb_resume(struct usb_interface *intf) | ||
771 | { | ||
772 | struct cm109_dev *dev = usb_get_intfdata(intf); | ||
773 | |||
774 | dev_info(&intf->dev, "cm109: usb_resume\n"); | ||
775 | |||
776 | mutex_lock(&dev->pm_mutex); | ||
777 | cm109_restore_state(dev); | ||
778 | mutex_unlock(&dev->pm_mutex); | ||
779 | |||
780 | return 0; | ||
781 | } | ||
782 | |||
783 | static int cm109_usb_pre_reset(struct usb_interface *intf) | ||
784 | { | ||
785 | struct cm109_dev *dev = usb_get_intfdata(intf); | ||
786 | |||
787 | mutex_lock(&dev->pm_mutex); | ||
788 | |||
789 | /* | ||
790 | * Make sure input events don't try to toggle buzzer | ||
791 | * while we are resetting | ||
792 | */ | ||
793 | dev->resetting = 1; | ||
794 | smp_wmb(); | ||
795 | |||
796 | cm109_stop_traffic(dev); | ||
797 | |||
798 | return 0; | ||
799 | } | ||
800 | |||
801 | static int cm109_usb_post_reset(struct usb_interface *intf) | ||
802 | { | ||
803 | struct cm109_dev *dev = usb_get_intfdata(intf); | ||
804 | |||
805 | dev->resetting = 0; | ||
806 | smp_wmb(); | ||
807 | |||
808 | cm109_restore_state(dev); | ||
809 | |||
810 | mutex_unlock(&dev->pm_mutex); | ||
811 | |||
812 | return 0; | ||
813 | } | ||
814 | |||
815 | static struct usb_driver cm109_driver = { | ||
816 | .name = "cm109", | ||
817 | .probe = cm109_usb_probe, | ||
818 | .disconnect = cm109_usb_disconnect, | ||
819 | .suspend = cm109_usb_suspend, | ||
820 | .resume = cm109_usb_resume, | ||
821 | .reset_resume = cm109_usb_resume, | ||
822 | .pre_reset = cm109_usb_pre_reset, | ||
823 | .post_reset = cm109_usb_post_reset, | ||
824 | .id_table = cm109_usb_table, | ||
825 | .supports_autosuspend = 1, | ||
826 | }; | ||
827 | |||
828 | static int __init cm109_select_keymap(void) | ||
829 | { | ||
830 | /* Load the phone keymap */ | ||
831 | if (!strcasecmp(phone, "kip1000")) { | ||
832 | keymap = keymap_kip1000; | ||
833 | printk(KERN_INFO KBUILD_MODNAME ": " | ||
834 | "Keymap for Komunikate KIP1000 phone loaded\n"); | ||
835 | } else if (!strcasecmp(phone, "gtalk")) { | ||
836 | keymap = keymap_gtalk; | ||
837 | printk(KERN_INFO KBUILD_MODNAME ": " | ||
838 | "Keymap for Genius G-talk phone loaded\n"); | ||
839 | } else if (!strcasecmp(phone, "usbph01")) { | ||
840 | keymap = keymap_usbph01; | ||
841 | printk(KERN_INFO KBUILD_MODNAME ": " | ||
842 | "Keymap for Allied-Telesis Corega USBPH01 phone loaded\n"); | ||
843 | } else { | ||
844 | printk(KERN_ERR KBUILD_MODNAME ": " | ||
845 | "Unsupported phone: %s\n", phone); | ||
846 | return -EINVAL; | ||
847 | } | ||
848 | |||
849 | return 0; | ||
850 | } | ||
851 | |||
852 | static int __init cm109_init(void) | ||
853 | { | ||
854 | int err; | ||
855 | |||
856 | err = cm109_select_keymap(); | ||
857 | if (err) | ||
858 | return err; | ||
859 | |||
860 | err = usb_register(&cm109_driver); | ||
861 | if (err) | ||
862 | return err; | ||
863 | |||
864 | printk(KERN_INFO KBUILD_MODNAME ": " | ||
865 | DRIVER_DESC ": " DRIVER_VERSION " (C) " DRIVER_AUTHOR "\n"); | ||
866 | |||
867 | return 0; | ||
868 | } | ||
869 | |||
870 | static void __exit cm109_exit(void) | ||
871 | { | ||
872 | usb_deregister(&cm109_driver); | ||
873 | } | ||
874 | |||
875 | module_init(cm109_init); | ||
876 | module_exit(cm109_exit); | ||
877 | |||
878 | MODULE_DEVICE_TABLE(usb, cm109_usb_table); | ||
879 | |||
880 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
881 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
882 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/map_to_7segment.h b/drivers/input/misc/map_to_7segment.h deleted file mode 100644 index a424094d9fe2..000000000000 --- a/drivers/input/misc/map_to_7segment.h +++ /dev/null | |||
@@ -1,189 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/usb/input/map_to_7segment.h | ||
3 | * | ||
4 | * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of | ||
9 | * the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #ifndef MAP_TO_7SEGMENT_H | ||
22 | #define MAP_TO_7SEGMENT_H | ||
23 | |||
24 | /* This file provides translation primitives and tables for the conversion | ||
25 | * of (ASCII) characters to a 7-segments notation. | ||
26 | * | ||
27 | * The 7 segment's wikipedia notation below is used as standard. | ||
28 | * See: http://en.wikipedia.org/wiki/Seven_segment_display | ||
29 | * | ||
30 | * Notation: +-a-+ | ||
31 | * f b | ||
32 | * +-g-+ | ||
33 | * e c | ||
34 | * +-d-+ | ||
35 | * | ||
36 | * Usage: | ||
37 | * | ||
38 | * Register a map variable, and fill it with a character set: | ||
39 | * static SEG7_DEFAULT_MAP(map_seg7); | ||
40 | * | ||
41 | * | ||
42 | * Then use for conversion: | ||
43 | * seg7 = map_to_seg7(&map_seg7, some_char); | ||
44 | * ... | ||
45 | * | ||
46 | * In device drivers it is recommended, if required, to make the char map | ||
47 | * accessible via the sysfs interface using the following scheme: | ||
48 | * | ||
49 | * static ssize_t show_map(struct device *dev, char *buf) { | ||
50 | * memcpy(buf, &map_seg7, sizeof(map_seg7)); | ||
51 | * return sizeof(map_seg7); | ||
52 | * } | ||
53 | * static ssize_t store_map(struct device *dev, const char *buf, size_t cnt) { | ||
54 | * if(cnt != sizeof(map_seg7)) | ||
55 | * return -EINVAL; | ||
56 | * memcpy(&map_seg7, buf, cnt); | ||
57 | * return cnt; | ||
58 | * } | ||
59 | * static DEVICE_ATTR(map_seg7, PERMS_RW, show_map, store_map); | ||
60 | * | ||
61 | * History: | ||
62 | * 2005-05-31 RFC linux-kernel@vger.kernel.org | ||
63 | */ | ||
64 | #include <linux/errno.h> | ||
65 | |||
66 | |||
67 | #define BIT_SEG7_A 0 | ||
68 | #define BIT_SEG7_B 1 | ||
69 | #define BIT_SEG7_C 2 | ||
70 | #define BIT_SEG7_D 3 | ||
71 | #define BIT_SEG7_E 4 | ||
72 | #define BIT_SEG7_F 5 | ||
73 | #define BIT_SEG7_G 6 | ||
74 | #define BIT_SEG7_RESERVED 7 | ||
75 | |||
76 | struct seg7_conversion_map { | ||
77 | unsigned char table[128]; | ||
78 | }; | ||
79 | |||
80 | static inline int map_to_seg7(struct seg7_conversion_map *map, int c) | ||
81 | { | ||
82 | return c >= 0 && c < sizeof(map->table) ? map->table[c] : -EINVAL; | ||
83 | } | ||
84 | |||
85 | #define SEG7_CONVERSION_MAP(_name, _map) \ | ||
86 | struct seg7_conversion_map _name = { .table = { _map } } | ||
87 | |||
88 | /* | ||
89 | * It is recommended to use a facility that allows user space to redefine | ||
90 | * custom character sets for LCD devices. Please use a sysfs interface | ||
91 | * as described above. | ||
92 | */ | ||
93 | #define MAP_TO_SEG7_SYSFS_FILE "map_seg7" | ||
94 | |||
95 | /******************************************************************************* | ||
96 | * ASCII conversion table | ||
97 | ******************************************************************************/ | ||
98 | |||
99 | #define _SEG7(l,a,b,c,d,e,f,g) \ | ||
100 | ( a<<BIT_SEG7_A | b<<BIT_SEG7_B | c<<BIT_SEG7_C | d<<BIT_SEG7_D | \ | ||
101 | e<<BIT_SEG7_E | f<<BIT_SEG7_F | g<<BIT_SEG7_G ) | ||
102 | |||
103 | #define _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ | ||
104 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
105 | |||
106 | #define _MAP_33_47_ASCII_SEG7_SYMBOL \ | ||
107 | _SEG7('!',0,0,0,0,1,1,0), _SEG7('"',0,1,0,0,0,1,0), _SEG7('#',0,1,1,0,1,1,0),\ | ||
108 | _SEG7('$',1,0,1,1,0,1,1), _SEG7('%',0,0,1,0,0,1,0), _SEG7('&',1,0,1,1,1,1,1),\ | ||
109 | _SEG7('\'',0,0,0,0,0,1,0),_SEG7('(',1,0,0,1,1,1,0), _SEG7(')',1,1,1,1,0,0,0),\ | ||
110 | _SEG7('*',0,1,1,0,1,1,1), _SEG7('+',0,1,1,0,0,0,1), _SEG7(',',0,0,0,0,1,0,0),\ | ||
111 | _SEG7('-',0,0,0,0,0,0,1), _SEG7('.',0,0,0,0,1,0,0), _SEG7('/',0,1,0,0,1,0,1), | ||
112 | |||
113 | #define _MAP_48_57_ASCII_SEG7_NUMERIC \ | ||
114 | _SEG7('0',1,1,1,1,1,1,0), _SEG7('1',0,1,1,0,0,0,0), _SEG7('2',1,1,0,1,1,0,1),\ | ||
115 | _SEG7('3',1,1,1,1,0,0,1), _SEG7('4',0,1,1,0,0,1,1), _SEG7('5',1,0,1,1,0,1,1),\ | ||
116 | _SEG7('6',1,0,1,1,1,1,1), _SEG7('7',1,1,1,0,0,0,0), _SEG7('8',1,1,1,1,1,1,1),\ | ||
117 | _SEG7('9',1,1,1,1,0,1,1), | ||
118 | |||
119 | #define _MAP_58_64_ASCII_SEG7_SYMBOL \ | ||
120 | _SEG7(':',0,0,0,1,0,0,1), _SEG7(';',0,0,0,1,0,0,1), _SEG7('<',1,0,0,0,0,1,1),\ | ||
121 | _SEG7('=',0,0,0,1,0,0,1), _SEG7('>',1,1,0,0,0,0,1), _SEG7('?',1,1,1,0,0,1,0),\ | ||
122 | _SEG7('@',1,1,0,1,1,1,1), | ||
123 | |||
124 | #define _MAP_65_90_ASCII_SEG7_ALPHA_UPPR \ | ||
125 | _SEG7('A',1,1,1,0,1,1,1), _SEG7('B',1,1,1,1,1,1,1), _SEG7('C',1,0,0,1,1,1,0),\ | ||
126 | _SEG7('D',1,1,1,1,1,1,0), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\ | ||
127 | _SEG7('G',1,1,1,1,0,1,1), _SEG7('H',0,1,1,0,1,1,1), _SEG7('I',0,1,1,0,0,0,0),\ | ||
128 | _SEG7('J',0,1,1,1,0,0,0), _SEG7('K',0,1,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\ | ||
129 | _SEG7('M',1,1,1,0,1,1,0), _SEG7('N',1,1,1,0,1,1,0), _SEG7('O',1,1,1,1,1,1,0),\ | ||
130 | _SEG7('P',1,1,0,0,1,1,1), _SEG7('Q',1,1,1,1,1,1,0), _SEG7('R',1,1,1,0,1,1,1),\ | ||
131 | _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('U',0,1,1,1,1,1,0),\ | ||
132 | _SEG7('V',0,1,1,1,1,1,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\ | ||
133 | _SEG7('Y',0,1,1,0,0,1,1), _SEG7('Z',1,1,0,1,1,0,1), | ||
134 | |||
135 | #define _MAP_91_96_ASCII_SEG7_SYMBOL \ | ||
136 | _SEG7('[',1,0,0,1,1,1,0), _SEG7('\\',0,0,1,0,0,1,1),_SEG7(']',1,1,1,1,0,0,0),\ | ||
137 | _SEG7('^',1,1,0,0,0,1,0), _SEG7('_',0,0,0,1,0,0,0), _SEG7('`',0,1,0,0,0,0,0), | ||
138 | |||
139 | #define _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ | ||
140 | _SEG7('A',1,1,1,0,1,1,1), _SEG7('b',0,0,1,1,1,1,1), _SEG7('c',0,0,0,1,1,0,1),\ | ||
141 | _SEG7('d',0,1,1,1,1,0,1), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\ | ||
142 | _SEG7('G',1,1,1,1,0,1,1), _SEG7('h',0,0,1,0,1,1,1), _SEG7('i',0,0,1,0,0,0,0),\ | ||
143 | _SEG7('j',0,0,1,1,0,0,0), _SEG7('k',0,0,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\ | ||
144 | _SEG7('M',1,1,1,0,1,1,0), _SEG7('n',0,0,1,0,1,0,1), _SEG7('o',0,0,1,1,1,0,1),\ | ||
145 | _SEG7('P',1,1,0,0,1,1,1), _SEG7('q',1,1,1,0,0,1,1), _SEG7('r',0,0,0,0,1,0,1),\ | ||
146 | _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('u',0,0,1,1,1,0,0),\ | ||
147 | _SEG7('v',0,0,1,1,1,0,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\ | ||
148 | _SEG7('y',0,1,1,1,0,1,1), _SEG7('Z',1,1,0,1,1,0,1), | ||
149 | |||
150 | #define _MAP_123_126_ASCII_SEG7_SYMBOL \ | ||
151 | _SEG7('{',1,0,0,1,1,1,0), _SEG7('|',0,0,0,0,1,1,0), _SEG7('}',1,1,1,1,0,0,0),\ | ||
152 | _SEG7('~',1,0,0,0,0,0,0), | ||
153 | |||
154 | /* Maps */ | ||
155 | |||
156 | /* This set tries to map as close as possible to the visible characteristics | ||
157 | * of the ASCII symbol, lowercase and uppercase letters may differ in | ||
158 | * presentation on the display. | ||
159 | */ | ||
160 | #define MAP_ASCII7SEG_ALPHANUM \ | ||
161 | _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ | ||
162 | _MAP_33_47_ASCII_SEG7_SYMBOL \ | ||
163 | _MAP_48_57_ASCII_SEG7_NUMERIC \ | ||
164 | _MAP_58_64_ASCII_SEG7_SYMBOL \ | ||
165 | _MAP_65_90_ASCII_SEG7_ALPHA_UPPR \ | ||
166 | _MAP_91_96_ASCII_SEG7_SYMBOL \ | ||
167 | _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ | ||
168 | _MAP_123_126_ASCII_SEG7_SYMBOL | ||
169 | |||
170 | /* This set tries to map as close as possible to the symbolic characteristics | ||
171 | * of the ASCII character for maximum discrimination. | ||
172 | * For now this means all alpha chars are in lower case representations. | ||
173 | * (This for example facilitates the use of hex numbers with uppercase input.) | ||
174 | */ | ||
175 | #define MAP_ASCII7SEG_ALPHANUM_LC \ | ||
176 | _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ | ||
177 | _MAP_33_47_ASCII_SEG7_SYMBOL \ | ||
178 | _MAP_48_57_ASCII_SEG7_NUMERIC \ | ||
179 | _MAP_58_64_ASCII_SEG7_SYMBOL \ | ||
180 | _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ | ||
181 | _MAP_91_96_ASCII_SEG7_SYMBOL \ | ||
182 | _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ | ||
183 | _MAP_123_126_ASCII_SEG7_SYMBOL | ||
184 | |||
185 | #define SEG7_DEFAULT_MAP(_name) \ | ||
186 | SEG7_CONVERSION_MAP(_name,MAP_ASCII7SEG_ALPHANUM) | ||
187 | |||
188 | #endif /* MAP_TO_7SEGMENT_H */ | ||
189 | |||
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index fe268be3293b..7c8957dd22c0 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -277,6 +277,16 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = { | |||
277 | { KE_END, 0 } | 277 | { KE_END, 0 } |
278 | }; | 278 | }; |
279 | 279 | ||
280 | static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = { | ||
281 | { KE_KEY, 0x01, {KEY_HELP} }, /* Fn+F1 */ | ||
282 | { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */ | ||
283 | { KE_BLUETOOTH, 0x30 }, /* Fn+F10 */ | ||
284 | { KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */ | ||
285 | { KE_KEY, 0x36, {KEY_WWW} }, /* www button */ | ||
286 | { KE_WIFI, 0x78 }, /* satelite dish button */ | ||
287 | { KE_END, 0 } | ||
288 | }; | ||
289 | |||
280 | static struct key_entry keymap_fujitsu_n3510[] __initdata = { | 290 | static struct key_entry keymap_fujitsu_n3510[] __initdata = { |
281 | { KE_KEY, 0x11, {KEY_PROG1} }, | 291 | { KE_KEY, 0x11, {KEY_PROG1} }, |
282 | { KE_KEY, 0x12, {KEY_PROG2} }, | 292 | { KE_KEY, 0x12, {KEY_PROG2} }, |
@@ -618,6 +628,15 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
618 | }, | 628 | }, |
619 | { | 629 | { |
620 | .callback = dmi_matched, | 630 | .callback = dmi_matched, |
631 | .ident = "Fujitsu-Siemens Amilo Pro Edition V3505", | ||
632 | .matches = { | ||
633 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
634 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Edition V3505"), | ||
635 | }, | ||
636 | .driver_data = keymap_fs_amilo_pro_v3505 | ||
637 | }, | ||
638 | { | ||
639 | .callback = dmi_matched, | ||
621 | .ident = "Fujitsu-Siemens Amilo M7400", | 640 | .ident = "Fujitsu-Siemens Amilo M7400", |
622 | .matches = { | 641 | .matches = { |
623 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 642 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index facefd3dba29..11b5c7e84ed1 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c | |||
@@ -52,8 +52,8 @@ | |||
52 | #include <linux/module.h> | 52 | #include <linux/module.h> |
53 | #include <linux/rwsem.h> | 53 | #include <linux/rwsem.h> |
54 | #include <linux/usb/input.h> | 54 | #include <linux/usb/input.h> |
55 | #include <linux/map_to_7segment.h> | ||
55 | 56 | ||
56 | #include "map_to_7segment.h" | ||
57 | #include "yealink.h" | 57 | #include "yealink.h" |
58 | 58 | ||
59 | #define DRIVER_VERSION "yld-20051230" | 59 | #define DRIVER_VERSION "yld-20051230" |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index f996546fc443..f488b6852baf 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -96,6 +96,16 @@ config MOUSE_PS2_TOUCHKIT | |||
96 | 96 | ||
97 | If unsure, say N. | 97 | If unsure, say N. |
98 | 98 | ||
99 | config MOUSE_PS2_OLPC | ||
100 | bool "OLPC PS/2 mouse protocol extension" | ||
101 | depends on MOUSE_PS2 && OLPC | ||
102 | help | ||
103 | Say Y here if you have an OLPC XO-1 laptop (with built-in | ||
104 | PS/2 touchpad/tablet device). The manufacturer calls the | ||
105 | touchpad an HGPK. | ||
106 | |||
107 | If unsure, say N. | ||
108 | |||
99 | config MOUSE_SERIAL | 109 | config MOUSE_SERIAL |
100 | tristate "Serial mouse" | 110 | tristate "Serial mouse" |
101 | select SERIO | 111 | select SERIO |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index d4d202516090..8e6e69097801 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -21,6 +21,7 @@ obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o | |||
21 | psmouse-objs := psmouse-base.o synaptics.o | 21 | psmouse-objs := psmouse-base.o synaptics.o |
22 | 22 | ||
23 | psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o | 23 | psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o |
24 | psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o | ||
24 | psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o | 25 | psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o |
25 | psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o | 26 | psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o |
26 | psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o | 27 | psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 385e32bcf6a6..cbedf957cc58 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -54,6 +54,7 @@ static const struct alps_model_info alps_model_data[] = { | |||
54 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ | 54 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ |
55 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, | 55 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, |
56 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ | 56 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ |
57 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */ | ||
57 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 } /* Dell Vostro 1400 */ | 58 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 } /* Dell Vostro 1400 */ |
58 | }; | 59 | }; |
59 | 60 | ||
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 1f41ae94f26b..079816e6b23b 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
@@ -136,12 +136,28 @@ MODULE_DEVICE_TABLE(usb, atp_table); | |||
136 | #define ATP_GEYSER_MODE_REQUEST_INDEX 0 | 136 | #define ATP_GEYSER_MODE_REQUEST_INDEX 0 |
137 | #define ATP_GEYSER_MODE_VENDOR_VALUE 0x04 | 137 | #define ATP_GEYSER_MODE_VENDOR_VALUE 0x04 |
138 | 138 | ||
139 | /** | ||
140 | * enum atp_status_bits - status bit meanings | ||
141 | * | ||
142 | * These constants represent the meaning of the status bits. | ||
143 | * (only Geyser 3/4) | ||
144 | * | ||
145 | * @ATP_STATUS_BUTTON: The button was pressed | ||
146 | * @ATP_STATUS_BASE_UPDATE: Update of the base values (untouched pad) | ||
147 | * @ATP_STATUS_FROM_RESET: Reset previously performed | ||
148 | */ | ||
149 | enum atp_status_bits { | ||
150 | ATP_STATUS_BUTTON = BIT(0), | ||
151 | ATP_STATUS_BASE_UPDATE = BIT(2), | ||
152 | ATP_STATUS_FROM_RESET = BIT(4), | ||
153 | }; | ||
154 | |||
139 | /* Structure to hold all of our device specific stuff */ | 155 | /* Structure to hold all of our device specific stuff */ |
140 | struct atp { | 156 | struct atp { |
141 | char phys[64]; | 157 | char phys[64]; |
142 | struct usb_device *udev; /* usb device */ | 158 | struct usb_device *udev; /* usb device */ |
143 | struct urb *urb; /* usb request block */ | 159 | struct urb *urb; /* usb request block */ |
144 | signed char *data; /* transferred data */ | 160 | u8 *data; /* transferred data */ |
145 | struct input_dev *input; /* input dev */ | 161 | struct input_dev *input; /* input dev */ |
146 | enum atp_touchpad_type type; /* type of touchpad */ | 162 | enum atp_touchpad_type type; /* type of touchpad */ |
147 | bool open; | 163 | bool open; |
@@ -251,8 +267,6 @@ static void atp_reinit(struct work_struct *work) | |||
251 | int retval; | 267 | int retval; |
252 | 268 | ||
253 | dprintk("appletouch: putting appletouch to sleep (reinit)\n"); | 269 | dprintk("appletouch: putting appletouch to sleep (reinit)\n"); |
254 | dev->idlecount = 0; | ||
255 | |||
256 | atp_geyser_init(udev); | 270 | atp_geyser_init(udev); |
257 | 271 | ||
258 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); | 272 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); |
@@ -327,11 +341,14 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers) | |||
327 | input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2); | 341 | input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2); |
328 | } | 342 | } |
329 | 343 | ||
330 | static void atp_complete(struct urb *urb) | 344 | /* Check URB status and for correct length of data package */ |
345 | |||
346 | #define ATP_URB_STATUS_SUCCESS 0 | ||
347 | #define ATP_URB_STATUS_ERROR 1 | ||
348 | #define ATP_URB_STATUS_ERROR_FATAL 2 | ||
349 | |||
350 | static int atp_status_check(struct urb *urb) | ||
331 | { | 351 | { |
332 | int x, y, x_z, y_z, x_f, y_f; | ||
333 | int retval, i, j; | ||
334 | int key; | ||
335 | struct atp *dev = urb->context; | 352 | struct atp *dev = urb->context; |
336 | 353 | ||
337 | switch (urb->status) { | 354 | switch (urb->status) { |
@@ -351,11 +368,12 @@ static void atp_complete(struct urb *urb) | |||
351 | /* This urb is terminated, clean up */ | 368 | /* This urb is terminated, clean up */ |
352 | dbg("atp_complete: urb shutting down with status: %d", | 369 | dbg("atp_complete: urb shutting down with status: %d", |
353 | urb->status); | 370 | urb->status); |
354 | return; | 371 | return ATP_URB_STATUS_ERROR_FATAL; |
372 | |||
355 | default: | 373 | default: |
356 | dbg("atp_complete: nonzero urb status received: %d", | 374 | dbg("atp_complete: nonzero urb status received: %d", |
357 | urb->status); | 375 | urb->status); |
358 | goto exit; | 376 | return ATP_URB_STATUS_ERROR; |
359 | } | 377 | } |
360 | 378 | ||
361 | /* drop incomplete datasets */ | 379 | /* drop incomplete datasets */ |
@@ -363,30 +381,33 @@ static void atp_complete(struct urb *urb) | |||
363 | dprintk("appletouch: incomplete data package" | 381 | dprintk("appletouch: incomplete data package" |
364 | " (first byte: %d, length: %d).\n", | 382 | " (first byte: %d, length: %d).\n", |
365 | dev->data[0], dev->urb->actual_length); | 383 | dev->data[0], dev->urb->actual_length); |
366 | goto exit; | 384 | return ATP_URB_STATUS_ERROR; |
367 | } | 385 | } |
368 | 386 | ||
369 | /* reorder the sensors values */ | 387 | return ATP_URB_STATUS_SUCCESS; |
370 | if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) { | 388 | } |
371 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); | ||
372 | 389 | ||
373 | /* | 390 | /* |
374 | * The values are laid out like this: | 391 | * USB interrupt callback functions |
375 | * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... | 392 | */ |
376 | * '-' is an unused value. | ||
377 | */ | ||
378 | 393 | ||
379 | /* read X values */ | 394 | /* Interrupt function for older touchpads: FOUNTAIN/GEYSER1/GEYSER2 */ |
380 | for (i = 0, j = 19; i < 20; i += 2, j += 3) { | 395 | |
381 | dev->xy_cur[i] = dev->data[j + 1]; | 396 | static void atp_complete_geyser_1_2(struct urb *urb) |
382 | dev->xy_cur[i + 1] = dev->data[j + 2]; | 397 | { |
383 | } | 398 | int x, y, x_z, y_z, x_f, y_f; |
384 | /* read Y values */ | 399 | int retval, i, j; |
385 | for (i = 0, j = 1; i < 9; i += 2, j += 3) { | 400 | int key; |
386 | dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; | 401 | struct atp *dev = urb->context; |
387 | dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; | 402 | int status = atp_status_check(urb); |
388 | } | 403 | |
389 | } else if (dev->type == ATP_GEYSER2) { | 404 | if (status == ATP_URB_STATUS_ERROR_FATAL) |
405 | return; | ||
406 | else if (status == ATP_URB_STATUS_ERROR) | ||
407 | goto exit; | ||
408 | |||
409 | /* reorder the sensors values */ | ||
410 | if (dev->type == ATP_GEYSER2) { | ||
390 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); | 411 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); |
391 | 412 | ||
392 | /* | 413 | /* |
@@ -427,34 +448,40 @@ static void atp_complete(struct urb *urb) | |||
427 | /* first sample */ | 448 | /* first sample */ |
428 | dev->valid = true; | 449 | dev->valid = true; |
429 | dev->x_old = dev->y_old = -1; | 450 | dev->x_old = dev->y_old = -1; |
451 | |||
452 | /* Store first sample */ | ||
430 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); | 453 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); |
431 | 454 | ||
432 | if (dev->size_detect_done || | 455 | /* Perform size detection, if not done already */ |
433 | dev->type == ATP_GEYSER3) /* No 17" Macbooks (yet) */ | 456 | if (!dev->size_detect_done) { |
434 | goto exit; | 457 | |
458 | /* 17" Powerbooks have extra X sensors */ | ||
459 | for (i = (dev->type == ATP_GEYSER2 ? 15 : 16); | ||
460 | i < ATP_XSENSORS; i++) { | ||
461 | if (!dev->xy_cur[i]) | ||
462 | continue; | ||
463 | |||
464 | printk(KERN_INFO | ||
465 | "appletouch: 17\" model detected.\n"); | ||
466 | |||
467 | if (dev->type == ATP_GEYSER2) | ||
468 | input_set_abs_params(dev->input, ABS_X, | ||
469 | 0, | ||
470 | (20 - 1) * | ||
471 | ATP_XFACT - 1, | ||
472 | ATP_FUZZ, 0); | ||
473 | else | ||
474 | input_set_abs_params(dev->input, ABS_X, | ||
475 | 0, | ||
476 | (26 - 1) * | ||
477 | ATP_XFACT - 1, | ||
478 | ATP_FUZZ, 0); | ||
479 | break; | ||
480 | } | ||
435 | 481 | ||
436 | /* 17" Powerbooks have extra X sensors */ | 482 | dev->size_detect_done = 1; |
437 | for (i = (dev->type == ATP_GEYSER2 ? 15 : 16); | 483 | goto exit; |
438 | i < ATP_XSENSORS; i++) { | ||
439 | if (!dev->xy_cur[i]) | ||
440 | continue; | ||
441 | |||
442 | printk(KERN_INFO "appletouch: 17\" model detected.\n"); | ||
443 | if (dev->type == ATP_GEYSER2) | ||
444 | input_set_abs_params(dev->input, ABS_X, 0, | ||
445 | (20 - 1) * | ||
446 | ATP_XFACT - 1, | ||
447 | ATP_FUZZ, 0); | ||
448 | else | ||
449 | input_set_abs_params(dev->input, ABS_X, 0, | ||
450 | (ATP_XSENSORS - 1) * | ||
451 | ATP_XFACT - 1, | ||
452 | ATP_FUZZ, 0); | ||
453 | break; | ||
454 | } | 484 | } |
455 | |||
456 | dev->size_detect_done = 1; | ||
457 | goto exit; | ||
458 | } | 485 | } |
459 | 486 | ||
460 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { | 487 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { |
@@ -475,7 +502,118 @@ static void atp_complete(struct urb *urb) | |||
475 | ATP_XFACT, &x_z, &x_f); | 502 | ATP_XFACT, &x_z, &x_f); |
476 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, | 503 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, |
477 | ATP_YFACT, &y_z, &y_f); | 504 | ATP_YFACT, &y_z, &y_f); |
478 | key = dev->data[dev->datalen - 1] & 1; | 505 | key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON; |
506 | |||
507 | if (x && y) { | ||
508 | if (dev->x_old != -1) { | ||
509 | x = (dev->x_old * 3 + x) >> 2; | ||
510 | y = (dev->y_old * 3 + y) >> 2; | ||
511 | dev->x_old = x; | ||
512 | dev->y_old = y; | ||
513 | |||
514 | if (debug > 1) | ||
515 | printk(KERN_DEBUG "appletouch: " | ||
516 | "X: %3d Y: %3d Xz: %3d Yz: %3d\n", | ||
517 | x, y, x_z, y_z); | ||
518 | |||
519 | input_report_key(dev->input, BTN_TOUCH, 1); | ||
520 | input_report_abs(dev->input, ABS_X, x); | ||
521 | input_report_abs(dev->input, ABS_Y, y); | ||
522 | input_report_abs(dev->input, ABS_PRESSURE, | ||
523 | min(ATP_PRESSURE, x_z + y_z)); | ||
524 | atp_report_fingers(dev->input, max(x_f, y_f)); | ||
525 | } | ||
526 | dev->x_old = x; | ||
527 | dev->y_old = y; | ||
528 | |||
529 | } else if (!x && !y) { | ||
530 | |||
531 | dev->x_old = dev->y_old = -1; | ||
532 | input_report_key(dev->input, BTN_TOUCH, 0); | ||
533 | input_report_abs(dev->input, ABS_PRESSURE, 0); | ||
534 | atp_report_fingers(dev->input, 0); | ||
535 | |||
536 | /* reset the accumulator on release */ | ||
537 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); | ||
538 | } | ||
539 | |||
540 | input_report_key(dev->input, BTN_LEFT, key); | ||
541 | input_sync(dev->input); | ||
542 | |||
543 | exit: | ||
544 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); | ||
545 | if (retval) | ||
546 | err("atp_complete: usb_submit_urb failed with result %d", | ||
547 | retval); | ||
548 | } | ||
549 | |||
550 | /* Interrupt function for older touchpads: GEYSER3/GEYSER4 */ | ||
551 | |||
552 | static void atp_complete_geyser_3_4(struct urb *urb) | ||
553 | { | ||
554 | int x, y, x_z, y_z, x_f, y_f; | ||
555 | int retval, i, j; | ||
556 | int key; | ||
557 | struct atp *dev = urb->context; | ||
558 | int status = atp_status_check(urb); | ||
559 | |||
560 | if (status == ATP_URB_STATUS_ERROR_FATAL) | ||
561 | return; | ||
562 | else if (status == ATP_URB_STATUS_ERROR) | ||
563 | goto exit; | ||
564 | |||
565 | /* Reorder the sensors values: | ||
566 | * | ||
567 | * The values are laid out like this: | ||
568 | * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... | ||
569 | * '-' is an unused value. | ||
570 | */ | ||
571 | |||
572 | /* read X values */ | ||
573 | for (i = 0, j = 19; i < 20; i += 2, j += 3) { | ||
574 | dev->xy_cur[i] = dev->data[j + 1]; | ||
575 | dev->xy_cur[i + 1] = dev->data[j + 2]; | ||
576 | } | ||
577 | /* read Y values */ | ||
578 | for (i = 0, j = 1; i < 9; i += 2, j += 3) { | ||
579 | dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; | ||
580 | dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; | ||
581 | } | ||
582 | |||
583 | dbg_dump("sample", dev->xy_cur); | ||
584 | |||
585 | /* Just update the base values (i.e. touchpad in untouched state) */ | ||
586 | if (dev->data[dev->datalen - 1] & ATP_STATUS_BASE_UPDATE) { | ||
587 | |||
588 | dprintk(KERN_DEBUG "appletouch: updated base values\n"); | ||
589 | |||
590 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); | ||
591 | goto exit; | ||
592 | } | ||
593 | |||
594 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { | ||
595 | /* calculate the change */ | ||
596 | dev->xy_acc[i] = dev->xy_cur[i] - dev->xy_old[i]; | ||
597 | |||
598 | /* this is a round-robin value, so couple with that */ | ||
599 | if (dev->xy_acc[i] > 127) | ||
600 | dev->xy_acc[i] -= 256; | ||
601 | |||
602 | if (dev->xy_acc[i] < -127) | ||
603 | dev->xy_acc[i] += 256; | ||
604 | |||
605 | /* prevent down drifting */ | ||
606 | if (dev->xy_acc[i] < 0) | ||
607 | dev->xy_acc[i] = 0; | ||
608 | } | ||
609 | |||
610 | dbg_dump("accumulator", dev->xy_acc); | ||
611 | |||
612 | x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS, | ||
613 | ATP_XFACT, &x_z, &x_f); | ||
614 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, | ||
615 | ATP_YFACT, &y_z, &y_f); | ||
616 | key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON; | ||
479 | 617 | ||
480 | if (x && y) { | 618 | if (x && y) { |
481 | if (dev->x_old != -1) { | 619 | if (dev->x_old != -1) { |
@@ -514,28 +652,27 @@ static void atp_complete(struct urb *urb) | |||
514 | input_sync(dev->input); | 652 | input_sync(dev->input); |
515 | 653 | ||
516 | /* | 654 | /* |
517 | * Many Geysers will continue to send packets continually after | 655 | * Geysers 3/4 will continue to send packets continually after |
518 | * the first touch unless reinitialised. Do so if it's been | 656 | * the first touch unless reinitialised. Do so if it's been |
519 | * idle for a while in order to avoid waking the kernel up | 657 | * idle for a while in order to avoid waking the kernel up |
520 | * several hundred times a second. Re-initialization does not | 658 | * several hundred times a second. |
521 | * work on Fountain touchpads. | ||
522 | */ | 659 | */ |
523 | if (dev->type != ATP_FOUNTAIN) { | 660 | |
524 | /* | 661 | /* |
525 | * Button must not be pressed when entering suspend, | 662 | * Button must not be pressed when entering suspend, |
526 | * otherwise we will never release the button. | 663 | * otherwise we will never release the button. |
527 | */ | 664 | */ |
528 | if (!x && !y && !key) { | 665 | if (!x && !y && !key) { |
529 | dev->idlecount++; | 666 | dev->idlecount++; |
530 | if (dev->idlecount == 10) { | 667 | if (dev->idlecount == 10) { |
531 | dev->valid = false; | 668 | dev->x_old = dev->y_old = -1; |
532 | schedule_work(&dev->work); | ||
533 | /* Don't resubmit urb here, wait for reinit */ | ||
534 | return; | ||
535 | } | ||
536 | } else | ||
537 | dev->idlecount = 0; | 669 | dev->idlecount = 0; |
538 | } | 670 | schedule_work(&dev->work); |
671 | /* Don't resubmit urb here, wait for reinit */ | ||
672 | return; | ||
673 | } | ||
674 | } else | ||
675 | dev->idlecount = 0; | ||
539 | 676 | ||
540 | exit: | 677 | exit: |
541 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); | 678 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); |
@@ -632,9 +769,19 @@ static int atp_probe(struct usb_interface *iface, | |||
632 | if (!dev->data) | 769 | if (!dev->data) |
633 | goto err_free_urb; | 770 | goto err_free_urb; |
634 | 771 | ||
635 | usb_fill_int_urb(dev->urb, udev, | 772 | /* Select the USB complete (callback) function */ |
636 | usb_rcvintpipe(udev, int_in_endpointAddr), | 773 | if (dev->type == ATP_FOUNTAIN || |
637 | dev->data, dev->datalen, atp_complete, dev, 1); | 774 | dev->type == ATP_GEYSER1 || |
775 | dev->type == ATP_GEYSER2) | ||
776 | usb_fill_int_urb(dev->urb, udev, | ||
777 | usb_rcvintpipe(udev, int_in_endpointAddr), | ||
778 | dev->data, dev->datalen, | ||
779 | atp_complete_geyser_1_2, dev, 1); | ||
780 | else | ||
781 | usb_fill_int_urb(dev->urb, udev, | ||
782 | usb_rcvintpipe(udev, int_in_endpointAddr), | ||
783 | dev->data, dev->datalen, | ||
784 | atp_complete_geyser_3_4, dev, 1); | ||
638 | 785 | ||
639 | error = atp_handle_geyser(dev); | 786 | error = atp_handle_geyser(dev); |
640 | if (error) | 787 | if (error) |
@@ -751,8 +898,6 @@ static int atp_suspend(struct usb_interface *iface, pm_message_t message) | |||
751 | struct atp *dev = usb_get_intfdata(iface); | 898 | struct atp *dev = usb_get_intfdata(iface); |
752 | 899 | ||
753 | usb_kill_urb(dev->urb); | 900 | usb_kill_urb(dev->urb); |
754 | dev->valid = false; | ||
755 | |||
756 | return 0; | 901 | return 0; |
757 | } | 902 | } |
758 | 903 | ||
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c new file mode 100644 index 000000000000..e82d34201e97 --- /dev/null +++ b/drivers/input/mouse/hgpk.c | |||
@@ -0,0 +1,477 @@ | |||
1 | /* | ||
2 | * OLPC HGPK (XO-1) touchpad PS/2 mouse driver | ||
3 | * | ||
4 | * Copyright (c) 2006-2008 One Laptop Per Child | ||
5 | * Authors: | ||
6 | * Zephaniah E. Hull | ||
7 | * Andres Salomon <dilinger@debian.org> | ||
8 | * | ||
9 | * This driver is partly based on the ALPS driver, which is: | ||
10 | * | ||
11 | * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au> | ||
12 | * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com> | ||
13 | * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> | ||
14 | * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License version 2 as | ||
18 | * published by the Free Software Foundation. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * The spec from ALPS is available from | ||
23 | * <http://wiki.laptop.org/go/Touch_Pad/Tablet>. It refers to this | ||
24 | * device as HGPK (Hybrid GS, PT, and Keymatrix). | ||
25 | * | ||
26 | * The earliest versions of the device had simultaneous reporting; that | ||
27 | * was removed. After that, the device used the Advanced Mode GS/PT streaming | ||
28 | * stuff. That turned out to be too buggy to support, so we've finally | ||
29 | * switched to Mouse Mode (which utilizes only the center 1/3 of the touchpad). | ||
30 | */ | ||
31 | |||
32 | #define DEBUG | ||
33 | #include <linux/input.h> | ||
34 | #include <linux/serio.h> | ||
35 | #include <linux/libps2.h> | ||
36 | #include <linux/delay.h> | ||
37 | #include <asm/olpc.h> | ||
38 | |||
39 | #include "psmouse.h" | ||
40 | #include "hgpk.h" | ||
41 | |||
42 | static int tpdebug; | ||
43 | module_param(tpdebug, int, 0644); | ||
44 | MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG."); | ||
45 | |||
46 | static int recalib_delta = 100; | ||
47 | module_param(recalib_delta, int, 0644); | ||
48 | MODULE_PARM_DESC(recalib_delta, | ||
49 | "packets containing a delta this large will cause a recalibration."); | ||
50 | |||
51 | /* | ||
52 | * When the touchpad gets ultra-sensitive, one can keep their finger 1/2" | ||
53 | * above the pad and still have it send packets. This causes a jump cursor | ||
54 | * when one places their finger on the pad. We can probably detect the | ||
55 | * jump as we see a large deltas (>= 100px). In mouse mode, I've been | ||
56 | * unable to even come close to 100px deltas during normal usage, so I think | ||
57 | * this threshold is safe. If a large delta occurs, trigger a recalibration. | ||
58 | */ | ||
59 | static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int y) | ||
60 | { | ||
61 | struct hgpk_data *priv = psmouse->private; | ||
62 | |||
63 | if (abs(x) > recalib_delta || abs(y) > recalib_delta) { | ||
64 | hgpk_err(psmouse, ">%dpx jump detected (%d,%d)\n", | ||
65 | recalib_delta, x, y); | ||
66 | /* My car gets forty rods to the hogshead and that's the | ||
67 | * way I likes it! */ | ||
68 | psmouse_queue_work(psmouse, &priv->recalib_wq, | ||
69 | msecs_to_jiffies(1000)); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * We have no idea why this particular hardware bug occurs. The touchpad | ||
75 | * will randomly start spewing packets without anything touching the | ||
76 | * pad. This wouldn't necessarily be bad, but it's indicative of a | ||
77 | * severely miscalibrated pad; attempting to use the touchpad while it's | ||
78 | * spewing means the cursor will jump all over the place, and act "drunk". | ||
79 | * | ||
80 | * The packets that are spewed tend to all have deltas between -2 and 2, and | ||
81 | * the cursor will move around without really going very far. It will | ||
82 | * tend to end up in the same location; if we tally up the changes over | ||
83 | * 100 packets, we end up w/ a final delta of close to 0. This happens | ||
84 | * pretty regularly when the touchpad is spewing, and is pretty hard to | ||
85 | * manually trigger (at least for *my* fingers). So, it makes a perfect | ||
86 | * scheme for detecting spews. | ||
87 | */ | ||
88 | static void hgpk_spewing_hack(struct psmouse *psmouse, | ||
89 | int l, int r, int x, int y) | ||
90 | { | ||
91 | struct hgpk_data *priv = psmouse->private; | ||
92 | |||
93 | /* ignore button press packets; many in a row could trigger | ||
94 | * a false-positive! */ | ||
95 | if (l || r) | ||
96 | return; | ||
97 | |||
98 | priv->x_tally += x; | ||
99 | priv->y_tally += y; | ||
100 | |||
101 | if (++priv->count > 100) { | ||
102 | if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) { | ||
103 | hgpk_dbg(psmouse, "packet spew detected (%d,%d)\n", | ||
104 | priv->x_tally, priv->y_tally); | ||
105 | psmouse_queue_work(psmouse, &priv->recalib_wq, | ||
106 | msecs_to_jiffies(1000)); | ||
107 | } | ||
108 | /* reset every 100 packets */ | ||
109 | priv->count = 0; | ||
110 | priv->x_tally = 0; | ||
111 | priv->y_tally = 0; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * HGPK Mouse Mode format (standard mouse format, sans middle button) | ||
117 | * | ||
118 | * byte 0: y-over x-over y-neg x-neg 1 0 swr swl | ||
119 | * byte 1: x7 x6 x5 x4 x3 x2 x1 x0 | ||
120 | * byte 2: y7 y6 y5 y4 y3 y2 y1 y0 | ||
121 | * | ||
122 | * swr/swl are the left/right buttons. | ||
123 | * x-neg/y-neg are the x and y delta negative bits | ||
124 | * x-over/y-over are the x and y overflow bits | ||
125 | */ | ||
126 | static int hgpk_validate_byte(unsigned char *packet) | ||
127 | { | ||
128 | return (packet[0] & 0x0C) == 0x08; | ||
129 | } | ||
130 | |||
131 | static void hgpk_process_packet(struct psmouse *psmouse) | ||
132 | { | ||
133 | struct input_dev *dev = psmouse->dev; | ||
134 | unsigned char *packet = psmouse->packet; | ||
135 | int x, y, left, right; | ||
136 | |||
137 | left = packet[0] & 1; | ||
138 | right = (packet[0] >> 1) & 1; | ||
139 | |||
140 | x = packet[1] - ((packet[0] << 4) & 0x100); | ||
141 | y = ((packet[0] << 3) & 0x100) - packet[2]; | ||
142 | |||
143 | hgpk_jumpy_hack(psmouse, x, y); | ||
144 | hgpk_spewing_hack(psmouse, left, right, x, y); | ||
145 | |||
146 | if (tpdebug) | ||
147 | hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y); | ||
148 | |||
149 | input_report_key(dev, BTN_LEFT, left); | ||
150 | input_report_key(dev, BTN_RIGHT, right); | ||
151 | |||
152 | input_report_rel(dev, REL_X, x); | ||
153 | input_report_rel(dev, REL_Y, y); | ||
154 | |||
155 | input_sync(dev); | ||
156 | } | ||
157 | |||
158 | static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse) | ||
159 | { | ||
160 | struct hgpk_data *priv = psmouse->private; | ||
161 | |||
162 | if (hgpk_validate_byte(psmouse->packet)) { | ||
163 | hgpk_dbg(psmouse, "%s: (%d) %02x %02x %02x\n", | ||
164 | __func__, psmouse->pktcnt, psmouse->packet[0], | ||
165 | psmouse->packet[1], psmouse->packet[2]); | ||
166 | return PSMOUSE_BAD_DATA; | ||
167 | } | ||
168 | |||
169 | if (psmouse->pktcnt >= psmouse->pktsize) { | ||
170 | hgpk_process_packet(psmouse); | ||
171 | return PSMOUSE_FULL_PACKET; | ||
172 | } | ||
173 | |||
174 | if (priv->recalib_window) { | ||
175 | if (time_before(jiffies, priv->recalib_window)) { | ||
176 | /* | ||
177 | * ugh, got a packet inside our recalibration | ||
178 | * window, schedule another recalibration. | ||
179 | */ | ||
180 | hgpk_dbg(psmouse, | ||
181 | "packet inside calibration window, " | ||
182 | "queueing another recalibration\n"); | ||
183 | psmouse_queue_work(psmouse, &priv->recalib_wq, | ||
184 | msecs_to_jiffies(1000)); | ||
185 | } | ||
186 | priv->recalib_window = 0; | ||
187 | } | ||
188 | |||
189 | return PSMOUSE_GOOD_DATA; | ||
190 | } | ||
191 | |||
192 | static int hgpk_force_recalibrate(struct psmouse *psmouse) | ||
193 | { | ||
194 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
195 | struct hgpk_data *priv = psmouse->private; | ||
196 | |||
197 | /* C-series touchpads added the recalibrate command */ | ||
198 | if (psmouse->model < HGPK_MODEL_C) | ||
199 | return 0; | ||
200 | |||
201 | /* we don't want to race with the irq handler, nor with resyncs */ | ||
202 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | ||
203 | |||
204 | /* start by resetting the device */ | ||
205 | psmouse_reset(psmouse); | ||
206 | |||
207 | /* send the recalibrate request */ | ||
208 | if (ps2_command(ps2dev, NULL, 0xf5) || | ||
209 | ps2_command(ps2dev, NULL, 0xf5) || | ||
210 | ps2_command(ps2dev, NULL, 0xe6) || | ||
211 | ps2_command(ps2dev, NULL, 0xf5)) { | ||
212 | return -1; | ||
213 | } | ||
214 | |||
215 | /* according to ALPS, 150mS is required for recalibration */ | ||
216 | msleep(150); | ||
217 | |||
218 | /* XXX: If a finger is down during this delay, recalibration will | ||
219 | * detect capacitance incorrectly. This is a hardware bug, and | ||
220 | * we don't have a good way to deal with it. The 2s window stuff | ||
221 | * (below) is our best option for now. | ||
222 | */ | ||
223 | |||
224 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) | ||
225 | return -1; | ||
226 | |||
227 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
228 | |||
229 | /* After we recalibrate, we shouldn't get any packets for 2s. If | ||
230 | * we do, it's likely that someone's finger was on the touchpad. | ||
231 | * If someone's finger *was* on the touchpad, it's probably | ||
232 | * miscalibrated. So, we should schedule another recalibration | ||
233 | */ | ||
234 | priv->recalib_window = jiffies + msecs_to_jiffies(2000); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | /* | ||
240 | * This kills power to the touchpad; according to ALPS, current consumption | ||
241 | * goes down to 50uA after running this. To turn power back on, we drive | ||
242 | * MS-DAT low. | ||
243 | */ | ||
244 | static int hgpk_toggle_power(struct psmouse *psmouse, int enable) | ||
245 | { | ||
246 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
247 | int timeo; | ||
248 | |||
249 | /* Added on D-series touchpads */ | ||
250 | if (psmouse->model < HGPK_MODEL_D) | ||
251 | return 0; | ||
252 | |||
253 | if (enable) { | ||
254 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | ||
255 | |||
256 | /* | ||
257 | * Sending a byte will drive MS-DAT low; this will wake up | ||
258 | * the controller. Once we get an ACK back from it, it | ||
259 | * means we can continue with the touchpad re-init. ALPS | ||
260 | * tells us that 1s should be long enough, so set that as | ||
261 | * the upper bound. | ||
262 | */ | ||
263 | for (timeo = 20; timeo > 0; timeo--) { | ||
264 | if (!ps2_sendbyte(&psmouse->ps2dev, | ||
265 | PSMOUSE_CMD_DISABLE, 20)) | ||
266 | break; | ||
267 | msleep(50); | ||
268 | } | ||
269 | |||
270 | psmouse_reset(psmouse); | ||
271 | |||
272 | /* should be all set, enable the touchpad */ | ||
273 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE); | ||
274 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
275 | |||
276 | } else { | ||
277 | hgpk_dbg(psmouse, "Powering off touchpad.\n"); | ||
278 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
279 | |||
280 | if (ps2_command(ps2dev, NULL, 0xec) || | ||
281 | ps2_command(ps2dev, NULL, 0xec) || | ||
282 | ps2_command(ps2dev, NULL, 0xea)) { | ||
283 | return -1; | ||
284 | } | ||
285 | |||
286 | /* probably won't see an ACK, the touchpad will be off */ | ||
287 | ps2_sendbyte(&psmouse->ps2dev, 0xec, 20); | ||
288 | } | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int hgpk_poll(struct psmouse *psmouse) | ||
294 | { | ||
295 | /* We can't poll, so always return failure. */ | ||
296 | return -1; | ||
297 | } | ||
298 | |||
299 | static int hgpk_reconnect(struct psmouse *psmouse) | ||
300 | { | ||
301 | /* During suspend/resume the ps2 rails remain powered. We don't want | ||
302 | * to do a reset because it's flush data out of buffers; however, | ||
303 | * earlier prototypes (B1) had some brokenness that required a reset. */ | ||
304 | if (olpc_board_at_least(olpc_board(0xb2))) | ||
305 | if (psmouse->ps2dev.serio->dev.power.power_state.event != | ||
306 | PM_EVENT_ON) | ||
307 | return 0; | ||
308 | |||
309 | psmouse_reset(psmouse); | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf) | ||
315 | { | ||
316 | struct hgpk_data *priv = psmouse->private; | ||
317 | |||
318 | return sprintf(buf, "%d\n", priv->powered); | ||
319 | } | ||
320 | |||
321 | static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data, | ||
322 | const char *buf, size_t count) | ||
323 | { | ||
324 | struct hgpk_data *priv = psmouse->private; | ||
325 | unsigned long value; | ||
326 | int err; | ||
327 | |||
328 | err = strict_strtoul(buf, 10, &value); | ||
329 | if (err || value > 1) | ||
330 | return -EINVAL; | ||
331 | |||
332 | if (value != priv->powered) { | ||
333 | /* | ||
334 | * hgpk_toggle_power will deal w/ state so | ||
335 | * we're not racing w/ irq | ||
336 | */ | ||
337 | err = hgpk_toggle_power(psmouse, value); | ||
338 | if (!err) | ||
339 | priv->powered = value; | ||
340 | } | ||
341 | |||
342 | return err ? err : count; | ||
343 | } | ||
344 | |||
345 | __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, | ||
346 | hgpk_show_powered, hgpk_set_powered, 0); | ||
347 | |||
348 | static void hgpk_disconnect(struct psmouse *psmouse) | ||
349 | { | ||
350 | struct hgpk_data *priv = psmouse->private; | ||
351 | |||
352 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
353 | &psmouse_attr_powered.dattr); | ||
354 | psmouse_reset(psmouse); | ||
355 | kfree(priv); | ||
356 | } | ||
357 | |||
358 | static void hgpk_recalib_work(struct work_struct *work) | ||
359 | { | ||
360 | struct delayed_work *w = container_of(work, struct delayed_work, work); | ||
361 | struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq); | ||
362 | struct psmouse *psmouse = priv->psmouse; | ||
363 | |||
364 | hgpk_dbg(psmouse, "recalibrating touchpad..\n"); | ||
365 | |||
366 | if (hgpk_force_recalibrate(psmouse)) | ||
367 | hgpk_err(psmouse, "recalibration failed!\n"); | ||
368 | } | ||
369 | |||
370 | static int hgpk_register(struct psmouse *psmouse) | ||
371 | { | ||
372 | struct input_dev *dev = psmouse->dev; | ||
373 | int err; | ||
374 | |||
375 | /* unset the things that psmouse-base sets which we don't have */ | ||
376 | __clear_bit(BTN_MIDDLE, dev->keybit); | ||
377 | |||
378 | /* set the things we do have */ | ||
379 | __set_bit(EV_KEY, dev->evbit); | ||
380 | __set_bit(EV_REL, dev->evbit); | ||
381 | |||
382 | __set_bit(REL_X, dev->relbit); | ||
383 | __set_bit(REL_Y, dev->relbit); | ||
384 | |||
385 | __set_bit(BTN_LEFT, dev->keybit); | ||
386 | __set_bit(BTN_RIGHT, dev->keybit); | ||
387 | |||
388 | /* register handlers */ | ||
389 | psmouse->protocol_handler = hgpk_process_byte; | ||
390 | psmouse->poll = hgpk_poll; | ||
391 | psmouse->disconnect = hgpk_disconnect; | ||
392 | psmouse->reconnect = hgpk_reconnect; | ||
393 | psmouse->pktsize = 3; | ||
394 | |||
395 | /* Disable the idle resync. */ | ||
396 | psmouse->resync_time = 0; | ||
397 | /* Reset after a lot of bad bytes. */ | ||
398 | psmouse->resetafter = 1024; | ||
399 | |||
400 | err = device_create_file(&psmouse->ps2dev.serio->dev, | ||
401 | &psmouse_attr_powered.dattr); | ||
402 | if (err) | ||
403 | hgpk_err(psmouse, "Failed to create sysfs attribute\n"); | ||
404 | |||
405 | return err; | ||
406 | } | ||
407 | |||
408 | int hgpk_init(struct psmouse *psmouse) | ||
409 | { | ||
410 | struct hgpk_data *priv; | ||
411 | int err = -ENOMEM; | ||
412 | |||
413 | priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL); | ||
414 | if (!priv) | ||
415 | goto alloc_fail; | ||
416 | |||
417 | psmouse->private = priv; | ||
418 | priv->psmouse = psmouse; | ||
419 | priv->powered = 1; | ||
420 | INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work); | ||
421 | |||
422 | err = psmouse_reset(psmouse); | ||
423 | if (err) | ||
424 | goto init_fail; | ||
425 | |||
426 | err = hgpk_register(psmouse); | ||
427 | if (err) | ||
428 | goto init_fail; | ||
429 | |||
430 | return 0; | ||
431 | |||
432 | init_fail: | ||
433 | kfree(priv); | ||
434 | alloc_fail: | ||
435 | return err; | ||
436 | } | ||
437 | |||
438 | static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse) | ||
439 | { | ||
440 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
441 | unsigned char param[3]; | ||
442 | |||
443 | /* E7, E7, E7, E9 gets us a 3 byte identifier */ | ||
444 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || | ||
445 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || | ||
446 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || | ||
447 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { | ||
448 | return -EIO; | ||
449 | } | ||
450 | |||
451 | hgpk_dbg(psmouse, "ID: %02x %02x %02x", param[0], param[1], param[2]); | ||
452 | |||
453 | /* HGPK signature: 0x67, 0x00, 0x<model> */ | ||
454 | if (param[0] != 0x67 || param[1] != 0x00) | ||
455 | return -ENODEV; | ||
456 | |||
457 | hgpk_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]); | ||
458 | |||
459 | return param[2]; | ||
460 | } | ||
461 | |||
462 | int hgpk_detect(struct psmouse *psmouse, int set_properties) | ||
463 | { | ||
464 | int version; | ||
465 | |||
466 | version = hgpk_get_model(psmouse); | ||
467 | if (version < 0) | ||
468 | return version; | ||
469 | |||
470 | if (set_properties) { | ||
471 | psmouse->vendor = "ALPS"; | ||
472 | psmouse->name = "HGPK"; | ||
473 | psmouse->model = version; | ||
474 | } | ||
475 | |||
476 | return 0; | ||
477 | } | ||
diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h new file mode 100644 index 000000000000..a4b2a96f5f54 --- /dev/null +++ b/drivers/input/mouse/hgpk.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * OLPC HGPK (XO-1) touchpad PS/2 mouse driver | ||
3 | */ | ||
4 | |||
5 | #ifndef _HGPK_H | ||
6 | #define _HGPK_H | ||
7 | |||
8 | enum hgpk_model_t { | ||
9 | HGPK_MODEL_PREA = 0x0a, /* pre-B1s */ | ||
10 | HGPK_MODEL_A = 0x14, /* found on B1s, PT disabled in hardware */ | ||
11 | HGPK_MODEL_B = 0x28, /* B2s, has capacitance issues */ | ||
12 | HGPK_MODEL_C = 0x3c, | ||
13 | HGPK_MODEL_D = 0x50, /* C1, mass production */ | ||
14 | }; | ||
15 | |||
16 | struct hgpk_data { | ||
17 | struct psmouse *psmouse; | ||
18 | int powered; | ||
19 | int count, x_tally, y_tally; /* hardware workaround stuff */ | ||
20 | unsigned long recalib_window; | ||
21 | struct delayed_work recalib_wq; | ||
22 | }; | ||
23 | |||
24 | #define hgpk_dbg(psmouse, format, arg...) \ | ||
25 | dev_dbg(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
26 | #define hgpk_err(psmouse, format, arg...) \ | ||
27 | dev_err(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
28 | #define hgpk_info(psmouse, format, arg...) \ | ||
29 | dev_info(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
30 | #define hgpk_warn(psmouse, format, arg...) \ | ||
31 | dev_warn(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
32 | #define hgpk_notice(psmouse, format, arg...) \ | ||
33 | dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
34 | |||
35 | #ifdef CONFIG_MOUSE_PS2_OLPC | ||
36 | int hgpk_detect(struct psmouse *psmouse, int set_properties); | ||
37 | int hgpk_init(struct psmouse *psmouse); | ||
38 | #else | ||
39 | static inline int hgpk_detect(struct psmouse *psmouse, int set_properties) | ||
40 | { | ||
41 | return -ENODEV; | ||
42 | } | ||
43 | static inline int hgpk_init(struct psmouse *psmouse) | ||
44 | { | ||
45 | return -ENODEV; | ||
46 | } | ||
47 | #endif | ||
48 | |||
49 | #endif | ||
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 0c5660d28caa..390f1dbb98a4 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c | |||
@@ -157,10 +157,8 @@ static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data, | |||
157 | static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count) | 157 | static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count) |
158 | { | 158 | { |
159 | unsigned long value; | 159 | unsigned long value; |
160 | char *rest; | ||
161 | 160 | ||
162 | value = simple_strtoul(buf, &rest, 10); | 161 | if (strict_strtoul(buf, 10, &value) || value > 1) |
163 | if (*rest || value > 1) | ||
164 | return -EINVAL; | 162 | return -EINVAL; |
165 | 163 | ||
166 | ps2pp_set_smartscroll(psmouse, value); | 164 | ps2pp_set_smartscroll(psmouse, value); |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index f5a6be1d3c46..126e977e199e 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "synaptics.h" | 25 | #include "synaptics.h" |
26 | #include "logips2pp.h" | 26 | #include "logips2pp.h" |
27 | #include "alps.h" | 27 | #include "alps.h" |
28 | #include "hgpk.h" | ||
28 | #include "lifebook.h" | 29 | #include "lifebook.h" |
29 | #include "trackpoint.h" | 30 | #include "trackpoint.h" |
30 | #include "touchkit_ps2.h" | 31 | #include "touchkit_ps2.h" |
@@ -201,6 +202,12 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) | |||
201 | return PSMOUSE_FULL_PACKET; | 202 | return PSMOUSE_FULL_PACKET; |
202 | } | 203 | } |
203 | 204 | ||
205 | void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, | ||
206 | unsigned long delay) | ||
207 | { | ||
208 | queue_delayed_work(kpsmoused_wq, work, delay); | ||
209 | } | ||
210 | |||
204 | /* | 211 | /* |
205 | * __psmouse_set_state() sets new psmouse state and resets all flags. | 212 | * __psmouse_set_state() sets new psmouse state and resets all flags. |
206 | */ | 213 | */ |
@@ -220,7 +227,7 @@ static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_sta | |||
220 | * is not a concern. | 227 | * is not a concern. |
221 | */ | 228 | */ |
222 | 229 | ||
223 | static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | 230 | void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) |
224 | { | 231 | { |
225 | serio_pause_rx(psmouse->ps2dev.serio); | 232 | serio_pause_rx(psmouse->ps2dev.serio); |
226 | __psmouse_set_state(psmouse, new_state); | 233 | __psmouse_set_state(psmouse, new_state); |
@@ -305,7 +312,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
305 | psmouse->name, psmouse->phys, psmouse->pktcnt); | 312 | psmouse->name, psmouse->phys, psmouse->pktcnt); |
306 | psmouse->badbyte = psmouse->packet[0]; | 313 | psmouse->badbyte = psmouse->packet[0]; |
307 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | 314 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); |
308 | queue_work(kpsmoused_wq, &psmouse->resync_work); | 315 | psmouse_queue_work(psmouse, &psmouse->resync_work, 0); |
309 | goto out; | 316 | goto out; |
310 | } | 317 | } |
311 | 318 | ||
@@ -342,7 +349,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
342 | time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) { | 349 | time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) { |
343 | psmouse->badbyte = psmouse->packet[0]; | 350 | psmouse->badbyte = psmouse->packet[0]; |
344 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | 351 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); |
345 | queue_work(kpsmoused_wq, &psmouse->resync_work); | 352 | psmouse_queue_work(psmouse, &psmouse->resync_work, 0); |
346 | goto out; | 353 | goto out; |
347 | } | 354 | } |
348 | 355 | ||
@@ -630,8 +637,20 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
630 | } | 637 | } |
631 | } | 638 | } |
632 | 639 | ||
633 | if (max_proto > PSMOUSE_IMEX) { | 640 | /* |
641 | * Try OLPC HGPK touchpad. | ||
642 | */ | ||
643 | if (max_proto > PSMOUSE_IMEX && | ||
644 | hgpk_detect(psmouse, set_properties) == 0) { | ||
645 | if (!set_properties || hgpk_init(psmouse) == 0) | ||
646 | return PSMOUSE_HGPK; | ||
647 | /* | ||
648 | * Init failed, try basic relative protocols | ||
649 | */ | ||
650 | max_proto = PSMOUSE_IMEX; | ||
651 | } | ||
634 | 652 | ||
653 | if (max_proto > PSMOUSE_IMEX) { | ||
635 | if (genius_detect(psmouse, set_properties) == 0) | 654 | if (genius_detect(psmouse, set_properties) == 0) |
636 | return PSMOUSE_GENPS; | 655 | return PSMOUSE_GENPS; |
637 | 656 | ||
@@ -762,6 +781,14 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
762 | .detect = touchkit_ps2_detect, | 781 | .detect = touchkit_ps2_detect, |
763 | }, | 782 | }, |
764 | #endif | 783 | #endif |
784 | #ifdef CONFIG_MOUSE_PS2_OLPC | ||
785 | { | ||
786 | .type = PSMOUSE_HGPK, | ||
787 | .name = "OLPC HGPK", | ||
788 | .alias = "hgpk", | ||
789 | .detect = hgpk_detect, | ||
790 | }, | ||
791 | #endif | ||
765 | { | 792 | { |
766 | .type = PSMOUSE_CORTRON, | 793 | .type = PSMOUSE_CORTRON, |
767 | .name = "CortronPS/2", | 794 | .name = "CortronPS/2", |
@@ -935,7 +962,7 @@ static int psmouse_poll(struct psmouse *psmouse) | |||
935 | static void psmouse_resync(struct work_struct *work) | 962 | static void psmouse_resync(struct work_struct *work) |
936 | { | 963 | { |
937 | struct psmouse *parent = NULL, *psmouse = | 964 | struct psmouse *parent = NULL, *psmouse = |
938 | container_of(work, struct psmouse, resync_work); | 965 | container_of(work, struct psmouse, resync_work.work); |
939 | struct serio *serio = psmouse->ps2dev.serio; | 966 | struct serio *serio = psmouse->ps2dev.serio; |
940 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; | 967 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; |
941 | int failed = 0, enabled = 0; | 968 | int failed = 0, enabled = 0; |
@@ -1194,7 +1221,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
1194 | goto err_free; | 1221 | goto err_free; |
1195 | 1222 | ||
1196 | ps2_init(&psmouse->ps2dev, serio); | 1223 | ps2_init(&psmouse->ps2dev, serio); |
1197 | INIT_WORK(&psmouse->resync_work, psmouse_resync); | 1224 | INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync); |
1198 | psmouse->dev = input_dev; | 1225 | psmouse->dev = input_dev; |
1199 | snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); | 1226 | snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); |
1200 | 1227 | ||
@@ -1395,25 +1422,29 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev | |||
1395 | 1422 | ||
1396 | psmouse = serio_get_drvdata(serio); | 1423 | psmouse = serio_get_drvdata(serio); |
1397 | 1424 | ||
1398 | if (psmouse->state == PSMOUSE_IGNORE) { | 1425 | if (attr->protect) { |
1399 | retval = -ENODEV; | 1426 | if (psmouse->state == PSMOUSE_IGNORE) { |
1400 | goto out_unlock; | 1427 | retval = -ENODEV; |
1401 | } | 1428 | goto out_unlock; |
1429 | } | ||
1402 | 1430 | ||
1403 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 1431 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
1404 | parent = serio_get_drvdata(serio->parent); | 1432 | parent = serio_get_drvdata(serio->parent); |
1405 | psmouse_deactivate(parent); | 1433 | psmouse_deactivate(parent); |
1406 | } | 1434 | } |
1407 | 1435 | ||
1408 | psmouse_deactivate(psmouse); | 1436 | psmouse_deactivate(psmouse); |
1437 | } | ||
1409 | 1438 | ||
1410 | retval = attr->set(psmouse, attr->data, buf, count); | 1439 | retval = attr->set(psmouse, attr->data, buf, count); |
1411 | 1440 | ||
1412 | if (retval != -ENODEV) | 1441 | if (attr->protect) { |
1413 | psmouse_activate(psmouse); | 1442 | if (retval != -ENODEV) |
1443 | psmouse_activate(psmouse); | ||
1414 | 1444 | ||
1415 | if (parent) | 1445 | if (parent) |
1416 | psmouse_activate(parent); | 1446 | psmouse_activate(parent); |
1447 | } | ||
1417 | 1448 | ||
1418 | out_unlock: | 1449 | out_unlock: |
1419 | mutex_unlock(&psmouse_mutex); | 1450 | mutex_unlock(&psmouse_mutex); |
@@ -1433,10 +1464,8 @@ static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const | |||
1433 | { | 1464 | { |
1434 | unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset); | 1465 | unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset); |
1435 | unsigned long value; | 1466 | unsigned long value; |
1436 | char *rest; | ||
1437 | 1467 | ||
1438 | value = simple_strtoul(buf, &rest, 10); | 1468 | if (strict_strtoul(buf, 10, &value)) |
1439 | if (*rest) | ||
1440 | return -EINVAL; | 1469 | return -EINVAL; |
1441 | 1470 | ||
1442 | if ((unsigned int)value != value) | 1471 | if ((unsigned int)value != value) |
@@ -1549,10 +1578,8 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co | |||
1549 | static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count) | 1578 | static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count) |
1550 | { | 1579 | { |
1551 | unsigned long value; | 1580 | unsigned long value; |
1552 | char *rest; | ||
1553 | 1581 | ||
1554 | value = simple_strtoul(buf, &rest, 10); | 1582 | if (strict_strtoul(buf, 10, &value)) |
1555 | if (*rest) | ||
1556 | return -EINVAL; | 1583 | return -EINVAL; |
1557 | 1584 | ||
1558 | psmouse->set_rate(psmouse, value); | 1585 | psmouse->set_rate(psmouse, value); |
@@ -1562,10 +1589,8 @@ static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const | |||
1562 | static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count) | 1589 | static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count) |
1563 | { | 1590 | { |
1564 | unsigned long value; | 1591 | unsigned long value; |
1565 | char *rest; | ||
1566 | 1592 | ||
1567 | value = simple_strtoul(buf, &rest, 10); | 1593 | if (strict_strtoul(buf, 10, &value)) |
1568 | if (*rest) | ||
1569 | return -EINVAL; | 1594 | return -EINVAL; |
1570 | 1595 | ||
1571 | psmouse->set_resolution(psmouse, value); | 1596 | psmouse->set_resolution(psmouse, value); |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 1317bdd8cc7c..8b608a1cdd12 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -39,7 +39,7 @@ struct psmouse { | |||
39 | void *private; | 39 | void *private; |
40 | struct input_dev *dev; | 40 | struct input_dev *dev; |
41 | struct ps2dev ps2dev; | 41 | struct ps2dev ps2dev; |
42 | struct work_struct resync_work; | 42 | struct delayed_work resync_work; |
43 | char *vendor; | 43 | char *vendor; |
44 | char *name; | 44 | char *name; |
45 | unsigned char packet[8]; | 45 | unsigned char packet[8]; |
@@ -89,20 +89,24 @@ enum psmouse_type { | |||
89 | PSMOUSE_TRACKPOINT, | 89 | PSMOUSE_TRACKPOINT, |
90 | PSMOUSE_TOUCHKIT_PS2, | 90 | PSMOUSE_TOUCHKIT_PS2, |
91 | PSMOUSE_CORTRON, | 91 | PSMOUSE_CORTRON, |
92 | PSMOUSE_HGPK, | ||
92 | PSMOUSE_AUTO /* This one should always be last */ | 93 | PSMOUSE_AUTO /* This one should always be last */ |
93 | }; | 94 | }; |
94 | 95 | ||
96 | void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, | ||
97 | unsigned long delay); | ||
95 | int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); | 98 | int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); |
96 | int psmouse_reset(struct psmouse *psmouse); | 99 | int psmouse_reset(struct psmouse *psmouse); |
100 | void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state); | ||
97 | void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution); | 101 | void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution); |
98 | 102 | ||
99 | |||
100 | struct psmouse_attribute { | 103 | struct psmouse_attribute { |
101 | struct device_attribute dattr; | 104 | struct device_attribute dattr; |
102 | void *data; | 105 | void *data; |
103 | ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf); | 106 | ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf); |
104 | ssize_t (*set)(struct psmouse *psmouse, void *data, | 107 | ssize_t (*set)(struct psmouse *psmouse, void *data, |
105 | const char *buf, size_t count); | 108 | const char *buf, size_t count); |
109 | int protect; | ||
106 | }; | 110 | }; |
107 | #define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr) | 111 | #define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr) |
108 | 112 | ||
@@ -111,7 +115,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *at | |||
111 | ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, | 115 | ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, |
112 | const char *buf, size_t count); | 116 | const char *buf, size_t count); |
113 | 117 | ||
114 | #define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ | 118 | #define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect) \ |
115 | static ssize_t _show(struct psmouse *, void *data, char *); \ | 119 | static ssize_t _show(struct psmouse *, void *data, char *); \ |
116 | static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \ | 120 | static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \ |
117 | static struct psmouse_attribute psmouse_attr_##_name = { \ | 121 | static struct psmouse_attribute psmouse_attr_##_name = { \ |
@@ -126,6 +130,10 @@ static struct psmouse_attribute psmouse_attr_##_name = { \ | |||
126 | .data = _data, \ | 130 | .data = _data, \ |
127 | .show = _show, \ | 131 | .show = _show, \ |
128 | .set = _set, \ | 132 | .set = _set, \ |
133 | .protect = _protect, \ | ||
129 | } | 134 | } |
130 | 135 | ||
136 | #define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ | ||
137 | __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, 1) | ||
138 | |||
131 | #endif /* _PSMOUSE_H */ | 139 | #endif /* _PSMOUSE_H */ |
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index 26b845fc186a..e68c814c4361 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c | |||
@@ -89,10 +89,8 @@ static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data, | |||
89 | struct trackpoint_attr_data *attr = data; | 89 | struct trackpoint_attr_data *attr = data; |
90 | unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); | 90 | unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); |
91 | unsigned long value; | 91 | unsigned long value; |
92 | char *rest; | ||
93 | 92 | ||
94 | value = simple_strtoul(buf, &rest, 10); | 93 | if (strict_strtoul(buf, 10, &value) || value > 255) |
95 | if (*rest || value > 255) | ||
96 | return -EINVAL; | 94 | return -EINVAL; |
97 | 95 | ||
98 | *field = value; | 96 | *field = value; |
@@ -117,10 +115,8 @@ static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data, | |||
117 | struct trackpoint_attr_data *attr = data; | 115 | struct trackpoint_attr_data *attr = data; |
118 | unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); | 116 | unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); |
119 | unsigned long value; | 117 | unsigned long value; |
120 | char *rest; | ||
121 | 118 | ||
122 | value = simple_strtoul(buf, &rest, 10); | 119 | if (strict_strtoul(buf, 10, &value) || value > 1) |
123 | if (*rest || value > 1) | ||
124 | return -EINVAL; | 120 | return -EINVAL; |
125 | 121 | ||
126 | if (attr->inverted) | 122 | if (attr->inverted) |
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h index f451c7351a9d..847f4aad7ed5 100644 --- a/drivers/input/serio/i8042-io.h +++ b/drivers/input/serio/i8042-io.h | |||
@@ -67,7 +67,7 @@ static inline int i8042_platform_init(void) | |||
67 | * On some platforms touching the i8042 data register region can do really | 67 | * On some platforms touching the i8042 data register region can do really |
68 | * bad things. Because of this the region is always reserved on such boxes. | 68 | * bad things. Because of this the region is always reserved on such boxes. |
69 | */ | 69 | */ |
70 | #if defined(CONFIG_PPC_MERGE) | 70 | #if defined(CONFIG_PPC) |
71 | if (check_legacy_ioport(I8042_DATA_REG)) | 71 | if (check_legacy_ioport(I8042_DATA_REG)) |
72 | return -ENODEV; | 72 | return -ENODEV; |
73 | #endif | 73 | #endif |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 5aafe24984c5..a321aea2c7b5 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -322,6 +322,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
322 | DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"), | 322 | DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"), |
323 | }, | 323 | }, |
324 | }, | 324 | }, |
325 | { | ||
326 | .ident = "IBM 2656", | ||
327 | .matches = { | ||
328 | DMI_MATCH(DMI_SYS_VENDOR, "IBM"), | ||
329 | DMI_MATCH(DMI_PRODUCT_NAME, "2656"), | ||
330 | }, | ||
331 | }, | ||
325 | { } | 332 | { } |
326 | }; | 333 | }; |
327 | 334 | ||
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index c9397c8ee97e..470770c09260 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c | |||
@@ -373,6 +373,12 @@ static struct serio_device_id serio_raw_serio_ids[] = { | |||
373 | .id = SERIO_ANY, | 373 | .id = SERIO_ANY, |
374 | .extra = SERIO_ANY, | 374 | .extra = SERIO_ANY, |
375 | }, | 375 | }, |
376 | { | ||
377 | .type = SERIO_8042_XL, | ||
378 | .proto = SERIO_ANY, | ||
379 | .id = SERIO_ANY, | ||
380 | .extra = SERIO_ANY, | ||
381 | }, | ||
376 | { 0 } | 382 | { 0 } |
377 | }; | 383 | }; |
378 | 384 | ||
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 8f037a1d44a6..e53c838f1866 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c | |||
@@ -1202,16 +1202,22 @@ static ssize_t | |||
1202 | store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1202 | store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1203 | { | 1203 | { |
1204 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1204 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1205 | int x; | 1205 | long x; |
1206 | |||
1207 | if (strict_strtol(buf, 10, &x)) { | ||
1208 | size_t len = buf[count - 1] == '\n' ? count - 1 : count; | ||
1209 | |||
1210 | if (strncmp(buf, "disable", len)) | ||
1211 | return -EINVAL; | ||
1206 | 1212 | ||
1207 | if (strcmp(buf, "disable") == 0) { | ||
1208 | aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE; | 1213 | aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE; |
1209 | } else { | 1214 | } else { |
1210 | x = (int)simple_strtol(buf, NULL, 10); | 1215 | if (x < AIPTEK_TILT_MIN || x > AIPTEK_TILT_MAX) |
1211 | if (x >= AIPTEK_TILT_MIN && x <= AIPTEK_TILT_MAX) { | 1216 | return -EINVAL; |
1212 | aiptek->newSetting.xTilt = x; | 1217 | |
1213 | } | 1218 | aiptek->newSetting.xTilt = x; |
1214 | } | 1219 | } |
1220 | |||
1215 | return count; | 1221 | return count; |
1216 | } | 1222 | } |
1217 | 1223 | ||
@@ -1238,16 +1244,22 @@ static ssize_t | |||
1238 | store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1244 | store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1239 | { | 1245 | { |
1240 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1246 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1241 | int y; | 1247 | long y; |
1248 | |||
1249 | if (strict_strtol(buf, 10, &y)) { | ||
1250 | size_t len = buf[count - 1] == '\n' ? count - 1 : count; | ||
1251 | |||
1252 | if (strncmp(buf, "disable", len)) | ||
1253 | return -EINVAL; | ||
1242 | 1254 | ||
1243 | if (strcmp(buf, "disable") == 0) { | ||
1244 | aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE; | 1255 | aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE; |
1245 | } else { | 1256 | } else { |
1246 | y = (int)simple_strtol(buf, NULL, 10); | 1257 | if (y < AIPTEK_TILT_MIN || y > AIPTEK_TILT_MAX) |
1247 | if (y >= AIPTEK_TILT_MIN && y <= AIPTEK_TILT_MAX) { | 1258 | return -EINVAL; |
1248 | aiptek->newSetting.yTilt = y; | 1259 | |
1249 | } | 1260 | aiptek->newSetting.yTilt = y; |
1250 | } | 1261 | } |
1262 | |||
1251 | return count; | 1263 | return count; |
1252 | } | 1264 | } |
1253 | 1265 | ||
@@ -1269,8 +1281,12 @@ static ssize_t | |||
1269 | store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1281 | store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1270 | { | 1282 | { |
1271 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1283 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1284 | long j; | ||
1285 | |||
1286 | if (strict_strtol(buf, 10, &j)) | ||
1287 | return -EINVAL; | ||
1272 | 1288 | ||
1273 | aiptek->newSetting.jitterDelay = (int)simple_strtol(buf, NULL, 10); | 1289 | aiptek->newSetting.jitterDelay = (int)j; |
1274 | return count; | 1290 | return count; |
1275 | } | 1291 | } |
1276 | 1292 | ||
@@ -1294,8 +1310,12 @@ static ssize_t | |||
1294 | store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1310 | store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1295 | { | 1311 | { |
1296 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1312 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1313 | long d; | ||
1297 | 1314 | ||
1298 | aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, NULL, 10); | 1315 | if (strict_strtol(buf, 10, &d)) |
1316 | return -EINVAL; | ||
1317 | |||
1318 | aiptek->newSetting.programmableDelay = (int)d; | ||
1299 | return count; | 1319 | return count; |
1300 | } | 1320 | } |
1301 | 1321 | ||
@@ -1541,8 +1561,11 @@ static ssize_t | |||
1541 | store_tabletWheel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1561 | store_tabletWheel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
1542 | { | 1562 | { |
1543 | struct aiptek *aiptek = dev_get_drvdata(dev); | 1563 | struct aiptek *aiptek = dev_get_drvdata(dev); |
1564 | long w; | ||
1565 | |||
1566 | if (strict_strtol(buf, 10, &w)) return -EINVAL; | ||
1544 | 1567 | ||
1545 | aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10); | 1568 | aiptek->newSetting.wheel = (int)w; |
1546 | return count; | 1569 | return count; |
1547 | } | 1570 | } |
1548 | 1571 | ||
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 8583c766d565..b9b7fc6ff1eb 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -69,6 +69,17 @@ struct ts_event { | |||
69 | int ignore; | 69 | int ignore; |
70 | }; | 70 | }; |
71 | 71 | ||
72 | /* | ||
73 | * We allocate this separately to avoid cache line sharing issues when | ||
74 | * driver is used with DMA-based SPI controllers (like atmel_spi) on | ||
75 | * systems where main memory is not DMA-coherent (most non-x86 boards). | ||
76 | */ | ||
77 | struct ads7846_packet { | ||
78 | u8 read_x, read_y, read_z1, read_z2, pwrdown; | ||
79 | u16 dummy; /* for the pwrdown read */ | ||
80 | struct ts_event tc; | ||
81 | }; | ||
82 | |||
72 | struct ads7846 { | 83 | struct ads7846 { |
73 | struct input_dev *input; | 84 | struct input_dev *input; |
74 | char phys[32]; | 85 | char phys[32]; |
@@ -86,9 +97,7 @@ struct ads7846 { | |||
86 | u16 x_plate_ohms; | 97 | u16 x_plate_ohms; |
87 | u16 pressure_max; | 98 | u16 pressure_max; |
88 | 99 | ||
89 | u8 read_x, read_y, read_z1, read_z2, pwrdown; | 100 | struct ads7846_packet *packet; |
90 | u16 dummy; /* for the pwrdown read */ | ||
91 | struct ts_event tc; | ||
92 | 101 | ||
93 | struct spi_transfer xfer[18]; | 102 | struct spi_transfer xfer[18]; |
94 | struct spi_message msg[5]; | 103 | struct spi_message msg[5]; |
@@ -463,10 +472,11 @@ static ssize_t ads7846_disable_store(struct device *dev, | |||
463 | const char *buf, size_t count) | 472 | const char *buf, size_t count) |
464 | { | 473 | { |
465 | struct ads7846 *ts = dev_get_drvdata(dev); | 474 | struct ads7846 *ts = dev_get_drvdata(dev); |
466 | char *endp; | 475 | long i; |
467 | int i; | 476 | |
477 | if (strict_strtoul(buf, 10, &i)) | ||
478 | return -EINVAL; | ||
468 | 479 | ||
469 | i = simple_strtoul(buf, &endp, 10); | ||
470 | spin_lock_irq(&ts->lock); | 480 | spin_lock_irq(&ts->lock); |
471 | 481 | ||
472 | if (i) | 482 | if (i) |
@@ -512,16 +522,17 @@ static int get_pendown_state(struct ads7846 *ts) | |||
512 | static void ads7846_rx(void *ads) | 522 | static void ads7846_rx(void *ads) |
513 | { | 523 | { |
514 | struct ads7846 *ts = ads; | 524 | struct ads7846 *ts = ads; |
525 | struct ads7846_packet *packet = ts->packet; | ||
515 | unsigned Rt; | 526 | unsigned Rt; |
516 | u16 x, y, z1, z2; | 527 | u16 x, y, z1, z2; |
517 | 528 | ||
518 | /* ads7846_rx_val() did in-place conversion (including byteswap) from | 529 | /* ads7846_rx_val() did in-place conversion (including byteswap) from |
519 | * on-the-wire format as part of debouncing to get stable readings. | 530 | * on-the-wire format as part of debouncing to get stable readings. |
520 | */ | 531 | */ |
521 | x = ts->tc.x; | 532 | x = packet->tc.x; |
522 | y = ts->tc.y; | 533 | y = packet->tc.y; |
523 | z1 = ts->tc.z1; | 534 | z1 = packet->tc.z1; |
524 | z2 = ts->tc.z2; | 535 | z2 = packet->tc.z2; |
525 | 536 | ||
526 | /* range filtering */ | 537 | /* range filtering */ |
527 | if (x == MAX_12BIT) | 538 | if (x == MAX_12BIT) |
@@ -545,10 +556,10 @@ static void ads7846_rx(void *ads) | |||
545 | * the maximum. Don't report it to user space, repeat at least | 556 | * the maximum. Don't report it to user space, repeat at least |
546 | * once more the measurement | 557 | * once more the measurement |
547 | */ | 558 | */ |
548 | if (ts->tc.ignore || Rt > ts->pressure_max) { | 559 | if (packet->tc.ignore || Rt > ts->pressure_max) { |
549 | #ifdef VERBOSE | 560 | #ifdef VERBOSE |
550 | pr_debug("%s: ignored %d pressure %d\n", | 561 | pr_debug("%s: ignored %d pressure %d\n", |
551 | ts->spi->dev.bus_id, ts->tc.ignore, Rt); | 562 | ts->spi->dev.bus_id, packet->tc.ignore, Rt); |
552 | #endif | 563 | #endif |
553 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | 564 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), |
554 | HRTIMER_MODE_REL); | 565 | HRTIMER_MODE_REL); |
@@ -641,6 +652,7 @@ static int ads7846_no_filter(void *ads, int data_idx, int *val) | |||
641 | static void ads7846_rx_val(void *ads) | 652 | static void ads7846_rx_val(void *ads) |
642 | { | 653 | { |
643 | struct ads7846 *ts = ads; | 654 | struct ads7846 *ts = ads; |
655 | struct ads7846_packet *packet = ts->packet; | ||
644 | struct spi_message *m; | 656 | struct spi_message *m; |
645 | struct spi_transfer *t; | 657 | struct spi_transfer *t; |
646 | int val; | 658 | int val; |
@@ -660,7 +672,7 @@ static void ads7846_rx_val(void *ads) | |||
660 | case ADS7846_FILTER_REPEAT: | 672 | case ADS7846_FILTER_REPEAT: |
661 | break; | 673 | break; |
662 | case ADS7846_FILTER_IGNORE: | 674 | case ADS7846_FILTER_IGNORE: |
663 | ts->tc.ignore = 1; | 675 | packet->tc.ignore = 1; |
664 | /* Last message will contain ads7846_rx() as the | 676 | /* Last message will contain ads7846_rx() as the |
665 | * completion function. | 677 | * completion function. |
666 | */ | 678 | */ |
@@ -668,7 +680,7 @@ static void ads7846_rx_val(void *ads) | |||
668 | break; | 680 | break; |
669 | case ADS7846_FILTER_OK: | 681 | case ADS7846_FILTER_OK: |
670 | *(u16 *)t->rx_buf = val; | 682 | *(u16 *)t->rx_buf = val; |
671 | ts->tc.ignore = 0; | 683 | packet->tc.ignore = 0; |
672 | m = &ts->msg[++ts->msg_idx]; | 684 | m = &ts->msg[++ts->msg_idx]; |
673 | break; | 685 | break; |
674 | default: | 686 | default: |
@@ -773,7 +785,6 @@ static void ads7846_disable(struct ads7846 *ts) | |||
773 | /* we know the chip's in lowpower mode since we always | 785 | /* we know the chip's in lowpower mode since we always |
774 | * leave it that way after every request | 786 | * leave it that way after every request |
775 | */ | 787 | */ |
776 | |||
777 | } | 788 | } |
778 | 789 | ||
779 | /* Must be called with ts->lock held */ | 790 | /* Must be called with ts->lock held */ |
@@ -849,6 +860,7 @@ static int __devinit setup_pendown(struct spi_device *spi, struct ads7846 *ts) | |||
849 | static int __devinit ads7846_probe(struct spi_device *spi) | 860 | static int __devinit ads7846_probe(struct spi_device *spi) |
850 | { | 861 | { |
851 | struct ads7846 *ts; | 862 | struct ads7846 *ts; |
863 | struct ads7846_packet *packet; | ||
852 | struct input_dev *input_dev; | 864 | struct input_dev *input_dev; |
853 | struct ads7846_platform_data *pdata = spi->dev.platform_data; | 865 | struct ads7846_platform_data *pdata = spi->dev.platform_data; |
854 | struct spi_message *m; | 866 | struct spi_message *m; |
@@ -884,14 +896,16 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
884 | return err; | 896 | return err; |
885 | 897 | ||
886 | ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); | 898 | ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); |
899 | packet = kzalloc(sizeof(struct ads7846_packet), GFP_KERNEL); | ||
887 | input_dev = input_allocate_device(); | 900 | input_dev = input_allocate_device(); |
888 | if (!ts || !input_dev) { | 901 | if (!ts || !packet || !input_dev) { |
889 | err = -ENOMEM; | 902 | err = -ENOMEM; |
890 | goto err_free_mem; | 903 | goto err_free_mem; |
891 | } | 904 | } |
892 | 905 | ||
893 | dev_set_drvdata(&spi->dev, ts); | 906 | dev_set_drvdata(&spi->dev, ts); |
894 | 907 | ||
908 | ts->packet = packet; | ||
895 | ts->spi = spi; | 909 | ts->spi = spi; |
896 | ts->input = input_dev; | 910 | ts->input = input_dev; |
897 | ts->vref_mv = pdata->vref_mv; | 911 | ts->vref_mv = pdata->vref_mv; |
@@ -963,13 +977,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
963 | spi_message_init(m); | 977 | spi_message_init(m); |
964 | 978 | ||
965 | /* y- still on; turn on only y+ (and ADC) */ | 979 | /* y- still on; turn on only y+ (and ADC) */ |
966 | ts->read_y = READ_Y(vref); | 980 | packet->read_y = READ_Y(vref); |
967 | x->tx_buf = &ts->read_y; | 981 | x->tx_buf = &packet->read_y; |
968 | x->len = 1; | 982 | x->len = 1; |
969 | spi_message_add_tail(x, m); | 983 | spi_message_add_tail(x, m); |
970 | 984 | ||
971 | x++; | 985 | x++; |
972 | x->rx_buf = &ts->tc.y; | 986 | x->rx_buf = &packet->tc.y; |
973 | x->len = 2; | 987 | x->len = 2; |
974 | spi_message_add_tail(x, m); | 988 | spi_message_add_tail(x, m); |
975 | 989 | ||
@@ -981,12 +995,12 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
981 | x->delay_usecs = pdata->settle_delay_usecs; | 995 | x->delay_usecs = pdata->settle_delay_usecs; |
982 | 996 | ||
983 | x++; | 997 | x++; |
984 | x->tx_buf = &ts->read_y; | 998 | x->tx_buf = &packet->read_y; |
985 | x->len = 1; | 999 | x->len = 1; |
986 | spi_message_add_tail(x, m); | 1000 | spi_message_add_tail(x, m); |
987 | 1001 | ||
988 | x++; | 1002 | x++; |
989 | x->rx_buf = &ts->tc.y; | 1003 | x->rx_buf = &packet->tc.y; |
990 | x->len = 2; | 1004 | x->len = 2; |
991 | spi_message_add_tail(x, m); | 1005 | spi_message_add_tail(x, m); |
992 | } | 1006 | } |
@@ -999,13 +1013,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
999 | 1013 | ||
1000 | /* turn y- off, x+ on, then leave in lowpower */ | 1014 | /* turn y- off, x+ on, then leave in lowpower */ |
1001 | x++; | 1015 | x++; |
1002 | ts->read_x = READ_X(vref); | 1016 | packet->read_x = READ_X(vref); |
1003 | x->tx_buf = &ts->read_x; | 1017 | x->tx_buf = &packet->read_x; |
1004 | x->len = 1; | 1018 | x->len = 1; |
1005 | spi_message_add_tail(x, m); | 1019 | spi_message_add_tail(x, m); |
1006 | 1020 | ||
1007 | x++; | 1021 | x++; |
1008 | x->rx_buf = &ts->tc.x; | 1022 | x->rx_buf = &packet->tc.x; |
1009 | x->len = 2; | 1023 | x->len = 2; |
1010 | spi_message_add_tail(x, m); | 1024 | spi_message_add_tail(x, m); |
1011 | 1025 | ||
@@ -1014,12 +1028,12 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1014 | x->delay_usecs = pdata->settle_delay_usecs; | 1028 | x->delay_usecs = pdata->settle_delay_usecs; |
1015 | 1029 | ||
1016 | x++; | 1030 | x++; |
1017 | x->tx_buf = &ts->read_x; | 1031 | x->tx_buf = &packet->read_x; |
1018 | x->len = 1; | 1032 | x->len = 1; |
1019 | spi_message_add_tail(x, m); | 1033 | spi_message_add_tail(x, m); |
1020 | 1034 | ||
1021 | x++; | 1035 | x++; |
1022 | x->rx_buf = &ts->tc.x; | 1036 | x->rx_buf = &packet->tc.x; |
1023 | x->len = 2; | 1037 | x->len = 2; |
1024 | spi_message_add_tail(x, m); | 1038 | spi_message_add_tail(x, m); |
1025 | } | 1039 | } |
@@ -1033,13 +1047,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1033 | spi_message_init(m); | 1047 | spi_message_init(m); |
1034 | 1048 | ||
1035 | x++; | 1049 | x++; |
1036 | ts->read_z1 = READ_Z1(vref); | 1050 | packet->read_z1 = READ_Z1(vref); |
1037 | x->tx_buf = &ts->read_z1; | 1051 | x->tx_buf = &packet->read_z1; |
1038 | x->len = 1; | 1052 | x->len = 1; |
1039 | spi_message_add_tail(x, m); | 1053 | spi_message_add_tail(x, m); |
1040 | 1054 | ||
1041 | x++; | 1055 | x++; |
1042 | x->rx_buf = &ts->tc.z1; | 1056 | x->rx_buf = &packet->tc.z1; |
1043 | x->len = 2; | 1057 | x->len = 2; |
1044 | spi_message_add_tail(x, m); | 1058 | spi_message_add_tail(x, m); |
1045 | 1059 | ||
@@ -1048,12 +1062,12 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1048 | x->delay_usecs = pdata->settle_delay_usecs; | 1062 | x->delay_usecs = pdata->settle_delay_usecs; |
1049 | 1063 | ||
1050 | x++; | 1064 | x++; |
1051 | x->tx_buf = &ts->read_z1; | 1065 | x->tx_buf = &packet->read_z1; |
1052 | x->len = 1; | 1066 | x->len = 1; |
1053 | spi_message_add_tail(x, m); | 1067 | spi_message_add_tail(x, m); |
1054 | 1068 | ||
1055 | x++; | 1069 | x++; |
1056 | x->rx_buf = &ts->tc.z1; | 1070 | x->rx_buf = &packet->tc.z1; |
1057 | x->len = 2; | 1071 | x->len = 2; |
1058 | spi_message_add_tail(x, m); | 1072 | spi_message_add_tail(x, m); |
1059 | } | 1073 | } |
@@ -1065,13 +1079,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1065 | spi_message_init(m); | 1079 | spi_message_init(m); |
1066 | 1080 | ||
1067 | x++; | 1081 | x++; |
1068 | ts->read_z2 = READ_Z2(vref); | 1082 | packet->read_z2 = READ_Z2(vref); |
1069 | x->tx_buf = &ts->read_z2; | 1083 | x->tx_buf = &packet->read_z2; |
1070 | x->len = 1; | 1084 | x->len = 1; |
1071 | spi_message_add_tail(x, m); | 1085 | spi_message_add_tail(x, m); |
1072 | 1086 | ||
1073 | x++; | 1087 | x++; |
1074 | x->rx_buf = &ts->tc.z2; | 1088 | x->rx_buf = &packet->tc.z2; |
1075 | x->len = 2; | 1089 | x->len = 2; |
1076 | spi_message_add_tail(x, m); | 1090 | spi_message_add_tail(x, m); |
1077 | 1091 | ||
@@ -1080,12 +1094,12 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1080 | x->delay_usecs = pdata->settle_delay_usecs; | 1094 | x->delay_usecs = pdata->settle_delay_usecs; |
1081 | 1095 | ||
1082 | x++; | 1096 | x++; |
1083 | x->tx_buf = &ts->read_z2; | 1097 | x->tx_buf = &packet->read_z2; |
1084 | x->len = 1; | 1098 | x->len = 1; |
1085 | spi_message_add_tail(x, m); | 1099 | spi_message_add_tail(x, m); |
1086 | 1100 | ||
1087 | x++; | 1101 | x++; |
1088 | x->rx_buf = &ts->tc.z2; | 1102 | x->rx_buf = &packet->tc.z2; |
1089 | x->len = 2; | 1103 | x->len = 2; |
1090 | spi_message_add_tail(x, m); | 1104 | spi_message_add_tail(x, m); |
1091 | } | 1105 | } |
@@ -1099,13 +1113,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1099 | spi_message_init(m); | 1113 | spi_message_init(m); |
1100 | 1114 | ||
1101 | x++; | 1115 | x++; |
1102 | ts->pwrdown = PWRDOWN; | 1116 | packet->pwrdown = PWRDOWN; |
1103 | x->tx_buf = &ts->pwrdown; | 1117 | x->tx_buf = &packet->pwrdown; |
1104 | x->len = 1; | 1118 | x->len = 1; |
1105 | spi_message_add_tail(x, m); | 1119 | spi_message_add_tail(x, m); |
1106 | 1120 | ||
1107 | x++; | 1121 | x++; |
1108 | x->rx_buf = &ts->dummy; | 1122 | x->rx_buf = &packet->dummy; |
1109 | x->len = 2; | 1123 | x->len = 2; |
1110 | CS_CHANGE(*x); | 1124 | CS_CHANGE(*x); |
1111 | spi_message_add_tail(x, m); | 1125 | spi_message_add_tail(x, m); |
@@ -1158,6 +1172,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1158 | ts->filter_cleanup(ts->filter_data); | 1172 | ts->filter_cleanup(ts->filter_data); |
1159 | err_free_mem: | 1173 | err_free_mem: |
1160 | input_free_device(input_dev); | 1174 | input_free_device(input_dev); |
1175 | kfree(packet); | ||
1161 | kfree(ts); | 1176 | kfree(ts); |
1162 | return err; | 1177 | return err; |
1163 | } | 1178 | } |
@@ -1183,6 +1198,7 @@ static int __devexit ads7846_remove(struct spi_device *spi) | |||
1183 | if (ts->filter_cleanup) | 1198 | if (ts->filter_cleanup) |
1184 | ts->filter_cleanup(ts->filter_data); | 1199 | ts->filter_cleanup(ts->filter_data); |
1185 | 1200 | ||
1201 | kfree(ts->packet); | ||
1186 | kfree(ts); | 1202 | kfree(ts); |
1187 | 1203 | ||
1188 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); | 1204 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); |
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index eee126b19e8b..a89a6a8f05e6 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
@@ -91,6 +91,9 @@ struct atmel_tsadcc { | |||
91 | char phys[32]; | 91 | char phys[32]; |
92 | struct clk *clk; | 92 | struct clk *clk; |
93 | int irq; | 93 | int irq; |
94 | unsigned int prev_absx; | ||
95 | unsigned int prev_absy; | ||
96 | unsigned char bufferedmeasure; | ||
94 | }; | 97 | }; |
95 | 98 | ||
96 | static void __iomem *tsc_base; | 99 | static void __iomem *tsc_base; |
@@ -100,10 +103,9 @@ static void __iomem *tsc_base; | |||
100 | 103 | ||
101 | static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) | 104 | static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) |
102 | { | 105 | { |
103 | struct input_dev *input_dev = ((struct atmel_tsadcc *)dev)->input; | 106 | struct atmel_tsadcc *ts_dev = (struct atmel_tsadcc *)dev; |
107 | struct input_dev *input_dev = ts_dev->input; | ||
104 | 108 | ||
105 | unsigned int absx; | ||
106 | unsigned int absy; | ||
107 | unsigned int status; | 109 | unsigned int status; |
108 | unsigned int reg; | 110 | unsigned int reg; |
109 | 111 | ||
@@ -121,6 +123,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) | |||
121 | atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); | 123 | atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); |
122 | 124 | ||
123 | input_report_key(input_dev, BTN_TOUCH, 0); | 125 | input_report_key(input_dev, BTN_TOUCH, 0); |
126 | ts_dev->bufferedmeasure = 0; | ||
124 | input_sync(input_dev); | 127 | input_sync(input_dev); |
125 | 128 | ||
126 | } else if (status & ATMEL_TSADCC_PENCNT) { | 129 | } else if (status & ATMEL_TSADCC_PENCNT) { |
@@ -138,16 +141,23 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) | |||
138 | } else if (status & ATMEL_TSADCC_EOC(3)) { | 141 | } else if (status & ATMEL_TSADCC_EOC(3)) { |
139 | /* Conversion finished */ | 142 | /* Conversion finished */ |
140 | 143 | ||
141 | absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10; | 144 | if (ts_dev->bufferedmeasure) { |
142 | absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2); | 145 | /* Last measurement is always discarded, since it can |
143 | 146 | * be erroneous. | |
144 | absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10; | 147 | * Always report previous measurement */ |
145 | absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0); | 148 | input_report_abs(input_dev, ABS_X, ts_dev->prev_absx); |
146 | 149 | input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy); | |
147 | input_report_abs(input_dev, ABS_X, absx); | 150 | input_report_key(input_dev, BTN_TOUCH, 1); |
148 | input_report_abs(input_dev, ABS_Y, absy); | 151 | input_sync(input_dev); |
149 | input_report_key(input_dev, BTN_TOUCH, 1); | 152 | } else |
150 | input_sync(input_dev); | 153 | ts_dev->bufferedmeasure = 1; |
154 | |||
155 | /* Now make new measurement */ | ||
156 | ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10; | ||
157 | ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2); | ||
158 | |||
159 | ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10; | ||
160 | ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0); | ||
151 | } | 161 | } |
152 | 162 | ||
153 | return IRQ_HANDLED; | 163 | return IRQ_HANDLED; |
@@ -223,6 +233,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) | |||
223 | } | 233 | } |
224 | 234 | ||
225 | ts_dev->input = input_dev; | 235 | ts_dev->input = input_dev; |
236 | ts_dev->bufferedmeasure = 0; | ||
226 | 237 | ||
227 | snprintf(ts_dev->phys, sizeof(ts_dev->phys), | 238 | snprintf(ts_dev->phys, sizeof(ts_dev->phys), |
228 | "%s/input0", pdev->dev.bus_id); | 239 | "%s/input0", pdev->dev.bus_id); |
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 37a555f37306..ba648750a8d9 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c | |||
@@ -3,8 +3,7 @@ | |||
3 | * Wolfson WM97xx AC97 Codecs. | 3 | * Wolfson WM97xx AC97 Codecs. |
4 | * | 4 | * |
5 | * Copyright 2004, 2007 Wolfson Microelectronics PLC. | 5 | * Copyright 2004, 2007 Wolfson Microelectronics PLC. |
6 | * Author: Liam Girdwood | 6 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
7 | * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com | ||
8 | * Parts Copyright : Ian Molton <spyro@f2s.com> | 7 | * Parts Copyright : Ian Molton <spyro@f2s.com> |
9 | * Andrew Zabolotny <zap@homelink.ru> | 8 | * Andrew Zabolotny <zap@homelink.ru> |
10 | * | 9 | * |
@@ -296,6 +295,6 @@ module_init(mainstone_wm97xx_init); | |||
296 | module_exit(mainstone_wm97xx_exit); | 295 | module_exit(mainstone_wm97xx_exit); |
297 | 296 | ||
298 | /* Module information */ | 297 | /* Module information */ |
299 | MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>"); | 298 | MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); |
300 | MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone"); | 299 | MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone"); |
301 | MODULE_LICENSE("GPL"); | 300 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c index 372efbc694ff..6b5be742c27d 100644 --- a/drivers/input/touchscreen/wm9705.c +++ b/drivers/input/touchscreen/wm9705.c | |||
@@ -2,8 +2,7 @@ | |||
2 | * wm9705.c -- Codec driver for Wolfson WM9705 AC97 Codec. | 2 | * wm9705.c -- Codec driver for Wolfson WM9705 AC97 Codec. |
3 | * | 3 | * |
4 | * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC. | 4 | * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC. |
5 | * Author: Liam Girdwood | 5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
6 | * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com | ||
7 | * Parts Copyright : Ian Molton <spyro@f2s.com> | 6 | * Parts Copyright : Ian Molton <spyro@f2s.com> |
8 | * Andrew Zabolotny <zap@homelink.ru> | 7 | * Andrew Zabolotny <zap@homelink.ru> |
9 | * Russell King <rmk@arm.linux.org.uk> | 8 | * Russell King <rmk@arm.linux.org.uk> |
@@ -347,6 +346,6 @@ struct wm97xx_codec_drv wm9705_codec = { | |||
347 | EXPORT_SYMBOL_GPL(wm9705_codec); | 346 | EXPORT_SYMBOL_GPL(wm9705_codec); |
348 | 347 | ||
349 | /* Module information */ | 348 | /* Module information */ |
350 | MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>"); | 349 | MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); |
351 | MODULE_DESCRIPTION("WM9705 Touch Screen Driver"); | 350 | MODULE_DESCRIPTION("WM9705 Touch Screen Driver"); |
352 | MODULE_LICENSE("GPL"); | 351 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c index c8bb1e7335fc..7490b05c3566 100644 --- a/drivers/input/touchscreen/wm9712.c +++ b/drivers/input/touchscreen/wm9712.c | |||
@@ -2,8 +2,7 @@ | |||
2 | * wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs. | 2 | * wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs. |
3 | * | 3 | * |
4 | * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC. | 4 | * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC. |
5 | * Author: Liam Girdwood | 5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
6 | * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com | ||
7 | * Parts Copyright : Ian Molton <spyro@f2s.com> | 6 | * Parts Copyright : Ian Molton <spyro@f2s.com> |
8 | * Andrew Zabolotny <zap@homelink.ru> | 7 | * Andrew Zabolotny <zap@homelink.ru> |
9 | * Russell King <rmk@arm.linux.org.uk> | 8 | * Russell King <rmk@arm.linux.org.uk> |
@@ -462,6 +461,6 @@ struct wm97xx_codec_drv wm9712_codec = { | |||
462 | EXPORT_SYMBOL_GPL(wm9712_codec); | 461 | EXPORT_SYMBOL_GPL(wm9712_codec); |
463 | 462 | ||
464 | /* Module information */ | 463 | /* Module information */ |
465 | MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>"); | 464 | MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); |
466 | MODULE_DESCRIPTION("WM9712 Touch Screen Driver"); | 465 | MODULE_DESCRIPTION("WM9712 Touch Screen Driver"); |
467 | MODULE_LICENSE("GPL"); | 466 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c index 781ee83547e6..238b5132712e 100644 --- a/drivers/input/touchscreen/wm9713.c +++ b/drivers/input/touchscreen/wm9713.c | |||
@@ -2,8 +2,7 @@ | |||
2 | * wm9713.c -- Codec touch driver for Wolfson WM9713 AC97 Codec. | 2 | * wm9713.c -- Codec touch driver for Wolfson WM9713 AC97 Codec. |
3 | * | 3 | * |
4 | * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC. | 4 | * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC. |
5 | * Author: Liam Girdwood | 5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
6 | * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com | ||
7 | * Parts Copyright : Ian Molton <spyro@f2s.com> | 6 | * Parts Copyright : Ian Molton <spyro@f2s.com> |
8 | * Andrew Zabolotny <zap@homelink.ru> | 7 | * Andrew Zabolotny <zap@homelink.ru> |
9 | * Russell King <rmk@arm.linux.org.uk> | 8 | * Russell King <rmk@arm.linux.org.uk> |
@@ -476,6 +475,6 @@ struct wm97xx_codec_drv wm9713_codec = { | |||
476 | EXPORT_SYMBOL_GPL(wm9713_codec); | 475 | EXPORT_SYMBOL_GPL(wm9713_codec); |
477 | 476 | ||
478 | /* Module information */ | 477 | /* Module information */ |
479 | MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>"); | 478 | MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); |
480 | MODULE_DESCRIPTION("WM9713 Touch Screen Driver"); | 479 | MODULE_DESCRIPTION("WM9713 Touch Screen Driver"); |
481 | MODULE_LICENSE("GPL"); | 480 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index d589ab0e3adc..d15aa11d7056 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c | |||
@@ -3,8 +3,7 @@ | |||
3 | * and WM9713 AC97 Codecs. | 3 | * and WM9713 AC97 Codecs. |
4 | * | 4 | * |
5 | * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC. | 5 | * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC. |
6 | * Author: Liam Girdwood | 6 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
7 | * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com | ||
8 | * Parts Copyright : Ian Molton <spyro@f2s.com> | 7 | * Parts Copyright : Ian Molton <spyro@f2s.com> |
9 | * Andrew Zabolotny <zap@homelink.ru> | 8 | * Andrew Zabolotny <zap@homelink.ru> |
10 | * Russell King <rmk@arm.linux.org.uk> | 9 | * Russell King <rmk@arm.linux.org.uk> |
@@ -824,6 +823,6 @@ module_init(wm97xx_init); | |||
824 | module_exit(wm97xx_exit); | 823 | module_exit(wm97xx_exit); |
825 | 824 | ||
826 | /* Module information */ | 825 | /* Module information */ |
827 | MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>"); | 826 | MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); |
828 | MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver"); | 827 | MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver"); |
829 | MODULE_LICENSE("GPL"); | 828 | MODULE_LICENSE("GPL"); |